Sat, 06 Aug 2022 22:10:28 +0200
Renamed prod_edit to prod_view.
www/Makefile | file | annotate | diff | comparison | revisions | |
www/js/prod_edit.js | file | annotate | diff | comparison | revisions | |
www/js/prod_inprod.js | file | annotate | diff | comparison | revisions | |
www/js/prod_view.js | file | annotate | diff | comparison | revisions | |
www/prod_edit.php | file | annotate | diff | comparison | revisions | |
www/prod_view.php | file | annotate | diff | comparison | revisions |
--- a/www/Makefile Sat Aug 06 22:02:42 2022 +0200 +++ b/www/Makefile Sat Aug 06 22:10:28 2022 +0200 @@ -10,7 +10,7 @@ index.php \ log_co2pressure.php log_fermentation.php log_ispindel.php \ mon_brewer.php mon_co2meter.php mon_fermenter.php mon_ispindel.php mon_node.php \ - prod_edit.php prod_inprod.php rec_view.php rec_main.php version.php + prod_view.php prod_inprod.php rec_view.php rec_main.php version.php SUB = version.php.in images/* css/* jqwidgets/* jqwidgets/styles/* \ jqwidgets/styles/images/* jqwidgets/globalization/* js/* \ includes/* fpdf/* import/*
--- a/www/js/prod_edit.js Sat Aug 06 22:02:42 2022 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3308 +0,0 @@ -/***************************************************************************** - * Copyright (C) 2018-2022 - * - * Michiel Broek <mbroek at mbse dot eu> - * - * This file is part of BMS - * - * This 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 2, or (at your option) any - * later version. - * - * BrewCloud 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 ThermFerm; see the file COPYING. If not, write to the Free - * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - *****************************************************************************/ - - -function block_fermentable(stage, added) { - if (stage > 5 && added < 4) // After fermentation and added before packaging - return true; - if (stage > 3 && added < 3) // After primary and added before sec/tert - return true; - if (stage > 2 && added < 2) // After boil and added during mash or boil - return true; - return false; -} - -function block_hop(stage, useat) -{ - if (stage > 2 && useat < 5) - return true; - return false; -} - -function block_misc(stage, use_use) { - if (stage > 5 && use_use < 5) - return true; - if (stage > 3 && use_use < 4) - return true; - if (stage > 2 && use_use < 3) - return true; - if (stage > 1 && use_use < 1) - return true; - return false; -} - -function block_yeast(stage, use) { - if (stage > 3 && use < 1) - return true; - if (stage > 4 && use < 2) - return true; - if (stage > 5 && use < 3) - return true; - if (stage > 6 && use < 4) - return true; - return false; -} - - -$(document).ready(function() { - - var i, - to_100 = false, // Fermentables adjust to 100% - preboil_sg = 0, - aboil_sg = 0, - est_mash_sg = 0, - psugar = 0, // Percentage real sugars - pcara = 0, // Percentage cara/crystal malts - svg = 77, // Default attenuation - mashkg = 0, // Malt in mash weight - initcells = 0, // Initial yeast cell count - - ok_fermentables = 1, // Fermentables are in stock - ok_hops = 1, // Hops are in stock - ok_miscs = 1, // Miscs are in stock - ok_yeasts = 1, // Yeasts are in stock - ok_waters = 1, // Waters are in stock - - data_loaded = 0; - error_count = 0; - k_cm = 0; - k_vol = 0; - k_what = 0; - - hop_flavour = 0, - hop_aroma = 0, - mash_infuse = 0, - last_acid = '', - - MMCa = 40.048, - MMMg = 24.305, - MMNa = 22.98976928, - MMCl = 35.453, - MMSO4 = 96.0626, - MMHCO3 = 61.01684, - MMCaSO4 = 172.171, - MMCaCl2 = 147.015, - MMCaCO3 = 100.087, - MMMgCl2 = 95.211, /* Since 27-06-2021 */ - MMMgSO4 = 246.475, - MMNaHCO3 = 84.007, - MMNa2CO3 = 105.996, - MMNaCl = 58.443, - MMCaOH2 = 74.06268, - - fermentableRow = 0, - fermentableData = {}, - fermentableInit = 1, - hopRow = 0, - hopData = {}, - miscRow = 0, - miscData = {}, - yeastRow = 0, - yeastData = {}, - mashRow = 0, - mashData = {}, - Ka1 = 0.0000004445, - Ka2 = 0.0000000000468, - dataRecord = {}, - url = 'includes/db_product.php', - MaltVolume = 0.87, // l/kg 0.688 volgens internetbronnen, gemeten 0.874 l/kg, na enige tijd maischen 0,715 l/kg (A3 Otten). - SpecificHeatWater = 1.0, - SpecificHeatMalt = 0.399, //cal/g.°C - SlakingHeat = 10.318, //cal/g.°C - - // Prepare the data - source = { - datatype: 'json', - cache: false, - async: true, - datafields: [ - // From prod_main - { name: 'record', type: 'number' }, - { name: 'uuid', type: 'string' }, - { name: 'name', type: 'string' }, - { name: 'code', type: 'string' }, - { name: 'birth', type: 'string' }, - { name: 'stage', type: 'int' }, - { name: 'notes', type: 'string' }, - { name: 'log_brew', type: 'int' }, - { name: 'log_fermentation', type: 'int' }, - { name: 'log_ispindel', type: 'int' }, - { name: 'log_co2pressure', type: 'int' }, - { name: 'inventory_reduced', type: 'int' }, - { name: 'locked', type: 'int' }, - { name: 'eq_name', type: 'string' }, - { name: 'eq_boil_size', type: 'float' }, - { name: 'eq_batch_size', type: 'float' }, - { name: 'eq_tun_volume', type: 'float' }, - { name: 'eq_tun_weight', type: 'float' }, - { name: 'eq_tun_specific_heat', type: 'float' }, - { name: 'eq_tun_material', type: 'int' }, - { name: 'eq_tun_height', type: 'float' }, - { name: 'eq_top_up_water', type: 'float' }, - { name: 'eq_trub_chiller_loss', type: 'float' }, - { name: 'eq_evap_rate', type: 'float' }, - { name: 'eq_boil_time', type: 'float' }, - { name: 'eq_calc_boil_volume', type: 'int' }, - { name: 'eq_top_up_kettle', type: 'float' }, - { name: 'eq_hop_utilization', type: 'float' }, - { name: 'eq_notes', type: 'string' }, - { name: 'eq_lauter_volume', type: 'float' }, - { name: 'eq_lauter_height', type: 'float' }, - { name: 'eq_lauter_deadspace', type: 'float' }, - { name: 'eq_kettle_volume', type: 'float' }, - { name: 'eq_kettle_height', type: 'float' }, - { name: 'eq_mash_volume', type: 'float' }, - { name: 'eq_mash_max', type: 'float' }, - { name: 'eq_efficiency', type: 'float' }, - { name: 'brew_date_start', type: 'string' }, - { name: 'brew_mash_ph', type: 'float' }, - { name: 'brew_mash_sg', type: 'float' }, - { name: 'brew_mash_efficiency', type: 'float' }, - { name: 'brew_sparge_est', type: 'float' }, - { name: 'brew_sparge_ph', type: 'float' }, - { name: 'brew_preboil_volume', type: 'float' }, - { name: 'brew_preboil_sg', type: 'float' }, - { name: 'brew_preboil_ph', type: 'float' }, - { name: 'brew_preboil_efficiency', type: 'float' }, - { name: 'brew_aboil_volume', type: 'float' }, - { name: 'brew_aboil_sg', type: 'float' }, - { name: 'brew_aboil_ph', type: 'float' }, - { name: 'brew_aboil_efficiency', type: 'float' }, - { name: 'brew_cooling_method', type: 'int' }, - { name: 'brew_cooling_time', type: 'float' }, - { name: 'brew_cooling_to', type: 'float' }, - { name: 'brew_whirlpool9', type: 'float' }, - { name: 'brew_whirlpool7', type: 'float' }, - { name: 'brew_whirlpool6', type: 'float' }, - { name: 'brew_whirlpool2', type: 'float' }, - { name: 'brew_fermenter_volume', type: 'float' }, - { name: 'brew_fermenter_extrawater', type: 'float' }, - { name: 'brew_fermenter_tcloss', type: 'float' }, - { name: 'brew_aeration_time', type: 'float' }, - { name: 'brew_aeration_speed', type: 'float' }, - { name: 'brew_aeration_type', type: 'int' }, - { name: 'brew_fermenter_sg', type: 'float' }, - { name: 'brew_fermenter_ibu', type: 'float' }, - { name: 'brew_fermenter_color', type: 'float' }, - { name: 'brew_date_end', type: 'string' }, - { name: 'og', type: 'float' }, - { name: 'fg', type: 'float' }, - { name: 'primary_start_temp', type: 'float' }, - { name: 'primary_max_temp', type: 'float' }, - { name: 'primary_end_temp', type: 'float' }, - { name: 'primary_end_sg', type: 'float' }, - { name: 'primary_end_date', type: 'string' }, - { name: 'secondary_temp', type: 'float' }, - { name: 'secondary_end_sg', type: 'float' }, - { name: 'secondary_end_date', type: 'string' }, - { name: 'tertiary_temp', type: 'float' }, - { name: 'package_date', type: 'string' }, - { name: 'package_volume', type: 'float' }, - { name: 'package_infuse_amount', type: 'float' }, - { name: 'package_infuse_abv', type: 'float' }, - { name: 'package_infuse_notes', type: 'string' }, - { name: 'package_abv', type: 'float' }, - { name: 'package_ph', type: 'float' }, - { name: 'bottle_amount', type: 'float' }, - { name: 'bottle_carbonation', type: 'float' }, - { name: 'bottle_priming_water', type: 'float' }, - { name: 'bottle_priming_amount', type: 'float' }, - { name: 'bottle_carbonation_temp', type: 'float' }, - { name: 'keg_amount', type: 'float' }, - { name: 'keg_carbonation', type: 'float' }, - { name: 'keg_priming_water', type: 'float' }, - { name: 'keg_priming_amount', type: 'float' }, - { name: 'keg_carbonation_temp', type: 'float' }, - { name: 'keg_forced_carb', type: 'int' }, - { name: 'keg_pressure', type: 'float' }, - { name: 'taste_notes', type: 'string' }, - { name: 'taste_rate', type: 'float' }, - { name: 'taste_date', type: 'string' }, - { name: 'taste_color', type: 'string' }, - { name: 'taste_transparency', type: 'string' }, - { name: 'taste_head', type: 'string' }, - { name: 'taste_aroma', type: 'string' }, - { name: 'taste_taste', type: 'string' }, - { name: 'taste_mouthfeel', type: 'string' }, - { name: 'taste_aftertaste', type: 'string' }, - { name: 'st_name', type: 'string' }, - { name: 'st_letter', type: 'string' }, - { name: 'st_guide', type: 'string' }, - { name: 'st_category', type: 'string' }, - { name: 'st_category_number', type: 'int' }, - { name: 'st_type', type: 'int' }, - { name: 'st_og_min', type: 'float' }, - { name: 'st_og_max', type: 'float' }, - { name: 'st_fg_min', type: 'float' }, - { name: 'st_fg_max', type: 'float' }, - { name: 'st_ibu_min', type: 'float' }, - { name: 'st_ibu_max', type: 'float' }, - { name: 'st_color_min', type: 'float' }, - { name: 'st_color_max', type: 'float' }, - { name: 'st_carb_min', type: 'float' }, - { name: 'st_carb_max', type: 'float' }, - { name: 'st_abv_min', type: 'float' }, - { name: 'st_abv_max', type: 'float' }, - { name: 'type', type: 'int' }, - { name: 'batch_size', type: 'float' }, - { name: 'boil_size', type: 'float' }, - { name: 'boil_time', type: 'float' }, - { name: 'efficiency', type: 'float' }, - { name: 'est_og', type: 'float' }, - { name: 'est_og3', type: 'float' }, - { name: 'est_fg', type: 'float' }, - { name: 'est_abv', type: 'float' }, - { name: 'est_color', type: 'float' }, - { name: 'color_method', type: 'int' }, - { name: 'est_ibu', type: 'float' }, - { name: 'ibu_method', type: 'int' }, - { name: 'est_carb', type: 'float' }, - { name: 'sparge_temp', type: 'float' }, - { name: 'sparge_ph', type: 'float' }, - { name: 'sparge_volume', type: 'float' }, - { name: 'sparge_source', type: 'int' }, - { name: 'sparge_acid_type', type: 'int' }, - { name: 'sparge_acid_perc', type: 'float' }, - { name: 'sparge_acid_amount', type: 'float' }, - { name: 'mash_ph', type: 'float' }, - { name: 'mash_name', type: 'string' }, - { name: 'calc_acid', type: 'int' }, - { name: 'w1_name', type: 'string' }, - { name: 'w1_amount', type: 'float' }, - { name: 'w1_calcium', type: 'float' }, - { name: 'w1_sulfate', type: 'float' }, - { name: 'w1_chloride', type: 'float' }, - { name: 'w1_sodium', type: 'float' }, - { name: 'w1_magnesium', type: 'float' }, - { name: 'w1_total_alkalinity', type: 'float' }, - { name: 'w1_ph', type: 'float' }, - { name: 'w1_cost', type: 'float' }, - { name: 'w2_name', type: 'string' }, - { name: 'w2_amount', type: 'float' }, - { name: 'w2_calcium', type: 'float' }, - { name: 'w2_sulfate', type: 'float' }, - { name: 'w2_chloride', type: 'float' }, - { name: 'w2_sodium', type: 'float' }, - { name: 'w2_magnesium', type: 'float' }, - { name: 'w2_total_alkalinity', type: 'float' }, - { name: 'w2_ph', type: 'float' }, - { name: 'w2_cost', type: 'float' }, - { name: 'wg_amount', type: 'float' }, - { name: 'wg_calcium', type: 'float' }, - { name: 'wg_sulfate', type: 'float' }, - { name: 'wg_chloride', type: 'float' }, - { name: 'wg_sodium', type: 'float' }, - { name: 'wg_magnesium', type: 'float' }, - { name: 'wg_total_alkalinity', type: 'float' }, - { name: 'wg_ph', type: 'float' }, - { name: 'wb_calcium', type: 'float' }, - { name: 'wb_sulfate', type: 'float' }, - { name: 'wb_chloride', type: 'float' }, - { name: 'wb_sodium', type: 'float' }, - { name: 'wb_magnesium', type: 'float' }, - { name: 'wb_total_alkalinity', type: 'float' }, - { name: 'wb_ph', type: 'float' }, - { name: 'wa_acid_name', type: 'int' }, - { name: 'wa_acid_perc', type: 'int' }, - { name: 'wa_base_name', type: 'int' }, - { name: 'starter_enable', type: 'int' }, - { name: 'starter_type', type: 'int' }, - { name: 'starter_sg', type: 'float' }, - { name: 'starter_viability', type: 'int' }, - { name: 'yeast_prod_date', type: 'string' }, - { name: 'yeast_pitchrate', type: 'float' }, - { name: 'prop1_type', type: 'int' }, - { name: 'prop1_volume', type: 'float' }, - { name: 'prop2_type', type: 'int' }, - { name: 'prop2_volume', type: 'float' }, - { name: 'prop3_type', type: 'int' }, - { name: 'prop3_volume', type: 'float' }, - { name: 'prop4_type', type: 'int' }, - { name: 'prop4_volume', type: 'float' }, - { name: 'divide_type', type: 'int' }, - { name: 'divide_size', type: 'float' }, - { name: 'divide_factor', type: 'float' }, - { name: 'divide_parts', type: 'int' }, - { name: 'divide_part', type: 'int' }, - { name: 'fermentables', type: 'string' }, - { name: 'hops', type: 'string' }, - { name: 'miscs', type: 'string' }, - { name: 'yeasts', type: 'string' }, - { name: 'mashs', type: 'string' } - ], - id: 'record', - url: url + '?record=' + my_record - }, - - // Load data and select one record. - dataAdapter = new $.jqx.dataAdapter(source, { - loadComplete: function() { - dataRecord = dataAdapter.records[0]; - // Hidden record uuid - $('#name').val(dataRecord.name); - $('#code').val(dataRecord.code); - $('#birth').val(dataRecord.birth); - $('#stage').val(StageData[dataRecord.stage].nl); - $('#notes').val(dataRecord.notes); - $('#locked').val(dataRecord.locked); - $('#eq_name').val(dataRecord.eq_name); - $('#eq_notes').val(dataRecord.eq_notes); - $('#eq_boil_size').val(dataRecord.eq_boil_size); - $('#eq_batch_size').val(dataRecord.eq_batch_size); - $('#eq_tun_volume').val(dataRecord.eq_tun_volume); - $('#eq_top_up_water').val(dataRecord.eq_top_up_water); - $('#eq_trub_chiller_loss').val(dataRecord.eq_trub_chiller_loss); - $('#eq_evap_rate').val(dataRecord.eq_evap_rate); - $('#eq_boil_time').val(dataRecord.eq_boil_time); - $('#eq_top_up_kettle').val(dataRecord.eq_top_up_kettle); - $('#eq_hop_utilization').val(dataRecord.eq_hop_utilization); - $('#eq_lauter_volume').val(dataRecord.eq_lauter_volume); - $('#eq_lauter_deadspace').val(dataRecord.eq_lauter_deadspace); - $('#eq_kettle_volume').val(dataRecord.eq_kettle_volume); - $('#eq_mash_volume').val(dataRecord.eq_mash_volume); - $('#eq_mash_max').val(dataRecord.eq_mash_max); - $('#eq_efficiency').val(dataRecord.eq_efficiency); - // Brewdate - $('#brew_date_start').val(dataRecord.brew_date_start); - $('#brew_mash_ph').val(dataRecord.brew_mash_ph); - $('#brew_mash_sg').val(dataRecord.brew_mash_sg); - $('#brew_mash_efficiency').val(dataRecord.brew_mash_efficiency); - // Header Spoelen en filteren - $('#brew_sparge_temperature').val(dataRecord.sparge_temp); - $('#brew_sparge_volume').val(dataRecord.sparge_volume); - $('#brew_sparge_est').val(dataRecord.brew_sparge_est); - $('#brew_sparge_ph').val(dataRecord.brew_sparge_ph); - // Header Beluchten - $('#brew_aeration_type').val(AerationTypeData[dataRecord.brew_aeration_type].nl); - $('#brew_aeration_time').val(dataRecord.brew_aeration_time); - $('#brew_aeration_speed').val(dataRecord.brew_aeration_speed); - - $('#brew_preboil_ph').val(dataRecord.brew_preboil_ph); - $('#brew_preboil_sg').val(dataRecord.brew_preboil_sg); - $('#brew_preboil_volume').val(dataRecord.brew_preboil_volume); - $('#brew_preboil_efficiency').val(dataRecord.brew_preboil_efficiency); - // Header Koelen en whirlpoolen - $('#brew_whirlpool9').val(dataRecord.brew_whirlpool9); - $('#brew_whirlpool7').val(dataRecord.brew_whirlpool7); - $('#brew_whirlpool6').val(dataRecord.brew_whirlpool6); - $('#brew_whirlpool2').val(dataRecord.brew_whirlpool2); - // Header Naar gistvat - $('#brew_fermenter_volume').val(dataRecord.brew_fermenter_volume); - $('#brew_fermenter_sg').val(dataRecord.brew_fermenter_sg); - $('#brew_fermenter_sg2').val(dataRecord.brew_fermenter_sg); - $('#brew_fermenter_ibu').val(dataRecord.brew_fermenter_ibu); - $('#brew_fermenter_color').val(dataRecord.brew_fermenter_color); - $('#brew_fermenter_extrawater').val(dataRecord.brew_fermenter_extrawater); - $('#brew_fermenter_tcloss').val(dataRecord.brew_fermenter_tcloss); - - $('#brew_aboil_ph').val(dataRecord.brew_aboil_ph); - $('#brew_aboil_sg').val(dataRecord.brew_aboil_sg); - $('#brew_aboil_volume').val(dataRecord.brew_aboil_volume); - $('#brew_aboil_efficiency').val(dataRecord.brew_aboil_efficiency); - // Header Koelen en whirlpoolen - $('#brew_cooling_to').val(dataRecord.brew_cooling_to); - $('#brew_cooling_method').val(CoolingTypeData[dataRecord.brew_cooling_method].nl); - $('#brew_cooling_time').val(dataRecord.brew_cooling_time); - // Niks - $('#brew_date_end').val(dataRecord.brew_date_end); - $('#og').val(dataRecord.og); - $('#fg').val(dataRecord.fg); - $('#primary_start_temp').val(dataRecord.primary_start_temp); - $('#primary_max_temp').val(dataRecord.primary_max_temp); - $('#primary_end_temp').val(dataRecord.primary_end_temp); - $('#primary_end_sg').val(dataRecord.primary_end_sg); - $('#primary_end_date').val(dataRecord.primary_end_date); - $('#secondary_temp').val(dataRecord.secondary_temp); - $('#secondary_end_sg').val(dataRecord.secondary_end_sg); - $('#secondary_end_date').val(dataRecord.secondary_end_date); - $('#tertiary_temp').val(dataRecord.tertiary_temp); - $('#package_date').val(dataRecord.package_date); - $('#package_volume').val(dataRecord.package_volume); - $('#package_infuse_amount').val(dataRecord.package_infuse_amount); - $('#package_infuse_abv').val(dataRecord.package_infuse_abv); - $('#package_infuse_notes').val(dataRecord.package_infuse_notes); - $('#package_abv').val(dataRecord.package_abv); - $('#package_ph').val(dataRecord.package_ph); - $('#bottle_amount').val(dataRecord.bottle_amount); - $('#bottle_carbonation').val(dataRecord.bottle_carbonation); - $('#bottle_priming_water').val(dataRecord.bottle_priming_water); - $('#bottle_priming_amount').val(dataRecord.bottle_priming_amount); - $('#bottle_carbonation_temp').val(dataRecord.bottle_carbonation_temp); - $('#keg_amount').val(dataRecord.keg_amount); - $('#keg_carbonation').val(dataRecord.keg_carbonation); - $('#keg_priming_water').val(dataRecord.keg_priming_water); - $('#keg_priming_amount').val(dataRecord.keg_priming_amount); - $('#keg_carbonation_temp').val(dataRecord.keg_carbonation_temp); - $('#keg_forced_carb').val(dataRecord.keg_forced_carb); - $('#keg_pressure').val(dataRecord.keg_pressure); - $('#taste_notes').val(dataRecord.taste_notes); - $('#taste_rate').val(dataRecord.taste_rate); - $('#taste_date').val(dataRecord.taste_date); - $('#taste_color').val(dataRecord.taste_color); - $('#taste_transparency').val(dataRecord.taste_transparency); - $('#taste_head').val(dataRecord.taste_head); - $('#taste_aroma').val(dataRecord.taste_aroma); - $('#taste_taste').val(dataRecord.taste_taste); - $('#taste_mouthfeel').val(dataRecord.taste_mouthfeel); - $('#taste_aftertaste').val(dataRecord.taste_aftertaste); - - // Recipe - $('#st_name').val(dataRecord.st_name); - $('#st_letter').val(dataRecord.st_letter); - $('#st_guide').val(dataRecord.st_guide); - $('#st_category').val(dataRecord.st_category); - $('#st_category_number').val(dataRecord.st_category_number); - $('#st_type').val(StyleTypeData[dataRecord.st_type].nl); - $('#st_og_min').val(dataRecord.st_og_min); - $('#st_og_max').val(dataRecord.st_og_max); - $('#st_fg_min').val(dataRecord.st_fg_min); - $('#st_fg_max').val(dataRecord.st_fg_max); - $('#st_abv_min').val(dataRecord.st_abv_min); - $('#st_abv_max').val(dataRecord.st_abv_max); - $('#st_color_min').val(dataRecord.st_color_min); - $('#st_color_max').val(dataRecord.st_color_max); - $('#st_ibu_min').val(dataRecord.st_ibu_min); - $('#st_ibu_max').val(dataRecord.st_ibu_max); - $('#st_carb_min').val(dataRecord.st_carb_min); - $('#st_carb_min2').val(dataRecord.st_carb_min); - $('#st_carb_max').val(dataRecord.st_carb_max); - $('#st_carb_max2').val(dataRecord.st_carb_max); - $('#type').val(RecipeTypeData[dataRecord.type].nl); - $('#batch_size').val(dataRecord.batch_size); - $('#est_a_vol').val(dataRecord.batch_size * 1.04); - $('#boil_size').val(dataRecord.boil_size); - $('#est_pre_vol').val(dataRecord.boil_size * 1.04); - $('#boil_time').val(dataRecord.boil_time); - $('#efficiency').val(dataRecord.efficiency); - $('#est_og').val(dataRecord.est_og); - $('#est_og2').val(dataRecord.est_og); - $('#est_og3').val(dataRecord.est_og3); - $('#est_fg').val(dataRecord.est_fg); - $('#est_fg2').val(dataRecord.est_fg); - $('#est_fg3').val(dataRecord.est_fg); - $('#est_color').val(dataRecord.est_color); - $('#est_color2').val(dataRecord.est_color); - $('#est_abv').val(dataRecord.est_abv); - $('#color_method').val(ColorMethodData[dataRecord.color_method].nl); - $('#est_ibu').val(dataRecord.est_ibu); - $('#est_ibu2').val(dataRecord.est_ibu); - $('#ibu_method').val(IBUmethodData[dataRecord.ibu_method].nl); - $('#est_carb').val(dataRecord.est_carb); - $('#mash_name').val(dataRecord.mash_name); - $('#mash_ph').val(dataRecord.mash_ph); - $('#sparge_temp').val(dataRecord.sparge_temp); - $('#sparge_ph').val(dataRecord.sparge_ph); - $('#sparge_volume').val(dataRecord.sparge_volume); - $('#sparge_source').val(dataRecord.sparge_source); - $('#sparge_acid_type').val(AcidTypeData[dataRecord.sparge_acid_type].nl); - $('#sparge_acid_perc').val(dataRecord.sparge_acid_perc); - $('#sparge_acid_amount').val(dataRecord.sparge_acid_amount * 1000); - $('#calc_acid').val(dataRecord.calc_acid); - $('#w1_name').val(dataRecord.w1_name); - $('#w1_amount').val(dataRecord.w1_amount); - $('#w1_calcium').val(dataRecord.w1_calcium); - $('#w1_sulfate').val(dataRecord.w1_sulfate); - $('#w1_chloride').val(dataRecord.w1_chloride); - $('#w1_sodium').val(dataRecord.w1_sodium); - $('#w1_magnesium').val(dataRecord.w1_magnesium); - $('#w1_total_alkalinity').val(dataRecord.w1_total_alkalinity); - $('#w1_bicarbonate').val(dataRecord.w1_total_alkalinity * 1.22); - $('#w1_ph').val(dataRecord.w1_ph); - $('#w1_cost').val(dataRecord.w1_cost); - $('#w2_name').val(dataRecord.w2_name); - $('#w2_amount').val(dataRecord.w2_amount); - $('#w2_calcium').val(dataRecord.w2_calcium); - $('#w2_sulfate').val(dataRecord.w2_sulfate); - $('#w2_chloride').val(dataRecord.w2_chloride); - $('#w2_sodium').val(dataRecord.w2_sodium); - $('#w2_magnesium').val(dataRecord.w2_magnesium); - $('#w2_total_alkalinity').val(dataRecord.w2_total_alkalinity); - $('#w2_bicarbonate').val(dataRecord.w2_total_alkalinity * 1.22); - $('#w2_ph').val(dataRecord.w2_ph); - $('#w2_cost').val(dataRecord.w2_cost); - $('#wg_amount').val(dataRecord.wg_amount); - $('#wg_calcium').val(dataRecord.wg_calcium); - $('#wg_sulfate').val(dataRecord.wg_sulfate); - $('#wg_chloride').val(dataRecord.wg_chloride); - $('#wg_sodium').val(dataRecord.wg_sodium); - $('#wg_magnesium').val(dataRecord.wg_magnesium); - $('#wg_total_alkalinity').val(dataRecord.wg_total_alkalinity); - $('#wg_ph').val(dataRecord.wg_ph); - $('#wb_calcium').val(dataRecord.wb_calcium); - $('#wb_sulfate').val(dataRecord.wb_sulfate); - $('#wb_chloride').val(dataRecord.wb_chloride); - $('#wb_sodium').val(dataRecord.wb_sodium); - $('#wb_magnesium').val(dataRecord.wb_magnesium); - $('#wb_total_alkalinity').val(dataRecord.wb_total_alkalinity); - $('#wb_ph').val(dataRecord.wb_ph); - $('#wa_acid_name').val(dataRecord.wa_acid_name); - $('#wa_acid_perc').val(dataRecord.wa_acid_perc); - $('#starter_type').val(StarterTypeData[dataRecord.starter_type].nl); - $('#starter_sg').val(dataRecord.starter_sg); - $('#starter_viability').val(dataRecord.starter_viability); - $('#yeast_prod_date').val(dataRecord.yeast_prod_date); - $('#yeast_pitchrate').val(dataRecord.yeast_pitchrate); - $('#prop1_type').val(StarterTypeData[dataRecord.prop1_type].nl); - $('#prop1_volume').val(dataRecord.prop1_volume); - $('#prop2_type').val(StarterTypeData[dataRecord.prop2_type].nl); - $('#prop2_volume').val(dataRecord.prop2_volume); - $('#prop3_type').val(StarterTypeData[dataRecord.prop3_type].nl); - $('#prop3_volume').val(dataRecord.prop3_volume); - $('#prop4_type').val(StarterTypeData[dataRecord.prop4_type].nl); - $('#prop4_volume').val(dataRecord.prop4_volume); - $('#divide_type').val(SplitData[dataRecord.divide_type].nl); - if (dataRecord.divide_type > 0) - $('#divide_batch').val((dataRecord.divide_part + 1) + ' van ' + (dataRecord.divide_parts + 1)); - else - $('#divide_batch').val('n.v.t.'); - // hidden divide_size - // hidden divide_factor - // hidden divide_parts - // hidden divide_part - editFermentable(dataRecord); - editHop(dataRecord); - editMisc(dataRecord); - editYeast(dataRecord); - editMash(dataRecord); - calcStage(); - $('#jqxTabs').jqxTabs('select', 2); - data_loaded = 1; - }, - loadError: function(jqXHR, status, error) { - console.log('main data load error: ' + status + ' ' + error); - } - }); - - // Inline fermentables editor - var editFermentable = function(data) { - var fermentableSource = { - localdata: data.fermentables, - datafields: [ - { name: 'f_name', type: 'string' }, - { name: 'f_origin', type: 'string' }, - { name: 'f_supplier', type: 'string' }, - { name: 'f_amount', type: 'float' }, - { name: 'f_cost', type: 'float' }, - { name: 'f_type', type: 'int' }, - { name: 'f_yield', type: 'float' }, - { name: 'f_color', type: 'float' }, - { name: 'f_coarse_fine_diff', type: 'float' }, - { name: 'f_moisture', type: 'float' }, - { name: 'f_diastatic_power', type: 'float' }, - { name: 'f_protein', type: 'float' }, - { name: 'f_max_in_batch', type: 'float' }, - { name: 'f_graintype', type: 'int' }, - { name: 'f_added', type: 'int' }, - { name: 'f_dissolved_protein', type: 'float' }, - { name: 'f_recommend_mash', type: 'int' }, - { name: 'f_add_after_boil', type: 'int' }, - { name: 'f_adjust_to_total_100', type: 'int' }, - { name: 'f_percentage', type: 'float' }, - { name: 'f_di_ph', type: 'float' }, - { name: 'f_acid_to_ph_57', type: 'float' }, - { name: 'f_inventory', type: 'float' }, - { name: 'f_avail', type: 'int' } - ], - }, - fermentableAdapter = new $.jqx.dataAdapter(fermentableSource); - - $('#fermentableGrid').jqxGrid({ - width: 1240, - height: 470, - source: fermentableAdapter, - theme: theme, - editable: false, - ready: function() { calcFermentables(); $('#jqxTabs').jqxTabs('next'); }, - columns: [ - { text: 'Vergistbaar ingrediënt', datafield: 'f_name' }, - { text: 'Leverancier', datafield: 'f_supplier', width: 180 }, - { text: 'Kleur', datafield: 'f_color', width: 90, align: 'right', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - return '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(value, 'f0') + ' EBC</span>'; - } - }, - { text: 'Type', width: 100, datafield: 'f_type', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - return '<span style="margin: 3px; margin-top: 6px; float: left;">' + FermentableTypeData[value].nl + '</span>'; - } - }, - { text: 'Moment', width: 110, datafield: 'f_added', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - return '<span style="margin: 3px; margin-top: 6px; float: left;">' + AddedData[value].nl + '</span>'; - } - }, - { text: 'Maxinbatch', datafield: 'f_max_in_batch', hidden: true }, - { text: 'Opbrengst', datafield: 'f_yield', width: 90, align: 'right', cellsalign: 'right', cellsformat: 'p1' }, - { text: 'Gewicht Kg', datafield: 'f_amount', width: 110, align: 'right', cellsalign: 'right', cellsformat: 'f3' }, - { text: 'Voorraad Kg', datafield: 'f_inventory', width: 110, align: 'right', - cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) { - var color = (value < rowdata.f_amount) ? '#ff4040':'#ffffff'; - if (block_fermentable(dataRecord.inventory_reduced, rowdata.f_added) == false) { - return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + fermentableAdapter.formatNumber(value, 'f3') + '</span>'; - } else { - return '<span></span>'; - } - } - }, - { text: 'Procent', datafield: 'f_percentage', width: 90, align: 'right', - cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) { - if (rowdata.f_added >= 4) - return '<span></span>'; - var color = (value > rowdata.f_max_in_batch) ? '#ff4040':'#ffffff'; - return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + fermentableAdapter.formatNumber(value, 'p1') + '</span>'; - } - }, - { text: '100%', datafield: 'f_adjust_to_total_100', width: 70, align: 'center', cellsalign: 'center', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - if (value == 0) - return '<span></span>'; - return '<span><img style="float:left; margin-left:25px; margin-top:4px;" src="images/dialog-ok-apply.png"></span>'; - } - } - ] - }); - }; - - // Inline hops editor - var editHop = function(data) { - var hopSource = { - localdata: data.hops, - datafields: [ - { name: 'h_name', type: 'string' }, - { name: 'h_origin', type: 'string' }, - { name: 'h_amount', type: 'float' }, - { name: 'h_cost', type: 'float' }, - { name: 'h_type', type: 'int' }, - { name: 'h_form', type: 'int' }, - { name: 'h_useat', type: 'int' }, - { name: 'h_time', type: 'int' }, - { name: 'h_alpha', type: 'float' }, - { name: 'h_beta', type: 'float' }, - { name: 'h_hsi', type: 'float' }, - { name: 'h_humulene', type: 'float' }, - { name: 'h_caryophyllene', type: 'float' }, - { name: 'h_cohumulone', type: 'float' }, - { name: 'h_myrcene', type: 'float' }, - { name: 'h_total_oil', type: 'float' }, - { name: 'h_inventory', type: 'float' }, - { name: 'h_avail', type: 'int' }, - { name: 'h_utilisation', type: 'float' }, - { name: 'h_bu_factor', type: 'float' } - ], - }, - hopAdapter = new $.jqx.dataAdapter(hopSource); - - $('#hopGrid').jqxGrid({ - width: 1240, - height: 560, - source: hopAdapter, - theme: theme, - editable: false, - ready: function() { $('#jqxTabs').jqxTabs('next'); }, - columns: [ - { text: 'Hop', datafield: 'h_name' }, - { text: 'Origin', width: 180, datafield: 'h_origin' }, - { text: 'Type', width: 90, datafield: 'h_type', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - return '<span style="margin: 4px; margin-top: 6px; float: left;">' + HopTypeData[value].nl + '</span>'; - } - }, - { text: 'Vorm', width: 110, datafield: 'h_form', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - return '<span style="margin: 4px; margin-top: 6px; float: left;">' + HopFormData[value].nl + '</span>'; - } - }, - { text: 'Alpha', datafield: 'h_alpha', width: 80, align: 'right', cellsalign: 'right', cellsformat: 'p1' }, - { text: 'Gebruik', width: 110, datafield: 'h_useat', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - return '<span style="margin: 4px; margin-top: 6px; float: left;">' + HopUseData[value].nl + '</span>'; - } - }, - { text: 'Tijdsduur', datafield: 'h_time', width: 90, align: 'right', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - var duration = ''; - if ((rowdata.h_useat == 2) || (rowdata.h_useat == 4)) // Boil, Whirlpool - duration = dataAdapter.formatNumber(value, 'f0') + ' min.'; - else if (rowdata.h_useat == 5) // Dry hop - duration = dataAdapter.formatNumber(value / 1440, 'f0') + ' dagen'; - return '<span style="margin: 4px; margin-top: 6px; float: right;">' + duration + '</span>'; - } - }, - { text: 'IBU', datafield: 'ibu', width: 80, align: 'right', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - var ibu = toIBU(rowdata.h_useat, rowdata.h_form, preboil_sg, parseFloat(dataRecord.batch_size), - parseFloat(rowdata.h_amount), parseFloat(rowdata.h_time), parseFloat(rowdata.h_alpha), dataRecord.ibu_method, - dataRecord.brew_whirlpool9, dataRecord.brew_whirlpool7, dataRecord.brew_whirlpool6); - return '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(ibu, 'f1') + '</span>'; - } - }, - { text: 'Gewicht', datafield: 'h_amount', width: 110, align: 'right', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - var amount = dataAdapter.formatNumber(value, 'f1') + ' kg'; - if (value < 1) - amount = dataAdapter.formatNumber(value * 1000, 'f1') + ' gr'; - return '<span style="margin: 4px; margin-top: 6px; float: right;">' + amount + '</span>'; - } - }, - { text: 'Voorraad', datafield: 'h_inventory', width: 110, align: 'right', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - if (block_hop(dataRecord.inventory_reduced, rowdata.h_useat) == false) { - var amount = dataAdapter.formatNumber(value, 'f1') + ' kg', - color = (value < rowdata.h_amount) ? '#ff4040':'#ffffff'; - if (value < 1) - amount = dataAdapter.formatNumber(value * 1000, 'f1') + ' gr'; - return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + amount + '</span>'; - } else { - return '<span></span>'; - } - } - } - ] - }); - }; - - // Inline miscs editor - var editMisc = function(data) { - var miscSource = { - localdata: data.miscs, - datafields: [ - { name: 'm_name', type: 'string' }, - { name: 'm_amount', type: 'float' }, - { name: 'm_cost', type: 'float' }, - { name: 'm_type', type: 'int' }, - { name: 'm_use_use', type: 'int' }, - { name: 'm_time', type: 'float' }, - { name: 'm_amount_is_weight', type: 'int' }, - { name: 'm_inventory', type: 'float' }, - { name: 'm_avail', type: 'int' } - ], - }, - miscAdapter = new $.jqx.dataAdapter(miscSource, { - beforeLoadComplete: function(records) { - var row, i, data = new Array(); - for (i = 0; i < records.length; i++) { - row = records[i]; - data.push(row); - // Initial set water agent values. - if (row.m_use_use == 1) { // Mash - switch (row.m_name) { - case 'CaCl2': - $('#wa_cacl2').val(row.m_amount * 1000); - break; - case 'CaSO4': - $('#wa_caso4').val(row.m_amount * 1000); - break; - case 'MgSO4': - $('#wa_mgso4').val(row.m_amount * 1000); - break; - case 'NaCl': - $('#wa_nacl').val(row.m_amount * 1000); - break; - case 'MgCl2': - $('#wa_mgcl2').val(row.m_amount * 1000); - break; - case 'NaHCO3': - $('#wa_nahco3').val(row.m_amount * 1000); - break; - case 'CaCO3': - $('#wa_caco3').val(row.m_amount * 1000); - break; - case 'Melkzuur': - $('#wa_acid_name').val(AcidTypeData[0].nl); - $('#wa_acid').val(row.m_amount * 1000); - $('#wa_acid_perc').val(AcidTypeData[0].AcidPrc); - last_acid = 'Melkzuur'; - break; - case 'Zoutzuur': - $('#wa_acid_name').val(AcidTypeData[1].nl); - $('#wa_acid').val(row.m_amount * 1000); - $('#wa_acid_perc').val(AcidTypeData[1].AcidPrc); - last_acid = 'Zoutzuur'; - break; - case 'Fosforzuur': - $('#wa_acid_name').val(AcidTypeData[2].nl); - $('#wa_acid').val(row.m_amount * 1000); - $('#wa_acid_perc').val(AcidTypeData[2].AcidPrc); - last_acid = 'Fosforzuur'; - break; - case 'Zwavelzuur': - $('#wa_acid_name').val(AcidTypeData[3].nl); - $('#wa_acid').val(row.m_amount * 1000); - $('#wa_acid_perc').val(AcidTypeData[3].AcidPrc); - last_acid = 'Zwavelzuur'; - break; - } - } - if (row.m_use_use == 6) { // Sparge - switch (row.m_name) { - case 'CaCl2': - $('#ss_cacl2').val(row.m_amount * 1000); - break; - case 'CaSO4': - $('#ss_caso4').val(row.m_amount * 1000); - break; - case 'MgSO4': - $('#ss_mgso4').val(row.m_amount * 1000); - break; - case 'NaCl': - $('#ss_nacl').val(row.m_amount * 1000); - break; - case 'MgCl2': - $('#ss_mgcl2').val(row.m_amount * 1000); - break; - } - } - } - return data; - }, - loadError: function(jqXHR, status, error) { console.log('miscs load error ' + status + ' ' + error); }, - }); - $('#miscGrid').jqxGrid({ - width: 1240, - height: 575, - source: miscAdapter, - theme: theme, - editable: false, - ready: function() { $('#jqxTabs').jqxTabs('next'); }, - columns: [ - { text: 'Ingredient', datafield: 'm_name' }, - { text: 'Type', width: 140, datafield: 'm_type', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - return '<span style="margin: 3px; margin-top: 6px; float: left;">' + MiscTypeData[value].nl + '</span>'; - } - }, - { text: 'Gebruik', width: 140, datafield: 'm_use_use', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - return '<span style="margin: 3px; margin-top: 6px; float: left;">' + MiscUseData[value].nl + '</span>'; - } - }, - { text: 'Tijd', datafield: 'm_time', width: 90, align: 'right', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - var duration = ''; - if (rowdata.m_use_use == 2) // Boil - duration = dataAdapter.formatNumber(value, 'f0') + ' min.'; - else if ((rowdata.m_use_use == 3) || (rowdata.m_use_use == 4)) // Primary or Secondary - duration = dataAdapter.formatNumber(value / 1440, 'f0') + ' dagen'; - return '<span style="margin: 4px; margin-top: 6px; float: right;">' + duration + '</span>'; - } - }, - { text: 'Hoeveel', datafield: 'm_amount', width: 110, align: 'right', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - var vstr = rowdata.m_amount_is_weight ? 'gr' : 'ml'; - return '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(value * 1000, 'f2') + ' ' + vstr + '</span>'; - } - }, - { text: 'Voorraad', datafield: 'm_inventory', width: 110, align: 'right', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - if (block_misc(dataRecord.inventory_reduced, rowdata.m_use_use) == false) { - var vstr = rowdata.m_amount_is_weight ? 'gr' : 'ml', - color = (value < rowdata.m_amount) ? '#ff4040':'#ffffff', - amount = dataAdapter.formatNumber(value * 1000, 'f2') + ' ' + vstr; - return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + amount + '</span>'; - } else { - return '<span></span>'; - } - } - } - ] - }); - }; - - // Inline yeasts editor - var editYeast = function(data) { - var yeastSource = { - localdata: data.yeasts, - datafields: [ - { name: 'y_name', type: 'string' }, - { name: 'y_laboratory', type: 'string' }, - { name: 'y_product_id', type: 'string' }, - { name: 'y_amount', type: 'float' }, - { name: 'y_cost', type: 'float' }, - { name: 'y_type', type: 'int' }, - { name: 'y_form', type: 'int' }, - { name: 'y_flocculation', type: 'int' }, - { name: 'y_min_temperature', type: 'float' }, - { name: 'y_max_temperature', type: 'float' }, - { name: 'y_attenuation', type: 'float' }, - { name: 'y_use', type: 'int' }, - { name: 'y_cells', type: 'float' }, - { name: 'y_tolerance', type: 'float' }, - { name: 'y_inventory', type: 'float' }, - { name: 'y_sta1', type: 'int' }, - { name: 'y_bacteria', type: 'int' }, - { name: 'y_harvest_top', type: 'int' }, - { name: 'y_harvest_time', type: 'int' }, - { name: 'y_pitch_temperature', type: 'float' }, - { name: 'y_pofpos', type: 'int' }, - { name: 'y_zymocide', type: 'int' }, - { name: 'y_gr_hl_lo', type: 'int' }, - { name: 'y_sg_lo', type: 'float' }, - { name: 'y_gr_hl_hi', type: 'int' }, - { name: 'y_sg_hi', type: 'float' }, - { name: 'y_avail', type: 'int' } - ], - }, - yeastAdapter = new $.jqx.dataAdapter(yeastSource); - - $('#yeastGrid').jqxGrid({ - width: 1240, - height: 325, - source: yeastAdapter, - theme: theme, - editable: false, - ready: function() { $('#jqxTabs').jqxTabs('next'); }, - columns: [ - { text: 'Gist', datafield: 'y_name' }, - { text: 'Laboratorium', width: 150, datafield: 'y_laboratory' }, - { text: 'Code', width: 90, datafield: 'y_product_id' }, - { text: 'Soort', width: 100, datafield: 'y_form', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - return '<span style="margin: 4px; margin-top: 6px; float: left;">' + YeastFormData[value].nl + '</span>'; - } - }, - { text: 'Min. °C', width: 70, align: 'right', cellsalign: 'right', datafield: 'y_min_temperature' }, - { text: 'Max. °C', width: 70, align: 'right', cellsalign: 'right', datafield: 'y_max_temperature' }, - { text: 'Tol. %', width: 60, align: 'right', cellsalign: 'right', datafield: 'y_tolerance', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - var amount = '', color = (dataRecord.est_abv > value) ? '#ff4040':'#ffffff'; - if (value > 0) { - amount = dataAdapter.formatNumber(value, 'f1'); - } - return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + amount + '</span>'; - } - }, - { text: 'Attn. %', width: 70, align: 'right', cellsalign: 'right', datafield: 'y_attenuation', cellsformat: 'f1' }, - { text: 'Voor', width: 120, datafield: 'y_use', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - return '<span style="margin: 4px; margin-top: 6px; float: left;">' + YeastUseData[value].nl + '</span>'; - } - }, - { text: 'Hoeveel', datafield: 'y_amount', width: 90, align: 'right', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - var amount = dataAdapter.formatNumber(value * 1000, 'f0') + ' ml'; - if (rowdata.y_form == 0) // Liquid - amount = dataAdapter.formatNumber(value, 'f0') + ' pk'; - else if (rowdata.y_form == 1 || rowdata.y_form == 6) // Dry - amount = dataAdapter.formatNumber(value * 1000, 'f1') + ' gr'; - return '<span style="margin: 4px; margin-top: 6px; float: right;">' + amount + '</span>'; - } - }, - { text: 'Voorraad', datafield: 'y_inventory', width: 90, align: 'right', - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - var color, amount; - if (block_yeast(dataRecord.inventory_reduced, rowdata.y_use) == false) { - color = '#ffffff'; - if (value < rowdata.y_amount) - color = '#ff4040'; - amount = dataAdapter.formatNumber(value * 1000, 'f0') + ' ml'; - if (rowdata.y_form == 0) // Liquid - amount = dataAdapter.formatNumber(value, 'f0') + ' pk'; - else if (rowdata.y_form == 1 || rowdata.y_form == 6) // Dry - amount = dataAdapter.formatNumber(value * 1000, 'f1') + ' gr'; - return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + amount + '</span>'; - } else { - return '<span></span>'; - } - } - } - ] - }); - }; - - // inline mash editor - var editMash = function(data) { - var mashSource = { - localdata: data.mashs, - datafields: [ - { name: 'step_name', type: 'string' }, - { name: 'step_type', type: 'int' }, - { name: 'step_volume', type: 'float' }, - { name: 'step_infuse_amount', type: 'float' }, - { name: 'step_infuse_temp', type: 'float' }, - { name: 'step_temp', type: 'float' }, - { name: 'step_time', type: 'float' }, - { name: 'step_wg_ratio', type: 'float' }, - { name: 'ramp_time', type: 'float' }, - { name: 'end_temp', type: 'float' }, - { name: 'step_ph', type: 'float' }, - { name: 'step_sg', type: 'float' } - ], - }, - mashAdapter = new $.jqx.dataAdapter(mashSource); - - $('#mashGrid').jqxGrid({ - width: 1240, - height: 400, - source: mashAdapter, - theme: theme, - selectionmode: 'singlerow', - editable: false, - ready: function() { - /* Calculate the whole recipe */ - console.log('ready mashs, start calculations'); - /* calcFermentables() must be first and is done by the grid load. Here it is too late. */ - calcMash(); - calcWater(); - calcIBUs(); - whirlpoolHops(); - calcMiscs(); - calcViability(); - calcYeast(); - kookTijd(); - calcFermentation(); - calcCarbonation(); - $('#FLog').jqxButton({ disabled: (dataRecord.log_fermentation) ? false : true}); - $('#ILog').jqxButton({ disabled: (dataRecord.log_ispindel) ? false : true}); - $('#CLog').jqxButton({ disabled: (dataRecord.log_co2pressure) ? false : true}); - console.log('calculations ready'); - $('#jqxLoader').jqxLoader('close'); - $('#jqxTabs').jqxTabs('first'); - }, - columns: [ - { text: 'Stap naam', datafield: 'step_name' }, - { text: 'Stap type', datafield: 'step_type', width: 150, - cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { - return '<span style="margin: 4px; margin-top: 6px; float: left;">' + MashStepTypeData[value].nl + '</span>'; - } - }, - { text: 'Start °C', datafield: 'step_temp', width: 80, align: 'right', cellsalign: 'right', cellsformat: 'f1' }, - { text: 'Eind °C', datafield: 'end_temp', width: 80, align: 'right', cellsalign: 'right', cellsformat: 'f1' }, - { text: 'Rust min.', datafield: 'step_time', width: 80, align: 'right', cellsalign: 'right' }, - { text: 'Stap min.', datafield: 'ramp_time', width: 80, align: 'right', cellsalign: 'right' }, - { text: 'Inf/dec L.', datafield: 'step_infuse_amount', width: 80, align: 'right', - cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) { - if (rowdata.step_type == 1) - return '<span></span>'; - var color = '#ffffff'; - var mvol = mashkg * MaltVolume; - if ((rowdata.step_wg_ratio * mashkg + mvol) > dataRecord.eq_tun_volume) - color = '#ff4040'; - return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + dataAdapter.formatNumber(value, 'f1') + '</span>'; - } - }, - { text: 'Inf/dec °C', datafield: 'step_infuse_temp', width: 90, align: 'right', - cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) { - if (rowdata.step_type == 1) - return '<span></span>'; - return '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(value, 'f2') + '</span>'; - } - }, - { text: 'L/Kg.', datafield: 'step_wg_ratio', width: 80, align: 'right', - cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) { - var color = '#ffffff'; - if (value < 2.0 || value > 6.0) - color = '#ff4040'; - return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + dataAdapter.formatNumber(value, 'f2') + '</span>'; - } - }, - { text: 'pH', datafield: 'step_ph', width: 70, align: 'right', cellsalign: 'right', cellsformat: 'f2' }, - { text: 'SG', datafield: 'step_sg', width: 80, align: 'right', cellsalign: 'right', cellsformat: 'f3' } - ] - }); - }; - - /* - * Remove the top menu so that we MUST use the button to leave the editor. - */ - $('#jqxMenu').jqxMenu('destroy'); - console.log('record:' + my_record + ' return:' + my_return + ' theme:' + theme); - $('#jqxLoader').jqxLoader({ width: 250, height: 150, isModal: true, text: 'Laden product ...', theme: theme }); - $('#jqxLoader').jqxLoader('open'); - - /* Moved to before all functions */ - dataAdapter.dataBind(); - - /* - * Generic functions - */ - function kookTijd() { - if (dataRecord.boil_time) { - $('#brew_pmpt_koken').html('Koken ' + dataRecord.boil_time + ' minuten'); - } else { - $('#brew_pmpt_koken').html('Koken "no-boil"'); - } - } - - function infusionVol(step_infused, step_mashkg, infuse_temp, step_temp, last_temp) { - var a = last_temp * (dataRecord.eq_tun_weight * dataRecord.eq_tun_specific_heat + step_infused * SpecificHeatWater + step_mashkg * SpecificHeatMalt); - var b = step_temp * (dataRecord.eq_tun_weight * dataRecord.eq_tun_specific_heat + step_infused * SpecificHeatWater + step_mashkg * SpecificHeatMalt); - var vol = Round(((b - a) / ((infuse_temp - step_temp) * SpecificHeatWater)), 2); - return vol; - } - - function decoctionVol(step_volume, step_temp, prev_temp) { - var a = (dataRecord.eq_tun_weight * dataRecord.eq_tun_specific_heat + step_volume * SpecificHeatWater) * (step_temp - prev_temp); - var b = SpecificHeatWater * (99 - step_temp); - var vol = 0; - if (b > 0) - vol = Round(a / b, 6); - return vol; - } - - function calcViability() { - var vpm = 1.00; - var max = 100; - var rowscount = dataRecord.yeasts.length; - if (rowscount) { - for (i = 0; i < rowscount; i++) { - row = dataRecord.yeasts[i]; - if (row.y_use == 0) { - if (row.y_form == 0) { // Liquid - vpm = 0.80; - max = 97; - if (row.y_laboratory == 'White Labs') { // PurePitch - vpm = 0.95; - max = 100; - } - } else if (row.y_form == 1) { // dry yeast - vpm = 0.998; - max = 100; - } else if (row.y_form == 6) { // Dried kveik - vpm = 0.92; - max = 100; - } else { // Slant, Culture, Frozen, Bottle - vpm = 0.99; - max = 97; - } - } - } - } - var base = max; - var days = 0; - - if (parseFloat($('#yeast_prod_date').val()) > 2000) { - console.log('calculate viability'); - var d = new Date(); - var date2 = $('#yeast_prod_date').val(); - date2 = date2.split('-'); - // Now we convert the array to a Date object - var date1 = new Date(d.getFullYear(), d.getMonth(), d.getDate()); - date2 = new Date(date2[0], date2[1] - 1, date2[2]); - var diff = parseInt(date1.getTime()) - parseInt(date2.getTime()); - days = Math.floor(diff/1000/60/60/24); - - var degrade = 1 - ((1 - vpm) / 30.41); // viability degradation per day. - for (i = 0; i < days; i++) { - base = base * degrade; - } - if (base > max) { - base = max; - } - base = Math.round(base); - } - console.log('age:' + days + ' max:' + max + ' vpm:' + vpm + ' base:' + base); - - if (dataRecord.starter_viability != base) { - dataRecord.starter_viability = base; - $('#starter_viability').val(dataRecord.starter_viability); - } - } - - function calcSupplies() { - if (dataRecord.inventory_reduced > 6) { - $('#ok_pmpt').hide(); - return; - } - if (ok_fermentables && ok_hops && ok_miscs && ok_yeasts && ok_waters) - $('#ok_supplies').html("<img src='images/dialog-ok-apply.png'>"); - else - $('#ok_supplies').html("<img src='images/dialog-error.png'>"); - } - - /* - * All calculations that depend on changes in the fermentables, - * volumes and equipments. - */ - function calcFermentables() { - - var sugarsf = 0, // fermentable sugars mash + boil - sugarsm = 0, // fermentable sugars in mash - vol = 0, // Volume sugars after boil - addedS = 0, // Added sugars after boil - addedmass = 0, // Added mass after boil - mvol = 0, // mash volume - infuse = 0, // mash infuse volume - colort = 0, // Colors srm * vol totals - colorh = 0, // Colors ebc * vol * kt - colorn = 0, // Colors ebc * pt * pct - my_100 = false, - mashtime = 0, // Total mash time - mashtemp = 0, // Average mash temperature - bv = 0.925, // Bierverlies rendement - sr = 0.95, // Mash en spoel rendement - lintner = 0, // Total recipe lintner - i, row, rows, org, timem, aboil_volume, spoelw, ogx, topw, s = 0, d, v, x, - sug, alc, pt, cw, color, scolor, fig; - - /* Init global variables */ - psugar = 0; - pcara = 0; - mashkg = 0; - ok_fermentables = 1; // All is in stock. - ok_yeasts = 1; - - if (dataRecord.mashs.length) { - for (i = 0; i < dataRecord.mashs.length; i++) { - row = dataRecord.mashs[i]; - if (parseFloat(row.step_type) == 0) // Infusion - mvol += parseFloat(row.step_infuse_amount); - if (row.step_temp <= 75 && row.step_temp >= 60) { // Ignore mashout - timem = row.step_time; - if (i > 0) - timem += row.ramp_time; - mashtime += timem; - mashtemp += timem * row.step_temp; - } - } - infuse = mvol; - mashtemp = Round(mashtemp / mashtime, 2); - } else { - console.log("calcFermentables() no mash steps"); - } - - if (! dataRecord.fermentables.length) { - console.log("calcFermentables() no fermentables"); - return; // grid not yet loaded. - } - - for (i = 0; i < dataRecord.fermentables.length; i++) { - row = dataRecord.fermentables[i]; - if (row.f_adjust_to_total_100) - my_100 = true; - if (row.f_type == 1 && row.f_added < 4) // Sugar - psugar += row.f_percentage; - if (row.f_graintype == 2 && row.f_added < 4) // Crystal - pcara += row.f_percentage; - d = row.f_amount * (row.f_yield / 100) * (1 - row.f_moisture / 100); - if (row.f_added == 0) { // Mash - if (mvol > 0) { // Only if mash already known. - mvol += row.f_amount * row.f_moisture / 100; - s += d; - } - d = parseFloat(dataRecord.efficiency) / 100 * d; - sugarsm += d; - mashkg += parseFloat(row.f_amount); - } - if (row.f_added == 0 || row.f_added == 1) // Mash or Boil - sugarsf += d; - if (row.f_added == 2 || row.f_added == 3) { // Fermentation or lagering - x = (row.f_yield / 100) * (1 - row.f_moisture / 100); - addedS += row.f_amount * x; - addedmass += row.f_amount; - vol += (x * sugardensity + (1 - x) * 1) * row.f_amount; - } - if (row.f_added < 4) { - colort += row.f_amount * ebc_to_srm(row.f_color); - colorh += row.f_amount * row.f_color * get_kt(row.f_color); - colorn += (row.f_percentage / 100) * row.f_color; // For 8.6 Pt wort. - } - if (fermentableInit) { - if (row.f_added == 4) { - $('#bottle_priming_total').val(row.f_amount * 1000); // Prevent clearing - $('#bottle_priming_sugar').val(row.f_name); - } - if (row.f_added == 5) { - $('#keg_priming_total').val(row.f_amount * 1000); - $('#keg_priming_sugar').val(row.f_name); - } - } - // Check supplies. - if ((((dataRecord.inventory_reduced <= 2) && (row.f_added <= 1)) || // Mash or boil - ((dataRecord.inventory_reduced <= 3) && (row.f_added == 2)) || // Primary - ((dataRecord.inventory_reduced <= 5) && (row.f_added == 3)) || // Secondary or Tertiary - ((dataRecord.inventory_reduced <= 6) && (row.f_added == 4)) || // Bottle - ((dataRecord.inventory_reduced <= 6) && (row.f_added == 5))) && row.f_inventory < row.f_amount) { - ok_fermentables = 0; - } - if (row.f_added == 0 && (row.f_type == 0 || row.f_type == 4) && row.f_color < 50) { // Mash and Grain/Adjunct and Color < 50 - lintner += row.f_diastatic_power * row.f_amount; - } - } - fermentableInit = 0; - $('#ferm_lintner').val(Math.round(parseFloat(lintner / mashkg))); - $('#mash_kg').val(mashkg); - console.log('calcFermentables() supplies:' + ok_fermentables + ' moutsuiker:' + Round(sugarsm, 3) + '/' + Round(sugarsf, 3)); - to_100 = my_100; - - if (mvol > 0) { - v = s / sugardensity + mvol; - s = 1000 * s / (v * 10); //deg. Plato - est_mash_sg = Round(plato_to_sg(s), 5); - $('#est_mash_sg').val(est_mash_sg); - } - - // Estimate total recipe OG. - dataRecord.est_og = estimate_sg(sugarsf + addedS, parseFloat(dataRecord.batch_size)); - $('#est_og').val(dataRecord.est_og); - $('#est_og2').val(dataRecord.est_og); - org = dataRecord.est_og; - - // Estimate SG in kettle after boil - aboil_sg = estimate_sg(sugarsf, parseFloat(dataRecord.batch_size)); - $('#est_og3').val(aboil_sg); - - // Estimate SG in kettle before boil - preboil_sg = estimate_sg(sugarsm, parseFloat(dataRecord.boil_size)); - $('#est_pre_sg').val(preboil_sg); - - // Recalculate volumes. - aboil_volume = parseFloat(dataRecord.batch_size); - if (dataRecord.brew_aboil_volume > 0) - aboil_volume = dataRecord.brew_aboil_volume / 1.04; // volume @ 20 degrees - if (dataRecord.brew_fermenter_tcloss == 0) { - dataRecord.brew_fermenter_tcloss = dataRecord.eq_trub_chiller_loss; - $('#brew_fermenter_tcloss').val(dataRecord.brew_fermenter_tcloss); - } - dataRecord.brew_fermenter_volume = aboil_volume - dataRecord.brew_fermenter_tcloss + dataRecord.brew_fermenter_extrawater; - $('#brew_fermenter_volume').val(dataRecord.brew_fermenter_volume); - // Calculate SG in fermenter - ogx = dataRecord.brew_aboil_sg; - if (ogx < 1.002) - ogx = aboil_sg; - topw = dataRecord.brew_fermenter_extrawater; - - if (dataRecord.brew_fermenter_volume > 0) { - sug = sg_to_plato(ogx) * dataRecord.brew_fermenter_volume * ogx / 100; //kg of sugar in - sug += addedS; //kg - - if ((dataRecord.brew_fermenter_volume * ogx + addedmass) > 0) { - pt = 100 * sug / (dataRecord.brew_fermenter_volume * ogx + addedmass + topw); - dataRecord.og = dataRecord.brew_fermenter_sg = Round(plato_to_sg(pt), 4); - $('#brew_fermenter_sg').val(dataRecord.brew_fermenter_sg); - // color - if (dataRecord.color_method == 4) { - dataRecord.brew_fermenter_color = Math.round(((pt / 8.6) * colorn) + (dataRecord.boil_time / 60)); - } else if (dataRecord.color_method == 3) { - dataRecord.brew_fermenter_color = Math.round((4.46 * bv * sr) / (aboil_volume + topw) * colorh); - } else { - cw = colort / (aboil_volume + topw) * 8.34436; - dataRecord.brew_fermenter_color = kw_to_ebc(dataRecord.color_method, cw); - } - $('#brew_fermenter_color').val(dataRecord.brew_fermenter_color); - scolor = ebc_to_color(dataRecord.brew_fermenter_color); - $('#bcolorf').show(); - document.getElementById('bcolorf').style.background = scolor; - } - } else { - // Negative volume - dataRecord.brew_fermenter_sg = dataRecord.brew_fermenter_color = 0; - $('#brew_fermenter_sg').val(0); - $('#brew_fermenter_color').val(0); - $('#bcolorf').hide(); - } - - // Color of the wort - if (dataRecord.color_method == 4) { - color = Math.round(((sg_to_plato(dataRecord.est_og) / 8.6) * colorn) + (dataRecord.boil_time / 60)); - } else if (dataRecord.color_method == 3) { // Hans Halberstadt - color = Math.round((4.46 * bv * sr) / parseFloat(dataRecord.batch_size) * colorh); - } else { - cw = colort / parseFloat(dataRecord.batch_size) * 8.34436; - color = kw_to_ebc(dataRecord.color_method, cw); - } - dataRecord.est_color = color; - $('#est_color').val(color); - $('#est_color2').val(color); - scolor = ebc_to_color(color); - document.getElementById('bcolor').style.background = scolor; - document.getElementById('bcolor2').style.background = scolor; - - // Progress bars - pmalts = mashkg / dataRecord.eq_mash_max * 100; - $('#perc_malts').jqxProgressBar('val', pmalts); - $('#perc_sugars').jqxProgressBar('val', psugar); - $('#perc_cara').jqxProgressBar('val', pcara); - calcStage(); - - // Calculate estimated svg. - svg = 0; // default. - initcells = 0; - for (i = 0; i < dataRecord.yeasts.length; i++) { - row = dataRecord.yeasts[i]; - if (row.y_use == 0) { // Primary - if (parseFloat(row.y_attenuation) > svg) - svg = parseFloat(row.y_attenuation); // Take the highest if multiple yeasts. - if (row.y_form == 0) - initcells += (parseFloat(row.y_cells) / 1000000000) * parseFloat(row.y_amount) * (dataRecord.starter_viability / 100); - else - initcells += (parseFloat(row.y_cells) / 1000000) * parseFloat(row.y_amount) * (dataRecord.starter_viability / 100); - } - // TODO: brett in secondary ?? - if ((((dataRecord.inventory_reduced <= 3) && (row.y_use == 0)) || // Primary - ((dataRecord.inventory_reduced <= 4) && (row.y_use == 1)) || // Secondary - ((dataRecord.inventory_reduced <= 5) && (row.y_use == 2)) || // Tertiary - ((dataRecord.inventory_reduced <= 6) && (row.y_use == 3))) && // Bottle - (row.y_inventory < row.y_amount)) { - ok_yeasts = 0; - } - } - calcSupplies(); - if (svg == 0) - svg = 77; - if ((mashkg > 0) && (infuse > 0) && (mashtime > 0) && (mashtemp > 0)) { - dataRecord.est_fg = estimate_fg(psugar, pcara, infuse / mashkg, mashtime, mashtemp, svg, dataRecord.est_og); - } else { - dataRecord.est_fg = estimate_fg(psugar, pcara, 0, 0, 0, svg, dataRecord.est_og); - } - $('#est_fg').val(dataRecord.est_fg); - $('#est_fg2').val(dataRecord.est_fg); - $('#est_fg3').val(dataRecord.est_fg); - fig = dataRecord.est_fg; - - dataRecord.est_abv = abvol(dataRecord.est_og, dataRecord.est_fg); - $('#est_abv').val(dataRecord.est_abv); - $('#est_abv2').val(dataRecord.est_abv); - - // Calculate the final svg if available use the real value. - if ((dataRecord.stage >= 6) && (dataRecord.fg > 0.990) && (dataRecord.fg < dataRecord.brew_fermenter_sg)) { - svg = calc_svg(dataRecord.brew_fermenter_sg, dataRecord.fg); - org = dataRecord.brew_fermenter_sg; - fig = dataRecord.fg; - } - - $('#yeast_cells').val(initcells); - $('#need_cells').val(getNeededYeastCells()); - - // Calculate the calories in kcal/l (from brouwhulp) - alc = 1881.22 * fig * (org - fig) / (1.775 - org); - sug = 3550 * fig * (0.1808 * org + 0.8192 * fig - 1.0004); - $('#kcal').val(Math.round((alc + sug) / (12 * 0.0295735296))); - }; - - function calcMash() { - - var h, m, infused = 0, mashtime = 0, mashvol = 0, vol, i, j, n, a, b, row, temp; - var lasttemp = 18.0; - var graintemp = 18.0; - var tuntemp = 18.0; - - if (dataRecord.mashs.length && (mashkg > 0)) { - console.log('calcMash()'); - for (i = 0; i < dataRecord.mashs.length; i++) { - row = dataRecord.mashs[i]; - if (row.step_type == 0) { // Infusion - if (i == 0) { - // First mash step, temperature from the mashtun and malt. - n = 20; // tun is preheated. - tuntemp = row.step_temp; - for (j = 0; j < n; j++) { - a = mashkg * graintemp * SpecificHeatMalt + dataRecord.eq_tun_weight * tuntemp * dataRecord.eq_tun_specific_heat; - b = row.step_temp * (dataRecord.eq_tun_weight * dataRecord.eq_tun_specific_heat + row.step_infuse_amount * SpecificHeatWater + mashkg * SpecificHeatMalt) - SlakingHeat * mashkg; - if (row.step_infuse_amount > 0) { - temp = (b - a) / (row.step_infuse_amount * SpecificHeatWater); - } else { - temp = 99; - } - tuntemp += (temp - tuntemp) / 2; - row.step_infuse_temp = Round(temp, 6); - } - //console.log('init infuse temp: ' + row.step_infuse_temp); - } else { - // Calculate amount of infusion water. - row.step_infuse_amount = infusionVol(infused, mashkg, row.step_infuse_temp, row.step_temp, lasttemp); - //console.log('vol: ' + row.step_infuse_amount + ' temp: ' + row.step_infuse_temp); - } - infused += parseFloat(row.step_infuse_amount); - } else if (row.step_type == 1) { // Temperature - if (i > 0) - row.step_infuse_amount = 0; - row.step_infuse_temp = 0; - } else if (row.step_type == 2) { // Decoction - row.step_infuse_amount = decoctionVol(infused, row.step_temp, lasttemp); - row.step_infuse_temp = 99; - } - row.step_volume = infused; - //console.log(i + ' type: ' + row.step_type + ' volume: ' + row.step_infuse_amount + ' temp: ' + row.step_infuse_temp); - lasttemp = row.step_temp; - mashtime += row.step_time + row.ramp_time; - row.step_wg_ratio = Round(infused / mashkg, 6); - $('#mashGrid').jqxGrid('updaterow', i, row); - } - } - if ((dataRecord.w1_amount + dataRecord.w2_amount) == 0) { - dataRecord.w1_amount = infused; - $('#w1_amount').val(infused); - console.log("calcMash() fixed water 1 to " + infused); - } - mashvol = Round(mashkg * MaltVolume + infused, 6); - $('#est_mashvol').val(mashvol); - h = Math.floor(mashtime / 60); - m = Math.floor(mashtime - (h * 60)); - if (h < 10) - h = '0' + h; - if (m < 10) - m = '0' + m; - $('#est_mashtime').val(h + ':' + m); - // Estimated needed sparge water corrected for the temperature. - spoelw = Round((dataRecord.boil_size - infused + (mashkg * my_grain_absorbtion) + dataRecord.eq_lauter_deadspace) * 1.03, 6); - $('#brew_sparge_est').val(spoelw); - } - - function getNeededYeastCells() { - - var plato, volume, sg = dataRecord.brew_fermenter_sg; - if (sg <= 1.0001 && dataRecord.fg > 1.000) - sg = dataRecord.fg; - else if (sg <= 1.0001) - sg = dataRecord.est_og; - plato = sg_to_plato(sg); - - volume = dataRecord.brew_fermenter_volume; - if (volume <= 0) - volume = dataRecord.batch_size - dataRecord.eq_trub_chiller_loss; - - return dataRecord.yeast_pitchrate * volume * plato; - } - - function hopFlavourContribution(bt, vol, use, amount) { - var result; - - if (use == 4 || use == 5) // Whirlpool or Dry-hop - return 0; - if (use == 1) { // First wort - result = 0.15; // assume 15% flavourcontribution for fwh - } else if (bt > 50) { - result = 0.10; // assume 10% flavourcontribution as a minimum - } else { - result = 15.25 / (6 * Math.sqrt(2 * Math.PI)) * Math.exp(-0.5 * Math.pow((bt - 21) / 6, 2)); - if (result < 0.10) - result = 0.10; // assume 10% flavourcontribution as a minimum - } - return (result * amount * 1000) / vol; - } - - function hopAromaContribution(bt, vol, use, amount) { - var result = 0; - - if (use == 5) { // Dry hop - result = 1.33; - } else if (use == 4) { // Whirlpool - if (bt > 30) - bt = 30; // Max 30 minutes - result = 0.62 * bt / 30; - } else if (bt > 20) { - result = 0; - } else if (bt > 7.5) { - result = 10.03 / (4 * Math.sqrt(2 * Math.PI)) * Math.exp(-0.5 * Math.pow((bt - 7.5) / 4, 2)); - } else if (use == 2) { // Boil - result = 1; - } else if (use == 3) { // Aroma - result = 1.2; - } - return (result * amount * 1000) / vol; - } - - function calcIBUs() { - var total_ibus = 0, ferm_ibus = 0, rows = {}, i, row; - hop_aroma = hop_flavour = 0; - if (!(rows = $('#hopGrid').jqxGrid('getrows'))) { - return; - } - ok_hops = 1; - for (i = 0; i < rows.length; i++) { - row = rows[i]; - total_ibus += toIBU(row.h_useat, row.h_form, preboil_sg, parseFloat(dataRecord.batch_size), - parseFloat(row.h_amount), parseFloat(row.h_time), parseFloat(row.h_alpha), dataRecord.ibu_method, - dataRecord.brew_whirlpool9, dataRecord.brew_whirlpool7, dataRecord.brew_whirlpool6); - ferm_ibus += toIBU(row.h_useat, row.h_form, preboil_sg, - parseFloat(dataRecord.brew_fermenter_volume) + parseFloat(dataRecord.brew_fermenter_tcloss), - parseFloat(row.h_amount), parseFloat(row.h_time), parseFloat(row.h_alpha), dataRecord.ibu_method, - dataRecord.brew_whirlpool9, dataRecord.brew_whirlpool7, dataRecord.brew_whirlpool6); - hop_flavour += hopFlavourContribution(parseFloat(row.h_time), parseFloat(dataRecord.batch_size), row.h_useat, parseFloat(row.h_amount)); - hop_aroma += hopAromaContribution(parseFloat(row.h_time), parseFloat(dataRecord.batch_size), row.h_useat, parseFloat(row.h_amount)); - if ((((dataRecord.inventory_reduced <= 2) && (row.h_useat <= 4)) || // Mash, FW, Boil, Aroma, Whirlpool - ((dataRecord.inventory_reduced <= 6) && (row.h_useat == 5))) && // Dry-hop - (row.h_inventory < row.h_amount)) - ok_hops = 0; - } - total_ibus = Round(total_ibus, 1); - ferm_ibus = Round(ferm_ibus, 1); - hop_flavour = Round(hop_flavour * 100 / 5, 1); - hop_aroma = Round(hop_aroma * 100 / 6, 1); - if (hop_flavour > 100) - hop_flavour = 100; - if (hop_aroma > 100) - hop_aroma = 100; - console.log('calcIBUs(): ' + total_ibus + ' flavour: ' + hop_flavour + ' aroma: ' + hop_aroma + - ' fermenter:' + ferm_ibus + ' supplies:' + ok_hops); - dataRecord.est_ibu = total_ibus; - $('#est_ibu').val(total_ibus); - $('#est_ibu2').val(total_ibus); - $('#hop_flavour').jqxProgressBar('val', hop_flavour); - $('#hop_aroma').jqxProgressBar('val', hop_aroma); - $('#brew_fermenter_ibu').val(ferm_ibus); - calcStage(); - calcSupplies(); - }; - - /* - * http://braukaiser.com/blog/blog/2012/11/03/estimating-yeast-growth/ - * - * stype: 0=stirred, 1=shaken, 2=simple - * totcells: initial cells - * egrams: gram extract - */ - function getGrowthRate(stype, totcells, egrams) { - - /* Cells per grams extract (B/g) */ - var cpe = totcells / egrams; - - if (cpe > 3.5) - return 0; // no growth - if (stype == 2) - return 0.4; // simple starter - if (stype == 1) - return 0.62; // shaken starter - if (cpe <= 1.4) // stirred starter - return 1.4; - return 2.33 - (.67 * cpe); - }; - - function calcStep(svol, stype, start) { - - var gperpoint = 2.72715, //number of grams of extract per point of starter gravity per liter - prate = start / svol * 1000, - irate = Round(prate, 1), - egrams = (dataRecord.starter_sg - 1) * svol * gperpoint, - grate = getGrowthRate(stype, start, egrams), - ncells = Round(egrams * grate, 1), - totcells = parseFloat(ncells) + start; - - return { - svol: svol, - irate: irate, - prate: Round(prate, 1), - ncells: ncells, - totcells: totcells, - growf: Round(ncells / start, 2) - }; - } - - function killstep2() { - - dataRecord.prop2_volume = 0; - $('#prop2_volume').val(0); - $('#prop2_tcells').val(0); - $('#prop2_type,#prop2_volume,#prop2_irate,#prop2_ncells,#prop2_tcells,#prop2_growf').hide(); - $('#r2_pmpt').show(); - } - - function killstep3() { - - dataRecord.prop3_volume = 0; - $('#prop3_volume').val(0); - $('#prop3_tcells').val(0); - $('#prop3_type,#prop3_volume,#prop3_irate,#prop3_ncells,#prop3_tcells,#prop3_growf').hide(); - $('#r3_pmpt').show(); - } - - function killstep4() { - - dataRecord.prop4_volume = 0; - $('#prop4_volume').val(0); - $('#prop4_tcells').val(0); - $('#prop4_type,#prop4_volume,#prop4_irate,#prop4_ncells,#prop4_tcells,#prop4_growf').hide(); - $('#r4_pmpt').show(); - } - - /* - * Calculate all starter steps. - * stype: final starter type: 0 = stirred, 1 = shaked, 2 = simple. - * start: initial cells in billions - * needed: needed cells in billions - * - * result: all values updated. - */ - function calcSteps(stype, start, needed) { - - var uvols = [20, 40, 60, 80, 100, 150, 200, 250, 375, 500, 625, 750, 875, 1000, 1250, 1500, 2000, 2500, 3000, 4000, 5000], - mvols = uvols.length, svol = 0, lasti = 0, result = {}, i; - - /* - * If no values are set, auto calculate the starter. - */ - if ((parseFloat($('#prop1_volume').jqxNumberInput('decimal')) + parseFloat($('#prop2_volume').jqxNumberInput('decimal')) + - parseFloat($('#prop3_volume').jqxNumberInput('decimal')) + parseFloat($('#prop4_volume').jqxNumberInput('decimal'))) == 0) { - // clear by default - for (i = 1; i < 5; i++) { - $('#prop' + i + '_type,#prop' + i + '_volume,#prop' + i + '_irate,#prop' + i + '_ncells,#prop' + i + '_tcells,#prop' + i + '_growf').hide(); - $('#r' + i + '_pmpt').show(); - $('#prop' + i + '_type').val(stype); - $('#prop' + i + '_volume').val(0); - } - if (start > needed) { - return; // no starter needed - } - $('#prop1_type,#prop1_volume,#prop1_irate,#prop1_ncells,#prop1_tcells,#prop1_growf').show(); - $('#r1_pmpt').hide(); - for (i = lasti; i <= mvols; i++) { - lasti = i; - svol = uvols[lasti]; - result = calcStep(svol, stype, start); - if (result.irate < 25) { - // inocculation rate too low, backup one step and break out. - lasti = i - 1; - svol = uvols[lasti]; - result = calcStep(svol, stype, start); - break; - } - if (result.totcells > needed || i == mvols) { // hit the target or loops done - break; - } - } - $('#prop1_volume').val(result.svol / 1000); // to liters - $('#prop1_irate').val(result.prate); - $('#prop1_ncells').val(result.ncells); - $('#prop1_tcells').val(result.totcells); - $('#prop1_growf').val(result.growf); - if (result.totcells > needed) - return; // hit the target - - // second stage - $('#r2_pmpt').hide(); - $('#prop2_type').val(stype); - $('#prop2_type,#prop2_volume,#prop2_irate,#prop2_ncells,#prop2_tcells,#prop2_growf').show(); - for (i = lasti; i <= mvols; i++) { - lasti = i; - svol = uvols[lasti]; - result = calcStep(svol, stype, $('#prop1_tcells').val()); - if (result.irate < 25) { - lasti = i - 1; - svol = uvols[lasti]; - result = calcStep(svol, stype, $('#prop1_tcells').val()); - break; - } - if (result.totcells > needed || i == mvols) { // hit the target or loops done - break; - } - } - $('#prop2_volume').val(result.svol / 1000); // to liters - $('#prop2_irate').val(result.prate); - $('#prop2_ncells').val(result.ncells); - $('#prop2_tcells').val(result.totcells); - $('#prop2_growf').val(result.growf); - if (result.totcells > needed) - return; // hit the target - - // third stage - $('#r3_pmpt').hide(); - $('#prop3_type').val(stype); - $('#prop3_type,#prop3_volume,#prop3_irate,#prop3_ncells,#prop3_tcells,#prop3_growf').show(); - for (i = lasti; i <= mvols; i++) { - lasti = i; - svol = uvols[lasti]; - result = calcStep(svol, stype, $('#prop2_tcells').val()); - if (result.irate < 25) { - lasti = i - 1; - svol = uvols[lasti]; - result = calcStep(svol, stype, $('#prop2_tcells').val()); - break; - } - if (result.totcells > needed || i == mvols) { // hit the target or loops done - break; - } - } - $('#prop3_volume').val(result.svol / 1000); // to liters - $('#prop3_irate').val(result.prate); - $('#prop3_ncells').val(result.ncells); - $('#prop3_tcells').val(result.totcells); - $('#prop3_growf').val(result.growf); - if (result.totcells > needed) - return; // hit the target - - // fourth stage - $('#r4_pmpt').hide(); - $('#prop4_type').val(stype); - $('#prop4_type,#prop4_volume,#prop4_irate,#prop4_ncells,#prop4_tcells,#prop4_growf').show(); - for (i = lasti; i <= mvols; i++) { - lasti = i; - svol = uvols[lasti]; - result = calcStep(svol, stype, $('#prop3_tcells').val()); - if (result.totcells > needed || i == mvols) { // hit the target or loops done - $('#prop4_volume').val(result.svol / 1000); // to liters - $('#prop4_irate').val(result.prate); - $('#prop4_ncells').val(result.ncells); - $('#prop4_tcells').val(result.totcells); - $('#prop4_growf').val(result.growf); - return; - } - } - } else { - // recalculate - if (dataRecord.prop1_volume > 0) { - $('#r1_pmpt').hide(); - $('#prop1_type,#prop1_volume,#prop1_irate,#prop1_ncells,#prop1_tcells,#prop1_growf').show(); - result = calcStep($('#prop1_volume').val() * 1000, dataRecord.prop1_type, start); - $('#prop1_irate').val(result.prate); - $('#prop1_ncells').val(result.ncells); - $('#prop1_tcells').val(result.totcells); - $('#prop1_growf').val(result.growf); - if (result.totcells > needed) { - killstep2(); - killstep3(); - killstep4(); - } else if (dataRecord.prop2_volume == 0) { - dataRecord.prop2_volume = dataRecord.prop1_volume; /* Extra step needed, start with the same size */ - dataRecord.prop2_type = dataRecord.prop1_type; - $('#prop2_volume').val(dataRecord.prop2_volume); - $('#prop2_type').val(dataRecord.prop2_type); - } - } - if (dataRecord.prop2_volume > 0) { - $('#r2_pmpt').hide(); - $('#prop2_type,#prop2_volume,#prop2_irate,#prop2_ncells,#prop2_tcells,#prop2_growf').show(); - result = calcStep($('#prop2_volume').val() * 1000, dataRecord.prop2_type, $('#prop1_tcells').val()); - $('#prop2_irate').val(result.prate); - $('#prop2_ncells').val(result.ncells); - $('#prop2_tcells').val(result.totcells); - $('#prop2_growf').val(result.growf); - if (result.totcells > needed) { - killstep3(); - killstep4(); - } else if (dataRecord.prop3_volume == 0) { - dataRecord.prop3_volume = dataRecord.prop2_volume; /* Extra step needed, start with the same size */ - dataRecord.prop3_type = dataRecord.prop2_type; - $('#prop3_volume').val(dataRecord.prop3_volume); - $('#prop3_type').val(dataRecord.prop3_type); - } - } - if (dataRecord.prop3_volume > 0) { - $('#r3_pmpt').hide(); - $('#prop3_type,#prop3_volume,#prop3_irate,#prop3_ncells,#prop3_tcells,#prop3_growf').show(); - result = calcStep($('#prop3_volume').val() * 1000, dataRecord.prop3_type, $('#prop2_tcells').val()); - $('#prop3_irate').val(result.prate); - $('#prop3_ncells').val(result.ncells); - $('#prop3_tcells').val(result.totcells); - $('#prop3_growf').val(result.growf); - if (result.totcells > needed) { - killstep4(); - } else if (dataRecord.prop4_volume == 0) { - dataRecord.prop4_volume = dataRecord.prop3_volume; /* Extra step needed, start with the same size */ - dataRecord.prop4_type = dataRecord.prop3_type; - $('#prop4_volume').val(dataRecord.prop4_volume); - $('#prop4_type').val(dataRecord.prop4_type); - } - } - if (dataRecord.prop4_volume > 0) { - $('#r4_pmpt').hide(); - $('#prop4_type,#prop4_volume,#prop4_irate,#prop4_ncells,#prop4_tcells,#prop4_growf').show(); - result = calcStep($('#prop4_volume').val() * 1000, dataRecord.prop4_type, $('#prop3_tcells').val()); - $('#prop4_irate').val(result.prate); - $('#prop4_ncells').val(result.ncells); - $('#prop4_tcells').val(result.totcells); - $('#prop4_growf').val(result.growf); - } - } - } - - function calcYeast() { - - // Calculate needed cells. - var plato, volume, rows, rowscount, row, i, needed, use_cells, sg = dataRecord.brew_fermenter_sg; - - if (sg <= 1.0001 && dataRecord.fg > 1.000) - sg = dataRecord.fg; - else if (sg <= 1.0001) - sg = dataRecord.est_og; - plato = sg_to_plato(sg); - - volume = dataRecord.brew_fermenter_volume; - if (volume > 0) { - if (dataRecord.brew_fermenter_extrawater > 0) - volume += dataRecord.brew_fermenter_extrawater; - } else { - volume = dataRecord.batch_size - dataRecord.eq_trub_chiller_loss; - } - - // Also in calcFermentables() - $('#yeast_cells').val(initcells); - - if (!(rows = $('#yeastGrid').jqxGrid('getrows'))) { - return; // grid not yet loaded. - } - rowscount = dataRecord.yeasts.length; - if (rowscount == 0) - return; // no yeast in recipe - - $('.primary_dry').hide(); - $('.primary_liquid').hide(); - - var maybe_starter = 0; - var pitchrate = 0.75; // Yeast pitch rate default - for (i = 0; i < rowscount; i++) { - row = dataRecord.yeasts[i]; - if (row.y_use == 0) { // primary - if (row.y_form == 1) { - // Dry yeast - $('.primary_dry').show(); - console.log('dry yeast: ' + row.y_gr_hl_lo + '@' + row.y_sg_lo + ' ' + row.y_gr_hl_hi + '@' + row.y_sg_hi); - // Build the formule with the yeast parameters. - // Based on https://www.lallemandbrewing.com/en/canada/brewers-corner/brewing-tools/pitching-rate-calculator/ - var og = row.y_sg_lo; - var f1 = row.y_gr_hl_lo / 100; - var f2 = Round(f1 / 5, 6); - // After a lot of try and error, study, the best thing to increase the pitch amount is actually - // use this simple formula by Lallemand. This is about the same as sugar weight increment in the wort. - var multiplier = (sg <= og) ? f1 : (f1 + f2 * (sg - og) / 0.008); - console.log('sg: ' + sg + ' og: ' + og + ' f1: ' + f1 + ' f2: ' + f2 + ' multiplier: ' + multiplier); - // dataRecord.starter_viability - var yeast_grams = Round(volume * multiplier * (100 / dataRecord.starter_viability), 2); - $('#yeast_grams').val(yeast_grams); - var yeast_gr_hl = Round(yeast_grams / (volume * 0.01), 2); - $('#yeast_gr_hl').val(yeast_gr_hl); - //console.log('need ' + yeast_grams + ' grams, gr/hl: ' + yeast_gr_hl); - - } else { - // Liquid yeast - $('.primary_liquid').show(); - // pitchrate see https://www.brewersfriend.com/yeast-pitch-rate-and-starter-calculator/ - // and http://braukaiser.com/blog/blog/2012/11/03/estimating-yeast-growth/ - if (row.y_type == 0) { // lager yeast - pitchrate = 1.5; - if (dataRecord.est_og > 1.060) - pitchrate = 2.0; - } else if (row.y_type == 6) { // Kveik - pitchrate = 0.075; - } else { - pitchrate = 0.75; - if (dataRecord.est_og > 1.060) - pitchrate = 1.0; - } - if (dataRecord.yeast_pitchrate < 0.01) { - dataRecord.yeast_pitchrate = pitchrate; - $('#yeast_pitchrate').val(pitchrate); - } - maybe_starter = 1; - } - } - } - - needed = Round(dataRecord.yeast_pitchrate * volume * plato, 1); - $('#need_cells').val(needed); - use_cells = initcells; - if (needed <= initcells) - maybe_starter = 0; - //console.log('calcYeast() pitchrate:' + dataRecord.yeast_pitchrate + ' start:' + initcells + ' needed:' + needed + ' volume:' + volume + ' maybe_starter:' + maybe_starter); - - if (maybe_starter != dataRecord.starter_enable) { - dataRecord.starter_enable = maybe_starter; - } - if (maybe_starter) - $('#propagator').show(); - else - $('#propagator').hide(); - - if (dataRecord.starter_enable) { - - calcSteps(dataRecord.starter_type, initcells, needed); - - for (i = 1; i < 5; i++) { - $('#r' + i + '_irate').html(''); - $('#r' + i + '_growf').html(''); - $('#r' + i + '_tcells').html(''); - if (parseFloat($('#prop' + i + '_volume').val()) > 0) { - if ((parseFloat($('#prop' + i + '_irate').val()) < 25) || (parseFloat($('#prop' + i + '_irate').val()) > 100)) { - $('#r' + i + '_irate').html("<img src='images/dialog-error.png'>"); - } else { - $('#r' + i + '_irate').html("<img src='images/dialog-ok-apply.png'>"); - } - if (parseFloat($('#prop' + i + '_growf').val()) < 1) - $('#r' + i + '_growf').html("<img src='images/dialog-error.png'>"); - if (($('#prop' + i + '_type').val() > 0) && (parseFloat($('#prop' + i + '_growf').val()) > 3)) - $('#r' + i + '_growf').html("<img src='images/dialog-error.png'>"); - if (parseFloat($('#prop' + i + '_tcells').val()) > needed) - $('#r' + i + '_tcells').html("<img src='images/dialog-ok-apply.png'>"); - use_cells = parseFloat($('#prop' + i + '_tcells').val()); - } else { - $('#r' + i + '_irate').html(''); - } - } - } - $('#plato_cells').val(parseFloat(use_cells / (volume * plato))); - }; - - function whirlpoolHops() { - var row, i, time, rowscount = dataRecord.hops.length; - if (rowscount == 0) - return; - for (i = 0; i < rowscount; i++) { - row = dataRecord.hops[i]; - if (row.h_useat == 4) { - time = parseFloat(dataRecord.brew_whirlpool9) + parseFloat(dataRecord.brew_whirlpool7) + parseFloat(dataRecord.brew_whirlpool6); - dataRecord.hops[i].h_time = time; - $('#hopGrid').jqxGrid('setcellvalue', i, 'h_time', time); - } - } - }; - - function calcMiscs() { - - ok_miscs = 1; - var row, i, rowscount = dataRecord.miscs.length; - if (rowscount == 0) - return; - for (i = 0; i < rowscount; i++) { - row = dataRecord.miscs[i]; - if ((((dataRecord.inventory_reduced <= 2) && (row.m_use_use <= 2)) || // Starter, Mash, Boil - ((dataRecord.inventory_reduced <= 2) && (row.m_use_use == 6)) || // Sparge - ((dataRecord.inventory_reduced <= 3) && (row.m_use_use == 3)) || // Primary - ((dataRecord.inventory_reduced <= 5) && (row.m_use_use == 4)) || // Secondary, Teriary - ((dataRecord.inventory_reduced <= 6) && (row.m_use_use == 5))) && // Bottle - (row.m_inventory < row.m_amount)) { - ok_miscs = 0; - } - } - calcSupplies(); - }; - - function GetBUGU() { - var gu = (dataRecord.est_og - 1) * 1000; - if (gu > 0) - return dataRecord.est_ibu / gu; - else - return 0.5; - } - - function GetOptSO4Clratio() { - var BUGU = GetBUGU(); - return (1.0 / (-1.2 * BUGU + 1.4)); - } - - function setWaterAgent(name, amount, use) { - var row, i, id, found = false, miscs, rows = $('#miscGrid').jqxGrid('getrows'); - if (amount == 0) { - for (i = 0; i < rows.length; i++) { - row = rows[i]; - if (row.m_name == name && row.m_use_use == use) { - id = $('#miscGrid').jqxGrid('getrowid', i); - $('#miscGrid').jqxGrid('deleterow', id); - } - } - } else { - for (i = 0; i < rows.length; i++) { - row = rows[i]; - if (row.m_name == name && row.m_use_use == use) { - found = true; - $('#miscGrid').jqxGrid('setcellvalue', i, 'm_amount', amount / 1000); - break; - } - } - if (! found) { - miscs = new $.jqx.dataAdapter(miscInvSource, { - loadComplete: function() { - var record, i, row = {}, records = miscs.records; - for (i = 0; i < records.length; i++) { - record = records[i]; - if (record.name == name) { - row['m_name'] = record.name; - row['m_amount'] = amount / 1000; - row['m_cost'] = record.cost; - row['m_type'] = record.type; - row['m_use_use'] = use; - row['m_time'] = 0; - row['m_amount_is_weight'] = record.amount_is_weight; - row['m_inventory'] = record.inventory; - row['m_avail'] = 1; - $('#miscGrid').jqxGrid('addrow', null, row); - } - } - } - }); - miscs.dataBind(); - return; - } - } - } - - function setRangeIndicator(ion, rangeCode) { - if ((rangeCode == 'laag') || (rangeCode == 'hoog')) - $('#wr_' + ion).html("<img src='images/dialog-error.png'><span style='vertical-align: top; font-size: 10px; font-style: italic;'>" + rangeCode + '</span>'); - else - $('#wr_' + ion).html("<img src='images/dialog-ok-apply.png'>"); - } - - function mix(v1, v2, c1, c2) { - if ((v1 + v2) > 0) { - return ((v1 * c1) + (v2 * c2)) / (v1 + v2); - } - return 0; - } - - function PartCO3(pH) { - var H = Math.pow(10, -pH); - return 100 * Ka1 * Ka2 / (H * H + H * Ka1 + Ka1 * Ka2); - } - - function PartHCO3(pH) { - var H = Math.pow(10, -pH); - return 100 * Ka1 * H / (H * H + H * Ka1 + Ka1 * Ka2); - } - - function Charge(pH) { - return (-2 * PartCO3(pH) - PartHCO3(pH)); - } - - //Z alkalinity is the amount of acid (in mEq/l) needed to bring water to the target pH (Z pH) - function ZAlkalinity(pHZ) { - var C43 = Charge(4.3), - Cw = Charge(parseFloat($('#wg_ph').jqxNumberInput('decimal'))), - Cz = Charge(pHZ), - DeltaCNaught = -C43 + Cw, - CT = parseFloat($('#wg_total_alkalinity').jqxNumberInput('decimal')) / 50 / DeltaCNaught, - DeltaCZ = -Cz + Cw; - return CT * DeltaCZ; - } - - //Z Residual alkalinity is the amount of acid (in mEq/l) needed to bring the water in the mash to the target pH (Z pH) - function ZRA(pHZ) { - - var Magn, Z, Calc = parseFloat($('#wg_calcium').jqxNumberInput('decimal')) / (MMCa / 2); - Magn = parseFloat($('#wg_magnesium').jqxNumberInput('decimal')) / (MMMg / 2); - Z = ZAlkalinity(pHZ); - return Z - (Calc / 3.5 + Magn / 7); - } - - function BufferCapacity(di_ph, acid_to_ph_57, ebc, graintype) { - C1 = 0; - if ((di_ph != 5.7) && ((acid_to_ph_57 < - 0.1) || (acid_to_ph_57 > 0.1))) { - C1 = acid_to_ph_57 / (di_ph - 5.7); - } else { - // If the acid_to_ph_5.7 is unknown from the maltster, guess the required acid. - switch (graintype) { - case 0: // Base, Special, Kilned - case 3: - case 5: C1 = 0.014 * ebc - 34.192; - break; - case 2: C1 = -0.0597 * ebc - 32.457; // Crystal - break; - case 1: C1 = 0.0107 * ebc - 54.768; // Roast - break; - case 4: C1 = -149; // Sour malt - break; - } - } - return C1; - } - - function ProtonDeficit(pHZ) { - - var i, C1, x, Result = ZRA(pHZ) * parseFloat($('#wg_amount').jqxNumberInput('decimal')); - // proton deficit for the grist - if (( $('#fermentableGrid').jqxGrid('getrows'))) { - for (i = 0; i < dataRecord.fermentables.length; i++) { - row = dataRecord.fermentables[i]; - if (row.f_added == 0 && row.f_graintype != 6) { // Added == Mash && graintype != No Malt - C1 = BufferCapacity(row.f_di_ph, row.f_acid_to_ph_57, row.f_color, row.f_graintype); - x = C1 * (pHZ - row.f_di_ph); // AcidRequired(ZpH) - Result += x * row.f_amount; - } - } - } else { - error_count++; - if (error_count < 5) - console.log('ProtonDeficit(' + pHZ + ') invalid grist, return ' + Result); - } - return Result; - } - - function MashpH() { - - var n = 0, pH = 5.4, deltapH = 0.001, deltapd = 0.1, pd = ProtonDeficit(pH); - while (((pd < -deltapd) || (pd > deltapd)) && (n < 2000)) { - n++; - if (pd < -deltapd) - pH -= deltapH; - else if (pd > deltapd) - pH += deltapH; - pd = ProtonDeficit(pH); - } - pH = Round(pH, 6); - //console.log('MashpH() n: ' + n + ' pH: ' + pH); - return pH; - } - - function calcWater() { - - /* Can be called during loading and building the screens */ - if (! data_loaded) { - console.log('calcWater() failsave'); - return; - } - - var liters = 0, - calcium = 0, - magnesium = 0, - sodium = 0, - total_alkalinity = 0, - chloride = 0, - sulfate = 0, - ph = 0, - RA = 0, - frac = 0, - TpH = 0, - protonDeficit = 0, - AT, /*BT,*/ - r1d, r2d, f1d, f2d, f3d, - deltapH, deltapd, pd, n, - Res; - - if (dataRecord.w1_name == '') { - return; - } - - $('#w1_hardness').val(Hardness(dataRecord.w1_calcium, dataRecord.w1_magnesium)); - $('#w1_ra').val(ResidualAlkalinity(dataRecord.w1_total_alkalinity, dataRecord.w1_calcium, dataRecord.w1_magnesium)); - - // If there is a dillute water source, mix the waters. - if ((dataRecord.w2_name != '') && (dataRecord.w2_name != 'Geen mengwater')) { - liters = dataRecord.w1_amount + dataRecord.w2_amount; - calcium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_calcium, dataRecord.w2_calcium); - magnesium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_magnesium, dataRecord.w2_magnesium); - sodium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_sodium, dataRecord.w2_sodium); - chloride = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_chloride, dataRecord.w2_chloride); - sulfate = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_sulfate, dataRecord.w2_sulfate); - total_alkalinity = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_total_alkalinity, dataRecord.w2_total_alkalinity); - ph = -Math.log10(((Math.pow(10, -dataRecord.w1_ph) * dataRecord.w1_amount) + (Math.pow(10, -dataRecord.w2_ph) * dataRecord.w2_amount)) / liters); - $('#w2_hardness').val(Hardness(dataRecord.w2_calcium, dataRecord.w2_magnesium)); - $('#w2_ra').val(ResidualAlkalinity(dataRecord.w2_total_alkalinity, dataRecord.w2_calcium, dataRecord.w2_magnesium)); - } else { - liters = dataRecord.w1_amount; - calcium = dataRecord.w1_calcium; - magnesium = dataRecord.w1_magnesium; - sodium = dataRecord.w1_sodium; - chloride = dataRecord.w1_chloride; - sulfate = dataRecord.w1_sulfate; - total_alkalinity = dataRecord.w1_total_alkalinity; - ph = dataRecord.w1_ph; - } - var bicarbonate = Bicarbonate(total_alkalinity, ph); - - /* Save mixed water ions for later */ - var wg_calcium = calcium; - var wg_sodium = sodium; - var wg_total_alkalinity = total_alkalinity; - var wg_chloride = chloride; - var wg_sulfate = sulfate; - var wg_bicarbonate = bicarbonate; - - dataRecord.wg_amount = liters; - dataRecord.wg_ph = ph; - - $('#wg_amount').val(liters); - $('#wg_calcium').val(Round(calcium, 1)); - $('#wg_magnesium').val(Round(magnesium, 1)); - $('#wg_sodium').val(Round(sodium, 1)); - $('#wg_bicarbonate').val(Round(bicarbonate, 1)); - $('#wg_total_alkalinity').val(Round(total_alkalinity, 1)); - $('#wg_chloride').val(Round(chloride, 1)); - $('#wg_sulfate').val(Round(sulfate, 1)); - $('#wg_ph').val(Round(ph, 2)); - $('#wg_hardness').val(Round(Hardness(calcium, magnesium), 1)); - $('#wg_ra').val(Round(ResidualAlkalinity(total_alkalinity, calcium, magnesium), 1)); - - var mash_ph = Round(MashpH(), 3); - console.log('Distilled water mash pH: ' + mash_ph); - - /* Calculate Salt additions */ - if (liters > 0) { - calcium += (parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 * 1000 + - parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 * 1000 + - parseFloat($('#wa_caco3').jqxNumberInput('decimal')) * MMCa / MMCaCO3 * 1000) / liters; - magnesium += (parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMMg / MMMgSO4 * 1000 + - parseFloat($('#wa_mgcl2').jqxNumberInput('decimal')) * MMMg / MMMgCl2 * 1000) / liters; - sodium += (parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000 + - parseFloat($('#wa_nahco3').jqxNumberInput('decimal')) * MMNa / MMNaHCO3 * 1000) / liters; - sulfate += (parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 * 1000 + - parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMSO4 / MMMgSO4 * 1000) / liters; - chloride += (2 * parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCl / MMCaCl2 * 1000 + - parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMCl / MMNaCl * 1000 + - parseFloat($('#wa_mgcl2').jqxNumberInput('decimal')) * MMCl / MMMgCl2 * 1000) / liters; - bicarbonate += (parseFloat($('#wa_nahco3').jqxNumberInput('decimal')) * MMHCO3 / MMNaHCO3 * 1000 + - parseFloat($('#wa_caco3').jqxNumberInput('decimal')) / 3 * MMHCO3 / MMCaCO3 * 1000) / liters; - } - - if (dataRecord.wa_acid_name < 0 || dataRecord,wa_acid_name >= AcidTypeData.length) { - $('#wa_acid_name').val(0); - dataRecord.wa_acid_name = 0; - dataRecord.wa_acid_perc = AcidTypeData[0].AcidPrc; - $('#wa_acid_perc').val(AcidTypeData[0].AcidPrc); - } - if (last_acid == '') - last_acid = AcidTypeData[dataRecord.wa_acid_name].nl; - - if (parseFloat(dataRecord.wa_acid_perc) == 0) { - dataRecord.wa_acid_perc = AcidTypeData[AT].AcidPrc; - $('#wa_acid_perc').val(AcidTypeData[AT].AcidPrc); - } - - AT = dataRecord.wa_acid_name; - - /* Note that the next calculations do not correct the pH change by the added salts. - This pH change is at most 0.1 pH and is a minor difference in Acid amount. */ - - if (dataRecord.calc_acid) { - /* Auto calculate pH */ - $('.c_mashph').show(); - TpH = parseFloat(dataRecord.mash_ph); - protonDeficit = ProtonDeficit(TpH); - //console.log('calc_acid tgt: ' + TpH + ' protonDeficit: ' + protonDeficit); - if (protonDeficit > 0) { // Add acid - frac = CalcFrac(TpH, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3); - Acid = protonDeficit / frac; - Acid *= AcidTypeData[AT].MolWt; // mg - Acidmg = Acid; - var RealSG = Round(((AcidTypeData[AT].AcidSG - 1000) * (parseFloat(dataRecord.wa_acid_perc) / 100)) + 1000, 2); - Acid /= RealSG; - Acid /= AcidTypeData[AT].AcidPrc / 100; - Acid = Round(Acid, 2); - console.log('Mash auto Acid final ml: ' + Acid); - $('#wa_acid').val(Acid); - setWaterAgent(AcidTypeData[AT].nl, Acid, 1); - - bicarbonate = bicarbonate - protonDeficit * frac / liters; - total_alkalinity = bicarbonate * 50 / 61; - } - ph = TpH; - dataRecord.wb_ph = ph; - $('#wb_ph').val(Round(ph, 2)); - $('#est_mash_ph').val(Round(ph, 2)); - } else { - /* Manual calculate pH */ - $('.c_mashph').hide(); - console.log('calc_acid no'); - pHa = Round(ph, 3); // Adjusted water pH - // Then calculate the new pH with added acids and malts - console.log('Mash pH: ' + pHa); - Acid = AcidTypeData[AT].AcidSG * (parseFloat(dataRecord.wa_acid_perc) / 100); // ml - Acid *= parseFloat($('#wa_acid').jqxNumberInput('decimal')); - Acid /= AcidTypeData[AT].MolWt; // mg - Acidmg = Acid; - - //find the pH where the protondeficit = protondeficit by the acid - frac = CalcFrac(pHa, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3); - protonDeficit = Round(Acid * frac, 3); - //console.log('protonDeficit Acid: ' + protonDeficit + ' frac: ' + frac + ' pH: ' + pHa); - - deltapH = 0.001; - deltapd = 0.1; - pd = Round(ProtonDeficit(pHa), 6); - n = 0; - while (((pd < (protonDeficit - deltapd)) || (pd > (protonDeficit + deltapd))) && (n < 4000)) { - n++; - if (pd < (protonDeficit - deltapd)) - pHa -= deltapH; - else if (pd > (protonDeficit + deltapd)) - pHa += deltapH; - frac = CalcFrac(pHa, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3); - protonDeficit = Acid * frac; - pd = ProtonDeficit(pHa); - } - //console.log('n: ' + n + ' pd: ' + pd + ' protonDeficit: ' + protonDeficit + ' frac: ' + frac + ' pHa: ' + pHa); - bicarbonate = wg_bicarbonate - protonDeficit * frac / liters; - total_alkalinity = bicarbonate * 50 / 61; - ph = pHa; - $('#wb_ph').val(Round(ph, 2)); - $('#est_mash_ph').val(Round(ph, 2)); - } - - if ((AT == 3) && (liters > 0)) { // Sulfuric / Zwavelzuur - RA = parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 + - parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMSO4 / MMMgSO4 + - Acidmg / 1000 * MMSO4 / (MMSO4 + 2); - RA = 1000 * RA / liters; - sulfate = wg_sulfate + RA; // Not add to sulfate?? - } else if ((AT == 1) && (liters > 0)) { // Hydrochloric, Zoutzuur - RA = parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCl / MMCaCl2 + - parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMCl / MMNaCl + - Acidmg / 1000 * MMCl / (MMCl + 1); - RA = 1000 * RA / liters; - chloride = wg_chloride + RA; - } - - var BUGU = GetBUGU(); - $('#tgt_bu').val(Round(BUGU, 2)); - // From brouwhulp. - if (BUGU < 0.32) - $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Zeer moutig en zoet</span>"); - else if (BUGU < 0.43) - $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Moutig, zoet</span>"); - else if (BUGU < 0.52) - $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Evenwichtig</span>"); - else if (BUGU < 0.63) - $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Licht hoppig, bitter</span>"); - else - $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Extra hoppig, zeer bitter</span>"); - - // Sulfate to Chloride ratio (Palmer). - var OptSO4Clratio = GetOptSO4Clratio(); - $('#tgt_so4_cl').val(Round(OptSO4Clratio, 1)); - if (OptSO4Clratio < 0.4) - $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Te moutig</span>"); - else if (OptSO4Clratio < 0.6) - $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Zeer moutig</span>"); - else if (OptSO4Clratio < 0.8) - $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Moutig</span>"); - else if (OptSO4Clratio < 1.5) - $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Gebalanceerd</span>"); - else if (OptSO4Clratio < 2.0) - $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Licht bitter</span>"); - else if (OptSO4Clratio < 4.0) - $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Bitter</span>"); - else if (OptSO4Clratio < 9.0) - $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Zeer bitter</span>"); - else - $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Te bitter</span>"); - if (chloride > 0) - RA = sulfate / chloride; - else - RA = 10; - $('#got_so4_cl').val(Round(RA, 1)); - Res = 'normaal'; - if (RA < (0.8 * OptSO4Clratio)) - Res = 'laag'; - else if (RA > (1.2 * OptSO4Clratio)) - Res = 'hoog'; - setRangeIndicator('so4_cl', Res); - - $('#wb_calcium').val(Round(calcium, 1)); - $('#wb_magnesium').val(Round(magnesium, 1)); - $('#wb_sodium').val(Round(sodium, 1)); - $('#wb_sulfate').val(Round(sulfate, 1)); - $('#wb_chloride').val(Round(chloride, 1)); - $('#wb_bicarbonate').val(Round(bicarbonate, 1)); - $('#wb_total_alkalinity').val(Round(total_alkalinity, 1)); - $('#wb_hardness').val(Hardness(calcium, magnesium)); - $('#wb_ra').val(ResidualAlkalinity(total_alkalinity, calcium, magnesium)); - - if (calcium < 40) { - setRangeIndicator('calcium', 'laag'); - } else if (calcium > 150) { - setRangeIndicator('calcium', 'hoog'); - } else { - setRangeIndicator('calcium', 'normaal'); - } - if (magnesium < 5) { - setRangeIndicator('magnesium', 'laag'); - } else if (magnesium > 40) { - setRangeIndicator('magnesium', 'hoog'); - } else { - setRangeIndicator('magnesium', 'normaal'); - } - if (sodium <= 150) { - setRangeIndicator('sodium', 'normaal'); - } else { - setRangeIndicator('sodium', 'hoog'); - } - // Both chloride and sulfate should be above 50 according to - // John Palmer. So the Cl/SO4 ratio calculation will work. - if (chloride <= 50) { - setRangeIndicator('chloride', 'laag'); - } else if (chloride <= 150) { - setRangeIndicator('chloride', 'normaal'); - } else { - setRangeIndicator('chloride', 'hoog'); - } - if (sulfate <= 50) { - setRangeIndicator('sulfate', 'laag'); - } else if (sulfate <= 400) { - setRangeIndicator('sulfate', 'normaal'); - } else { - setRangeIndicator('sulfate', 'hoog'); - } - // (cloride + sulfate) > 500 is too high - if ((chloride + sulfate) > 500) { - setRangeIndicator('chloride', 'hoog'); - setRangeIndicator('sulfate', 'hoog'); - } - if (ph < 5.2) { - setRangeIndicator('ph', 'laag'); - } else if (ph > 5.6) { - setRangeIndicator('ph', 'hoog'); - } else { - setRangeIndicator('ph', 'normaal'); - } - if (bicarbonate > 250) { - setRangeIndicator('bicarbonate', 'hoog'); - } else { - setRangeIndicator('bicarbonate', 'normaal'); - } - calcSparge(); - calcMiscs(); - calcSupplies(); - } - - function calcSparge() { - - /* Based on the work of ajDeLange. */ - var ws_calcium, ws_magnesium, ws_total_alkalinity, ws_sodium, ws_chloride; - var ws_sulfate, ws_ph, ws_hardness, ws_ra; - var TargetpH = dataRecord.sparge_ph; - var Source_pH = 7.0; - - // Select watersource or fallback to the first source. - if ((dataRecord.sparge_source == 1) && (dataRecord.w2_ph > 0.0)) { // Source 2 - ws_calcium = dataRecord.w2_calcium; - ws_magnesium = dataRecord.w2_magnesium; - ws_total_alkalinity = dataRecord.w2_total_alkalinity; - ws_sodium = dataRecord.w2_sodium; - ws_chloride = dataRecord.w2_chloride; - ws_sulfate = dataRecord.w2_sulfate; - Source_pH = dataRecord.w2_ph; - $('#w2_button').jqxRadioButton({ checked: true }); - } else if ((dataRecord.sparge_source == 2) && (dataRecord.w2_ph > 0.0)) { // Mixed - ws_calcium = dataRecord.wg_calcium; - ws_magnesium = dataRecord.wg_magnesium; - ws_total_alkalinity = dataRecord.wg_total_alkalinity; - ws_sodium = dataRecord.wg_sodium; - ws_chloride = dataRecord.wg_chloride; - ws_sulfate = dataRecord.wg_sulfate; - Source_pH = dataRecord.wg_ph; - $('#wg_button').jqxRadioButton({ checked: true }); - } else { - ws_calcium = dataRecord.w1_calcium; - ws_magnesium = dataRecord.w1_magnesium; - ws_total_alkalinity = dataRecord.w1_total_alkalinity; - ws_sodium = dataRecord.w1_sodium; - ws_chloride = dataRecord.w1_chloride; - ws_sulfate = dataRecord.w1_sulfate; - Source_pH = dataRecord.w1_ph; - $('#w1_button').jqxRadioButton({ checked: true }); - } - - if (dataRecord.sparge_volume > 0) { - ws_calcium += (parseFloat($('#ss_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 * 1000 + - parseFloat($('#ss_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 * 1000) / dataRecord.sparge_volume; - ws_magnesium += (parseFloat($('#ss_mgso4').jqxNumberInput('decimal')) * MMMg / MMMgSO4 * 1000 + - parseFloat($('#ss_mgcl2').jqxNumberInput('decimal')) * MMMg / MMMgCl2 * 1000) / dataRecord.sparge_volume; - ws_sodium += (parseFloat($('#ss_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000) / dataRecord.sparge_volume; - ws_sulfate += (parseFloat($('#ss_caso4').jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 * 1000 + - parseFloat($('#ss_mgso4').jqxNumberInput('decimal')) * MMSO4 / MMMgSO4 * 1000) / dataRecord.sparge_volume; - ws_chloride += (2 * parseFloat($('#ss_cacl2').jqxNumberInput('decimal')) * MMCl / MMCaCl2 * 1000 + - parseFloat($('#ss_nacl').jqxNumberInput('decimal')) * MMCl / MMNaCl * 1000 + - parseFloat($('#ss_mgcl2').jqxNumberInput('decimal')) * MMCl / MMMgCl2 * 1000) / dataRecord.sparge_volume; - } - - /* Show the spargewate with salt additions */ - $('#sw_calcium').val(Round(ws_calcium, 1)); - $('#sw_magnesium').val(Round(ws_magnesium, 1)); - $('#sw_sodium').val(Round(ws_sodium, 1)); - $('#sw_sulfate').val(Round(ws_sulfate, 1)); - $('#sw_chloride').val(Round(ws_chloride, 1)); - $('#sw_bicarbonate').val(Round(Bicarbonate(ws_total_alkalinity, Source_pH), 1)); - $('#sw_total_alkalinity').val(Round(ws_total_alkalinity, 1)); - $('#sw_ph').val(dataRecord.sparge_ph); - $('#sw_hardness').val(Hardness(ws_calcium, ws_magnesium)); - $('#sw_ra').val(ResidualAlkalinity(ws_total_alkalinity, ws_calcium, ws_magnesium)); - - AT = dataRecord.sparge_acid_type; - if (AT < 0 || AT >= AcidTypeData.length) { - AT = 0; - dataRecord.sparge_acid_type = 0; - $('#sparge_acid_type').val(AcidTypeData[0].nl); - dataRecord.sparge_acid_perc = AcidTypeData[0].AcidPrc; - $('#sparge_acid_perc').val(dataRecord.sparge_acid_perc); - } - - /* - * Auto calculate the required acid - */ - if (dataRecord.calc_acid) { - // Step 1: Compute the mole fractions of carbonic (f1) and carbonate(f3) at the source water pH - var r1 = Math.pow(10, Source_pH - 6.35); - var r2 = Math.pow(10, Source_pH - 10.33); - var d = 1 + r1 + r1 * r2; - var f1 = 1 / d; - var f3 = r1 * r2 / d; - - //Step 2. Compute the mole fractions at pH = 4.3 (the pH which defines alkalinity) - var r143 = Math.pow(10, 4.3 - 6.35); - var r243 = Math.pow(10, 4.3 - 10.33); - var d43 = 1 + r143 + r143 * r243; - var f143 = 1 / d43; - var f343 = r143 * r243 / d43; - - //Step 4. Solve - var Ct = ws_total_alkalinity / 50 / ((f143 - f1) + (f3 - f343)); - - //Step 5. Compute mole fractions at desired pH - var r1g = Math.pow(10, TargetpH - 6.35); - var r2g = Math.pow(10, TargetpH - 10.33); - var dg = 1 + r1g + r1g * r2g; - var f1g = 1 / dg; - var f3g = r1g * r2g / dg; - - //Step 6. Use these to compute the milliequivalents acid required per liter (mEq/L) - var Acid = Ct * ((f1g - f1) + (f3 - f3g)) + Math.pow(10, -TargetpH) - Math.pow(10, -Source_pH); //mEq/l - Acid += 0.01; // Add acid that would be required for distilled water. - - //Step 8. Get the acid data. - var fract = CalcFrac(TargetpH, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3); - - //Step 9. Now divide the mEq required by the "fraction". This is the required number of moles of acid. - Acid /= fract; - - //Step 10. Multiply by molecular weight of the acid - Acid *= AcidTypeData[AT].MolWt; //mg - - //Step 11. Divide by Specific Gravity and Percentage to get the final ml. - var RealSG = Round(((AcidTypeData[AT].AcidSG - 1000) * (dataRecord.sparge_acid_perc / 100)) + 1000, 2); - Acid = Acid / RealSG; //ml - Acid *= dataRecord.sparge_volume; //ml acid total at 100% - Acid /= AcidTypeData[AT].AcidPrc / 100; //ml acid at supplied strength - Acid = Round(Acid, 2); - dataRecord.sparge_acid_amount = Acid / 1000; - $('#sparge_acid_amount').val(Acid); - } - - // Finally calculate the estimate preboil pH - var ph = -Math.log10(((Math.pow(10, -dataRecord.wb_ph) * dataRecord.wg_amount) + (Math.pow(10, -dataRecord.sparge_ph) * dataRecord.sparge_volume)) / - (dataRecord.wg_amount + dataRecord.sparge_volume)); - $('#preboil_ph').val(ph); - } - - function calcFermentation() { - var primary_svg, secondary_svg, final_svg, ABV; - if (dataRecord.brew_fermenter_sg < 1.020) - return; - if ((dataRecord.primary_end_sg > 0.990) && (dataRecord.primary_end_sg < dataRecord.brew_fermenter_sg)) { - primary_svg = Round(calc_svg(dataRecord.brew_fermenter_sg, dataRecord.primary_end_sg), 1); - $('#primary_svg').val(primary_svg); - if ((dataRecord.secondary_end_sg > 0.990) && (dataRecord.secondary_end_sg < dataRecord.brew_fermenter_sg)) { - secondary_svg = Round(calc_svg(dataRecord.brew_fermenter_sg, dataRecord.secondary_end_sg), 1); - $('#secondary_svg').val(secondary_svg); - if ((dataRecord.fg > 0.990) && (dataRecord.fg < dataRecord.brew_fermenter_sg)) { - final_svg = Round(calc_svg(dataRecord.brew_fermenter_sg, dataRecord.fg), 1); - $('#final_svg').val(final_svg); - ABV = Round(abvol(dataRecord.brew_fermenter_sg, dataRecord.fg), 2); - $('#final_abv').val(ABV); - } - } - } - } - - function ResCO2(T) { - var F = T * 1.8 + 32; - return Round(3.0378 - 0.050062 * F + 0.00026555 * F * F, 6); - } - - function CarbCO2toS(CO2, T, SFactor) { - //var sugar = SFactor * (CO2 - ResCO2(CO2, T)) / 0.286; - var sugar = Round(SFactor * (CO2 - ResCO2(T)) * 4.014094, 6); - if (sugar < 0) - sugar = 0; - return Round(sugar, 3); - } - - function GetPressure(CO2, T1, T2) { - var P, V = CO2 - ResCO2(T1); - V = CO2; // TODO: temp only total pressure, testing - if (V < 0) - return 0; - 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, 2); // atm to bar - console.log("GetPressure(" + CO2 + ", " + T1 + ", " + T2 + ") V:" + V + " Bar: " + P + " ignored ResCO2: " + ResCO2(T1)); - return P; - } - - function CarbCO2ToPressure(CO2, T) { - return (CO2 - (-0.000005594056 * Math.pow(T, 4) + 0.000144357886 * Math.pow(T, 3) + - 0.000362999168 * T * T - 0.064872987645 * T + 1.641145175049)) / - (0.00000498031 * Math.pow(T, 4) - 0.00024358267 * Math.pow(T, 3) + 0.00385867329 * T * T - 0.05671206825 * T + 1.53801423376); - } - - function calcCarbonation() { - - var TSec, ABV, bvol, balc, babv, mvol, malc, tvol, talc, i, row, SFactor, pvol, pabv, Pressure, kabv; - - console.log('calcCarbonation()'); - - TSec = dataRecord.secondary_temp; - if (TSec < 1) - TSec = dataRecord.primary_end_temp; - if (TSec < 1) - TSec = 18; - - if (dataRecord.fg == 0.000) - ABV = abvol(dataRecord.brew_fermenter_sg, parseFloat($('#est_fg').jqxNumberInput('decimal'))); - else - ABV = abvol(dataRecord.brew_fermenter_sg, dataRecord.fg); - - /* Calculate new volume and alcohol. */ - bvol = dataRecord.package_volume - (ABV * dataRecord.package_volume) / 100; - balc = dataRecord.package_volume - bvol; - mvol = dataRecord.package_infuse_amount - (dataRecord.package_infuse_abv * dataRecord.package_infuse_amount) / 100; - malc = dataRecord.package_infuse_amount - mvol; - talc = balc + malc; - tvol = bvol + mvol; - ABV = Round(talc / (tvol + talc) * 100, 2); - dataRecord.package_abv = ABV; - $('#package_abv').val(ABV); - - //console.log("calcCarbonation() TSec:"+TSec+" ABV:"+ABV); - if (!(rows = $('#fermentableGrid').jqxGrid('getrows'))) { - return; - } - - // Bottles - dataRecord.bottle_priming_amount = 0; - dataRecord.bottle_priming_total = 0; - for (i = 0; i < rows.length; i++) { - row = rows[i]; - if (row.f_added == 4) { - SFactor = 1 / ((row.f_yield / 100) * (1 - row.f_moisture / 100)); - dataRecord.bottle_priming_amount = CarbCO2toS(dataRecord.bottle_carbonation, TSec, SFactor); - dataRecord.bottle_priming_total = Round(dataRecord.bottle_amount * dataRecord.bottle_priming_amount, 2); - $('#fermentableGrid').jqxGrid('setcellvalue', i, 'f_amount', dataRecord.bottle_priming_total / 1000); - } - } - $('#bottle_priming_amount').val(Round(dataRecord.bottle_priming_amount, 1)); - $('#bottle_priming_total').val(dataRecord.bottle_priming_total); - pabv = ABV + dataRecord.bottle_priming_amount * 0.47 / 7.907; - pvol = dataRecord.bottle_amount - (pabv * dataRecord.bottle_amount) / 100; - talc = dataRecord.bottle_amount - pvol; - tvol = pvol + dataRecord.bottle_priming_water; - babv = Round(talc / (tvol + talc) * 100, 2); - //console.log("bottle pabv:"+pabv+" pvol:"+pvol+" wvol:"+dataRecord.bottle_priming_water+" tvol:"+tvol+" talc:"+talc+" abv:"+babv); - $('#bottle_abv').val(babv); - $('#bottle_pressure').val(GetPressure(dataRecord.bottle_carbonation, TSec, dataRecord.bottle_carbonation_temp)); - - // Kegs - Pressure = CarbCO2ToPressure(dataRecord.keg_carbonation, dataRecord.keg_carbonation_temp); - if (Pressure < 0) - Pressure = 0; - dataRecord.keg_pressure = Pressure; - $('#keg_pressure').val(Round(Pressure, 1)); - - dataRecord.keg_priming_amount = 0; - dataRecord.keg_priming_total = 0; - if (!dataRecord.keg_forced_carb) { - for (i = 0; i < rows.length; i++) { - row = rows[i]; - if (row.f_added == 5) { - SFactor = 1 / ((row.f_yield / 100) * (1 - row.f_moisture / 100)); - dataRecord.keg_priming_amount = CarbCO2toS(dataRecord.keg_carbonation, TSec, SFactor); - dataRecord.keg_priming_total = Round(dataRecord.keg_amount * dataRecord.keg_priming_amount, 2); - $('#fermentableGrid').jqxGrid('setcellvalue', i, 'f_amount', dataRecord.keg_priming_total / 1000); - } - } - $('#keg_priming_amount').val(Round(dataRecord.keg_priming_amount, 1)); - $('#keg_priming_total').val(dataRecord.keg_priming_total); - pabv = ABV + dataRecord.keg_priming_amount * 0.47 / 7.907; - pvol = dataRecord.keg_amount - (pabv * dataRecord.keg_amount) / 100; - talc = dataRecord.keg_amount - pvol; - tvol = pvol + dataRecord.keg_priming_water; - kabv = Round(talc / (tvol + talc) * 100, 2); - //console.log("kegs pabv:"+pabv+" pvol:"+pvol+" wvol:"+dataRecord.keg_priming_water+" tvol:"+tvol+" talc:"+talc+" abv:"+kabv); - $('#keg_abv').val(kabv); - } else { - $('#keg_priming_amount').val(0); - $('#keg_priming_total').val(0); - $('#keg_abv').val(ABV); - } - } - - function calcStage() { - /* - * Set stage and enable or disable parts of the screens. - */ - $('#stage').val(StageData[dataRecord.stage].nl); - - /* - * Enable or disable parts of the screens. - */ - $('#jqxTabs').jqxTabs((dataRecord.stage < 1) ? 'disableAt':'enableAt', 8); // Brewday tab - $('#jqxTabs').jqxTabs((dataRecord.stage > 2) ? 'enableAt':'disableAt', 9); // Fermentation tab - $('#jqxTabs').jqxTabs((dataRecord.stage < 9) ? 'disableAt':'enableAt', 11); // Tasting tab - } - - - // initialize the input fields. - // Tab 1, Algemeen - $('#name').jqxTooltip({ content: 'De naam voor dit product.' }); - $('#code').jqxTooltip({ content: 'Product code nummer.' }); - $('#birth').jqxTooltip({ content: 'De ontwerp datum van dit product.' }); - $('#stage').jqxTooltip({ content: 'De productie fase van dit product.' }); - $('#divide_batch').jqxTooltip({ content: 'Het aantal extra gesplitste batches.' }); - $('#divide_type').jqxTooltip({ content: 'Het splitsing moment in het productie proces.' }); - $('#notes').jqxTooltip({ content: 'De uitgebreide opmerkingen over dit product.' }); - $('#type').jqxTooltip({ content: 'Het brouw type van dit recept.' }); - $('#efficiency').jqxTooltip({ content: 'Het rendement van maischen en koken.' }); - $('#batch_size').jqxTooltip({ content: 'Het volume van het gekoelde wort na het koken.' }); - $('#boil_time').jqxTooltip({ content: 'De kooktijd in minuten.' }); - $('#boil_size').jqxTooltip({ content: 'Het volume van het wort voor het koken.' }); - $('#st_guide').jqxTooltip({ content: 'De bierstijl gids voor dit recept.'}); - $('#st_name').jqxTooltip({ content: 'De bierstijl naam voor dit recept.'}); - $('#st_letter').jqxTooltip({ content: 'De bierstijl letter voor dit recept.'}); - $('#st_letter').jqxInput({ theme: theme, width: 90, height: 23 }); - $('#st_type').jqxTooltip({ content: 'Het bierstijl type.'}); - $('#st_category').jqxTooltip({ content: 'De Amerikaanse bierstijl categorie.'}); - $('#st_category_number').jqxTooltip({ content: 'De Amerikaanse bierstijl categorie sub nummer.'}); - $('#est_og').jqxTooltip({ content: 'Het begin SG wat je wilt bereiken. De moutstort wordt automatisch herberekend.' }); - $('#st_og_min').jqxTooltip({ content: 'Het minimum begin SG voor deze bierstijl.'}); - $('#st_og_max').jqxTooltip({ content: 'Het maximum begin SG voor deze bierstijl.'}); - $('#est_fg').jqxTooltip({ content: 'Het verwachte eind SG. Dit wordt automatisch berekend.' }); - $('#st_fg_min').jqxTooltip({ content: 'Het minimum eind SG voor deze bierstijl.'}); - $('#st_fg_max').jqxTooltip({ content: 'Het maximum eind SG voor deze bierstijl.'}); - $('#est_abv').jqxTooltip({ content: 'Alcohol volume %. Dit wordt automatisch berekend.' }); - $('#st_abv_min').jqxTooltip({ content: 'Het minimum alcohol volume % voor deze bierstijl.'}); - $('#st_abv_max').jqxTooltip({ content: 'Het maximum alcohol volume % voor deze bierstijl.'}); - $('#est_color').jqxTooltip({ content: 'De kleur in EBC. Dit wordt automatisch berekend.' }); - $('#st_color_min').jqxTooltip({ content: 'De minimum kleur voor deze bierstijl.'}); - $('#st_color_max').jqxTooltip({ content: 'De maximum kleur voor deze bierstijl.'}); - $('#est_ibu').jqxTooltip({ content: 'De bitterheid in IBU. Dit wordt automatisch berekend.' }); - $('#st_ibu_min').jqxTooltip({ content: 'De minimum bitterheid voor deze bierstijl.'}); - $('#st_ibu_max').jqxTooltip({ content: 'De maximum bitterheid voor deze bierstijl.'}); - $('#kcal').jqxTooltip({ content: 'Energie-inhoud in kcal/liter.' }); - $('#est_carb').jqxTooltip({ content: 'Koolzuur volume. Dit wordt automatisch berekend.' }); - $('#st_carb_min').jqxTooltip({ content: 'Het minimum koolzuur volume voor deze bierstijl.'}); - $('#st_carb_max').jqxTooltip({ content: 'Het maximum koolzuur volume voor deze bierstijl.'}); - - $('#name').jqxInput({ theme: theme, width: 640, height: 23 }); - $('#code, #stage').jqxInput({ theme: theme, width: 100, height: 23 }); - $('#locked').jqxCheckBox({ theme: theme, width: 120, height: 23, disabled: true }); - $('#birth,#divide_batch,#divide_type').jqxInput({ theme: theme, width: 120, height: 23 }); - $('#notes').jqxInput({ theme: theme, width: 960, height: 100 }); - $('#type').jqxInput({ theme: theme, width: 180, height: 23 }); - $('#efficiency').jqxNumberInput(Show1dec); - $('#batch_size').jqxNumberInput(Show1dec); - $('#boil_time').jqxNumberInput(Show0dec); - $('#boil_size').jqxNumberInput(Show2dec); - $('#st_guide,#st_name,#st_type,#st_category').jqxInput({ theme: theme, width: 250, height: 23 }); - $('#est_og').jqxNumberInput(Show3dec); - $('#est_fg').jqxNumberInput(Show3dec); - $('#st_og_min,#st_og_max,#st_fg_min,#st_fg_max').jqxNumberInput({ inputMode: 'simple', theme: theme, width: 50, height: 23, decimalDigits: 3, readOnly: true }); - $('#est_ibu,#est_color').jqxNumberInput(Show0dec); - $('#color_method').jqxInput({ theme: theme, width: 180, height: 23 }); - $('#st_color_min,#st_color_max,#st_category_number,#st_ibu_min,#st_ibu_max,#kcal').jqxNumberInput(Smal0dec); - $('#ibu_method').jqxInput({ theme: theme, width: 180, height: 23 }); - $('#est_abv,#st_abv_min,#st_abv_max,#est_carb,#st_carb_min,#st_carb_max').jqxNumberInput(Smal1dec); - - // Tab 2, Equipment - $('#eq_name').jqxTooltip({ content: 'De naam van deze brouw apparatuur.' }); - $('#eq_boil_size').jqxTooltip({ content: 'Normaal kook volume in liters' }); - $('#eq_batch_size').jqxTooltip({ content: 'Berekende batch grootte in liters aan het eind van de kook.' }); - $('#eq_tun_volume').jqxTooltip({ content: 'Maisch ketel volume.' }); - $('#eq_top_up_water').jqxTooltip({ content: 'Extra water in het gistvat.' }); - $('#eq_trub_chiller_loss').jqxTooltip({ content: 'Standaard verlies bij het overbrengen naar het gistvat.' }); - $('#eq_evap_rate').jqxTooltip({ content: 'Verdamping in liters per uur.' }); - $('#eq_boil_time').jqxTooltip({ content: 'Normale kooktijd in minuten, 0 voor no-boil recepten.' }); - $('#eq_top_up_kettle').jqxTooltip({ content: 'Extra water toevoegen tijdens de kook.' }); - $('#eq_hop_utilization').jqxTooltip({ content: '100% voor kleine installaties, hoger voor grote brouwerijen.' }); - $('#eq_notes').jqxTooltip({ content: 'Opmerkingen over deze apparatuur.' }); - $('#eq_lauter_volume').jqxTooltip({ content: 'Filterkuip volume.' }); - $('#eq_lauter_deadspace').jqxTooltip({ content: 'Filterkuip verlies in liters.' }); - $('#eq_kettle_volume').jqxTooltip({ content: 'Kook ketel volume in liters.' }); - $('#eq_mash_volume').jqxTooltip({ content: 'Maisch water voor de eerste stap.' }); - $('#eq_mash_max').jqxTooltip({ content: 'De maximale moutstort in Kg.' }); - $('#eq_efficiency').jqxTooltip({ content: 'Gemiddeld brouwzaal rendement.' }); - - $('#eq_name').jqxInput({ theme: theme, width: 250, height: 23 }); - $('#eq_evap_rate').jqxNumberInput(Show2dec); - $('#eq_boil_time,#eq_hop_utilization').jqxNumberInput(Show0dec); - $('#eq_notes').jqxInput({ theme: theme, width: 960, height: 200 }); - $('#eq_boil_size,#eq_batch_size,#eq_tun_volume,#eq_top_up_water,#eq_trub_chiller_loss,#eq_top_up_kettle').jqxNumberInput(Show1dec); - $('#eq_lauter_volume,#eq_lauter_deadspace,#eq_kettle_volume,#eq_mash_volume,#eq_mash_max,#eq_efficiency').jqxNumberInput(Show1dec); - - // Tab 3, Fermentables - $('#est_color2').jqxTooltip({ content: 'De kleur in EBC. Dit wordt automatisch berekend.' }); - $('#est_og2').jqxTooltip({ content: 'Het geschatte begin SG van dit product.' }); - $('#mash_kg').jqxTooltip({ content: 'Het gewicht van alle mouten in de maisch.' }); - - $('#est_color2').jqxNumberInput(Show0dec); - $('#est_og2,#mash_kg').jqxNumberInput(Show3dec); - - $('#perc_malts').jqxProgressBar({ - width: 300, height: 23, theme: theme, showText: true, max: 120, animationDuration: 0, - colorRanges: [{ stop: 90, color: '#008C00' },{ stop: 100, color: '#EB7331' },{ stop: 120, color: '#FF0000' }], - renderText: function(text) { return (Math.round(parseInt(text) * 1.2)) + '%'; } - }); - $('#perc_sugars').jqxProgressBar({ - width: 300, height: 23, theme: theme, showText: true, max: 50, animationDuration: 0, - colorRanges: [{ stop: 20, color: '#008C00' },{ stop: 50, color: '#FF0000' }], - renderText: function(text) { return (Math.round(parseInt(text) * 5) / 10) + '%'; } - }); - $('#perc_cara').jqxProgressBar({ - width: 300, height: 23, theme: theme, showText: true, max: 50, animationDuration: 0, - colorRanges: [{ stop: 25, color: '#008C00' },{ stop: 50, color: '#FF0000' }], - renderText: function(text) { return (Math.round(parseInt(text) * 5) / 10) + '%'; } - }); - $('#ferm_lintner').jqxProgressBar({ - width: 300, height: 23, theme: theme, showText: true, max: 200, animationDuration: 0, - colorRanges: [{ stop: 30, color: '#FF0000' },{ stop: 40, color: '#EB7331' },{ stop: 200, color: '#008C00' }], - renderText: function(text) { return (parseInt(text) * 2) + ' lintner'; } - }); - - // Tab 4, Hops - $('#est_ibu2').jqxTooltip({ content: 'De bitterheid in IBU. Dit wordt automatisch berekend.' }); - $('#est_ibu2').jqxNumberInput(Smal0dec); - $('#hop_flavour').jqxProgressBar({ - width: 300, height: 23, theme: theme, showText: true, animationDuration: 0, - colorRanges: [ - { stop: 20, color: '#004D00' }, - { stop: 40, color: '#008C00' }, - { stop: 60, color: '#00BF00' }, - { stop: 80, color: '#00FF00' }, - { stop: 100, color: '#80FF80' } - ], - renderText: function(text) { - var val = parseInt(text); - if (val < 20) - return 'Weinig'; - else if (val < 40) - return 'Matig'; - else if (val < 60) - return 'Redelijk'; - else if (val < 80) - return 'Veel'; - else - return 'Zeer veel'; - } - }); - $('#hop_aroma').jqxProgressBar({ - width: 300, height: 23, theme: theme, showText: true, animationDuration: 0, - colorRanges: [ - { stop: 20, color: '#004D00' }, - { stop: 40, color: '#008C00' }, - { stop: 60, color: '#00BF00' }, - { stop: 80, color: '#00FF00' }, - { stop: 100, color: '#80FF80' } - ], - renderText: function(text) { - var val = parseInt(text); - if (val < 20) - return 'Weinig'; - else if (val < 40) - return 'Matig'; - else if (val < 60) - return 'Redelijk'; - else if (val < 80) - return 'Veel'; - else - return 'Zeer veel'; - } - }); - - // Tab 5, Miscs - - // Tab 6, Yeasts - $('#est_fg2').jqxTooltip({ content: 'Het verwachte eind SG. Dit wordt automatisch berekend.' }); - $('#est_abv2').jqxTooltip({ content: 'Verwacht alcohol volume %. Dit wordt automatisch berekend.' }); - $('#yeast_grams').jqxTooltip({ content: 'De gewenste totale hoeveelheid droge gist voor dit bier.' }); - $('#yeast_gr_hl').jqxTooltip({ content: 'De werkelijke hoeveelheid gist per hectoliter.' }); - $('#yeast_cells').jqxTooltip({ content: 'Het aantal miljard beschikbare gistcellen zonder eventuele starter.' }); - $('#need_cells').jqxTooltip({ content: 'Het aantal miljard nodige cellen is afhankelijk van het begin SG, biertype en volume.' }); - $('#plato_cells').jqxTooltip({ content: 'De berekende pitchrate in miljard cellen per ml per graad Plato.' }); - $('#yeast_prod_date').jqxTooltip({ content: 'Bij korrelgisten is meestal "best voor" datum op het zakje gedrukt.<br>Gebruik die datum maar dan twee jaar eerder als productie datum.<br>Bij White Labs is de productie datum vier maanden voor de "Best by" datum die geprint op het buisje.<br>Bij Wyeast is dit de "manufacture date" die op het pak geprint is.<br>Voor schuine buis, slurry, opkweek en gedroogd is dit de datum dat je de gist geoogst hebt.' }); - $('#yeast_pitchrate').jqxTooltip({ content: 'De gewenste pitchrate in miljard cellen per ml per graad Plato voor de vergisting van dit bier.' }); - - $('#est_fg2,#plato_cells').jqxNumberInput(Show3dec); - $('#est_fg2').jqxNumberInput({ width: 70 }); - $('#est_abv2').jqxNumberInput(Show2dec); - $('#est_abv2').jqxNumberInput({ width: 70, symbol: '%', symbolPosition: 'right' }); - $('#yeast_grams').jqxNumberInput(Show1dec); - $('#yeast_gr_hl').jqxNumberInput(Show1dec); - $('#yeast_cells,#need_cells').jqxNumberInput(Show1dec); - $('#yeast_prod_date').jqxDateTimeInput(Dateopts); - $('#yeast_prod_date').jqxDateTimeInput({ disabled: true }); - $('#yeast_pitchrate').jqxNumberInput(Show3dec); - for (i = 1; i < 5; i++) { - $('#prop' + i + '_volume').jqxTooltip({ content: 'Het volume van deze starter stap.' }); - $('#prop' + i + '_irate').jqxTooltip({ content: 'Voor de beste gistgroei, houd de injectie factor tussen de 25 en 100 miljoen cellen per ml.' }); - $('#prop' + i + '_ncells').jqxTooltip({ content: 'Het aantal miljard nieuwe gistcellen in deze stap.' }); - $('#prop' + i + '_tcells').jqxTooltip({ content: 'Het totaal aantal miljard gistcellen na deze stap.' }); - $('#prop' + i + '_growf').jqxTooltip({ content: 'De groeifactor, minstens 1. Ongeroerde starters komen meestal niet boven de 3.' }); - - $('#prop' + i + '_type').jqxInput({ theme: theme, width: 120, height: 23 }); - $('#prop' + i + '_volume').jqxNumberInput(Show3dec); - $('#prop' + i + '_irate,#prop' + i + '_ncells,#prop' + i + '_tcells').jqxNumberInput(Show1dec); - $('#prop' + i + '_growf').jqxNumberInput(Show2dec); - $('#prop' + i + '_type,#prop' + i + '_volume,#prop' + i + '_irate,#prop' + i + '_ncells,#prop' + i + '_tcells,#prop' + i + '_growf').hide(); - } - $('#starter_type').jqxInput({ theme: theme, width: 120, height: 23 }); - $('#starter_sg').jqxTooltip({ content: 'Het ideale starter SG moet tussen de 1.030 en 1.040 zijn. Optimaal is 1.037.' }); - $('#starter_sg').jqxNumberInput(Show3dec); - $('#starter_viability').jqxTooltip({ content: 'De gist conditie.' }); - $('#starter_viability').jqxNumberInput(Show0dec); - - // Tab 7, Mashing - $('#mash_name').jqxTooltip({ content: 'De omschrijving van dit maisch profiel.' }); - $('#mash_name').jqxInput({ theme: theme, width: 320, height: 23 }); - $('#est_mashvol').jqxTooltip({ content: 'Het totale volume van het maishwater en de mout in de maish pan.' }); - $('#est_mashvol').jqxNumberInput(Show1dec); - $('#est_mashtime').jqxTooltip({ content: 'De totale tijdsduur van het maischen.' }); - $('#est_mashtime').jqxInput({ theme: theme, width: 70, height: 23 }); - - // Tab 8, Water - $('#tgt_bu').jqxNumberInput(Show2wat); - $('#tgt_so4_cl,#got_so4_cl').jqxNumberInput(Show1wat); - $('#preboil_ph').jqxNumberInput(Show2wat); - - // Water source 1 - $('#w1_name').jqxInput({ theme: theme, width: 200, height: 23 }); - $('#w1_button').jqxRadioButton({ theme: theme, width: 50, height: 23, disabled: true }); - $('#w1_amount,#w1_calcium,#w1_magnesium,#w1_sodium,#w1_bicarbonate,#w1_total_alkalinity,#w1_chloride,#w1_sulfate').jqxNumberInput(Show1wat); - $('#w1_ph').jqxNumberInput(Show2wat); - $('#w1_hardness').jqxNumberInput(Show1wat); - $('#w1_ra').jqxNumberInput(Show1wat); - // Water source 2 - $('#w2_name').jqxInput({ theme: theme, width: 200, height: 23 }); - $('#w2_button').jqxRadioButton({ theme: theme, width: 50, height: 23, disabled: true }); - $('#w2_amount').jqxNumberInput(Show1wat); - $('#w2_calcium,#w2_magnesium,#w2_sodium,#w2_bicarbonate,#w2_total_alkalinity,#w2_chloride,#w2_sulfate').jqxNumberInput(Show1wat); - $('#w2_ph').jqxNumberInput(Show2wat); - $('#w2_hardness').jqxNumberInput(Show1wat); - $('#w2_ra').jqxNumberInput(Show1wat); - // Water mixed - $('#wg_button').jqxRadioButton({ theme: theme, width: 50, height: 23, disabled: true }); - $('#wg_amount,#wg_calcium,#wg_magnesium,#wg_sodium,#wg_bicarbonate,#wg_total_alkalinity,#wg_chloride,#wg_sulfate').jqxNumberInput(Show1wat); - $('#wg_ph').jqxNumberInput(Show2wat); - $('#wg_hardness').jqxNumberInput(Show1wat); - $('#wg_ra').jqxNumberInput(Show1wat); - // Water treated - $('#wb_calcium').jqxTooltip({ content: 'De ideale hoeveelheid Calcium is tussen 40 en 150.'}); - $('#wb_calcium').jqxNumberInput(Show1wat); - $('#wb_magnesium').jqxTooltip({ content: 'De ideale hoeveelheid Magnesium is tussen 5 en 40.'}); - $('#wb_magnesium').jqxNumberInput(Show1wat); - $('#wb_sodium').jqxTooltip({ content: 'De ideale hoeveelheid Natrium is lager dan 150.'}); - $('#wb_sodium').jqxNumberInput(Show1wat); - $('#wb_chloride').jqxTooltip({ content: 'De ideale hoeveelheid Chloride is tussen 50 en 150. Samen met Sulfaat minder dan 500.'}); - $('#wb_chloride').jqxNumberInput(Show1wat); - $('#wb_sulfate').jqxTooltip({ content: 'De ideale hoeveelheid Sulfaat is tussen 50 en 400. Samen met Chloride minder dan 500.'}); - $('#wb_sulfate').jqxNumberInput(Show1wat); - $('#wb_bicarbonate').jqxTooltip({ content: '0 tot 50 lichte bieren, 50 tot 150 amber bieren, 150 tot 250 donkere bieren.'}); - $('#wb_bicarbonate').jqxNumberInput(Show1wat); - $('#wb_ph').jqxNumberInput(Show2wat); - $('#wb_hardness').jqxNumberInput(Show1wat); - $('#wb_ra').jqxNumberInput(Show1wat); - // Sparge water - $('#sw_amount').jqxNumberInput(Show1wat); - $('#sw_calcium').jqxNumberInput(Show1wat); - $('#sw_magnesium').jqxNumberInput(Show1wat); - $('#sw_sodium').jqxNumberInput(Show1wat); - $('#sw_bicarbonate').jqxNumberInput(Show1wat); - $('#sw_total_alkalinity').jqxNumberInput(Show1wat); - $('#sw_chloride').jqxNumberInput(Show1wat); - $('#sw_sulfate').jqxNumberInput(Show1wat); - $('#sw_ph').jqxNumberInput(Show2wat); - $('#sw_hardness').jqxNumberInput(Show1wat); - $('#sw_ra').jqxNumberInput(Show1wat); - - // Water agents - $('#wa_cacl2').jqxTooltip({ content: 'Voor het maken van een ander waterprofiel. Voegt calcium en chloride toe. Voor het verbeteren van zoetere bieren.' }); - $('#wa_cacl2').jqxNumberInput(Show2wat); - $('#ss_cacl2').jqxNumberInput(Show2wat); - - $('#wa_caso4').jqxTooltip({ - content: 'Gips. Voor het maken van een ander waterprofiel. Voegt calcium en sulfaat toe. Voor het verbeteren van bittere bieren.' - }); - $('#wa_caso4').jqxNumberInput(Show2wat); - $('#ss_caso4').jqxNumberInput(Show2wat); - - $('#wa_mgso4').jqxTooltip({ content: 'Epsom zout. Voor het maken van een ander waterprofiel. Voegt magnesium en sulfaat toe. Gebruik spaarzaam!' }); - $('#wa_mgso4').jqxNumberInput(Show2wat); - $('#ss_mgso4').jqxNumberInput(Show2wat); - - $('#wa_nacl').jqxTooltip({ - content: 'Keukenzout. Voor het maken van een ander waterprofiel. Voegt natrium en chloride toe. ' + - 'Voor het accentueren van zoetheid. Bij hoge dosering wordt het bier ziltig.' - }); - $('#wa_nacl').jqxNumberInput(Show2wat); - $('#ss_nacl').jqxNumberInput(Show2wat); - - $('#wa_mgcl2').jqxTooltip({ content: 'Magnesiumchloride'}); - $('#wa_mgcl2').jqxNumberInput(Show2wat); - $('#ss_mgcl2').jqxNumberInput(Show2wat); - - $('#wa_nahco3').jqxTooltip({ content: 'Baksoda'}); - $('#wa_caco3').jqxTooltip({ content: 'Kalk'}); - $('#wa_nahco3,#wa_caco3').jqxNumberInput(Show2wat); - - $('#mash_ph').jqxTooltip({ content: 'Maisch pH tussen 5.2 en 5.6. Gebruik 5.2 voor lichte en 5.5 voor donkere bieren.'}); - $('#mash_ph').jqxNumberInput(Show2dec); - - $('#calc_acid').jqxCheckBox({ theme: theme, width: 120, height: 23, disabled: true }); - - $('#wa_acid_name').jqxInput({ theme: theme, width: 130, height: 23 }); - $('#wa_acid').jqxNumberInput(Show2dec); - $('#wa_acid').jqxNumberInput({ symbol: ' ml', symbolPosition: 'right' }); - $('#wa_acid_perc').jqxNumberInput(Show0dec); - $('#wa_acid_perc').jqxNumberInput({ symbol: '%', symbolPosition: 'right' }); - - // Sparge water - $('#sparge_ph').jqxNumberInput(Show2dec); - $('#sparge_acid_amount').jqxNumberInput(Show2dec); - $('#sparge_acid_amount').jqxNumberInput({ symbol: ' ml', symbolPosition: 'right' }); - $('#sparge_acid_type').jqxInput({ theme: theme, width: 130, height: 23 }); - $('#sparge_acid_perc').jqxNumberInput(Show0dec); - $('#sparge_acid_perc').jqxNumberInput({ symbol: '%', symbolPosition: 'right' }); - - // Tab 9, Brewday - $('#brew_date_start').jqxTooltip({ content: 'Brouw datum en tijd. Voor planning laat de tijd op 00:00:00 staan.' }); - $('#brew_date_end').jqxTooltip({ content: 'End datum en tijd van de brouw. Leeg laten als er nog niet gebrouwen is.' }); - $('#brew_mash_ph').jqxTooltip({ content: 'De gemeten pH tijdens het maischen eventueel na correctie.' }); - $('#est_mash_ph').jqxTooltip({ content: 'De gewenste pH tijdens het maischen.' }); - $('#brew_preboil_ph').jqxTooltip({ content: 'De gemeten pH in de kookketel na het spoelen en voor de kook.' }); - $('#brew_aboil_ph').jqxTooltip({ content: 'De gemeten pH na het koken.' }); - $('#brew_mash_sg').jqxTooltip({ content: 'Het bereikte SG na het maischen.' }); - $('#est_mash_sg').jqxTooltip({ content: 'Het berekende verwachte SG na het maischen.' }); - $('#brew_preboil_sg').jqxTooltip({ content: 'Het gemeten SG in de kookketel na het spoelen en voor het koken.' }); - $('#est_pre_sg').jqxTooltip({ content: 'Het berekende SG in de kookketel na het spoelen en voor het koken.' }); - $('#brew_aboil_sg').jqxTooltip({ content: 'Het gemeten SG in de kookketel na het koken.' }); - $('#est_og3').jqxTooltip({ content: 'Het gewenste SG in de kookketel na het koken zonder eventuele suikers die tijdens de vergisting toegevoegd worden.' }); - $('#brew_mash_efficiency').jqxTooltip({ content: 'Het behaalde maisch rendement.' }); - $('#brew_preboil_volume').jqxTooltip({ content: 'Het gemeten volume van het wort voor het koken.' }); - $('#est_pre_vol').jqxTooltip({ content: 'Het berekende volume van het wort voor het koken.' }); - $('#brew_aboil_volume').jqxTooltip({ content: 'Het gemeten volume van het wort na het koken.' }); - $('#est_a_vol').jqxTooltip({ content: 'Het gewenste volume na het koken.' }); - $('#brew_preboil_efficiency').jqxTooltip({ content: 'Het berekende rendement voor het koken.' }); - $('#brew_aboil_efficiency').jqxTooltip({ content: 'Het bereikte rendement na het koken.' }); - $('#brew_sparge_temperature').jqxTooltip({ content: 'De spoelwater temperatuur, in te stellen in de Water tab.' }); - $('#brew_sparge_volume').jqxTooltip({ content: 'Het spoelwater voorraad volume, in te stellen in de Water tab.' }); - $('#brew_date_start,#brew_date_end').jqxDateTimeInput(DateTimeopts); - $('#brew_date_start,#brew_date_end').jqxDateTimeInput({ disabled: true }); - $('#est_mash_ph').jqxNumberInput(Show2wat); - $('#brew_mash_ph,#brew_preboil_ph,#brew_aboil_ph').jqxNumberInput(Show2dec); - $('#brew_mash_sg,#brew_preboil_sg,#brew_aboil_sg').jqxNumberInput(Show3dec); - $('#est_mash_sg,#est_pre_sg,#est_og3').jqxNumberInput(Show3wat); - $('#brew_mash_efficiency').jqxNumberInput(Show1dec); - $('#brew_preboil_volume,#brew_aboil_volume').jqxNumberInput(Show1dec); - $('#ketel_volume').jqxNumberInput(Show1dec); - $('#ketel_cm').jqxNumberInput(Show1dec); - $('#est_pre_vol,#est_a_vol').jqxNumberInput(Show1wat); - $('#brew_preboil_efficiency,#brew_aboil_efficiency,#brew_sparge_temperature,#brew_sparge_volume,#brew_sparge_est').jqxNumberInput(Show1dec); - $('#brew_cooling_to').jqxNumberInput(Show1dec); - $('#brew_sparge_ph').jqxNumberInput(Show2dec); - $('#brew_cooling_method').jqxInput({ theme: theme, width: 180, height: 23 }); - $('#brew_cooling_time,#brew_whirlpool9,#brew_whirlpool7,#brew_whirlpool6,#brew_whirlpool2,#brew_aeration_time,#brew_aeration_speed').jqxNumberInput(Show0dec); - $('#brew_aeration_type').jqxInput({ theme: theme, width: 180, height: 23 }); - $('#brew_fermenter_volume').jqxNumberInput(Show1dec); - $('#brew_fermenter_sg').jqxNumberInput(Show3dec); - $('#brew_fermenter_extrawater,#brew_fermenter_tcloss').jqxNumberInput(Show1dec); - $('#brew_fermenter_ibu,#brew_fermenter_color').jqxNumberInput(Show0dec); - - // Tab 10, Fermentation - $('#brew_fermenter_sg2').jqxTooltip({ content: 'Het behaalde SG in het gistvat, overgenomen van de brouwdag.' }); - $('#primary_start_temp').jqxTooltip({ content: 'De begintemperatuur van de hoofdvergisting.' }); - $('#primary_max_temp').jqxTooltip({ content: 'De hoogst bereikte piek temperatuur tijdens de hoofgvergisting.' }); - $('#primary_end_temp').jqxTooltip({ content: 'De eind temperatuur van de hoofdvergisting.' }); - $('#primary_end_sg').jqxTooltip({ content: 'Het gemeten SG aan het eind van de hoofdvergisting.' }); - $('#primary_svg').jqxTooltip({ content: 'De schijnbare vergisting graad behaald na de hoofdgisting.' }); - $('#primary_end_date').jqxTooltip({ content: 'De eind datum van de hoofdvergisting en eventueel overhevelen.' }); - $('#secondary_end_sg').jqxTooltip({ content: 'Het gemeten SG aan het eind van de navergisting.' }); - $('#secondary_svg').jqxTooltip({ content: 'De schijnbare vergisting graad behaald na de nagisting.' }); - $('#secondary_end_date').jqxTooltip({ content: 'De eind datum van de navergisting en het begin van het lageren.' }); - $('#est_fg3').jqxTooltip({ content: 'Het verwachte eind SG. Dit wordt automatisch berekend.' }); - - $('#primary_end_sg,#secondary_end_sg').jqxNumberInput(Show3dec); - $('#primary_end_date,#secondary_end_date').jqxDateTimeInput(Dateopts); - $('#primary_end_date,#secondary_end_date').jqxDateTimeInput({ disabled: true }); - $('#primary_start_temp,#primary_max_temp,#primary_end_temp,#secondary_temp,#tertiary_temp').jqxNumberInput(Show1dec); - $('#fg').jqxNumberInput(Show3dec); - $('#brew_fermenter_sg2,#est_fg3').jqxNumberInput(Show3dec); - $('#final_abv').jqxNumberInput(Show2dec); - $('#primary_svg,#secondary_svg,#final_svg').jqxNumberInput(Show1dec); - $('#FLog').jqxButton({ template: 'info', width: '150px', theme: theme }); - $('#FLog').click(function() { - // Open log in a new tab. - window.open('log_fermentation.php?code=' + dataRecord.code + '&name=' + dataRecord.name); - }); - $('#ILog').jqxButton({ template: 'info', width: '150px', theme: theme }); - $('#ILog').click(function() { - // Open log in a new tab. - window.open('log_ispindel.php?code=' + dataRecord.code + '&name=' + dataRecord.name); - }); - - // Tab 11, Packaging - // TODO: high gravity packaging, extra water and recalc abv, color and ibu. - $('#package_date').jqxTooltip({ content: 'De verpakkings datum van dit bier.' }); - $('#package_volume').jqxTooltip({ content: 'Het beschikbare volume om te bottelen of op fust te zetten.' }); - $('#package_infuse_amount').jqxTooltip({ content: 'De hoeveelheid water of drank extra toe te voegen.' }); - $('#package_infuse_abv').jqxTooltip({ content: 'De hoeveelheid alcohol in de drank, of 0.0 als het water is.' }); - $('#package_infuse_notes').jqxTooltip({ content: 'Omschrijving van de extra toevoeging.' }); - $('#package_abv').jqxTooltip({ content: 'De uiteindelijke hoeveelheid alcohol volume %.' }); - $('#package_ph').jqxTooltip({ content: 'De gemeten pH vlak voor het verpakken.' }); - $('#st_carb_min2').jqxTooltip({ content: 'Het minimum aanbevolen koolzuur volume voor deze bierstijl.'}); - $('#st_carb_max2').jqxTooltip({ content: 'Het maximum aamnevolen koolzuur volume voor deze bierstijl.'}); - $('#bottle_amount').jqxTooltip({ content: 'De totale hoeveelheid te bottelen bier.' }); - $('#keg_amount').jqxTooltip({ content: 'De totale hoeveelheid op fust te zetten bier.' }); - $('#bottle_carbonation').jqxTooltip({ content: 'Het gewenste CO2 volume in de flessen.' }); - $('#keg_carbonation').jqxTooltip({ content: 'Het gewenste CO2 volume door de suiker in de fusten.' }); - $('#bottle_priming_water,#keg_priming_water').jqxTooltip({ content: 'De hoeveelheid water om de suiker op te lossen.' }); - $('#bottle_pressure').jqxTooltip({ content: 'De maximaal te verwachten druk tijdens het hergisten.' }); - $('#package_date').jqxDateTimeInput(Dateopts); - $('#package_date').jqxDateTimeInput({ disabled: true }); - $('#package_infuse_amount').jqxNumberInput(Show3dec); - $('#package_infuse_notes').jqxInput({ theme: theme, width: 640, height: 23 }); - $('#package_abv').jqxNumberInput(Show2dec); - $('#package_ph').jqxNumberInput(Show2dec); - $('#st_carb_min2,#st_carb_max2').jqxNumberInput(Smal1dec); - $('#package_volume,#package_infuse_abv,#bottle_amount,#keg_amount').jqxNumberInput(Show1dec); - $('#bottle_carbonation,#keg_carbonation').jqxNumberInput(Show2dec); - $('#bottle_priming_sugar').jqxInput({ theme: theme, width: 200, height: 23 }); - $('#keg_priming_sugar').jqxInput({ theme: theme, width: 200, height: 23 }); - $('#bottle_priming_water,#keg_priming_water').jqxNumberInput(Show3dec); - $('#keg_forced_carb').jqxCheckBox({ theme: theme, width: 120, height: 23, disabled: true }); - $('#bottle_priming_amount,#keg_priming_amount,#bottle_priming_total,#bottle_pressure,#keg_priming_total,#keg_pressure').jqxNumberInput(Show1dec); - $('#bottle_abv,#keg_abv').jqxNumberInput(Show2dec); - $('#bottle_carbonation_temp,#keg_carbonation_temp').jqxNumberInput(Show1dec); - $('#CLog').jqxButton({ template: 'info', width: '150px', theme: theme }); - $('#CLog').click(function() { - // Open log in a new tab. - window.open('log_co2pressure.php?code=' + dataRecord.code + '&name=' + dataRecord.name); - }); - - // Tab 12, Tasting - $('#taste_date').jqxTooltip({ content: 'De proef datum van dit bier.' }); - $('#taste_date').jqxDateTimeInput(Dateopts); - $('#taste_date').jqxDateTimeInput({ disabled: true }); - $('#taste_rate').jqxTooltip({ content: 'Het cijfer voor dit bier van 1 tot 10.' }); - $('#taste_rate').jqxNumberInput(Show1dec); - $('#taste_color').jqxTooltip({ content: 'De kleur van het bier.' }); - $('#taste_transparency').jqxTooltip({ content: 'De helderheid van het bier.' }); - $('#taste_head').jqxTooltip({ content: 'Het schuim op het bier.' }); - $('#taste_color,#taste_transparency,#taste_head').jqxInput({ theme: theme, width: 320, height: 23 }); - $('#taste_aroma').jqxTooltip({ content: 'Het aroma van het bier.' }); - $('#taste_taste').jqxTooltip({ content: 'De smaak van het bier.' }); - $('#taste_aftertaste').jqxTooltip({ content: 'De nasmaak van het bier.' }); - $('#taste_mouthfeel').jqxTooltip({ content: 'Het mondgevoelvan het bier.' }); - $('#taste_aroma,#taste_taste,#taste_aftertaste,#taste_mouthfeel').jqxInput({ theme: theme, width: 960, height: 23 }); - $('#taste_notes').jqxTooltip({ content: 'Het oordeel en opmerkingen over dit bier.' }); - $('#taste_notes').jqxInput({ theme: theme, width: 960, height: 100 }); - - $('#jqxTabs').jqxTabs({ - theme: theme, - width: 1280, - height: 660, - autoHeight: false, - position: 'top' - }); - - // Buttons below - $('#Terug').jqxButton({ template: 'primary', width: '80px', theme: theme }); - $('#Terug').bind('click', function() { - window.location.href = my_return; - }); -}); -
--- a/www/js/prod_inprod.js Sat Aug 06 22:02:42 2022 +0200 +++ b/www/js/prod_inprod.js Sat Aug 06 22:10:28 2022 +0200 @@ -80,10 +80,10 @@ } }, { text: '', datafield: 'Edit', width: 100, align: 'center', columntype: 'button', cellsrenderer: function() { - return 'Wijzig'; + return 'Bekijk'; }, buttonclick: function(row) { var datarecord = dataAdapter.records[row]; - window.location.href = 'prod_edit.php?record=' + datarecord.record + '&select=inprod&return=prod_inprod.php'; + window.location.href = 'prod_view.php?record=' + datarecord.record + '&select=inprod&return=prod_inprod.php'; } } ],
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/www/js/prod_view.js Sat Aug 06 22:10:28 2022 +0200 @@ -0,0 +1,3306 @@ +/***************************************************************************** + * Copyright (C) 2018-2022 + * + * Michiel Broek <mbroek at mbse dot eu> + * + * This file is part of BMS + * + * This 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 2, or (at your option) any + * later version. + * + * BrewCloud 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 ThermFerm; see the file COPYING. If not, write to the Free + * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + *****************************************************************************/ + + +function block_fermentable(stage, added) { + if (stage > 5 && added < 4) // After fermentation and added before packaging + return true; + if (stage > 3 && added < 3) // After primary and added before sec/tert + return true; + if (stage > 2 && added < 2) // After boil and added during mash or boil + return true; + return false; +} + +function block_hop(stage, useat) +{ + if (stage > 2 && useat < 5) + return true; + return false; +} + +function block_misc(stage, use_use) { + if (stage > 5 && use_use < 5) + return true; + if (stage > 3 && use_use < 4) + return true; + if (stage > 2 && use_use < 3) + return true; + if (stage > 1 && use_use < 1) + return true; + return false; +} + +function block_yeast(stage, use) { + if (stage > 3 && use < 1) + return true; + if (stage > 4 && use < 2) + return true; + if (stage > 5 && use < 3) + return true; + if (stage > 6 && use < 4) + return true; + return false; +} + + +$(document).ready(function() { + + var i, + to_100 = false, // Fermentables adjust to 100% + preboil_sg = 0, + aboil_sg = 0, + est_mash_sg = 0, + psugar = 0, // Percentage real sugars + pcara = 0, // Percentage cara/crystal malts + svg = 77, // Default attenuation + mashkg = 0, // Malt in mash weight + initcells = 0, // Initial yeast cell count + + ok_fermentables = 1, // Fermentables are in stock + ok_hops = 1, // Hops are in stock + ok_miscs = 1, // Miscs are in stock + ok_yeasts = 1, // Yeasts are in stock + ok_waters = 1, // Waters are in stock + + data_loaded = 0; + error_count = 0; + k_cm = 0; + k_vol = 0; + k_what = 0; + + hop_flavour = 0, + hop_aroma = 0, + mash_infuse = 0, + last_acid = '', + + MMCa = 40.048, + MMMg = 24.305, + MMNa = 22.98976928, + MMCl = 35.453, + MMSO4 = 96.0626, + MMHCO3 = 61.01684, + MMCaSO4 = 172.171, + MMCaCl2 = 147.015, + MMCaCO3 = 100.087, + MMMgCl2 = 95.211, /* Since 27-06-2021 */ + MMMgSO4 = 246.475, + MMNaHCO3 = 84.007, + MMNa2CO3 = 105.996, + MMNaCl = 58.443, + MMCaOH2 = 74.06268, + + fermentableRow = 0, + fermentableData = {}, + fermentableInit = 1, + hopRow = 0, + hopData = {}, + miscRow = 0, + miscData = {}, + yeastRow = 0, + yeastData = {}, + mashRow = 0, + mashData = {}, + Ka1 = 0.0000004445, + Ka2 = 0.0000000000468, + dataRecord = {}, + url = 'includes/db_product.php', + MaltVolume = 0.87, // l/kg 0.688 volgens internetbronnen, gemeten 0.874 l/kg, na enige tijd maischen 0,715 l/kg (A3 Otten). + SpecificHeatWater = 1.0, + SpecificHeatMalt = 0.399, //cal/g.°C + SlakingHeat = 10.318, //cal/g.°C + + // Prepare the data + source = { + datatype: 'json', + cache: false, + async: true, + datafields: [ + // From prod_main + { name: 'record', type: 'number' }, + { name: 'uuid', type: 'string' }, + { name: 'name', type: 'string' }, + { name: 'code', type: 'string' }, + { name: 'birth', type: 'string' }, + { name: 'stage', type: 'int' }, + { name: 'notes', type: 'string' }, + { name: 'log_brew', type: 'int' }, + { name: 'log_fermentation', type: 'int' }, + { name: 'log_ispindel', type: 'int' }, + { name: 'log_co2pressure', type: 'int' }, + { name: 'inventory_reduced', type: 'int' }, + { name: 'locked', type: 'int' }, + { name: 'eq_name', type: 'string' }, + { name: 'eq_boil_size', type: 'float' }, + { name: 'eq_batch_size', type: 'float' }, + { name: 'eq_tun_volume', type: 'float' }, + { name: 'eq_tun_weight', type: 'float' }, + { name: 'eq_tun_specific_heat', type: 'float' }, + { name: 'eq_tun_material', type: 'int' }, + { name: 'eq_tun_height', type: 'float' }, + { name: 'eq_top_up_water', type: 'float' }, + { name: 'eq_trub_chiller_loss', type: 'float' }, + { name: 'eq_evap_rate', type: 'float' }, + { name: 'eq_boil_time', type: 'float' }, + { name: 'eq_calc_boil_volume', type: 'int' }, + { name: 'eq_top_up_kettle', type: 'float' }, + { name: 'eq_hop_utilization', type: 'float' }, + { name: 'eq_notes', type: 'string' }, + { name: 'eq_lauter_volume', type: 'float' }, + { name: 'eq_lauter_height', type: 'float' }, + { name: 'eq_lauter_deadspace', type: 'float' }, + { name: 'eq_kettle_volume', type: 'float' }, + { name: 'eq_kettle_height', type: 'float' }, + { name: 'eq_mash_volume', type: 'float' }, + { name: 'eq_mash_max', type: 'float' }, + { name: 'eq_efficiency', type: 'float' }, + { name: 'brew_date_start', type: 'string' }, + { name: 'brew_mash_ph', type: 'float' }, + { name: 'brew_mash_sg', type: 'float' }, + { name: 'brew_mash_efficiency', type: 'float' }, + { name: 'brew_sparge_est', type: 'float' }, + { name: 'brew_sparge_ph', type: 'float' }, + { name: 'brew_preboil_volume', type: 'float' }, + { name: 'brew_preboil_sg', type: 'float' }, + { name: 'brew_preboil_ph', type: 'float' }, + { name: 'brew_preboil_efficiency', type: 'float' }, + { name: 'brew_aboil_volume', type: 'float' }, + { name: 'brew_aboil_sg', type: 'float' }, + { name: 'brew_aboil_ph', type: 'float' }, + { name: 'brew_aboil_efficiency', type: 'float' }, + { name: 'brew_cooling_method', type: 'int' }, + { name: 'brew_cooling_time', type: 'float' }, + { name: 'brew_cooling_to', type: 'float' }, + { name: 'brew_whirlpool9', type: 'float' }, + { name: 'brew_whirlpool7', type: 'float' }, + { name: 'brew_whirlpool6', type: 'float' }, + { name: 'brew_whirlpool2', type: 'float' }, + { name: 'brew_fermenter_volume', type: 'float' }, + { name: 'brew_fermenter_extrawater', type: 'float' }, + { name: 'brew_fermenter_tcloss', type: 'float' }, + { name: 'brew_aeration_time', type: 'float' }, + { name: 'brew_aeration_speed', type: 'float' }, + { name: 'brew_aeration_type', type: 'int' }, + { name: 'brew_fermenter_sg', type: 'float' }, + { name: 'brew_fermenter_ibu', type: 'float' }, + { name: 'brew_fermenter_color', type: 'float' }, + { name: 'brew_date_end', type: 'string' }, + { name: 'og', type: 'float' }, + { name: 'fg', type: 'float' }, + { name: 'primary_start_temp', type: 'float' }, + { name: 'primary_max_temp', type: 'float' }, + { name: 'primary_end_temp', type: 'float' }, + { name: 'primary_end_sg', type: 'float' }, + { name: 'primary_end_date', type: 'string' }, + { name: 'secondary_temp', type: 'float' }, + { name: 'secondary_end_sg', type: 'float' }, + { name: 'secondary_end_date', type: 'string' }, + { name: 'tertiary_temp', type: 'float' }, + { name: 'package_date', type: 'string' }, + { name: 'package_volume', type: 'float' }, + { name: 'package_infuse_amount', type: 'float' }, + { name: 'package_infuse_abv', type: 'float' }, + { name: 'package_infuse_notes', type: 'string' }, + { name: 'package_abv', type: 'float' }, + { name: 'package_ph', type: 'float' }, + { name: 'bottle_amount', type: 'float' }, + { name: 'bottle_carbonation', type: 'float' }, + { name: 'bottle_priming_water', type: 'float' }, + { name: 'bottle_priming_amount', type: 'float' }, + { name: 'bottle_carbonation_temp', type: 'float' }, + { name: 'keg_amount', type: 'float' }, + { name: 'keg_carbonation', type: 'float' }, + { name: 'keg_priming_water', type: 'float' }, + { name: 'keg_priming_amount', type: 'float' }, + { name: 'keg_carbonation_temp', type: 'float' }, + { name: 'keg_forced_carb', type: 'int' }, + { name: 'keg_pressure', type: 'float' }, + { name: 'taste_notes', type: 'string' }, + { name: 'taste_rate', type: 'float' }, + { name: 'taste_date', type: 'string' }, + { name: 'taste_color', type: 'string' }, + { name: 'taste_transparency', type: 'string' }, + { name: 'taste_head', type: 'string' }, + { name: 'taste_aroma', type: 'string' }, + { name: 'taste_taste', type: 'string' }, + { name: 'taste_mouthfeel', type: 'string' }, + { name: 'taste_aftertaste', type: 'string' }, + { name: 'st_name', type: 'string' }, + { name: 'st_letter', type: 'string' }, + { name: 'st_guide', type: 'string' }, + { name: 'st_category', type: 'string' }, + { name: 'st_category_number', type: 'int' }, + { name: 'st_type', type: 'int' }, + { name: 'st_og_min', type: 'float' }, + { name: 'st_og_max', type: 'float' }, + { name: 'st_fg_min', type: 'float' }, + { name: 'st_fg_max', type: 'float' }, + { name: 'st_ibu_min', type: 'float' }, + { name: 'st_ibu_max', type: 'float' }, + { name: 'st_color_min', type: 'float' }, + { name: 'st_color_max', type: 'float' }, + { name: 'st_carb_min', type: 'float' }, + { name: 'st_carb_max', type: 'float' }, + { name: 'st_abv_min', type: 'float' }, + { name: 'st_abv_max', type: 'float' }, + { name: 'type', type: 'int' }, + { name: 'batch_size', type: 'float' }, + { name: 'boil_size', type: 'float' }, + { name: 'boil_time', type: 'float' }, + { name: 'efficiency', type: 'float' }, + { name: 'est_og', type: 'float' }, + { name: 'est_og3', type: 'float' }, + { name: 'est_fg', type: 'float' }, + { name: 'est_abv', type: 'float' }, + { name: 'est_color', type: 'float' }, + { name: 'color_method', type: 'int' }, + { name: 'est_ibu', type: 'float' }, + { name: 'ibu_method', type: 'int' }, + { name: 'est_carb', type: 'float' }, + { name: 'sparge_temp', type: 'float' }, + { name: 'sparge_ph', type: 'float' }, + { name: 'sparge_volume', type: 'float' }, + { name: 'sparge_source', type: 'int' }, + { name: 'sparge_acid_type', type: 'int' }, + { name: 'sparge_acid_perc', type: 'float' }, + { name: 'sparge_acid_amount', type: 'float' }, + { name: 'mash_ph', type: 'float' }, + { name: 'mash_name', type: 'string' }, + { name: 'calc_acid', type: 'int' }, + { name: 'w1_name', type: 'string' }, + { name: 'w1_amount', type: 'float' }, + { name: 'w1_calcium', type: 'float' }, + { name: 'w1_sulfate', type: 'float' }, + { name: 'w1_chloride', type: 'float' }, + { name: 'w1_sodium', type: 'float' }, + { name: 'w1_magnesium', type: 'float' }, + { name: 'w1_total_alkalinity', type: 'float' }, + { name: 'w1_ph', type: 'float' }, + { name: 'w1_cost', type: 'float' }, + { name: 'w2_name', type: 'string' }, + { name: 'w2_amount', type: 'float' }, + { name: 'w2_calcium', type: 'float' }, + { name: 'w2_sulfate', type: 'float' }, + { name: 'w2_chloride', type: 'float' }, + { name: 'w2_sodium', type: 'float' }, + { name: 'w2_magnesium', type: 'float' }, + { name: 'w2_total_alkalinity', type: 'float' }, + { name: 'w2_ph', type: 'float' }, + { name: 'w2_cost', type: 'float' }, + { name: 'wg_amount', type: 'float' }, + { name: 'wg_calcium', type: 'float' }, + { name: 'wg_sulfate', type: 'float' }, + { name: 'wg_chloride', type: 'float' }, + { name: 'wg_sodium', type: 'float' }, + { name: 'wg_magnesium', type: 'float' }, + { name: 'wg_total_alkalinity', type: 'float' }, + { name: 'wg_ph', type: 'float' }, + { name: 'wb_calcium', type: 'float' }, + { name: 'wb_sulfate', type: 'float' }, + { name: 'wb_chloride', type: 'float' }, + { name: 'wb_sodium', type: 'float' }, + { name: 'wb_magnesium', type: 'float' }, + { name: 'wb_total_alkalinity', type: 'float' }, + { name: 'wb_ph', type: 'float' }, + { name: 'wa_acid_name', type: 'int' }, + { name: 'wa_acid_perc', type: 'int' }, + { name: 'wa_base_name', type: 'int' }, + { name: 'starter_enable', type: 'int' }, + { name: 'starter_type', type: 'int' }, + { name: 'starter_sg', type: 'float' }, + { name: 'starter_viability', type: 'int' }, + { name: 'yeast_prod_date', type: 'string' }, + { name: 'yeast_pitchrate', type: 'float' }, + { name: 'prop1_type', type: 'int' }, + { name: 'prop1_volume', type: 'float' }, + { name: 'prop2_type', type: 'int' }, + { name: 'prop2_volume', type: 'float' }, + { name: 'prop3_type', type: 'int' }, + { name: 'prop3_volume', type: 'float' }, + { name: 'prop4_type', type: 'int' }, + { name: 'prop4_volume', type: 'float' }, + { name: 'divide_type', type: 'int' }, + { name: 'divide_size', type: 'float' }, + { name: 'divide_factor', type: 'float' }, + { name: 'divide_parts', type: 'int' }, + { name: 'divide_part', type: 'int' }, + { name: 'fermentables', type: 'string' }, + { name: 'hops', type: 'string' }, + { name: 'miscs', type: 'string' }, + { name: 'yeasts', type: 'string' }, + { name: 'mashs', type: 'string' } + ], + id: 'record', + url: url + '?record=' + my_record + }, + + // Load data and select one record. + dataAdapter = new $.jqx.dataAdapter(source, { + loadComplete: function() { + dataRecord = dataAdapter.records[0]; + // Hidden record uuid + $('#name').val(dataRecord.name); + $('#code').val(dataRecord.code); + $('#birth').val(dataRecord.birth); + $('#stage').val(StageData[dataRecord.stage].nl); + $('#notes').val(dataRecord.notes); + $('#locked').val(dataRecord.locked); + $('#eq_name').val(dataRecord.eq_name); + $('#eq_notes').val(dataRecord.eq_notes); + $('#eq_boil_size').val(dataRecord.eq_boil_size); + $('#eq_batch_size').val(dataRecord.eq_batch_size); + $('#eq_tun_volume').val(dataRecord.eq_tun_volume); + $('#eq_top_up_water').val(dataRecord.eq_top_up_water); + $('#eq_trub_chiller_loss').val(dataRecord.eq_trub_chiller_loss); + $('#eq_evap_rate').val(dataRecord.eq_evap_rate); + $('#eq_boil_time').val(dataRecord.eq_boil_time); + $('#eq_top_up_kettle').val(dataRecord.eq_top_up_kettle); + $('#eq_hop_utilization').val(dataRecord.eq_hop_utilization); + $('#eq_lauter_volume').val(dataRecord.eq_lauter_volume); + $('#eq_lauter_deadspace').val(dataRecord.eq_lauter_deadspace); + $('#eq_kettle_volume').val(dataRecord.eq_kettle_volume); + $('#eq_mash_volume').val(dataRecord.eq_mash_volume); + $('#eq_mash_max').val(dataRecord.eq_mash_max); + $('#eq_efficiency').val(dataRecord.eq_efficiency); + // Brewdate + $('#brew_date_start').val(dataRecord.brew_date_start); + $('#brew_mash_ph').val(dataRecord.brew_mash_ph); + $('#brew_mash_sg').val(dataRecord.brew_mash_sg); + $('#brew_mash_efficiency').val(dataRecord.brew_mash_efficiency); + // Header Spoelen en filteren + $('#brew_sparge_temperature').val(dataRecord.sparge_temp); + $('#brew_sparge_volume').val(dataRecord.sparge_volume); + $('#brew_sparge_est').val(dataRecord.brew_sparge_est); + $('#brew_sparge_ph').val(dataRecord.brew_sparge_ph); + // Header Beluchten + $('#brew_aeration_type').val(AerationTypeData[dataRecord.brew_aeration_type].nl); + $('#brew_aeration_time').val(dataRecord.brew_aeration_time); + $('#brew_aeration_speed').val(dataRecord.brew_aeration_speed); + + $('#brew_preboil_ph').val(dataRecord.brew_preboil_ph); + $('#brew_preboil_sg').val(dataRecord.brew_preboil_sg); + $('#brew_preboil_volume').val(dataRecord.brew_preboil_volume); + $('#brew_preboil_efficiency').val(dataRecord.brew_preboil_efficiency); + // Header Koelen en whirlpoolen + $('#brew_whirlpool9').val(dataRecord.brew_whirlpool9); + $('#brew_whirlpool7').val(dataRecord.brew_whirlpool7); + $('#brew_whirlpool6').val(dataRecord.brew_whirlpool6); + $('#brew_whirlpool2').val(dataRecord.brew_whirlpool2); + // Header Naar gistvat + $('#brew_fermenter_volume').val(dataRecord.brew_fermenter_volume); + $('#brew_fermenter_sg').val(dataRecord.brew_fermenter_sg); + $('#brew_fermenter_sg2').val(dataRecord.brew_fermenter_sg); + $('#brew_fermenter_ibu').val(dataRecord.brew_fermenter_ibu); + $('#brew_fermenter_color').val(dataRecord.brew_fermenter_color); + $('#brew_fermenter_extrawater').val(dataRecord.brew_fermenter_extrawater); + $('#brew_fermenter_tcloss').val(dataRecord.brew_fermenter_tcloss); + + $('#brew_aboil_ph').val(dataRecord.brew_aboil_ph); + $('#brew_aboil_sg').val(dataRecord.brew_aboil_sg); + $('#brew_aboil_volume').val(dataRecord.brew_aboil_volume); + $('#brew_aboil_efficiency').val(dataRecord.brew_aboil_efficiency); + // Header Koelen en whirlpoolen + $('#brew_cooling_to').val(dataRecord.brew_cooling_to); + $('#brew_cooling_method').val(CoolingTypeData[dataRecord.brew_cooling_method].nl); + $('#brew_cooling_time').val(dataRecord.brew_cooling_time); + // Niks + $('#brew_date_end').val(dataRecord.brew_date_end); + $('#og').val(dataRecord.og); + $('#fg').val(dataRecord.fg); + $('#primary_start_temp').val(dataRecord.primary_start_temp); + $('#primary_max_temp').val(dataRecord.primary_max_temp); + $('#primary_end_temp').val(dataRecord.primary_end_temp); + $('#primary_end_sg').val(dataRecord.primary_end_sg); + $('#primary_end_date').val(dataRecord.primary_end_date); + $('#secondary_temp').val(dataRecord.secondary_temp); + $('#secondary_end_sg').val(dataRecord.secondary_end_sg); + $('#secondary_end_date').val(dataRecord.secondary_end_date); + $('#tertiary_temp').val(dataRecord.tertiary_temp); + $('#package_date').val(dataRecord.package_date); + $('#package_volume').val(dataRecord.package_volume); + $('#package_infuse_amount').val(dataRecord.package_infuse_amount); + $('#package_infuse_abv').val(dataRecord.package_infuse_abv); + $('#package_infuse_notes').val(dataRecord.package_infuse_notes); + $('#package_abv').val(dataRecord.package_abv); + $('#package_ph').val(dataRecord.package_ph); + $('#bottle_amount').val(dataRecord.bottle_amount); + $('#bottle_carbonation').val(dataRecord.bottle_carbonation); + $('#bottle_priming_water').val(dataRecord.bottle_priming_water); + $('#bottle_priming_amount').val(dataRecord.bottle_priming_amount); + $('#bottle_carbonation_temp').val(dataRecord.bottle_carbonation_temp); + $('#keg_amount').val(dataRecord.keg_amount); + $('#keg_carbonation').val(dataRecord.keg_carbonation); + $('#keg_priming_water').val(dataRecord.keg_priming_water); + $('#keg_priming_amount').val(dataRecord.keg_priming_amount); + $('#keg_carbonation_temp').val(dataRecord.keg_carbonation_temp); + $('#keg_forced_carb').val(dataRecord.keg_forced_carb); + $('#keg_pressure').val(dataRecord.keg_pressure); + $('#taste_notes').val(dataRecord.taste_notes); + $('#taste_rate').val(dataRecord.taste_rate); + $('#taste_date').val(dataRecord.taste_date); + $('#taste_color').val(dataRecord.taste_color); + $('#taste_transparency').val(dataRecord.taste_transparency); + $('#taste_head').val(dataRecord.taste_head); + $('#taste_aroma').val(dataRecord.taste_aroma); + $('#taste_taste').val(dataRecord.taste_taste); + $('#taste_mouthfeel').val(dataRecord.taste_mouthfeel); + $('#taste_aftertaste').val(dataRecord.taste_aftertaste); + + // Recipe + $('#st_name').val(dataRecord.st_name); + $('#st_letter').val(dataRecord.st_letter); + $('#st_guide').val(dataRecord.st_guide); + $('#st_category').val(dataRecord.st_category); + $('#st_category_number').val(dataRecord.st_category_number); + $('#st_type').val(StyleTypeData[dataRecord.st_type].nl); + $('#st_og_min').val(dataRecord.st_og_min); + $('#st_og_max').val(dataRecord.st_og_max); + $('#st_fg_min').val(dataRecord.st_fg_min); + $('#st_fg_max').val(dataRecord.st_fg_max); + $('#st_abv_min').val(dataRecord.st_abv_min); + $('#st_abv_max').val(dataRecord.st_abv_max); + $('#st_color_min').val(dataRecord.st_color_min); + $('#st_color_max').val(dataRecord.st_color_max); + $('#st_ibu_min').val(dataRecord.st_ibu_min); + $('#st_ibu_max').val(dataRecord.st_ibu_max); + $('#st_carb_min').val(dataRecord.st_carb_min); + $('#st_carb_min2').val(dataRecord.st_carb_min); + $('#st_carb_max').val(dataRecord.st_carb_max); + $('#st_carb_max2').val(dataRecord.st_carb_max); + $('#type').val(RecipeTypeData[dataRecord.type].nl); + $('#batch_size').val(dataRecord.batch_size); + $('#est_a_vol').val(dataRecord.batch_size * 1.04); + $('#boil_size').val(dataRecord.boil_size); + $('#est_pre_vol').val(dataRecord.boil_size * 1.04); + $('#boil_time').val(dataRecord.boil_time); + $('#efficiency').val(dataRecord.efficiency); + $('#est_og').val(dataRecord.est_og); + $('#est_og2').val(dataRecord.est_og); + $('#est_og3').val(dataRecord.est_og3); + $('#est_fg').val(dataRecord.est_fg); + $('#est_fg2').val(dataRecord.est_fg); + $('#est_fg3').val(dataRecord.est_fg); + $('#est_color').val(dataRecord.est_color); + $('#est_color2').val(dataRecord.est_color); + $('#est_abv').val(dataRecord.est_abv); + $('#color_method').val(ColorMethodData[dataRecord.color_method].nl); + $('#est_ibu').val(dataRecord.est_ibu); + $('#est_ibu2').val(dataRecord.est_ibu); + $('#ibu_method').val(IBUmethodData[dataRecord.ibu_method].nl); + $('#est_carb').val(dataRecord.est_carb); + $('#mash_name').val(dataRecord.mash_name); + $('#mash_ph').val(dataRecord.mash_ph); + $('#sparge_temp').val(dataRecord.sparge_temp); + $('#sparge_ph').val(dataRecord.sparge_ph); + $('#sparge_volume').val(dataRecord.sparge_volume); + $('#sparge_source').val(dataRecord.sparge_source); + $('#sparge_acid_type').val(AcidTypeData[dataRecord.sparge_acid_type].nl); + $('#sparge_acid_perc').val(dataRecord.sparge_acid_perc); + $('#sparge_acid_amount').val(dataRecord.sparge_acid_amount * 1000); + $('#calc_acid').val(dataRecord.calc_acid); + $('#w1_name').val(dataRecord.w1_name); + $('#w1_amount').val(dataRecord.w1_amount); + $('#w1_calcium').val(dataRecord.w1_calcium); + $('#w1_sulfate').val(dataRecord.w1_sulfate); + $('#w1_chloride').val(dataRecord.w1_chloride); + $('#w1_sodium').val(dataRecord.w1_sodium); + $('#w1_magnesium').val(dataRecord.w1_magnesium); + $('#w1_total_alkalinity').val(dataRecord.w1_total_alkalinity); + $('#w1_bicarbonate').val(dataRecord.w1_total_alkalinity * 1.22); + $('#w1_ph').val(dataRecord.w1_ph); + $('#w1_cost').val(dataRecord.w1_cost); + $('#w2_name').val(dataRecord.w2_name); + $('#w2_amount').val(dataRecord.w2_amount); + $('#w2_calcium').val(dataRecord.w2_calcium); + $('#w2_sulfate').val(dataRecord.w2_sulfate); + $('#w2_chloride').val(dataRecord.w2_chloride); + $('#w2_sodium').val(dataRecord.w2_sodium); + $('#w2_magnesium').val(dataRecord.w2_magnesium); + $('#w2_total_alkalinity').val(dataRecord.w2_total_alkalinity); + $('#w2_bicarbonate').val(dataRecord.w2_total_alkalinity * 1.22); + $('#w2_ph').val(dataRecord.w2_ph); + $('#w2_cost').val(dataRecord.w2_cost); + $('#wg_amount').val(dataRecord.wg_amount); + $('#wg_calcium').val(dataRecord.wg_calcium); + $('#wg_sulfate').val(dataRecord.wg_sulfate); + $('#wg_chloride').val(dataRecord.wg_chloride); + $('#wg_sodium').val(dataRecord.wg_sodium); + $('#wg_magnesium').val(dataRecord.wg_magnesium); + $('#wg_total_alkalinity').val(dataRecord.wg_total_alkalinity); + $('#wg_ph').val(dataRecord.wg_ph); + $('#wb_calcium').val(dataRecord.wb_calcium); + $('#wb_sulfate').val(dataRecord.wb_sulfate); + $('#wb_chloride').val(dataRecord.wb_chloride); + $('#wb_sodium').val(dataRecord.wb_sodium); + $('#wb_magnesium').val(dataRecord.wb_magnesium); + $('#wb_total_alkalinity').val(dataRecord.wb_total_alkalinity); + $('#wb_ph').val(dataRecord.wb_ph); + $('#wa_acid_name').val(dataRecord.wa_acid_name); + $('#wa_acid_perc').val(dataRecord.wa_acid_perc); + $('#starter_type').val(StarterTypeData[dataRecord.starter_type].nl); + $('#starter_sg').val(dataRecord.starter_sg); + $('#starter_viability').val(dataRecord.starter_viability); + $('#yeast_prod_date').val(dataRecord.yeast_prod_date); + $('#yeast_pitchrate').val(dataRecord.yeast_pitchrate); + $('#prop1_type').val(StarterTypeData[dataRecord.prop1_type].nl); + $('#prop1_volume').val(dataRecord.prop1_volume); + $('#prop2_type').val(StarterTypeData[dataRecord.prop2_type].nl); + $('#prop2_volume').val(dataRecord.prop2_volume); + $('#prop3_type').val(StarterTypeData[dataRecord.prop3_type].nl); + $('#prop3_volume').val(dataRecord.prop3_volume); + $('#prop4_type').val(StarterTypeData[dataRecord.prop4_type].nl); + $('#prop4_volume').val(dataRecord.prop4_volume); + $('#divide_type').val(SplitData[dataRecord.divide_type].nl); + if (dataRecord.divide_type > 0) + $('#divide_batch').val((dataRecord.divide_part + 1) + ' van ' + (dataRecord.divide_parts + 1)); + else + $('#divide_batch').val('n.v.t.'); + // hidden divide_size + // hidden divide_factor + // hidden divide_parts + // hidden divide_part + editFermentable(dataRecord); + editHop(dataRecord); + editMisc(dataRecord); + editYeast(dataRecord); + editMash(dataRecord); + calcStage(); + $('#jqxTabs').jqxTabs('select', 2); + data_loaded = 1; + }, + loadError: function(jqXHR, status, error) { + console.log('main data load error: ' + status + ' ' + error); + } + }); + + // Inline fermentables editor + var editFermentable = function(data) { + var fermentableSource = { + localdata: data.fermentables, + datafields: [ + { name: 'f_name', type: 'string' }, + { name: 'f_origin', type: 'string' }, + { name: 'f_supplier', type: 'string' }, + { name: 'f_amount', type: 'float' }, + { name: 'f_cost', type: 'float' }, + { name: 'f_type', type: 'int' }, + { name: 'f_yield', type: 'float' }, + { name: 'f_color', type: 'float' }, + { name: 'f_coarse_fine_diff', type: 'float' }, + { name: 'f_moisture', type: 'float' }, + { name: 'f_diastatic_power', type: 'float' }, + { name: 'f_protein', type: 'float' }, + { name: 'f_max_in_batch', type: 'float' }, + { name: 'f_graintype', type: 'int' }, + { name: 'f_added', type: 'int' }, + { name: 'f_dissolved_protein', type: 'float' }, + { name: 'f_recommend_mash', type: 'int' }, + { name: 'f_add_after_boil', type: 'int' }, + { name: 'f_adjust_to_total_100', type: 'int' }, + { name: 'f_percentage', type: 'float' }, + { name: 'f_di_ph', type: 'float' }, + { name: 'f_acid_to_ph_57', type: 'float' }, + { name: 'f_inventory', type: 'float' }, + { name: 'f_avail', type: 'int' } + ], + }, + fermentableAdapter = new $.jqx.dataAdapter(fermentableSource); + + $('#fermentableGrid').jqxGrid({ + width: 1240, + height: 470, + source: fermentableAdapter, + theme: theme, + editable: false, + ready: function() { calcFermentables(); $('#jqxTabs').jqxTabs('next'); }, + columns: [ + { text: 'Vergistbaar ingrediënt', datafield: 'f_name' }, + { text: 'Leverancier', datafield: 'f_supplier', width: 180 }, + { text: 'Kleur', datafield: 'f_color', width: 90, align: 'right', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + return '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(value, 'f0') + ' EBC</span>'; + } + }, + { text: 'Type', width: 100, datafield: 'f_type', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + return '<span style="margin: 3px; margin-top: 6px; float: left;">' + FermentableTypeData[value].nl + '</span>'; + } + }, + { text: 'Moment', width: 110, datafield: 'f_added', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + return '<span style="margin: 3px; margin-top: 6px; float: left;">' + AddedData[value].nl + '</span>'; + } + }, + { text: 'Maxinbatch', datafield: 'f_max_in_batch', hidden: true }, + { text: 'Opbrengst', datafield: 'f_yield', width: 90, align: 'right', cellsalign: 'right', cellsformat: 'p1' }, + { text: 'Gewicht Kg', datafield: 'f_amount', width: 110, align: 'right', cellsalign: 'right', cellsformat: 'f3' }, + { text: 'Voorraad Kg', datafield: 'f_inventory', width: 110, align: 'right', + cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) { + var color = (value < rowdata.f_amount) ? '#ff4040':'#ffffff'; + if (block_fermentable(dataRecord.inventory_reduced, rowdata.f_added) == false) { + return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + fermentableAdapter.formatNumber(value, 'f3') + '</span>'; + } else { + return '<span></span>'; + } + } + }, + { text: 'Procent', datafield: 'f_percentage', width: 90, align: 'right', + cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) { + if (rowdata.f_added >= 4) + return '<span></span>'; + var color = (value > rowdata.f_max_in_batch) ? '#ff4040':'#ffffff'; + return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + fermentableAdapter.formatNumber(value, 'p1') + '</span>'; + } + }, + { text: '100%', datafield: 'f_adjust_to_total_100', width: 70, align: 'center', cellsalign: 'center', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + if (value == 0) + return '<span></span>'; + return '<span><img style="float:left; margin-left:25px; margin-top:4px;" src="images/dialog-ok-apply.png"></span>'; + } + } + ] + }); + }; + + // Inline hops editor + var editHop = function(data) { + var hopSource = { + localdata: data.hops, + datafields: [ + { name: 'h_name', type: 'string' }, + { name: 'h_origin', type: 'string' }, + { name: 'h_amount', type: 'float' }, + { name: 'h_cost', type: 'float' }, + { name: 'h_type', type: 'int' }, + { name: 'h_form', type: 'int' }, + { name: 'h_useat', type: 'int' }, + { name: 'h_time', type: 'int' }, + { name: 'h_alpha', type: 'float' }, + { name: 'h_beta', type: 'float' }, + { name: 'h_hsi', type: 'float' }, + { name: 'h_humulene', type: 'float' }, + { name: 'h_caryophyllene', type: 'float' }, + { name: 'h_cohumulone', type: 'float' }, + { name: 'h_myrcene', type: 'float' }, + { name: 'h_total_oil', type: 'float' }, + { name: 'h_inventory', type: 'float' }, + { name: 'h_avail', type: 'int' }, + { name: 'h_utilisation', type: 'float' }, + { name: 'h_bu_factor', type: 'float' } + ], + }, + hopAdapter = new $.jqx.dataAdapter(hopSource); + + $('#hopGrid').jqxGrid({ + width: 1240, + height: 560, + source: hopAdapter, + theme: theme, + editable: false, + ready: function() { $('#jqxTabs').jqxTabs('next'); }, + columns: [ + { text: 'Hop', datafield: 'h_name' }, + { text: 'Origin', width: 180, datafield: 'h_origin' }, + { text: 'Type', width: 90, datafield: 'h_type', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + return '<span style="margin: 4px; margin-top: 6px; float: left;">' + HopTypeData[value].nl + '</span>'; + } + }, + { text: 'Vorm', width: 110, datafield: 'h_form', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + return '<span style="margin: 4px; margin-top: 6px; float: left;">' + HopFormData[value].nl + '</span>'; + } + }, + { text: 'Alpha', datafield: 'h_alpha', width: 80, align: 'right', cellsalign: 'right', cellsformat: 'p1' }, + { text: 'Gebruik', width: 110, datafield: 'h_useat', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + return '<span style="margin: 4px; margin-top: 6px; float: left;">' + HopUseData[value].nl + '</span>'; + } + }, + { text: 'Tijdsduur', datafield: 'h_time', width: 90, align: 'right', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + var duration = ''; + if ((rowdata.h_useat == 2) || (rowdata.h_useat == 4)) // Boil, Whirlpool + duration = dataAdapter.formatNumber(value, 'f0') + ' min.'; + else if (rowdata.h_useat == 5) // Dry hop + duration = dataAdapter.formatNumber(value / 1440, 'f0') + ' dagen'; + return '<span style="margin: 4px; margin-top: 6px; float: right;">' + duration + '</span>'; + } + }, + { text: 'IBU', datafield: 'ibu', width: 80, align: 'right', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + var ibu = toIBU(rowdata.h_useat, rowdata.h_form, preboil_sg, parseFloat(dataRecord.batch_size), + parseFloat(rowdata.h_amount), parseFloat(rowdata.h_time), parseFloat(rowdata.h_alpha), dataRecord.ibu_method, + dataRecord.brew_whirlpool9, dataRecord.brew_whirlpool7, dataRecord.brew_whirlpool6); + return '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(ibu, 'f1') + '</span>'; + } + }, + { text: 'Gewicht', datafield: 'h_amount', width: 110, align: 'right', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + var amount = dataAdapter.formatNumber(value, 'f1') + ' kg'; + if (value < 1) + amount = dataAdapter.formatNumber(value * 1000, 'f1') + ' gr'; + return '<span style="margin: 4px; margin-top: 6px; float: right;">' + amount + '</span>'; + } + }, + { text: 'Voorraad', datafield: 'h_inventory', width: 110, align: 'right', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + if (block_hop(dataRecord.inventory_reduced, rowdata.h_useat) == false) { + var amount = dataAdapter.formatNumber(value, 'f1') + ' kg', + color = (value < rowdata.h_amount) ? '#ff4040':'#ffffff'; + if (value < 1) + amount = dataAdapter.formatNumber(value * 1000, 'f1') + ' gr'; + return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + amount + '</span>'; + } else { + return '<span></span>'; + } + } + } + ] + }); + }; + + // Inline miscs editor + var editMisc = function(data) { + var miscSource = { + localdata: data.miscs, + datafields: [ + { name: 'm_name', type: 'string' }, + { name: 'm_amount', type: 'float' }, + { name: 'm_cost', type: 'float' }, + { name: 'm_type', type: 'int' }, + { name: 'm_use_use', type: 'int' }, + { name: 'm_time', type: 'float' }, + { name: 'm_amount_is_weight', type: 'int' }, + { name: 'm_inventory', type: 'float' }, + { name: 'm_avail', type: 'int' } + ], + }, + miscAdapter = new $.jqx.dataAdapter(miscSource, { + beforeLoadComplete: function(records) { + var row, i, data = new Array(); + for (i = 0; i < records.length; i++) { + row = records[i]; + data.push(row); + // Initial set water agent values. + if (row.m_use_use == 1) { // Mash + switch (row.m_name) { + case 'CaCl2': + $('#wa_cacl2').val(row.m_amount * 1000); + break; + case 'CaSO4': + $('#wa_caso4').val(row.m_amount * 1000); + break; + case 'MgSO4': + $('#wa_mgso4').val(row.m_amount * 1000); + break; + case 'NaCl': + $('#wa_nacl').val(row.m_amount * 1000); + break; + case 'MgCl2': + $('#wa_mgcl2').val(row.m_amount * 1000); + break; + case 'NaHCO3': + $('#wa_nahco3').val(row.m_amount * 1000); + break; + case 'CaCO3': + $('#wa_caco3').val(row.m_amount * 1000); + break; + case 'Melkzuur': + $('#wa_acid_name').val(AcidTypeData[0].nl); + $('#wa_acid').val(row.m_amount * 1000); + $('#wa_acid_perc').val(AcidTypeData[0].AcidPrc); + last_acid = 'Melkzuur'; + break; + case 'Zoutzuur': + $('#wa_acid_name').val(AcidTypeData[1].nl); + $('#wa_acid').val(row.m_amount * 1000); + $('#wa_acid_perc').val(AcidTypeData[1].AcidPrc); + last_acid = 'Zoutzuur'; + break; + case 'Fosforzuur': + $('#wa_acid_name').val(AcidTypeData[2].nl); + $('#wa_acid').val(row.m_amount * 1000); + $('#wa_acid_perc').val(AcidTypeData[2].AcidPrc); + last_acid = 'Fosforzuur'; + break; + case 'Zwavelzuur': + $('#wa_acid_name').val(AcidTypeData[3].nl); + $('#wa_acid').val(row.m_amount * 1000); + $('#wa_acid_perc').val(AcidTypeData[3].AcidPrc); + last_acid = 'Zwavelzuur'; + break; + } + } + if (row.m_use_use == 6) { // Sparge + switch (row.m_name) { + case 'CaCl2': + $('#ss_cacl2').val(row.m_amount * 1000); + break; + case 'CaSO4': + $('#ss_caso4').val(row.m_amount * 1000); + break; + case 'MgSO4': + $('#ss_mgso4').val(row.m_amount * 1000); + break; + case 'NaCl': + $('#ss_nacl').val(row.m_amount * 1000); + break; + case 'MgCl2': + $('#ss_mgcl2').val(row.m_amount * 1000); + break; + } + } + } + return data; + }, + loadError: function(jqXHR, status, error) { console.log('miscs load error ' + status + ' ' + error); }, + }); + $('#miscGrid').jqxGrid({ + width: 1240, + height: 575, + source: miscAdapter, + theme: theme, + editable: false, + ready: function() { $('#jqxTabs').jqxTabs('next'); }, + columns: [ + { text: 'Ingredient', datafield: 'm_name' }, + { text: 'Type', width: 140, datafield: 'm_type', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + return '<span style="margin: 3px; margin-top: 6px; float: left;">' + MiscTypeData[value].nl + '</span>'; + } + }, + { text: 'Gebruik', width: 140, datafield: 'm_use_use', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + return '<span style="margin: 3px; margin-top: 6px; float: left;">' + MiscUseData[value].nl + '</span>'; + } + }, + { text: 'Tijd', datafield: 'm_time', width: 90, align: 'right', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + var duration = ''; + if (rowdata.m_use_use == 2) // Boil + duration = dataAdapter.formatNumber(value, 'f0') + ' min.'; + else if ((rowdata.m_use_use == 3) || (rowdata.m_use_use == 4)) // Primary or Secondary + duration = dataAdapter.formatNumber(value / 1440, 'f0') + ' dagen'; + return '<span style="margin: 4px; margin-top: 6px; float: right;">' + duration + '</span>'; + } + }, + { text: 'Hoeveel', datafield: 'm_amount', width: 110, align: 'right', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + var vstr = rowdata.m_amount_is_weight ? 'gr' : 'ml'; + return '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(value * 1000, 'f2') + ' ' + vstr + '</span>'; + } + }, + { text: 'Voorraad', datafield: 'm_inventory', width: 110, align: 'right', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + if (block_misc(dataRecord.inventory_reduced, rowdata.m_use_use) == false) { + var vstr = rowdata.m_amount_is_weight ? 'gr' : 'ml', + color = (value < rowdata.m_amount) ? '#ff4040':'#ffffff', + amount = dataAdapter.formatNumber(value * 1000, 'f2') + ' ' + vstr; + return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + amount + '</span>'; + } else { + return '<span></span>'; + } + } + } + ] + }); + }; + + // Inline yeasts editor + var editYeast = function(data) { + var yeastSource = { + localdata: data.yeasts, + datafields: [ + { name: 'y_name', type: 'string' }, + { name: 'y_laboratory', type: 'string' }, + { name: 'y_product_id', type: 'string' }, + { name: 'y_amount', type: 'float' }, + { name: 'y_cost', type: 'float' }, + { name: 'y_type', type: 'int' }, + { name: 'y_form', type: 'int' }, + { name: 'y_flocculation', type: 'int' }, + { name: 'y_min_temperature', type: 'float' }, + { name: 'y_max_temperature', type: 'float' }, + { name: 'y_attenuation', type: 'float' }, + { name: 'y_use', type: 'int' }, + { name: 'y_cells', type: 'float' }, + { name: 'y_tolerance', type: 'float' }, + { name: 'y_inventory', type: 'float' }, + { name: 'y_sta1', type: 'int' }, + { name: 'y_bacteria', type: 'int' }, + { name: 'y_harvest_top', type: 'int' }, + { name: 'y_harvest_time', type: 'int' }, + { name: 'y_pitch_temperature', type: 'float' }, + { name: 'y_pofpos', type: 'int' }, + { name: 'y_zymocide', type: 'int' }, + { name: 'y_gr_hl_lo', type: 'int' }, + { name: 'y_sg_lo', type: 'float' }, + { name: 'y_gr_hl_hi', type: 'int' }, + { name: 'y_sg_hi', type: 'float' }, + { name: 'y_avail', type: 'int' } + ], + }, + yeastAdapter = new $.jqx.dataAdapter(yeastSource); + + $('#yeastGrid').jqxGrid({ + width: 1240, + height: 325, + source: yeastAdapter, + theme: theme, + editable: false, + ready: function() { $('#jqxTabs').jqxTabs('next'); }, + columns: [ + { text: 'Gist', datafield: 'y_name' }, + { text: 'Laboratorium', width: 150, datafield: 'y_laboratory' }, + { text: 'Code', width: 90, datafield: 'y_product_id' }, + { text: 'Soort', width: 100, datafield: 'y_form', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + return '<span style="margin: 4px; margin-top: 6px; float: left;">' + YeastFormData[value].nl + '</span>'; + } + }, + { text: 'Min. °C', width: 70, align: 'right', cellsalign: 'right', datafield: 'y_min_temperature' }, + { text: 'Max. °C', width: 70, align: 'right', cellsalign: 'right', datafield: 'y_max_temperature' }, + { text: 'Tol. %', width: 60, align: 'right', cellsalign: 'right', datafield: 'y_tolerance', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + var amount = '', color = (dataRecord.est_abv > value) ? '#ff4040':'#ffffff'; + if (value > 0) { + amount = dataAdapter.formatNumber(value, 'f1'); + } + return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + amount + '</span>'; + } + }, + { text: 'Attn. %', width: 70, align: 'right', cellsalign: 'right', datafield: 'y_attenuation', cellsformat: 'f1' }, + { text: 'Voor', width: 120, datafield: 'y_use', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + return '<span style="margin: 4px; margin-top: 6px; float: left;">' + YeastUseData[value].nl + '</span>'; + } + }, + { text: 'Hoeveel', datafield: 'y_amount', width: 90, align: 'right', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + var amount = dataAdapter.formatNumber(value * 1000, 'f0') + ' ml'; + if (rowdata.y_form == 0) // Liquid + amount = dataAdapter.formatNumber(value, 'f0') + ' pk'; + else if (rowdata.y_form == 1 || rowdata.y_form == 6) // Dry + amount = dataAdapter.formatNumber(value * 1000, 'f1') + ' gr'; + return '<span style="margin: 4px; margin-top: 6px; float: right;">' + amount + '</span>'; + } + }, + { text: 'Voorraad', datafield: 'y_inventory', width: 90, align: 'right', + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + var color, amount; + if (block_yeast(dataRecord.inventory_reduced, rowdata.y_use) == false) { + color = '#ffffff'; + if (value < rowdata.y_amount) + color = '#ff4040'; + amount = dataAdapter.formatNumber(value * 1000, 'f0') + ' ml'; + if (rowdata.y_form == 0) // Liquid + amount = dataAdapter.formatNumber(value, 'f0') + ' pk'; + else if (rowdata.y_form == 1 || rowdata.y_form == 6) // Dry + amount = dataAdapter.formatNumber(value * 1000, 'f1') + ' gr'; + return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + amount + '</span>'; + } else { + return '<span></span>'; + } + } + } + ] + }); + }; + + // inline mash editor + var editMash = function(data) { + var mashSource = { + localdata: data.mashs, + datafields: [ + { name: 'step_name', type: 'string' }, + { name: 'step_type', type: 'int' }, + { name: 'step_volume', type: 'float' }, + { name: 'step_infuse_amount', type: 'float' }, + { name: 'step_infuse_temp', type: 'float' }, + { name: 'step_temp', type: 'float' }, + { name: 'step_time', type: 'float' }, + { name: 'step_wg_ratio', type: 'float' }, + { name: 'ramp_time', type: 'float' }, + { name: 'end_temp', type: 'float' }, + { name: 'step_ph', type: 'float' }, + { name: 'step_sg', type: 'float' } + ], + }, + mashAdapter = new $.jqx.dataAdapter(mashSource); + + $('#mashGrid').jqxGrid({ + width: 1240, + height: 400, + source: mashAdapter, + theme: theme, + selectionmode: 'singlerow', + editable: false, + ready: function() { + /* Calculate the whole recipe */ + console.log('ready mashs, start calculations'); + /* calcFermentables() must be first and is done by the grid load. Here it is too late. */ + calcMash(); + calcWater(); + calcIBUs(); + whirlpoolHops(); + calcMiscs(); + calcViability(); + calcYeast(); + kookTijd(); + calcFermentation(); + calcCarbonation(); + $('#FLog').jqxButton({ disabled: (dataRecord.log_fermentation) ? false : true}); + $('#ILog').jqxButton({ disabled: (dataRecord.log_ispindel) ? false : true}); + $('#CLog').jqxButton({ disabled: (dataRecord.log_co2pressure) ? false : true}); + console.log('calculations ready'); + $('#jqxLoader').jqxLoader('close'); + $('#jqxTabs').jqxTabs('first'); + }, + columns: [ + { text: 'Stap naam', datafield: 'step_name' }, + { text: 'Stap type', datafield: 'step_type', width: 150, + cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) { + return '<span style="margin: 4px; margin-top: 6px; float: left;">' + MashStepTypeData[value].nl + '</span>'; + } + }, + { text: 'Start °C', datafield: 'step_temp', width: 80, align: 'right', cellsalign: 'right', cellsformat: 'f1' }, + { text: 'Eind °C', datafield: 'end_temp', width: 80, align: 'right', cellsalign: 'right', cellsformat: 'f1' }, + { text: 'Rust min.', datafield: 'step_time', width: 80, align: 'right', cellsalign: 'right' }, + { text: 'Stap min.', datafield: 'ramp_time', width: 80, align: 'right', cellsalign: 'right' }, + { text: 'Inf/dec L.', datafield: 'step_infuse_amount', width: 80, align: 'right', + cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) { + if (rowdata.step_type == 1) + return '<span></span>'; + var color = '#ffffff'; + var mvol = mashkg * MaltVolume; + if ((rowdata.step_wg_ratio * mashkg + mvol) > dataRecord.eq_tun_volume) + color = '#ff4040'; + return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + dataAdapter.formatNumber(value, 'f1') + '</span>'; + } + }, + { text: 'Inf/dec °C', datafield: 'step_infuse_temp', width: 90, align: 'right', + cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) { + if (rowdata.step_type == 1) + return '<span></span>'; + return '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(value, 'f2') + '</span>'; + } + }, + { text: 'L/Kg.', datafield: 'step_wg_ratio', width: 80, align: 'right', + cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) { + var color = '#ffffff'; + if (value < 2.0 || value > 6.0) + color = '#ff4040'; + return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + dataAdapter.formatNumber(value, 'f2') + '</span>'; + } + }, + { text: 'pH', datafield: 'step_ph', width: 70, align: 'right', cellsalign: 'right', cellsformat: 'f2' }, + { text: 'SG', datafield: 'step_sg', width: 80, align: 'right', cellsalign: 'right', cellsformat: 'f3' } + ] + }); + }; + + /* + * Remove the top menu so that we MUST use the button to leave the editor. + */ + $('#jqxMenu').jqxMenu('destroy'); + console.log('record:' + my_record + ' return:' + my_return + ' theme:' + theme); + $('#jqxLoader').jqxLoader({ width: 250, height: 150, isModal: true, text: 'Laden product ...', theme: theme }); + $('#jqxLoader').jqxLoader('open'); + + /* Moved to before all functions */ + dataAdapter.dataBind(); + + /* + * Generic functions + */ + function kookTijd() { + if (dataRecord.boil_time) { + $('#brew_pmpt_koken').html('Koken ' + dataRecord.boil_time + ' minuten'); + } else { + $('#brew_pmpt_koken').html('Koken "no-boil"'); + } + } + + function infusionVol(step_infused, step_mashkg, infuse_temp, step_temp, last_temp) { + var a = last_temp * (dataRecord.eq_tun_weight * dataRecord.eq_tun_specific_heat + step_infused * SpecificHeatWater + step_mashkg * SpecificHeatMalt); + var b = step_temp * (dataRecord.eq_tun_weight * dataRecord.eq_tun_specific_heat + step_infused * SpecificHeatWater + step_mashkg * SpecificHeatMalt); + var vol = Round(((b - a) / ((infuse_temp - step_temp) * SpecificHeatWater)), 2); + return vol; + } + + function decoctionVol(step_volume, step_temp, prev_temp) { + var a = (dataRecord.eq_tun_weight * dataRecord.eq_tun_specific_heat + step_volume * SpecificHeatWater) * (step_temp - prev_temp); + var b = SpecificHeatWater * (99 - step_temp); + var vol = 0; + if (b > 0) + vol = Round(a / b, 6); + return vol; + } + + function calcViability() { + var vpm = 1.00; + var max = 100; + var rowscount = dataRecord.yeasts.length; + if (rowscount) { + for (i = 0; i < rowscount; i++) { + row = dataRecord.yeasts[i]; + if (row.y_use == 0) { + if (row.y_form == 0) { // Liquid + vpm = 0.80; + max = 97; + if (row.y_laboratory == 'White Labs') { // PurePitch + vpm = 0.95; + max = 100; + } + } else if (row.y_form == 1) { // dry yeast + vpm = 0.998; + max = 100; + } else if (row.y_form == 6) { // Dried kveik + vpm = 0.92; + max = 100; + } else { // Slant, Culture, Frozen, Bottle + vpm = 0.99; + max = 97; + } + } + } + } + var base = max; + var days = 0; + + if (parseFloat($('#yeast_prod_date').val()) > 2000) { + console.log('calculate viability'); + var d = new Date(); + var date2 = $('#yeast_prod_date').val(); + date2 = date2.split('-'); + // Now we convert the array to a Date object + var date1 = new Date(d.getFullYear(), d.getMonth(), d.getDate()); + date2 = new Date(date2[0], date2[1] - 1, date2[2]); + var diff = parseInt(date1.getTime()) - parseInt(date2.getTime()); + days = Math.floor(diff/1000/60/60/24); + + var degrade = 1 - ((1 - vpm) / 30.41); // viability degradation per day. + for (i = 0; i < days; i++) { + base = base * degrade; + } + if (base > max) { + base = max; + } + base = Math.round(base); + } + console.log('age:' + days + ' max:' + max + ' vpm:' + vpm + ' base:' + base); + + if (dataRecord.starter_viability != base) { + dataRecord.starter_viability = base; + $('#starter_viability').val(dataRecord.starter_viability); + } + } + + function calcSupplies() { + if (dataRecord.inventory_reduced > 6) { + $('#ok_pmpt').hide(); + return; + } + if (ok_fermentables && ok_hops && ok_miscs && ok_yeasts && ok_waters) + $('#ok_supplies').html("<img src='images/dialog-ok-apply.png'>"); + else + $('#ok_supplies').html("<img src='images/dialog-error.png'>"); + } + + /* + * All calculations that depend on changes in the fermentables, + * volumes and equipments. + */ + function calcFermentables() { + + var sugarsf = 0, // fermentable sugars mash + boil + sugarsm = 0, // fermentable sugars in mash + vol = 0, // Volume sugars after boil + addedS = 0, // Added sugars after boil + addedmass = 0, // Added mass after boil + mvol = 0, // mash volume + infuse = 0, // mash infuse volume + colort = 0, // Colors srm * vol totals + colorh = 0, // Colors ebc * vol * kt + colorn = 0, // Colors ebc * pt * pct + my_100 = false, + mashtime = 0, // Total mash time + mashtemp = 0, // Average mash temperature + bv = 0.925, // Bierverlies rendement + sr = 0.95, // Mash en spoel rendement + lintner = 0, // Total recipe lintner + i, row, rows, org, timem, aboil_volume, spoelw, ogx, topw, s = 0, d, v, x, + sug, alc, pt, cw, color, scolor, fig; + + /* Init global variables */ + psugar = 0; + pcara = 0; + mashkg = 0; + ok_fermentables = 1; // All is in stock. + ok_yeasts = 1; + + if (dataRecord.mashs.length) { + for (i = 0; i < dataRecord.mashs.length; i++) { + row = dataRecord.mashs[i]; + if (parseFloat(row.step_type) == 0) // Infusion + mvol += parseFloat(row.step_infuse_amount); + if (row.step_temp <= 75 && row.step_temp >= 60) { // Ignore mashout + timem = row.step_time; + if (i > 0) + timem += row.ramp_time; + mashtime += timem; + mashtemp += timem * row.step_temp; + } + } + infuse = mvol; + mashtemp = Round(mashtemp / mashtime, 2); + } else { + console.log("calcFermentables() no mash steps"); + } + + if (! dataRecord.fermentables.length) { + console.log("calcFermentables() no fermentables"); + return; // grid not yet loaded. + } + + for (i = 0; i < dataRecord.fermentables.length; i++) { + row = dataRecord.fermentables[i]; + if (row.f_adjust_to_total_100) + my_100 = true; + if (row.f_type == 1 && row.f_added < 4) // Sugar + psugar += row.f_percentage; + if (row.f_graintype == 2 && row.f_added < 4) // Crystal + pcara += row.f_percentage; + d = row.f_amount * (row.f_yield / 100) * (1 - row.f_moisture / 100); + if (row.f_added == 0) { // Mash + if (mvol > 0) { // Only if mash already known. + mvol += row.f_amount * row.f_moisture / 100; + s += d; + } + d = parseFloat(dataRecord.efficiency) / 100 * d; + sugarsm += d; + mashkg += parseFloat(row.f_amount); + } + if (row.f_added == 0 || row.f_added == 1) // Mash or Boil + sugarsf += d; + if (row.f_added == 2 || row.f_added == 3) { // Fermentation or lagering + x = (row.f_yield / 100) * (1 - row.f_moisture / 100); + addedS += row.f_amount * x; + addedmass += row.f_amount; + vol += (x * sugardensity + (1 - x) * 1) * row.f_amount; + } + if (row.f_added < 4) { + colort += row.f_amount * ebc_to_srm(row.f_color); + colorh += row.f_amount * row.f_color * get_kt(row.f_color); + colorn += (row.f_percentage / 100) * row.f_color; // For 8.6 Pt wort. + } + if (fermentableInit) { + if (row.f_added == 4) { + $('#bottle_priming_total').val(row.f_amount * 1000); // Prevent clearing + $('#bottle_priming_sugar').val(row.f_name); + } + if (row.f_added == 5) { + $('#keg_priming_total').val(row.f_amount * 1000); + $('#keg_priming_sugar').val(row.f_name); + } + } + // Check supplies. + if ((((dataRecord.inventory_reduced <= 2) && (row.f_added <= 1)) || // Mash or boil + ((dataRecord.inventory_reduced <= 3) && (row.f_added == 2)) || // Primary + ((dataRecord.inventory_reduced <= 5) && (row.f_added == 3)) || // Secondary or Tertiary + ((dataRecord.inventory_reduced <= 6) && (row.f_added == 4)) || // Bottle + ((dataRecord.inventory_reduced <= 6) && (row.f_added == 5))) && row.f_inventory < row.f_amount) { + ok_fermentables = 0; + } + if (row.f_added == 0 && (row.f_type == 0 || row.f_type == 4) && row.f_color < 50) { // Mash and Grain/Adjunct and Color < 50 + lintner += row.f_diastatic_power * row.f_amount; + } + } + fermentableInit = 0; + $('#ferm_lintner').val(Math.round(parseFloat(lintner / mashkg))); + $('#mash_kg').val(mashkg); + console.log('calcFermentables() supplies:' + ok_fermentables + ' moutsuiker:' + Round(sugarsm, 3) + '/' + Round(sugarsf, 3)); + to_100 = my_100; + + if (mvol > 0) { + v = s / sugardensity + mvol; + s = 1000 * s / (v * 10); //deg. Plato + est_mash_sg = Round(plato_to_sg(s), 5); + $('#est_mash_sg').val(est_mash_sg); + } + + // Estimate total recipe OG. + dataRecord.est_og = estimate_sg(sugarsf + addedS, parseFloat(dataRecord.batch_size)); + $('#est_og').val(dataRecord.est_og); + $('#est_og2').val(dataRecord.est_og); + org = dataRecord.est_og; + + // Estimate SG in kettle after boil + aboil_sg = estimate_sg(sugarsf, parseFloat(dataRecord.batch_size)); + $('#est_og3').val(aboil_sg); + + // Estimate SG in kettle before boil + preboil_sg = estimate_sg(sugarsm, parseFloat(dataRecord.boil_size)); + $('#est_pre_sg').val(preboil_sg); + + // Recalculate volumes. + aboil_volume = parseFloat(dataRecord.batch_size); + if (dataRecord.brew_aboil_volume > 0) + aboil_volume = dataRecord.brew_aboil_volume / 1.04; // volume @ 20 degrees + if (dataRecord.brew_fermenter_tcloss == 0) { + dataRecord.brew_fermenter_tcloss = dataRecord.eq_trub_chiller_loss; + $('#brew_fermenter_tcloss').val(dataRecord.brew_fermenter_tcloss); + } + dataRecord.brew_fermenter_volume = aboil_volume - dataRecord.brew_fermenter_tcloss + dataRecord.brew_fermenter_extrawater; + $('#brew_fermenter_volume').val(dataRecord.brew_fermenter_volume); + // Calculate SG in fermenter + ogx = dataRecord.brew_aboil_sg; + if (ogx < 1.002) + ogx = aboil_sg; + topw = dataRecord.brew_fermenter_extrawater; + + if (dataRecord.brew_fermenter_volume > 0) { + sug = sg_to_plato(ogx) * dataRecord.brew_fermenter_volume * ogx / 100; //kg of sugar in + sug += addedS; //kg + + if ((dataRecord.brew_fermenter_volume * ogx + addedmass) > 0) { + pt = 100 * sug / (dataRecord.brew_fermenter_volume * ogx + addedmass + topw); + dataRecord.og = dataRecord.brew_fermenter_sg = Round(plato_to_sg(pt), 4); + $('#brew_fermenter_sg').val(dataRecord.brew_fermenter_sg); + // color + if (dataRecord.color_method == 4) { + dataRecord.brew_fermenter_color = Math.round(((pt / 8.6) * colorn) + (dataRecord.boil_time / 60)); + } else if (dataRecord.color_method == 3) { + dataRecord.brew_fermenter_color = Math.round((4.46 * bv * sr) / (aboil_volume + topw) * colorh); + } else { + cw = colort / (aboil_volume + topw) * 8.34436; + dataRecord.brew_fermenter_color = kw_to_ebc(dataRecord.color_method, cw); + } + $('#brew_fermenter_color').val(dataRecord.brew_fermenter_color); + scolor = ebc_to_color(dataRecord.brew_fermenter_color); + $('#bcolorf').show(); + document.getElementById('bcolorf').style.background = scolor; + } + } else { + // Negative volume + dataRecord.brew_fermenter_sg = dataRecord.brew_fermenter_color = 0; + $('#brew_fermenter_sg').val(0); + $('#brew_fermenter_color').val(0); + $('#bcolorf').hide(); + } + + // Color of the wort + if (dataRecord.color_method == 4) { + color = Math.round(((sg_to_plato(dataRecord.est_og) / 8.6) * colorn) + (dataRecord.boil_time / 60)); + } else if (dataRecord.color_method == 3) { // Hans Halberstadt + color = Math.round((4.46 * bv * sr) / parseFloat(dataRecord.batch_size) * colorh); + } else { + cw = colort / parseFloat(dataRecord.batch_size) * 8.34436; + color = kw_to_ebc(dataRecord.color_method, cw); + } + dataRecord.est_color = color; + $('#est_color').val(color); + $('#est_color2').val(color); + scolor = ebc_to_color(color); + document.getElementById('bcolor').style.background = scolor; + document.getElementById('bcolor2').style.background = scolor; + + // Progress bars + pmalts = mashkg / dataRecord.eq_mash_max * 100; + $('#perc_malts').jqxProgressBar('val', pmalts); + $('#perc_sugars').jqxProgressBar('val', psugar); + $('#perc_cara').jqxProgressBar('val', pcara); + calcStage(); + + // Calculate estimated svg. + svg = 0; // default. + initcells = 0; + for (i = 0; i < dataRecord.yeasts.length; i++) { + row = dataRecord.yeasts[i]; + if (row.y_use == 0) { // Primary + if (parseFloat(row.y_attenuation) > svg) + svg = parseFloat(row.y_attenuation); // Take the highest if multiple yeasts. + if (row.y_form == 0) + initcells += (parseFloat(row.y_cells) / 1000000000) * parseFloat(row.y_amount) * (dataRecord.starter_viability / 100); + else + initcells += (parseFloat(row.y_cells) / 1000000) * parseFloat(row.y_amount) * (dataRecord.starter_viability / 100); + } + // TODO: brett in secondary ?? + if ((((dataRecord.inventory_reduced <= 3) && (row.y_use == 0)) || // Primary + ((dataRecord.inventory_reduced <= 4) && (row.y_use == 1)) || // Secondary + ((dataRecord.inventory_reduced <= 5) && (row.y_use == 2)) || // Tertiary + ((dataRecord.inventory_reduced <= 6) && (row.y_use == 3))) && // Bottle + (row.y_inventory < row.y_amount)) { + ok_yeasts = 0; + } + } + calcSupplies(); + if (svg == 0) + svg = 77; + if ((mashkg > 0) && (infuse > 0) && (mashtime > 0) && (mashtemp > 0)) { + dataRecord.est_fg = estimate_fg(psugar, pcara, infuse / mashkg, mashtime, mashtemp, svg, dataRecord.est_og); + } else { + dataRecord.est_fg = estimate_fg(psugar, pcara, 0, 0, 0, svg, dataRecord.est_og); + } + $('#est_fg').val(dataRecord.est_fg); + $('#est_fg2').val(dataRecord.est_fg); + $('#est_fg3').val(dataRecord.est_fg); + fig = dataRecord.est_fg; + + dataRecord.est_abv = abvol(dataRecord.est_og, dataRecord.est_fg); + $('#est_abv').val(dataRecord.est_abv); + $('#est_abv2').val(dataRecord.est_abv); + + // Calculate the final svg if available use the real value. + if ((dataRecord.stage >= 6) && (dataRecord.fg > 0.990) && (dataRecord.fg < dataRecord.brew_fermenter_sg)) { + svg = calc_svg(dataRecord.brew_fermenter_sg, dataRecord.fg); + org = dataRecord.brew_fermenter_sg; + fig = dataRecord.fg; + } + + $('#yeast_cells').val(initcells); + $('#need_cells').val(getNeededYeastCells()); + + // Calculate the calories in kcal/l (from brouwhulp) + alc = 1881.22 * fig * (org - fig) / (1.775 - org); + sug = 3550 * fig * (0.1808 * org + 0.8192 * fig - 1.0004); + $('#kcal').val(Math.round((alc + sug) / (12 * 0.0295735296))); + }; + + function calcMash() { + + var h, m, infused = 0, mashtime = 0, mashvol = 0, vol, i, j, n, a, b, row, temp; + var lasttemp = 18.0; + var graintemp = 18.0; + var tuntemp = 18.0; + + if (dataRecord.mashs.length && (mashkg > 0)) { + console.log('calcMash()'); + for (i = 0; i < dataRecord.mashs.length; i++) { + row = dataRecord.mashs[i]; + if (row.step_type == 0) { // Infusion + if (i == 0) { + // First mash step, temperature from the mashtun and malt. + n = 20; // tun is preheated. + tuntemp = row.step_temp; + for (j = 0; j < n; j++) { + a = mashkg * graintemp * SpecificHeatMalt + dataRecord.eq_tun_weight * tuntemp * dataRecord.eq_tun_specific_heat; + b = row.step_temp * (dataRecord.eq_tun_weight * dataRecord.eq_tun_specific_heat + row.step_infuse_amount * SpecificHeatWater + mashkg * SpecificHeatMalt) - SlakingHeat * mashkg; + if (row.step_infuse_amount > 0) { + temp = (b - a) / (row.step_infuse_amount * SpecificHeatWater); + } else { + temp = 99; + } + tuntemp += (temp - tuntemp) / 2; + row.step_infuse_temp = Round(temp, 6); + } + //console.log('init infuse temp: ' + row.step_infuse_temp); + } else { + // Calculate amount of infusion water. + row.step_infuse_amount = infusionVol(infused, mashkg, row.step_infuse_temp, row.step_temp, lasttemp); + //console.log('vol: ' + row.step_infuse_amount + ' temp: ' + row.step_infuse_temp); + } + infused += parseFloat(row.step_infuse_amount); + } else if (row.step_type == 1) { // Temperature + if (i > 0) + row.step_infuse_amount = 0; + row.step_infuse_temp = 0; + } else if (row.step_type == 2) { // Decoction + row.step_infuse_amount = decoctionVol(infused, row.step_temp, lasttemp); + row.step_infuse_temp = 99; + } + row.step_volume = infused; + //console.log(i + ' type: ' + row.step_type + ' volume: ' + row.step_infuse_amount + ' temp: ' + row.step_infuse_temp); + lasttemp = row.step_temp; + mashtime += row.step_time + row.ramp_time; + row.step_wg_ratio = Round(infused / mashkg, 6); + $('#mashGrid').jqxGrid('updaterow', i, row); + } + } + if ((dataRecord.w1_amount + dataRecord.w2_amount) == 0) { + dataRecord.w1_amount = infused; + $('#w1_amount').val(infused); + console.log("calcMash() fixed water 1 to " + infused); + } + mashvol = Round(mashkg * MaltVolume + infused, 6); + $('#est_mashvol').val(mashvol); + h = Math.floor(mashtime / 60); + m = Math.floor(mashtime - (h * 60)); + if (h < 10) + h = '0' + h; + if (m < 10) + m = '0' + m; + $('#est_mashtime').val(h + ':' + m); + // Estimated needed sparge water corrected for the temperature. + spoelw = Round((dataRecord.boil_size - infused + (mashkg * my_grain_absorbtion) + dataRecord.eq_lauter_deadspace) * 1.03, 6); + $('#brew_sparge_est').val(spoelw); + } + + function getNeededYeastCells() { + + var plato, volume, sg = dataRecord.brew_fermenter_sg; + if (sg <= 1.0001 && dataRecord.fg > 1.000) + sg = dataRecord.fg; + else if (sg <= 1.0001) + sg = dataRecord.est_og; + plato = sg_to_plato(sg); + + volume = dataRecord.brew_fermenter_volume; + if (volume <= 0) + volume = dataRecord.batch_size - dataRecord.eq_trub_chiller_loss; + + return dataRecord.yeast_pitchrate * volume * plato; + } + + function hopFlavourContribution(bt, vol, use, amount) { + var result; + + if (use == 4 || use == 5) // Whirlpool or Dry-hop + return 0; + if (use == 1) { // First wort + result = 0.15; // assume 15% flavourcontribution for fwh + } else if (bt > 50) { + result = 0.10; // assume 10% flavourcontribution as a minimum + } else { + result = 15.25 / (6 * Math.sqrt(2 * Math.PI)) * Math.exp(-0.5 * Math.pow((bt - 21) / 6, 2)); + if (result < 0.10) + result = 0.10; // assume 10% flavourcontribution as a minimum + } + return (result * amount * 1000) / vol; + } + + function hopAromaContribution(bt, vol, use, amount) { + var result = 0; + + if (use == 5) { // Dry hop + result = 1.33; + } else if (use == 4) { // Whirlpool + if (bt > 30) + bt = 30; // Max 30 minutes + result = 0.62 * bt / 30; + } else if (bt > 20) { + result = 0; + } else if (bt > 7.5) { + result = 10.03 / (4 * Math.sqrt(2 * Math.PI)) * Math.exp(-0.5 * Math.pow((bt - 7.5) / 4, 2)); + } else if (use == 2) { // Boil + result = 1; + } else if (use == 3) { // Aroma + result = 1.2; + } + return (result * amount * 1000) / vol; + } + + function calcIBUs() { + var total_ibus = 0, ferm_ibus = 0, rows = {}, i, row; + hop_aroma = hop_flavour = 0; + if (!(rows = $('#hopGrid').jqxGrid('getrows'))) { + return; + } + ok_hops = 1; + for (i = 0; i < rows.length; i++) { + row = rows[i]; + total_ibus += toIBU(row.h_useat, row.h_form, preboil_sg, parseFloat(dataRecord.batch_size), + parseFloat(row.h_amount), parseFloat(row.h_time), parseFloat(row.h_alpha), dataRecord.ibu_method, + dataRecord.brew_whirlpool9, dataRecord.brew_whirlpool7, dataRecord.brew_whirlpool6); + ferm_ibus += toIBU(row.h_useat, row.h_form, preboil_sg, + parseFloat(dataRecord.brew_fermenter_volume) + parseFloat(dataRecord.brew_fermenter_tcloss), + parseFloat(row.h_amount), parseFloat(row.h_time), parseFloat(row.h_alpha), dataRecord.ibu_method, + dataRecord.brew_whirlpool9, dataRecord.brew_whirlpool7, dataRecord.brew_whirlpool6); + hop_flavour += hopFlavourContribution(parseFloat(row.h_time), parseFloat(dataRecord.batch_size), row.h_useat, parseFloat(row.h_amount)); + hop_aroma += hopAromaContribution(parseFloat(row.h_time), parseFloat(dataRecord.batch_size), row.h_useat, parseFloat(row.h_amount)); + if ((((dataRecord.inventory_reduced <= 2) && (row.h_useat <= 4)) || // Mash, FW, Boil, Aroma, Whirlpool + ((dataRecord.inventory_reduced <= 6) && (row.h_useat == 5))) && // Dry-hop + (row.h_inventory < row.h_amount)) + ok_hops = 0; + } + total_ibus = Round(total_ibus, 1); + ferm_ibus = Round(ferm_ibus, 1); + hop_flavour = Round(hop_flavour * 100 / 5, 1); + hop_aroma = Round(hop_aroma * 100 / 6, 1); + if (hop_flavour > 100) + hop_flavour = 100; + if (hop_aroma > 100) + hop_aroma = 100; + console.log('calcIBUs(): ' + total_ibus + ' flavour: ' + hop_flavour + ' aroma: ' + hop_aroma + + ' fermenter:' + ferm_ibus + ' supplies:' + ok_hops); + dataRecord.est_ibu = total_ibus; + $('#est_ibu').val(total_ibus); + $('#est_ibu2').val(total_ibus); + $('#hop_flavour').jqxProgressBar('val', hop_flavour); + $('#hop_aroma').jqxProgressBar('val', hop_aroma); + $('#brew_fermenter_ibu').val(ferm_ibus); + calcStage(); + calcSupplies(); + }; + + /* + * http://braukaiser.com/blog/blog/2012/11/03/estimating-yeast-growth/ + * + * stype: 0=stirred, 1=shaken, 2=simple + * totcells: initial cells + * egrams: gram extract + */ + function getGrowthRate(stype, totcells, egrams) { + + /* Cells per grams extract (B/g) */ + var cpe = totcells / egrams; + + if (cpe > 3.5) + return 0; // no growth + if (stype == 2) + return 0.4; // simple starter + if (stype == 1) + return 0.62; // shaken starter + if (cpe <= 1.4) // stirred starter + return 1.4; + return 2.33 - (.67 * cpe); + }; + + function calcStep(svol, stype, start) { + + var gperpoint = 2.72715, //number of grams of extract per point of starter gravity per liter + prate = start / svol * 1000, + irate = Round(prate, 1), + egrams = (dataRecord.starter_sg - 1) * svol * gperpoint, + grate = getGrowthRate(stype, start, egrams), + ncells = Round(egrams * grate, 1), + totcells = parseFloat(ncells) + start; + + return { + svol: svol, + irate: irate, + prate: Round(prate, 1), + ncells: ncells, + totcells: totcells, + growf: Round(ncells / start, 2) + }; + } + + function killstep2() { + + dataRecord.prop2_volume = 0; + $('#prop2_volume').val(0); + $('#prop2_tcells').val(0); + $('#prop2_type,#prop2_volume,#prop2_irate,#prop2_ncells,#prop2_tcells,#prop2_growf').hide(); + $('#r2_pmpt').show(); + } + + function killstep3() { + + dataRecord.prop3_volume = 0; + $('#prop3_volume').val(0); + $('#prop3_tcells').val(0); + $('#prop3_type,#prop3_volume,#prop3_irate,#prop3_ncells,#prop3_tcells,#prop3_growf').hide(); + $('#r3_pmpt').show(); + } + + function killstep4() { + + dataRecord.prop4_volume = 0; + $('#prop4_volume').val(0); + $('#prop4_tcells').val(0); + $('#prop4_type,#prop4_volume,#prop4_irate,#prop4_ncells,#prop4_tcells,#prop4_growf').hide(); + $('#r4_pmpt').show(); + } + + /* + * Calculate all starter steps. + * stype: final starter type: 0 = stirred, 1 = shaked, 2 = simple. + * start: initial cells in billions + * needed: needed cells in billions + * + * result: all values updated. + */ + function calcSteps(stype, start, needed) { + + var uvols = [20, 40, 60, 80, 100, 150, 200, 250, 375, 500, 625, 750, 875, 1000, 1250, 1500, 2000, 2500, 3000, 4000, 5000], + mvols = uvols.length, svol = 0, lasti = 0, result = {}, i; + + /* + * If no values are set, auto calculate the starter. + */ + if ((parseFloat($('#prop1_volume').jqxNumberInput('decimal')) + parseFloat($('#prop2_volume').jqxNumberInput('decimal')) + + parseFloat($('#prop3_volume').jqxNumberInput('decimal')) + parseFloat($('#prop4_volume').jqxNumberInput('decimal'))) == 0) { + // clear by default + for (i = 1; i < 5; i++) { + $('#prop' + i + '_type,#prop' + i + '_volume,#prop' + i + '_irate,#prop' + i + '_ncells,#prop' + i + '_tcells,#prop' + i + '_growf').hide(); + $('#r' + i + '_pmpt').show(); + $('#prop' + i + '_type').val(stype); + $('#prop' + i + '_volume').val(0); + } + if (start > needed) { + return; // no starter needed + } + $('#prop1_type,#prop1_volume,#prop1_irate,#prop1_ncells,#prop1_tcells,#prop1_growf').show(); + $('#r1_pmpt').hide(); + for (i = lasti; i <= mvols; i++) { + lasti = i; + svol = uvols[lasti]; + result = calcStep(svol, stype, start); + if (result.irate < 25) { + // inocculation rate too low, backup one step and break out. + lasti = i - 1; + svol = uvols[lasti]; + result = calcStep(svol, stype, start); + break; + } + if (result.totcells > needed || i == mvols) { // hit the target or loops done + break; + } + } + $('#prop1_volume').val(result.svol / 1000); // to liters + $('#prop1_irate').val(result.prate); + $('#prop1_ncells').val(result.ncells); + $('#prop1_tcells').val(result.totcells); + $('#prop1_growf').val(result.growf); + if (result.totcells > needed) + return; // hit the target + + // second stage + $('#r2_pmpt').hide(); + $('#prop2_type').val(stype); + $('#prop2_type,#prop2_volume,#prop2_irate,#prop2_ncells,#prop2_tcells,#prop2_growf').show(); + for (i = lasti; i <= mvols; i++) { + lasti = i; + svol = uvols[lasti]; + result = calcStep(svol, stype, $('#prop1_tcells').val()); + if (result.irate < 25) { + lasti = i - 1; + svol = uvols[lasti]; + result = calcStep(svol, stype, $('#prop1_tcells').val()); + break; + } + if (result.totcells > needed || i == mvols) { // hit the target or loops done + break; + } + } + $('#prop2_volume').val(result.svol / 1000); // to liters + $('#prop2_irate').val(result.prate); + $('#prop2_ncells').val(result.ncells); + $('#prop2_tcells').val(result.totcells); + $('#prop2_growf').val(result.growf); + if (result.totcells > needed) + return; // hit the target + + // third stage + $('#r3_pmpt').hide(); + $('#prop3_type').val(stype); + $('#prop3_type,#prop3_volume,#prop3_irate,#prop3_ncells,#prop3_tcells,#prop3_growf').show(); + for (i = lasti; i <= mvols; i++) { + lasti = i; + svol = uvols[lasti]; + result = calcStep(svol, stype, $('#prop2_tcells').val()); + if (result.irate < 25) { + lasti = i - 1; + svol = uvols[lasti]; + result = calcStep(svol, stype, $('#prop2_tcells').val()); + break; + } + if (result.totcells > needed || i == mvols) { // hit the target or loops done + break; + } + } + $('#prop3_volume').val(result.svol / 1000); // to liters + $('#prop3_irate').val(result.prate); + $('#prop3_ncells').val(result.ncells); + $('#prop3_tcells').val(result.totcells); + $('#prop3_growf').val(result.growf); + if (result.totcells > needed) + return; // hit the target + + // fourth stage + $('#r4_pmpt').hide(); + $('#prop4_type').val(stype); + $('#prop4_type,#prop4_volume,#prop4_irate,#prop4_ncells,#prop4_tcells,#prop4_growf').show(); + for (i = lasti; i <= mvols; i++) { + lasti = i; + svol = uvols[lasti]; + result = calcStep(svol, stype, $('#prop3_tcells').val()); + if (result.totcells > needed || i == mvols) { // hit the target or loops done + $('#prop4_volume').val(result.svol / 1000); // to liters + $('#prop4_irate').val(result.prate); + $('#prop4_ncells').val(result.ncells); + $('#prop4_tcells').val(result.totcells); + $('#prop4_growf').val(result.growf); + return; + } + } + } else { + // recalculate + if (dataRecord.prop1_volume > 0) { + $('#r1_pmpt').hide(); + $('#prop1_type,#prop1_volume,#prop1_irate,#prop1_ncells,#prop1_tcells,#prop1_growf').show(); + result = calcStep($('#prop1_volume').val() * 1000, dataRecord.prop1_type, start); + $('#prop1_irate').val(result.prate); + $('#prop1_ncells').val(result.ncells); + $('#prop1_tcells').val(result.totcells); + $('#prop1_growf').val(result.growf); + if (result.totcells > needed) { + killstep2(); + killstep3(); + killstep4(); + } else if (dataRecord.prop2_volume == 0) { + dataRecord.prop2_volume = dataRecord.prop1_volume; /* Extra step needed, start with the same size */ + dataRecord.prop2_type = dataRecord.prop1_type; + $('#prop2_volume').val(dataRecord.prop2_volume); + $('#prop2_type').val(dataRecord.prop2_type); + } + } + if (dataRecord.prop2_volume > 0) { + $('#r2_pmpt').hide(); + $('#prop2_type,#prop2_volume,#prop2_irate,#prop2_ncells,#prop2_tcells,#prop2_growf').show(); + result = calcStep($('#prop2_volume').val() * 1000, dataRecord.prop2_type, $('#prop1_tcells').val()); + $('#prop2_irate').val(result.prate); + $('#prop2_ncells').val(result.ncells); + $('#prop2_tcells').val(result.totcells); + $('#prop2_growf').val(result.growf); + if (result.totcells > needed) { + killstep3(); + killstep4(); + } else if (dataRecord.prop3_volume == 0) { + dataRecord.prop3_volume = dataRecord.prop2_volume; /* Extra step needed, start with the same size */ + dataRecord.prop3_type = dataRecord.prop2_type; + $('#prop3_volume').val(dataRecord.prop3_volume); + $('#prop3_type').val(dataRecord.prop3_type); + } + } + if (dataRecord.prop3_volume > 0) { + $('#r3_pmpt').hide(); + $('#prop3_type,#prop3_volume,#prop3_irate,#prop3_ncells,#prop3_tcells,#prop3_growf').show(); + result = calcStep($('#prop3_volume').val() * 1000, dataRecord.prop3_type, $('#prop2_tcells').val()); + $('#prop3_irate').val(result.prate); + $('#prop3_ncells').val(result.ncells); + $('#prop3_tcells').val(result.totcells); + $('#prop3_growf').val(result.growf); + if (result.totcells > needed) { + killstep4(); + } else if (dataRecord.prop4_volume == 0) { + dataRecord.prop4_volume = dataRecord.prop3_volume; /* Extra step needed, start with the same size */ + dataRecord.prop4_type = dataRecord.prop3_type; + $('#prop4_volume').val(dataRecord.prop4_volume); + $('#prop4_type').val(dataRecord.prop4_type); + } + } + if (dataRecord.prop4_volume > 0) { + $('#r4_pmpt').hide(); + $('#prop4_type,#prop4_volume,#prop4_irate,#prop4_ncells,#prop4_tcells,#prop4_growf').show(); + result = calcStep($('#prop4_volume').val() * 1000, dataRecord.prop4_type, $('#prop3_tcells').val()); + $('#prop4_irate').val(result.prate); + $('#prop4_ncells').val(result.ncells); + $('#prop4_tcells').val(result.totcells); + $('#prop4_growf').val(result.growf); + } + } + } + + function calcYeast() { + + // Calculate needed cells. + var plato, volume, rows, rowscount, row, i, needed, use_cells, sg = dataRecord.brew_fermenter_sg; + + if (sg <= 1.0001 && dataRecord.fg > 1.000) + sg = dataRecord.fg; + else if (sg <= 1.0001) + sg = dataRecord.est_og; + plato = sg_to_plato(sg); + + volume = dataRecord.brew_fermenter_volume; + if (volume > 0) { + if (dataRecord.brew_fermenter_extrawater > 0) + volume += dataRecord.brew_fermenter_extrawater; + } else { + volume = dataRecord.batch_size - dataRecord.eq_trub_chiller_loss; + } + + // Also in calcFermentables() + $('#yeast_cells').val(initcells); + + if (!(rows = $('#yeastGrid').jqxGrid('getrows'))) { + return; // grid not yet loaded. + } + rowscount = dataRecord.yeasts.length; + if (rowscount == 0) + return; // no yeast in recipe + + $('.primary_dry').hide(); + $('.primary_liquid').hide(); + + var maybe_starter = 0; + var pitchrate = 0.75; // Yeast pitch rate default + for (i = 0; i < rowscount; i++) { + row = dataRecord.yeasts[i]; + if (row.y_use == 0) { // primary + if (row.y_form == 1) { + // Dry yeast + $('.primary_dry').show(); + console.log('dry yeast: ' + row.y_gr_hl_lo + '@' + row.y_sg_lo + ' ' + row.y_gr_hl_hi + '@' + row.y_sg_hi); + // Build the formule with the yeast parameters. + // Based on https://www.lallemandbrewing.com/en/canada/brewers-corner/brewing-tools/pitching-rate-calculator/ + var og = row.y_sg_lo; + var f1 = row.y_gr_hl_lo / 100; + var f2 = Round(f1 / 5, 6); + // After a lot of try and error, study, the best thing to increase the pitch amount is actually + // use this simple formula by Lallemand. This is about the same as sugar weight increment in the wort. + var multiplier = (sg <= og) ? f1 : (f1 + f2 * (sg - og) / 0.008); + console.log('sg: ' + sg + ' og: ' + og + ' f1: ' + f1 + ' f2: ' + f2 + ' multiplier: ' + multiplier); + // dataRecord.starter_viability + var yeast_grams = Round(volume * multiplier * (100 / dataRecord.starter_viability), 2); + $('#yeast_grams').val(yeast_grams); + var yeast_gr_hl = Round(yeast_grams / (volume * 0.01), 2); + $('#yeast_gr_hl').val(yeast_gr_hl); + //console.log('need ' + yeast_grams + ' grams, gr/hl: ' + yeast_gr_hl); + + } else { + // Liquid yeast + $('.primary_liquid').show(); + // pitchrate see https://www.brewersfriend.com/yeast-pitch-rate-and-starter-calculator/ + // and http://braukaiser.com/blog/blog/2012/11/03/estimating-yeast-growth/ + if (row.y_type == 0) { // lager yeast + pitchrate = 1.5; + if (dataRecord.est_og > 1.060) + pitchrate = 2.0; + } else if (row.y_type == 6) { // Kveik + pitchrate = 0.075; + } else { + pitchrate = 0.75; + if (dataRecord.est_og > 1.060) + pitchrate = 1.0; + } + if (dataRecord.yeast_pitchrate < 0.01) { + dataRecord.yeast_pitchrate = pitchrate; + $('#yeast_pitchrate').val(pitchrate); + } + maybe_starter = 1; + } + } + } + + needed = Round(dataRecord.yeast_pitchrate * volume * plato, 1); + $('#need_cells').val(needed); + use_cells = initcells; + if (needed <= initcells) + maybe_starter = 0; + //console.log('calcYeast() pitchrate:' + dataRecord.yeast_pitchrate + ' start:' + initcells + ' needed:' + needed + ' volume:' + volume + ' maybe_starter:' + maybe_starter); + + if (maybe_starter != dataRecord.starter_enable) { + dataRecord.starter_enable = maybe_starter; + } + if (maybe_starter) + $('#propagator').show(); + else + $('#propagator').hide(); + + if (dataRecord.starter_enable) { + + calcSteps(dataRecord.starter_type, initcells, needed); + + for (i = 1; i < 5; i++) { + $('#r' + i + '_irate').html(''); + $('#r' + i + '_growf').html(''); + $('#r' + i + '_tcells').html(''); + if (parseFloat($('#prop' + i + '_volume').val()) > 0) { + if ((parseFloat($('#prop' + i + '_irate').val()) < 25) || (parseFloat($('#prop' + i + '_irate').val()) > 100)) { + $('#r' + i + '_irate').html("<img src='images/dialog-error.png'>"); + } else { + $('#r' + i + '_irate').html("<img src='images/dialog-ok-apply.png'>"); + } + if (parseFloat($('#prop' + i + '_growf').val()) < 1) + $('#r' + i + '_growf').html("<img src='images/dialog-error.png'>"); + if (($('#prop' + i + '_type').val() > 0) && (parseFloat($('#prop' + i + '_growf').val()) > 3)) + $('#r' + i + '_growf').html("<img src='images/dialog-error.png'>"); + if (parseFloat($('#prop' + i + '_tcells').val()) > needed) + $('#r' + i + '_tcells').html("<img src='images/dialog-ok-apply.png'>"); + use_cells = parseFloat($('#prop' + i + '_tcells').val()); + } else { + $('#r' + i + '_irate').html(''); + } + } + } + $('#plato_cells').val(parseFloat(use_cells / (volume * plato))); + }; + + function whirlpoolHops() { + var row, i, time, rowscount = dataRecord.hops.length; + if (rowscount == 0) + return; + for (i = 0; i < rowscount; i++) { + row = dataRecord.hops[i]; + if (row.h_useat == 4) { + time = parseFloat(dataRecord.brew_whirlpool9) + parseFloat(dataRecord.brew_whirlpool7) + parseFloat(dataRecord.brew_whirlpool6); + dataRecord.hops[i].h_time = time; + $('#hopGrid').jqxGrid('setcellvalue', i, 'h_time', time); + } + } + }; + + function calcMiscs() { + + ok_miscs = 1; + var row, i, rowscount = dataRecord.miscs.length; + if (rowscount == 0) + return; + for (i = 0; i < rowscount; i++) { + row = dataRecord.miscs[i]; + if ((((dataRecord.inventory_reduced <= 2) && (row.m_use_use <= 2)) || // Starter, Mash, Boil + ((dataRecord.inventory_reduced <= 2) && (row.m_use_use == 6)) || // Sparge + ((dataRecord.inventory_reduced <= 3) && (row.m_use_use == 3)) || // Primary + ((dataRecord.inventory_reduced <= 5) && (row.m_use_use == 4)) || // Secondary, Teriary + ((dataRecord.inventory_reduced <= 6) && (row.m_use_use == 5))) && // Bottle + (row.m_inventory < row.m_amount)) { + ok_miscs = 0; + } + } + calcSupplies(); + }; + + function GetBUGU() { + var gu = (dataRecord.est_og - 1) * 1000; + if (gu > 0) + return dataRecord.est_ibu / gu; + else + return 0.5; + } + + function GetOptSO4Clratio() { + var BUGU = GetBUGU(); + return (1.0 / (-1.2 * BUGU + 1.4)); + } + + function setWaterAgent(name, amount, use) { + var row, i, id, found = false, miscs, rows = $('#miscGrid').jqxGrid('getrows'); + if (amount == 0) { + for (i = 0; i < rows.length; i++) { + row = rows[i]; + if (row.m_name == name && row.m_use_use == use) { + id = $('#miscGrid').jqxGrid('getrowid', i); + $('#miscGrid').jqxGrid('deleterow', id); + } + } + } else { + for (i = 0; i < rows.length; i++) { + row = rows[i]; + if (row.m_name == name && row.m_use_use == use) { + found = true; + $('#miscGrid').jqxGrid('setcellvalue', i, 'm_amount', amount / 1000); + break; + } + } + if (! found) { + miscs = new $.jqx.dataAdapter(miscInvSource, { + loadComplete: function() { + var record, i, row = {}, records = miscs.records; + for (i = 0; i < records.length; i++) { + record = records[i]; + if (record.name == name) { + row['m_name'] = record.name; + row['m_amount'] = amount / 1000; + row['m_cost'] = record.cost; + row['m_type'] = record.type; + row['m_use_use'] = use; + row['m_time'] = 0; + row['m_amount_is_weight'] = record.amount_is_weight; + row['m_inventory'] = record.inventory; + row['m_avail'] = 1; + $('#miscGrid').jqxGrid('addrow', null, row); + } + } + } + }); + miscs.dataBind(); + return; + } + } + } + + function setRangeIndicator(ion, rangeCode) { + if ((rangeCode == 'laag') || (rangeCode == 'hoog')) + $('#wr_' + ion).html("<img src='images/dialog-error.png'><span style='vertical-align: top; font-size: 10px; font-style: italic;'>" + rangeCode + '</span>'); + else + $('#wr_' + ion).html("<img src='images/dialog-ok-apply.png'>"); + } + + function mix(v1, v2, c1, c2) { + if ((v1 + v2) > 0) { + return ((v1 * c1) + (v2 * c2)) / (v1 + v2); + } + return 0; + } + + function PartCO3(pH) { + var H = Math.pow(10, -pH); + return 100 * Ka1 * Ka2 / (H * H + H * Ka1 + Ka1 * Ka2); + } + + function PartHCO3(pH) { + var H = Math.pow(10, -pH); + return 100 * Ka1 * H / (H * H + H * Ka1 + Ka1 * Ka2); + } + + function Charge(pH) { + return (-2 * PartCO3(pH) - PartHCO3(pH)); + } + + //Z alkalinity is the amount of acid (in mEq/l) needed to bring water to the target pH (Z pH) + function ZAlkalinity(pHZ) { + var C43 = Charge(4.3), + Cw = Charge(parseFloat($('#wg_ph').jqxNumberInput('decimal'))), + Cz = Charge(pHZ), + DeltaCNaught = -C43 + Cw, + CT = parseFloat($('#wg_total_alkalinity').jqxNumberInput('decimal')) / 50 / DeltaCNaught, + DeltaCZ = -Cz + Cw; + return CT * DeltaCZ; + } + + //Z Residual alkalinity is the amount of acid (in mEq/l) needed to bring the water in the mash to the target pH (Z pH) + function ZRA(pHZ) { + + var Magn, Z, Calc = parseFloat($('#wg_calcium').jqxNumberInput('decimal')) / (MMCa / 2); + Magn = parseFloat($('#wg_magnesium').jqxNumberInput('decimal')) / (MMMg / 2); + Z = ZAlkalinity(pHZ); + return Z - (Calc / 3.5 + Magn / 7); + } + + function BufferCapacity(di_ph, acid_to_ph_57, ebc, graintype) { + C1 = 0; + if ((di_ph != 5.7) && ((acid_to_ph_57 < - 0.1) || (acid_to_ph_57 > 0.1))) { + C1 = acid_to_ph_57 / (di_ph - 5.7); + } else { + // If the acid_to_ph_5.7 is unknown from the maltster, guess the required acid. + switch (graintype) { + case 0: // Base, Special, Kilned + case 3: + case 5: C1 = 0.014 * ebc - 34.192; + break; + case 2: C1 = -0.0597 * ebc - 32.457; // Crystal + break; + case 1: C1 = 0.0107 * ebc - 54.768; // Roast + break; + case 4: C1 = -149; // Sour malt + break; + } + } + return C1; + } + + function ProtonDeficit(pHZ) { + + var i, C1, x, Result = ZRA(pHZ) * parseFloat($('#wg_amount').jqxNumberInput('decimal')); + // proton deficit for the grist + if (( $('#fermentableGrid').jqxGrid('getrows'))) { + for (i = 0; i < dataRecord.fermentables.length; i++) { + row = dataRecord.fermentables[i]; + if (row.f_added == 0 && row.f_graintype != 6) { // Added == Mash && graintype != No Malt + C1 = BufferCapacity(row.f_di_ph, row.f_acid_to_ph_57, row.f_color, row.f_graintype); + x = C1 * (pHZ - row.f_di_ph); // AcidRequired(ZpH) + Result += x * row.f_amount; + } + } + } else { + error_count++; + if (error_count < 5) + console.log('ProtonDeficit(' + pHZ + ') invalid grist, return ' + Result); + } + return Result; + } + + function MashpH() { + + var n = 0, pH = 5.4, deltapH = 0.001, deltapd = 0.1, pd = ProtonDeficit(pH); + while (((pd < -deltapd) || (pd > deltapd)) && (n < 2000)) { + n++; + if (pd < -deltapd) + pH -= deltapH; + else if (pd > deltapd) + pH += deltapH; + pd = ProtonDeficit(pH); + } + pH = Round(pH, 6); + //console.log('MashpH() n: ' + n + ' pH: ' + pH); + return pH; + } + + function calcWater() { + + /* Can be called during loading and building the screens */ + if (! data_loaded) { + console.log('calcWater() failsave'); + return; + } + + var liters = 0, + calcium = 0, + magnesium = 0, + sodium = 0, + total_alkalinity = 0, + chloride = 0, + sulfate = 0, + ph = 0, + RA = 0, + frac = 0, + TpH = 0, + protonDeficit = 0, + AT, /*BT,*/ + r1d, r2d, f1d, f2d, f3d, + deltapH, deltapd, pd, n, + Res; + + if (dataRecord.w1_name == '') { + return; + } + + $('#w1_hardness').val(Hardness(dataRecord.w1_calcium, dataRecord.w1_magnesium)); + $('#w1_ra').val(ResidualAlkalinity(dataRecord.w1_total_alkalinity, dataRecord.w1_calcium, dataRecord.w1_magnesium)); + + // If there is a dillute water source, mix the waters. + if ((dataRecord.w2_name != '') && (dataRecord.w2_name != 'Geen mengwater')) { + liters = dataRecord.w1_amount + dataRecord.w2_amount; + calcium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_calcium, dataRecord.w2_calcium); + magnesium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_magnesium, dataRecord.w2_magnesium); + sodium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_sodium, dataRecord.w2_sodium); + chloride = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_chloride, dataRecord.w2_chloride); + sulfate = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_sulfate, dataRecord.w2_sulfate); + total_alkalinity = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_total_alkalinity, dataRecord.w2_total_alkalinity); + ph = -Math.log10(((Math.pow(10, -dataRecord.w1_ph) * dataRecord.w1_amount) + (Math.pow(10, -dataRecord.w2_ph) * dataRecord.w2_amount)) / liters); + $('#w2_hardness').val(Hardness(dataRecord.w2_calcium, dataRecord.w2_magnesium)); + $('#w2_ra').val(ResidualAlkalinity(dataRecord.w2_total_alkalinity, dataRecord.w2_calcium, dataRecord.w2_magnesium)); + } else { + liters = dataRecord.w1_amount; + calcium = dataRecord.w1_calcium; + magnesium = dataRecord.w1_magnesium; + sodium = dataRecord.w1_sodium; + chloride = dataRecord.w1_chloride; + sulfate = dataRecord.w1_sulfate; + total_alkalinity = dataRecord.w1_total_alkalinity; + ph = dataRecord.w1_ph; + } + var bicarbonate = Bicarbonate(total_alkalinity, ph); + + /* Save mixed water ions for later */ + var wg_calcium = calcium; + var wg_sodium = sodium; + var wg_total_alkalinity = total_alkalinity; + var wg_chloride = chloride; + var wg_sulfate = sulfate; + var wg_bicarbonate = bicarbonate; + + dataRecord.wg_amount = liters; + dataRecord.wg_ph = ph; + + $('#wg_amount').val(liters); + $('#wg_calcium').val(Round(calcium, 1)); + $('#wg_magnesium').val(Round(magnesium, 1)); + $('#wg_sodium').val(Round(sodium, 1)); + $('#wg_bicarbonate').val(Round(bicarbonate, 1)); + $('#wg_total_alkalinity').val(Round(total_alkalinity, 1)); + $('#wg_chloride').val(Round(chloride, 1)); + $('#wg_sulfate').val(Round(sulfate, 1)); + $('#wg_ph').val(Round(ph, 2)); + $('#wg_hardness').val(Round(Hardness(calcium, magnesium), 1)); + $('#wg_ra').val(Round(ResidualAlkalinity(total_alkalinity, calcium, magnesium), 1)); + + var mash_ph = Round(MashpH(), 3); + console.log('Distilled water mash pH: ' + mash_ph); + + /* Calculate Salt additions */ + if (liters > 0) { + calcium += (parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 * 1000 + + parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 * 1000 + + parseFloat($('#wa_caco3').jqxNumberInput('decimal')) * MMCa / MMCaCO3 * 1000) / liters; + magnesium += (parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMMg / MMMgSO4 * 1000 + + parseFloat($('#wa_mgcl2').jqxNumberInput('decimal')) * MMMg / MMMgCl2 * 1000) / liters; + sodium += (parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000 + + parseFloat($('#wa_nahco3').jqxNumberInput('decimal')) * MMNa / MMNaHCO3 * 1000) / liters; + sulfate += (parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 * 1000 + + parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMSO4 / MMMgSO4 * 1000) / liters; + chloride += (2 * parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCl / MMCaCl2 * 1000 + + parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMCl / MMNaCl * 1000 + + parseFloat($('#wa_mgcl2').jqxNumberInput('decimal')) * MMCl / MMMgCl2 * 1000) / liters; + bicarbonate += (parseFloat($('#wa_nahco3').jqxNumberInput('decimal')) * MMHCO3 / MMNaHCO3 * 1000 + + parseFloat($('#wa_caco3').jqxNumberInput('decimal')) / 3 * MMHCO3 / MMCaCO3 * 1000) / liters; + } + + if (dataRecord.wa_acid_name < 0 || dataRecord,wa_acid_name >= AcidTypeData.length) { + $('#wa_acid_name').val(0); + dataRecord.wa_acid_name = 0; + dataRecord.wa_acid_perc = AcidTypeData[0].AcidPrc; + $('#wa_acid_perc').val(AcidTypeData[0].AcidPrc); + } + if (last_acid == '') + last_acid = AcidTypeData[dataRecord.wa_acid_name].nl; + + if (parseFloat(dataRecord.wa_acid_perc) == 0) { + dataRecord.wa_acid_perc = AcidTypeData[AT].AcidPrc; + $('#wa_acid_perc').val(AcidTypeData[AT].AcidPrc); + } + + AT = dataRecord.wa_acid_name; + + /* Note that the next calculations do not correct the pH change by the added salts. + This pH change is at most 0.1 pH and is a minor difference in Acid amount. */ + + if (dataRecord.calc_acid) { + /* Auto calculate pH */ + $('.c_mashph').show(); + TpH = parseFloat(dataRecord.mash_ph); + protonDeficit = ProtonDeficit(TpH); + //console.log('calc_acid tgt: ' + TpH + ' protonDeficit: ' + protonDeficit); + if (protonDeficit > 0) { // Add acid + frac = CalcFrac(TpH, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3); + Acid = protonDeficit / frac; + Acid *= AcidTypeData[AT].MolWt; // mg + Acidmg = Acid; + var RealSG = Round(((AcidTypeData[AT].AcidSG - 1000) * (parseFloat(dataRecord.wa_acid_perc) / 100)) + 1000, 2); + Acid /= RealSG; + Acid /= AcidTypeData[AT].AcidPrc / 100; + Acid = Round(Acid, 2); + console.log('Mash auto Acid final ml: ' + Acid); + $('#wa_acid').val(Acid); + setWaterAgent(AcidTypeData[AT].nl, Acid, 1); + + bicarbonate = bicarbonate - protonDeficit * frac / liters; + total_alkalinity = bicarbonate * 50 / 61; + } + ph = TpH; + dataRecord.wb_ph = ph; + $('#wb_ph').val(Round(ph, 2)); + $('#est_mash_ph').val(Round(ph, 2)); + } else { + /* Manual calculate pH */ + $('.c_mashph').hide(); + console.log('calc_acid no'); + pHa = Round(ph, 3); // Adjusted water pH + // Then calculate the new pH with added acids and malts + console.log('Mash pH: ' + pHa); + Acid = AcidTypeData[AT].AcidSG * (parseFloat(dataRecord.wa_acid_perc) / 100); // ml + Acid *= parseFloat($('#wa_acid').jqxNumberInput('decimal')); + Acid /= AcidTypeData[AT].MolWt; // mg + Acidmg = Acid; + + //find the pH where the protondeficit = protondeficit by the acid + frac = CalcFrac(pHa, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3); + protonDeficit = Round(Acid * frac, 3); + //console.log('protonDeficit Acid: ' + protonDeficit + ' frac: ' + frac + ' pH: ' + pHa); + + deltapH = 0.001; + deltapd = 0.1; + pd = Round(ProtonDeficit(pHa), 6); + n = 0; + while (((pd < (protonDeficit - deltapd)) || (pd > (protonDeficit + deltapd))) && (n < 4000)) { + n++; + if (pd < (protonDeficit - deltapd)) + pHa -= deltapH; + else if (pd > (protonDeficit + deltapd)) + pHa += deltapH; + frac = CalcFrac(pHa, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3); + protonDeficit = Acid * frac; + pd = ProtonDeficit(pHa); + } + //console.log('n: ' + n + ' pd: ' + pd + ' protonDeficit: ' + protonDeficit + ' frac: ' + frac + ' pHa: ' + pHa); + bicarbonate = wg_bicarbonate - protonDeficit * frac / liters; + total_alkalinity = bicarbonate * 50 / 61; + ph = pHa; + $('#wb_ph').val(Round(ph, 2)); + $('#est_mash_ph').val(Round(ph, 2)); + } + + if ((AT == 3) && (liters > 0)) { // Sulfuric / Zwavelzuur + RA = parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 + + parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMSO4 / MMMgSO4 + + Acidmg / 1000 * MMSO4 / (MMSO4 + 2); + RA = 1000 * RA / liters; + sulfate = wg_sulfate + RA; // Not add to sulfate?? + } else if ((AT == 1) && (liters > 0)) { // Hydrochloric, Zoutzuur + RA = parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCl / MMCaCl2 + + parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMCl / MMNaCl + + Acidmg / 1000 * MMCl / (MMCl + 1); + RA = 1000 * RA / liters; + chloride = wg_chloride + RA; + } + + var BUGU = GetBUGU(); + $('#tgt_bu').val(Round(BUGU, 2)); + // From brouwhulp. + if (BUGU < 0.32) + $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Zeer moutig en zoet</span>"); + else if (BUGU < 0.43) + $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Moutig, zoet</span>"); + else if (BUGU < 0.52) + $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Evenwichtig</span>"); + else if (BUGU < 0.63) + $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Licht hoppig, bitter</span>"); + else + $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Extra hoppig, zeer bitter</span>"); + + // Sulfate to Chloride ratio (Palmer). + var OptSO4Clratio = GetOptSO4Clratio(); + $('#tgt_so4_cl').val(Round(OptSO4Clratio, 1)); + if (OptSO4Clratio < 0.4) + $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Te moutig</span>"); + else if (OptSO4Clratio < 0.6) + $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Zeer moutig</span>"); + else if (OptSO4Clratio < 0.8) + $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Moutig</span>"); + else if (OptSO4Clratio < 1.5) + $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Gebalanceerd</span>"); + else if (OptSO4Clratio < 2.0) + $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Licht bitter</span>"); + else if (OptSO4Clratio < 4.0) + $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Bitter</span>"); + else if (OptSO4Clratio < 9.0) + $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Zeer bitter</span>"); + else + $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Te bitter</span>"); + if (chloride > 0) + RA = sulfate / chloride; + else + RA = 10; + $('#got_so4_cl').val(Round(RA, 1)); + Res = 'normaal'; + if (RA < (0.8 * OptSO4Clratio)) + Res = 'laag'; + else if (RA > (1.2 * OptSO4Clratio)) + Res = 'hoog'; + setRangeIndicator('so4_cl', Res); + + $('#wb_calcium').val(Round(calcium, 1)); + $('#wb_magnesium').val(Round(magnesium, 1)); + $('#wb_sodium').val(Round(sodium, 1)); + $('#wb_sulfate').val(Round(sulfate, 1)); + $('#wb_chloride').val(Round(chloride, 1)); + $('#wb_bicarbonate').val(Round(bicarbonate, 1)); + $('#wb_total_alkalinity').val(Round(total_alkalinity, 1)); + $('#wb_hardness').val(Hardness(calcium, magnesium)); + $('#wb_ra').val(ResidualAlkalinity(total_alkalinity, calcium, magnesium)); + + if (calcium < 40) { + setRangeIndicator('calcium', 'laag'); + } else if (calcium > 150) { + setRangeIndicator('calcium', 'hoog'); + } else { + setRangeIndicator('calcium', 'normaal'); + } + if (magnesium < 5) { + setRangeIndicator('magnesium', 'laag'); + } else if (magnesium > 40) { + setRangeIndicator('magnesium', 'hoog'); + } else { + setRangeIndicator('magnesium', 'normaal'); + } + if (sodium <= 150) { + setRangeIndicator('sodium', 'normaal'); + } else { + setRangeIndicator('sodium', 'hoog'); + } + // Both chloride and sulfate should be above 50 according to + // John Palmer. So the Cl/SO4 ratio calculation will work. + if (chloride <= 50) { + setRangeIndicator('chloride', 'laag'); + } else if (chloride <= 150) { + setRangeIndicator('chloride', 'normaal'); + } else { + setRangeIndicator('chloride', 'hoog'); + } + if (sulfate <= 50) { + setRangeIndicator('sulfate', 'laag'); + } else if (sulfate <= 400) { + setRangeIndicator('sulfate', 'normaal'); + } else { + setRangeIndicator('sulfate', 'hoog'); + } + // (cloride + sulfate) > 500 is too high + if ((chloride + sulfate) > 500) { + setRangeIndicator('chloride', 'hoog'); + setRangeIndicator('sulfate', 'hoog'); + } + if (ph < 5.2) { + setRangeIndicator('ph', 'laag'); + } else if (ph > 5.6) { + setRangeIndicator('ph', 'hoog'); + } else { + setRangeIndicator('ph', 'normaal'); + } + if (bicarbonate > 250) { + setRangeIndicator('bicarbonate', 'hoog'); + } else { + setRangeIndicator('bicarbonate', 'normaal'); + } + calcSparge(); + calcMiscs(); + calcSupplies(); + } + + function calcSparge() { + + /* Based on the work of ajDeLange. */ + var ws_calcium, ws_magnesium, ws_total_alkalinity, ws_sodium, ws_chloride; + var ws_sulfate, ws_ph, ws_hardness, ws_ra; + var TargetpH = dataRecord.sparge_ph; + var Source_pH = 7.0; + + // Select watersource or fallback to the first source. + if ((dataRecord.sparge_source == 1) && (dataRecord.w2_ph > 0.0)) { // Source 2 + ws_calcium = dataRecord.w2_calcium; + ws_magnesium = dataRecord.w2_magnesium; + ws_total_alkalinity = dataRecord.w2_total_alkalinity; + ws_sodium = dataRecord.w2_sodium; + ws_chloride = dataRecord.w2_chloride; + ws_sulfate = dataRecord.w2_sulfate; + Source_pH = dataRecord.w2_ph; + $('#w2_button').jqxRadioButton({ checked: true }); + } else if ((dataRecord.sparge_source == 2) && (dataRecord.w2_ph > 0.0)) { // Mixed + ws_calcium = dataRecord.wg_calcium; + ws_magnesium = dataRecord.wg_magnesium; + ws_total_alkalinity = dataRecord.wg_total_alkalinity; + ws_sodium = dataRecord.wg_sodium; + ws_chloride = dataRecord.wg_chloride; + ws_sulfate = dataRecord.wg_sulfate; + Source_pH = dataRecord.wg_ph; + $('#wg_button').jqxRadioButton({ checked: true }); + } else { + ws_calcium = dataRecord.w1_calcium; + ws_magnesium = dataRecord.w1_magnesium; + ws_total_alkalinity = dataRecord.w1_total_alkalinity; + ws_sodium = dataRecord.w1_sodium; + ws_chloride = dataRecord.w1_chloride; + ws_sulfate = dataRecord.w1_sulfate; + Source_pH = dataRecord.w1_ph; + $('#w1_button').jqxRadioButton({ checked: true }); + } + + if (dataRecord.sparge_volume > 0) { + ws_calcium += (parseFloat($('#ss_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 * 1000 + + parseFloat($('#ss_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 * 1000) / dataRecord.sparge_volume; + ws_magnesium += (parseFloat($('#ss_mgso4').jqxNumberInput('decimal')) * MMMg / MMMgSO4 * 1000 + + parseFloat($('#ss_mgcl2').jqxNumberInput('decimal')) * MMMg / MMMgCl2 * 1000) / dataRecord.sparge_volume; + ws_sodium += (parseFloat($('#ss_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000) / dataRecord.sparge_volume; + ws_sulfate += (parseFloat($('#ss_caso4').jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 * 1000 + + parseFloat($('#ss_mgso4').jqxNumberInput('decimal')) * MMSO4 / MMMgSO4 * 1000) / dataRecord.sparge_volume; + ws_chloride += (2 * parseFloat($('#ss_cacl2').jqxNumberInput('decimal')) * MMCl / MMCaCl2 * 1000 + + parseFloat($('#ss_nacl').jqxNumberInput('decimal')) * MMCl / MMNaCl * 1000 + + parseFloat($('#ss_mgcl2').jqxNumberInput('decimal')) * MMCl / MMMgCl2 * 1000) / dataRecord.sparge_volume; + } + + /* Show the spargewate with salt additions */ + $('#sw_calcium').val(Round(ws_calcium, 1)); + $('#sw_magnesium').val(Round(ws_magnesium, 1)); + $('#sw_sodium').val(Round(ws_sodium, 1)); + $('#sw_sulfate').val(Round(ws_sulfate, 1)); + $('#sw_chloride').val(Round(ws_chloride, 1)); + $('#sw_bicarbonate').val(Round(Bicarbonate(ws_total_alkalinity, Source_pH), 1)); + $('#sw_total_alkalinity').val(Round(ws_total_alkalinity, 1)); + $('#sw_ph').val(dataRecord.sparge_ph); + $('#sw_hardness').val(Hardness(ws_calcium, ws_magnesium)); + $('#sw_ra').val(ResidualAlkalinity(ws_total_alkalinity, ws_calcium, ws_magnesium)); + + AT = dataRecord.sparge_acid_type; + if (AT < 0 || AT >= AcidTypeData.length) { + AT = 0; + dataRecord.sparge_acid_type = 0; + $('#sparge_acid_type').val(AcidTypeData[0].nl); + dataRecord.sparge_acid_perc = AcidTypeData[0].AcidPrc; + $('#sparge_acid_perc').val(dataRecord.sparge_acid_perc); + } + + /* + * Auto calculate the required acid + */ + if (dataRecord.calc_acid) { + // Step 1: Compute the mole fractions of carbonic (f1) and carbonate(f3) at the source water pH + var r1 = Math.pow(10, Source_pH - 6.35); + var r2 = Math.pow(10, Source_pH - 10.33); + var d = 1 + r1 + r1 * r2; + var f1 = 1 / d; + var f3 = r1 * r2 / d; + + //Step 2. Compute the mole fractions at pH = 4.3 (the pH which defines alkalinity) + var r143 = Math.pow(10, 4.3 - 6.35); + var r243 = Math.pow(10, 4.3 - 10.33); + var d43 = 1 + r143 + r143 * r243; + var f143 = 1 / d43; + var f343 = r143 * r243 / d43; + + //Step 4. Solve + var Ct = ws_total_alkalinity / 50 / ((f143 - f1) + (f3 - f343)); + + //Step 5. Compute mole fractions at desired pH + var r1g = Math.pow(10, TargetpH - 6.35); + var r2g = Math.pow(10, TargetpH - 10.33); + var dg = 1 + r1g + r1g * r2g; + var f1g = 1 / dg; + var f3g = r1g * r2g / dg; + + //Step 6. Use these to compute the milliequivalents acid required per liter (mEq/L) + var Acid = Ct * ((f1g - f1) + (f3 - f3g)) + Math.pow(10, -TargetpH) - Math.pow(10, -Source_pH); //mEq/l + Acid += 0.01; // Add acid that would be required for distilled water. + + //Step 8. Get the acid data. + var fract = CalcFrac(TargetpH, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3); + + //Step 9. Now divide the mEq required by the "fraction". This is the required number of moles of acid. + Acid /= fract; + + //Step 10. Multiply by molecular weight of the acid + Acid *= AcidTypeData[AT].MolWt; //mg + + //Step 11. Divide by Specific Gravity and Percentage to get the final ml. + var RealSG = Round(((AcidTypeData[AT].AcidSG - 1000) * (dataRecord.sparge_acid_perc / 100)) + 1000, 2); + Acid = Acid / RealSG; //ml + Acid *= dataRecord.sparge_volume; //ml acid total at 100% + Acid /= AcidTypeData[AT].AcidPrc / 100; //ml acid at supplied strength + Acid = Round(Acid, 2); + dataRecord.sparge_acid_amount = Acid / 1000; + $('#sparge_acid_amount').val(Acid); + } + + // Finally calculate the estimate preboil pH + var ph = -Math.log10(((Math.pow(10, -dataRecord.wb_ph) * dataRecord.wg_amount) + (Math.pow(10, -dataRecord.sparge_ph) * dataRecord.sparge_volume)) / + (dataRecord.wg_amount + dataRecord.sparge_volume)); + $('#preboil_ph').val(ph); + } + + function calcFermentation() { + var primary_svg, secondary_svg, final_svg, ABV; + if (dataRecord.brew_fermenter_sg < 1.020) + return; + if ((dataRecord.primary_end_sg > 0.990) && (dataRecord.primary_end_sg < dataRecord.brew_fermenter_sg)) { + primary_svg = Round(calc_svg(dataRecord.brew_fermenter_sg, dataRecord.primary_end_sg), 1); + $('#primary_svg').val(primary_svg); + if ((dataRecord.secondary_end_sg > 0.990) && (dataRecord.secondary_end_sg < dataRecord.brew_fermenter_sg)) { + secondary_svg = Round(calc_svg(dataRecord.brew_fermenter_sg, dataRecord.secondary_end_sg), 1); + $('#secondary_svg').val(secondary_svg); + if ((dataRecord.fg > 0.990) && (dataRecord.fg < dataRecord.brew_fermenter_sg)) { + final_svg = Round(calc_svg(dataRecord.brew_fermenter_sg, dataRecord.fg), 1); + $('#final_svg').val(final_svg); + ABV = Round(abvol(dataRecord.brew_fermenter_sg, dataRecord.fg), 2); + $('#final_abv').val(ABV); + } + } + } + } + + function ResCO2(T) { + var F = T * 1.8 + 32; + return Round(3.0378 - 0.050062 * F + 0.00026555 * F * F, 6); + } + + function CarbCO2toS(CO2, T, SFactor) { + //var sugar = SFactor * (CO2 - ResCO2(CO2, T)) / 0.286; + var sugar = Round(SFactor * (CO2 - ResCO2(T)) * 4.014094, 6); + if (sugar < 0) + sugar = 0; + return Round(sugar, 3); + } + + function GetPressure(CO2, T1, T2) { + var P, V = CO2 - ResCO2(T1); + V = CO2; // TODO: temp only total pressure, testing + if (V < 0) + return 0; + 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, 2); // atm to bar + console.log("GetPressure(" + CO2 + ", " + T1 + ", " + T2 + ") V:" + V + " Bar: " + P + " ignored ResCO2: " + ResCO2(T1)); + return P; + } + + function CarbCO2ToPressure(CO2, T) { + return (CO2 - (-0.000005594056 * Math.pow(T, 4) + 0.000144357886 * Math.pow(T, 3) + + 0.000362999168 * T * T - 0.064872987645 * T + 1.641145175049)) / + (0.00000498031 * Math.pow(T, 4) - 0.00024358267 * Math.pow(T, 3) + 0.00385867329 * T * T - 0.05671206825 * T + 1.53801423376); + } + + function calcCarbonation() { + + var TSec, ABV, bvol, balc, babv, mvol, malc, tvol, talc, i, row, SFactor, pvol, pabv, Pressure, kabv; + + console.log('calcCarbonation()'); + + TSec = dataRecord.secondary_temp; + if (TSec < 1) + TSec = dataRecord.primary_end_temp; + if (TSec < 1) + TSec = 18; + + if (dataRecord.fg == 0.000) + ABV = abvol(dataRecord.brew_fermenter_sg, parseFloat($('#est_fg').jqxNumberInput('decimal'))); + else + ABV = abvol(dataRecord.brew_fermenter_sg, dataRecord.fg); + + /* Calculate new volume and alcohol. */ + bvol = dataRecord.package_volume - (ABV * dataRecord.package_volume) / 100; + balc = dataRecord.package_volume - bvol; + mvol = dataRecord.package_infuse_amount - (dataRecord.package_infuse_abv * dataRecord.package_infuse_amount) / 100; + malc = dataRecord.package_infuse_amount - mvol; + talc = balc + malc; + tvol = bvol + mvol; + ABV = Round(talc / (tvol + talc) * 100, 2); + dataRecord.package_abv = ABV; + $('#package_abv').val(ABV); + + //console.log("calcCarbonation() TSec:"+TSec+" ABV:"+ABV); + if (!(rows = $('#fermentableGrid').jqxGrid('getrows'))) { + return; + } + + // Bottles + dataRecord.bottle_priming_amount = 0; + dataRecord.bottle_priming_total = 0; + for (i = 0; i < rows.length; i++) { + row = rows[i]; + if (row.f_added == 4) { + SFactor = 1 / ((row.f_yield / 100) * (1 - row.f_moisture / 100)); + dataRecord.bottle_priming_amount = CarbCO2toS(dataRecord.bottle_carbonation, TSec, SFactor); + dataRecord.bottle_priming_total = Round(dataRecord.bottle_amount * dataRecord.bottle_priming_amount, 2); + $('#fermentableGrid').jqxGrid('setcellvalue', i, 'f_amount', dataRecord.bottle_priming_total / 1000); + } + } + $('#bottle_priming_amount').val(Round(dataRecord.bottle_priming_amount, 1)); + $('#bottle_priming_total').val(dataRecord.bottle_priming_total); + pabv = ABV + dataRecord.bottle_priming_amount * 0.47 / 7.907; + pvol = dataRecord.bottle_amount - (pabv * dataRecord.bottle_amount) / 100; + talc = dataRecord.bottle_amount - pvol; + tvol = pvol + dataRecord.bottle_priming_water; + babv = Round(talc / (tvol + talc) * 100, 2); + //console.log("bottle pabv:"+pabv+" pvol:"+pvol+" wvol:"+dataRecord.bottle_priming_water+" tvol:"+tvol+" talc:"+talc+" abv:"+babv); + $('#bottle_abv').val(babv); + $('#bottle_pressure').val(GetPressure(dataRecord.bottle_carbonation, TSec, dataRecord.bottle_carbonation_temp)); + + // Kegs + Pressure = CarbCO2ToPressure(dataRecord.keg_carbonation, dataRecord.keg_carbonation_temp); + if (Pressure < 0) + Pressure = 0; + dataRecord.keg_pressure = Pressure; + $('#keg_pressure').val(Round(Pressure, 1)); + + dataRecord.keg_priming_amount = 0; + dataRecord.keg_priming_total = 0; + if (!dataRecord.keg_forced_carb) { + for (i = 0; i < rows.length; i++) { + row = rows[i]; + if (row.f_added == 5) { + SFactor = 1 / ((row.f_yield / 100) * (1 - row.f_moisture / 100)); + dataRecord.keg_priming_amount = CarbCO2toS(dataRecord.keg_carbonation, TSec, SFactor); + dataRecord.keg_priming_total = Round(dataRecord.keg_amount * dataRecord.keg_priming_amount, 2); + $('#fermentableGrid').jqxGrid('setcellvalue', i, 'f_amount', dataRecord.keg_priming_total / 1000); + } + } + $('#keg_priming_amount').val(Round(dataRecord.keg_priming_amount, 1)); + $('#keg_priming_total').val(dataRecord.keg_priming_total); + pabv = ABV + dataRecord.keg_priming_amount * 0.47 / 7.907; + pvol = dataRecord.keg_amount - (pabv * dataRecord.keg_amount) / 100; + talc = dataRecord.keg_amount - pvol; + tvol = pvol + dataRecord.keg_priming_water; + kabv = Round(talc / (tvol + talc) * 100, 2); + //console.log("kegs pabv:"+pabv+" pvol:"+pvol+" wvol:"+dataRecord.keg_priming_water+" tvol:"+tvol+" talc:"+talc+" abv:"+kabv); + $('#keg_abv').val(kabv); + } else { + $('#keg_priming_amount').val(0); + $('#keg_priming_total').val(0); + $('#keg_abv').val(ABV); + } + } + + function calcStage() { + /* + * Set stage and enable or disable parts of the screens. + */ + $('#stage').val(StageData[dataRecord.stage].nl); + + /* + * Enable or disable parts of the screens. + */ + $('#jqxTabs').jqxTabs((dataRecord.stage < 1) ? 'disableAt':'enableAt', 8); // Brewday tab + $('#jqxTabs').jqxTabs((dataRecord.stage > 2) ? 'enableAt':'disableAt', 9); // Fermentation tab + $('#jqxTabs').jqxTabs((dataRecord.stage < 9) ? 'disableAt':'enableAt', 11); // Tasting tab + } + + + // initialize the input fields. + // Tab 1, Algemeen + $('#name').jqxTooltip({ content: 'De naam voor dit product.' }); + $('#code').jqxTooltip({ content: 'Product code nummer.' }); + $('#birth').jqxTooltip({ content: 'De ontwerp datum van dit product.' }); + $('#stage').jqxTooltip({ content: 'De productie fase van dit product.' }); + $('#divide_batch').jqxTooltip({ content: 'Het aantal extra gesplitste batches.' }); + $('#divide_type').jqxTooltip({ content: 'Het splitsing moment in het productie proces.' }); + $('#notes').jqxTooltip({ content: 'De uitgebreide opmerkingen over dit product.' }); + $('#type').jqxTooltip({ content: 'Het brouw type van dit recept.' }); + $('#efficiency').jqxTooltip({ content: 'Het rendement van maischen en koken.' }); + $('#batch_size').jqxTooltip({ content: 'Het volume van het gekoelde wort na het koken.' }); + $('#boil_time').jqxTooltip({ content: 'De kooktijd in minuten.' }); + $('#boil_size').jqxTooltip({ content: 'Het volume van het wort voor het koken.' }); + $('#st_guide').jqxTooltip({ content: 'De bierstijl gids voor dit recept.'}); + $('#st_name').jqxTooltip({ content: 'De bierstijl naam voor dit recept.'}); + $('#st_letter').jqxTooltip({ content: 'De bierstijl letter voor dit recept.'}); + $('#st_letter').jqxInput({ theme: theme, width: 90, height: 23 }); + $('#st_type').jqxTooltip({ content: 'Het bierstijl type.'}); + $('#st_category').jqxTooltip({ content: 'De Amerikaanse bierstijl categorie.'}); + $('#st_category_number').jqxTooltip({ content: 'De Amerikaanse bierstijl categorie sub nummer.'}); + $('#est_og').jqxTooltip({ content: 'Het begin SG wat je wilt bereiken. De moutstort wordt automatisch herberekend.' }); + $('#st_og_min').jqxTooltip({ content: 'Het minimum begin SG voor deze bierstijl.'}); + $('#st_og_max').jqxTooltip({ content: 'Het maximum begin SG voor deze bierstijl.'}); + $('#est_fg').jqxTooltip({ content: 'Het verwachte eind SG. Dit wordt automatisch berekend.' }); + $('#st_fg_min').jqxTooltip({ content: 'Het minimum eind SG voor deze bierstijl.'}); + $('#st_fg_max').jqxTooltip({ content: 'Het maximum eind SG voor deze bierstijl.'}); + $('#est_abv').jqxTooltip({ content: 'Alcohol volume %. Dit wordt automatisch berekend.' }); + $('#st_abv_min').jqxTooltip({ content: 'Het minimum alcohol volume % voor deze bierstijl.'}); + $('#st_abv_max').jqxTooltip({ content: 'Het maximum alcohol volume % voor deze bierstijl.'}); + $('#est_color').jqxTooltip({ content: 'De kleur in EBC. Dit wordt automatisch berekend.' }); + $('#st_color_min').jqxTooltip({ content: 'De minimum kleur voor deze bierstijl.'}); + $('#st_color_max').jqxTooltip({ content: 'De maximum kleur voor deze bierstijl.'}); + $('#est_ibu').jqxTooltip({ content: 'De bitterheid in IBU. Dit wordt automatisch berekend.' }); + $('#st_ibu_min').jqxTooltip({ content: 'De minimum bitterheid voor deze bierstijl.'}); + $('#st_ibu_max').jqxTooltip({ content: 'De maximum bitterheid voor deze bierstijl.'}); + $('#kcal').jqxTooltip({ content: 'Energie-inhoud in kcal/liter.' }); + $('#est_carb').jqxTooltip({ content: 'Koolzuur volume. Dit wordt automatisch berekend.' }); + $('#st_carb_min').jqxTooltip({ content: 'Het minimum koolzuur volume voor deze bierstijl.'}); + $('#st_carb_max').jqxTooltip({ content: 'Het maximum koolzuur volume voor deze bierstijl.'}); + + $('#name').jqxInput({ theme: theme, width: 640, height: 23 }); + $('#code, #stage').jqxInput({ theme: theme, width: 100, height: 23 }); + $('#locked').jqxCheckBox({ theme: theme, width: 120, height: 23, disabled: true }); + $('#birth,#divide_batch,#divide_type').jqxInput({ theme: theme, width: 120, height: 23 }); + $('#notes').jqxInput({ theme: theme, width: 960, height: 100 }); + $('#type').jqxInput({ theme: theme, width: 180, height: 23 }); + $('#efficiency').jqxNumberInput(Show1dec); + $('#batch_size').jqxNumberInput(Show1dec); + $('#boil_time').jqxNumberInput(Show0dec); + $('#boil_size').jqxNumberInput(Show2dec); + $('#st_guide,#st_name,#st_type,#st_category').jqxInput({ theme: theme, width: 250, height: 23 }); + $('#est_og').jqxNumberInput(Show3dec); + $('#est_fg').jqxNumberInput(Show3dec); + $('#st_og_min,#st_og_max,#st_fg_min,#st_fg_max').jqxNumberInput({ inputMode: 'simple', theme: theme, width: 50, height: 23, decimalDigits: 3, readOnly: true }); + $('#est_ibu,#est_color').jqxNumberInput(Show0dec); + $('#color_method').jqxInput({ theme: theme, width: 180, height: 23 }); + $('#st_color_min,#st_color_max,#st_category_number,#st_ibu_min,#st_ibu_max,#kcal').jqxNumberInput(Smal0dec); + $('#ibu_method').jqxInput({ theme: theme, width: 180, height: 23 }); + $('#est_abv,#st_abv_min,#st_abv_max,#est_carb,#st_carb_min,#st_carb_max').jqxNumberInput(Smal1dec); + + // Tab 2, Equipment + $('#eq_name').jqxTooltip({ content: 'De naam van deze brouw apparatuur.' }); + $('#eq_boil_size').jqxTooltip({ content: 'Normaal kook volume in liters' }); + $('#eq_batch_size').jqxTooltip({ content: 'Berekende batch grootte in liters aan het eind van de kook.' }); + $('#eq_tun_volume').jqxTooltip({ content: 'Maisch ketel volume.' }); + $('#eq_top_up_water').jqxTooltip({ content: 'Extra water in het gistvat.' }); + $('#eq_trub_chiller_loss').jqxTooltip({ content: 'Standaard verlies bij het overbrengen naar het gistvat.' }); + $('#eq_evap_rate').jqxTooltip({ content: 'Verdamping in liters per uur.' }); + $('#eq_boil_time').jqxTooltip({ content: 'Normale kooktijd in minuten, 0 voor no-boil recepten.' }); + $('#eq_top_up_kettle').jqxTooltip({ content: 'Extra water toevoegen tijdens de kook.' }); + $('#eq_hop_utilization').jqxTooltip({ content: '100% voor kleine installaties, hoger voor grote brouwerijen.' }); + $('#eq_notes').jqxTooltip({ content: 'Opmerkingen over deze apparatuur.' }); + $('#eq_lauter_volume').jqxTooltip({ content: 'Filterkuip volume.' }); + $('#eq_lauter_deadspace').jqxTooltip({ content: 'Filterkuip verlies in liters.' }); + $('#eq_kettle_volume').jqxTooltip({ content: 'Kook ketel volume in liters.' }); + $('#eq_mash_volume').jqxTooltip({ content: 'Maisch water voor de eerste stap.' }); + $('#eq_mash_max').jqxTooltip({ content: 'De maximale moutstort in Kg.' }); + $('#eq_efficiency').jqxTooltip({ content: 'Gemiddeld brouwzaal rendement.' }); + + $('#eq_name').jqxInput({ theme: theme, width: 250, height: 23 }); + $('#eq_evap_rate').jqxNumberInput(Show2dec); + $('#eq_boil_time,#eq_hop_utilization').jqxNumberInput(Show0dec); + $('#eq_notes').jqxInput({ theme: theme, width: 960, height: 200 }); + $('#eq_boil_size,#eq_batch_size,#eq_tun_volume,#eq_top_up_water,#eq_trub_chiller_loss,#eq_top_up_kettle').jqxNumberInput(Show1dec); + $('#eq_lauter_volume,#eq_lauter_deadspace,#eq_kettle_volume,#eq_mash_volume,#eq_mash_max,#eq_efficiency').jqxNumberInput(Show1dec); + + // Tab 3, Fermentables + $('#est_color2').jqxTooltip({ content: 'De kleur in EBC. Dit wordt automatisch berekend.' }); + $('#est_og2').jqxTooltip({ content: 'Het geschatte begin SG van dit product.' }); + $('#mash_kg').jqxTooltip({ content: 'Het gewicht van alle mouten in de maisch.' }); + + $('#est_color2').jqxNumberInput(Show0dec); + $('#est_og2,#mash_kg').jqxNumberInput(Show3dec); + + $('#perc_malts').jqxProgressBar({ + width: 300, height: 23, theme: theme, showText: true, max: 120, animationDuration: 0, + colorRanges: [{ stop: 90, color: '#008C00' },{ stop: 100, color: '#EB7331' },{ stop: 120, color: '#FF0000' }], + renderText: function(text) { return (Math.round(parseInt(text) * 1.2)) + '%'; } + }); + $('#perc_sugars').jqxProgressBar({ + width: 300, height: 23, theme: theme, showText: true, max: 50, animationDuration: 0, + colorRanges: [{ stop: 20, color: '#008C00' },{ stop: 50, color: '#FF0000' }], + renderText: function(text) { return (Math.round(parseInt(text) * 5) / 10) + '%'; } + }); + $('#perc_cara').jqxProgressBar({ + width: 300, height: 23, theme: theme, showText: true, max: 50, animationDuration: 0, + colorRanges: [{ stop: 25, color: '#008C00' },{ stop: 50, color: '#FF0000' }], + renderText: function(text) { return (Math.round(parseInt(text) * 5) / 10) + '%'; } + }); + $('#ferm_lintner').jqxProgressBar({ + width: 300, height: 23, theme: theme, showText: true, max: 200, animationDuration: 0, + colorRanges: [{ stop: 30, color: '#FF0000' },{ stop: 40, color: '#EB7331' },{ stop: 200, color: '#008C00' }], + renderText: function(text) { return (parseInt(text) * 2) + ' lintner'; } + }); + + // Tab 4, Hops + $('#est_ibu2').jqxTooltip({ content: 'De bitterheid in IBU. Dit wordt automatisch berekend.' }); + $('#est_ibu2').jqxNumberInput(Smal0dec); + $('#hop_flavour').jqxProgressBar({ + width: 300, height: 23, theme: theme, showText: true, animationDuration: 0, + colorRanges: [ + { stop: 20, color: '#004D00' }, + { stop: 40, color: '#008C00' }, + { stop: 60, color: '#00BF00' }, + { stop: 80, color: '#00FF00' }, + { stop: 100, color: '#80FF80' } + ], + renderText: function(text) { + var val = parseInt(text); + if (val < 20) + return 'Weinig'; + else if (val < 40) + return 'Matig'; + else if (val < 60) + return 'Redelijk'; + else if (val < 80) + return 'Veel'; + else + return 'Zeer veel'; + } + }); + $('#hop_aroma').jqxProgressBar({ + width: 300, height: 23, theme: theme, showText: true, animationDuration: 0, + colorRanges: [ + { stop: 20, color: '#004D00' }, + { stop: 40, color: '#008C00' }, + { stop: 60, color: '#00BF00' }, + { stop: 80, color: '#00FF00' }, + { stop: 100, color: '#80FF80' } + ], + renderText: function(text) { + var val = parseInt(text); + if (val < 20) + return 'Weinig'; + else if (val < 40) + return 'Matig'; + else if (val < 60) + return 'Redelijk'; + else if (val < 80) + return 'Veel'; + else + return 'Zeer veel'; + } + }); + + // Tab 5, Miscs + + // Tab 6, Yeasts + $('#est_fg2').jqxTooltip({ content: 'Het verwachte eind SG. Dit wordt automatisch berekend.' }); + $('#est_abv2').jqxTooltip({ content: 'Verwacht alcohol volume %. Dit wordt automatisch berekend.' }); + $('#yeast_grams').jqxTooltip({ content: 'De gewenste totale hoeveelheid droge gist voor dit bier.' }); + $('#yeast_gr_hl').jqxTooltip({ content: 'De werkelijke hoeveelheid gist per hectoliter.' }); + $('#yeast_cells').jqxTooltip({ content: 'Het aantal miljard beschikbare gistcellen zonder eventuele starter.' }); + $('#need_cells').jqxTooltip({ content: 'Het aantal miljard nodige cellen is afhankelijk van het begin SG, biertype en volume.' }); + $('#plato_cells').jqxTooltip({ content: 'De berekende pitchrate in miljard cellen per ml per graad Plato.' }); + $('#yeast_prod_date').jqxTooltip({ content: 'Bij korrelgisten is meestal "best voor" datum op het zakje gedrukt.<br>Gebruik die datum maar dan twee jaar eerder als productie datum.<br>Bij White Labs is de productie datum vier maanden voor de "Best by" datum die geprint op het buisje.<br>Bij Wyeast is dit de "manufacture date" die op het pak geprint is.<br>Voor schuine buis, slurry, opkweek en gedroogd is dit de datum dat je de gist geoogst hebt.' }); + $('#yeast_pitchrate').jqxTooltip({ content: 'De gewenste pitchrate in miljard cellen per ml per graad Plato voor de vergisting van dit bier.' }); + + $('#est_fg2,#plato_cells').jqxNumberInput(Show3dec); + $('#est_fg2').jqxNumberInput({ width: 70 }); + $('#est_abv2').jqxNumberInput(Show2dec); + $('#est_abv2').jqxNumberInput({ width: 70, symbol: '%', symbolPosition: 'right' }); + $('#yeast_grams').jqxNumberInput(Show1dec); + $('#yeast_gr_hl').jqxNumberInput(Show1dec); + $('#yeast_cells,#need_cells').jqxNumberInput(Show1dec); + $('#yeast_prod_date').jqxDateTimeInput(Dateopts); + $('#yeast_prod_date').jqxDateTimeInput({ disabled: true }); + $('#yeast_pitchrate').jqxNumberInput(Show3dec); + for (i = 1; i < 5; i++) { + $('#prop' + i + '_volume').jqxTooltip({ content: 'Het volume van deze starter stap.' }); + $('#prop' + i + '_irate').jqxTooltip({ content: 'Voor de beste gistgroei, houd de injectie factor tussen de 25 en 100 miljoen cellen per ml.' }); + $('#prop' + i + '_ncells').jqxTooltip({ content: 'Het aantal miljard nieuwe gistcellen in deze stap.' }); + $('#prop' + i + '_tcells').jqxTooltip({ content: 'Het totaal aantal miljard gistcellen na deze stap.' }); + $('#prop' + i + '_growf').jqxTooltip({ content: 'De groeifactor, minstens 1. Ongeroerde starters komen meestal niet boven de 3.' }); + + $('#prop' + i + '_type').jqxInput({ theme: theme, width: 120, height: 23 }); + $('#prop' + i + '_volume').jqxNumberInput(Show3dec); + $('#prop' + i + '_irate,#prop' + i + '_ncells,#prop' + i + '_tcells').jqxNumberInput(Show1dec); + $('#prop' + i + '_growf').jqxNumberInput(Show2dec); + $('#prop' + i + '_type,#prop' + i + '_volume,#prop' + i + '_irate,#prop' + i + '_ncells,#prop' + i + '_tcells,#prop' + i + '_growf').hide(); + } + $('#starter_type').jqxInput({ theme: theme, width: 120, height: 23 }); + $('#starter_sg').jqxTooltip({ content: 'Het ideale starter SG moet tussen de 1.030 en 1.040 zijn. Optimaal is 1.037.' }); + $('#starter_sg').jqxNumberInput(Show3dec); + $('#starter_viability').jqxTooltip({ content: 'De gist conditie.' }); + $('#starter_viability').jqxNumberInput(Show0dec); + + // Tab 7, Mashing + $('#mash_name').jqxTooltip({ content: 'De omschrijving van dit maisch profiel.' }); + $('#mash_name').jqxInput({ theme: theme, width: 320, height: 23 }); + $('#est_mashvol').jqxTooltip({ content: 'Het totale volume van het maishwater en de mout in de maish pan.' }); + $('#est_mashvol').jqxNumberInput(Show1dec); + $('#est_mashtime').jqxTooltip({ content: 'De totale tijdsduur van het maischen.' }); + $('#est_mashtime').jqxInput({ theme: theme, width: 70, height: 23 }); + + // Tab 8, Water + $('#tgt_bu').jqxNumberInput(Show2wat); + $('#tgt_so4_cl,#got_so4_cl').jqxNumberInput(Show1wat); + $('#preboil_ph').jqxNumberInput(Show2wat); + + // Water source 1 + $('#w1_name').jqxInput({ theme: theme, width: 200, height: 23 }); + $('#w1_button').jqxRadioButton({ theme: theme, width: 50, height: 23, disabled: true }); + $('#w1_amount,#w1_calcium,#w1_magnesium,#w1_sodium,#w1_bicarbonate,#w1_total_alkalinity,#w1_chloride,#w1_sulfate').jqxNumberInput(Show1wat); + $('#w1_ph').jqxNumberInput(Show2wat); + $('#w1_hardness').jqxNumberInput(Show1wat); + $('#w1_ra').jqxNumberInput(Show1wat); + // Water source 2 + $('#w2_name').jqxInput({ theme: theme, width: 200, height: 23 }); + $('#w2_button').jqxRadioButton({ theme: theme, width: 50, height: 23, disabled: true }); + $('#w2_amount').jqxNumberInput(Show1wat); + $('#w2_calcium,#w2_magnesium,#w2_sodium,#w2_bicarbonate,#w2_total_alkalinity,#w2_chloride,#w2_sulfate').jqxNumberInput(Show1wat); + $('#w2_ph').jqxNumberInput(Show2wat); + $('#w2_hardness').jqxNumberInput(Show1wat); + $('#w2_ra').jqxNumberInput(Show1wat); + // Water mixed + $('#wg_button').jqxRadioButton({ theme: theme, width: 50, height: 23, disabled: true }); + $('#wg_amount,#wg_calcium,#wg_magnesium,#wg_sodium,#wg_bicarbonate,#wg_total_alkalinity,#wg_chloride,#wg_sulfate').jqxNumberInput(Show1wat); + $('#wg_ph').jqxNumberInput(Show2wat); + $('#wg_hardness').jqxNumberInput(Show1wat); + $('#wg_ra').jqxNumberInput(Show1wat); + // Water treated + $('#wb_calcium').jqxTooltip({ content: 'De ideale hoeveelheid Calcium is tussen 40 en 150.'}); + $('#wb_calcium').jqxNumberInput(Show1wat); + $('#wb_magnesium').jqxTooltip({ content: 'De ideale hoeveelheid Magnesium is tussen 5 en 40.'}); + $('#wb_magnesium').jqxNumberInput(Show1wat); + $('#wb_sodium').jqxTooltip({ content: 'De ideale hoeveelheid Natrium is lager dan 150.'}); + $('#wb_sodium').jqxNumberInput(Show1wat); + $('#wb_chloride').jqxTooltip({ content: 'De ideale hoeveelheid Chloride is tussen 50 en 150. Samen met Sulfaat minder dan 500.'}); + $('#wb_chloride').jqxNumberInput(Show1wat); + $('#wb_sulfate').jqxTooltip({ content: 'De ideale hoeveelheid Sulfaat is tussen 50 en 400. Samen met Chloride minder dan 500.'}); + $('#wb_sulfate').jqxNumberInput(Show1wat); + $('#wb_bicarbonate').jqxTooltip({ content: '0 tot 50 lichte bieren, 50 tot 150 amber bieren, 150 tot 250 donkere bieren.'}); + $('#wb_bicarbonate').jqxNumberInput(Show1wat); + $('#wb_ph').jqxNumberInput(Show2wat); + $('#wb_hardness').jqxNumberInput(Show1wat); + $('#wb_ra').jqxNumberInput(Show1wat); + // Sparge water + $('#sw_amount').jqxNumberInput(Show1wat); + $('#sw_calcium').jqxNumberInput(Show1wat); + $('#sw_magnesium').jqxNumberInput(Show1wat); + $('#sw_sodium').jqxNumberInput(Show1wat); + $('#sw_bicarbonate').jqxNumberInput(Show1wat); + $('#sw_total_alkalinity').jqxNumberInput(Show1wat); + $('#sw_chloride').jqxNumberInput(Show1wat); + $('#sw_sulfate').jqxNumberInput(Show1wat); + $('#sw_ph').jqxNumberInput(Show2wat); + $('#sw_hardness').jqxNumberInput(Show1wat); + $('#sw_ra').jqxNumberInput(Show1wat); + + // Water agents + $('#wa_cacl2').jqxTooltip({ content: 'Voor het maken van een ander waterprofiel. Voegt calcium en chloride toe. Voor het verbeteren van zoetere bieren.' }); + $('#wa_cacl2').jqxNumberInput(Show2wat); + $('#ss_cacl2').jqxNumberInput(Show2wat); + + $('#wa_caso4').jqxTooltip({ + content: 'Gips. Voor het maken van een ander waterprofiel. Voegt calcium en sulfaat toe. Voor het verbeteren van bittere bieren.' + }); + $('#wa_caso4').jqxNumberInput(Show2wat); + $('#ss_caso4').jqxNumberInput(Show2wat); + + $('#wa_mgso4').jqxTooltip({ content: 'Epsom zout. Voor het maken van een ander waterprofiel. Voegt magnesium en sulfaat toe. Gebruik spaarzaam!' }); + $('#wa_mgso4').jqxNumberInput(Show2wat); + $('#ss_mgso4').jqxNumberInput(Show2wat); + + $('#wa_nacl').jqxTooltip({ + content: 'Keukenzout. Voor het maken van een ander waterprofiel. Voegt natrium en chloride toe. ' + + 'Voor het accentueren van zoetheid. Bij hoge dosering wordt het bier ziltig.' + }); + $('#wa_nacl').jqxNumberInput(Show2wat); + $('#ss_nacl').jqxNumberInput(Show2wat); + + $('#wa_mgcl2').jqxTooltip({ content: 'Magnesiumchloride'}); + $('#wa_mgcl2').jqxNumberInput(Show2wat); + $('#ss_mgcl2').jqxNumberInput(Show2wat); + + $('#wa_nahco3').jqxTooltip({ content: 'Baksoda'}); + $('#wa_caco3').jqxTooltip({ content: 'Kalk'}); + $('#wa_nahco3,#wa_caco3').jqxNumberInput(Show2wat); + + $('#mash_ph').jqxTooltip({ content: 'Maisch pH tussen 5.2 en 5.6. Gebruik 5.2 voor lichte en 5.5 voor donkere bieren.'}); + $('#mash_ph').jqxNumberInput(Show2dec); + + $('#calc_acid').jqxCheckBox({ theme: theme, width: 120, height: 23, disabled: true }); + + $('#wa_acid_name').jqxInput({ theme: theme, width: 130, height: 23 }); + $('#wa_acid').jqxNumberInput(Show2dec); + $('#wa_acid').jqxNumberInput({ symbol: ' ml', symbolPosition: 'right' }); + $('#wa_acid_perc').jqxNumberInput(Show0dec); + $('#wa_acid_perc').jqxNumberInput({ symbol: '%', symbolPosition: 'right' }); + + // Sparge water + $('#sparge_ph').jqxNumberInput(Show2dec); + $('#sparge_acid_amount').jqxNumberInput(Show2dec); + $('#sparge_acid_amount').jqxNumberInput({ symbol: ' ml', symbolPosition: 'right' }); + $('#sparge_acid_type').jqxInput({ theme: theme, width: 130, height: 23 }); + $('#sparge_acid_perc').jqxNumberInput(Show0dec); + $('#sparge_acid_perc').jqxNumberInput({ symbol: '%', symbolPosition: 'right' }); + + // Tab 9, Brewday + $('#brew_date_start').jqxTooltip({ content: 'Brouw datum en tijd. Voor planning laat de tijd op 00:00:00 staan.' }); + $('#brew_date_end').jqxTooltip({ content: 'End datum en tijd van de brouw. Leeg laten als er nog niet gebrouwen is.' }); + $('#brew_mash_ph').jqxTooltip({ content: 'De gemeten pH tijdens het maischen eventueel na correctie.' }); + $('#est_mash_ph').jqxTooltip({ content: 'De gewenste pH tijdens het maischen.' }); + $('#brew_preboil_ph').jqxTooltip({ content: 'De gemeten pH in de kookketel na het spoelen en voor de kook.' }); + $('#brew_aboil_ph').jqxTooltip({ content: 'De gemeten pH na het koken.' }); + $('#brew_mash_sg').jqxTooltip({ content: 'Het bereikte SG na het maischen.' }); + $('#est_mash_sg').jqxTooltip({ content: 'Het berekende verwachte SG na het maischen.' }); + $('#brew_preboil_sg').jqxTooltip({ content: 'Het gemeten SG in de kookketel na het spoelen en voor het koken.' }); + $('#est_pre_sg').jqxTooltip({ content: 'Het berekende SG in de kookketel na het spoelen en voor het koken.' }); + $('#brew_aboil_sg').jqxTooltip({ content: 'Het gemeten SG in de kookketel na het koken.' }); + $('#est_og3').jqxTooltip({ content: 'Het gewenste SG in de kookketel na het koken zonder eventuele suikers die tijdens de vergisting toegevoegd worden.' }); + $('#brew_mash_efficiency').jqxTooltip({ content: 'Het behaalde maisch rendement.' }); + $('#brew_preboil_volume').jqxTooltip({ content: 'Het gemeten volume van het wort voor het koken.' }); + $('#est_pre_vol').jqxTooltip({ content: 'Het berekende volume van het wort voor het koken.' }); + $('#brew_aboil_volume').jqxTooltip({ content: 'Het gemeten volume van het wort na het koken.' }); + $('#est_a_vol').jqxTooltip({ content: 'Het gewenste volume na het koken.' }); + $('#brew_preboil_efficiency').jqxTooltip({ content: 'Het berekende rendement voor het koken.' }); + $('#brew_aboil_efficiency').jqxTooltip({ content: 'Het bereikte rendement na het koken.' }); + $('#brew_sparge_temperature').jqxTooltip({ content: 'De spoelwater temperatuur, in te stellen in de Water tab.' }); + $('#brew_sparge_volume').jqxTooltip({ content: 'Het spoelwater voorraad volume, in te stellen in de Water tab.' }); + $('#brew_date_start,#brew_date_end').jqxDateTimeInput(DateTimeopts); + $('#brew_date_start,#brew_date_end').jqxDateTimeInput({ disabled: true }); + $('#est_mash_ph').jqxNumberInput(Show2wat); + $('#brew_mash_ph,#brew_preboil_ph,#brew_aboil_ph').jqxNumberInput(Show2dec); + $('#brew_mash_sg,#brew_preboil_sg,#brew_aboil_sg').jqxNumberInput(Show3dec); + $('#est_mash_sg,#est_pre_sg,#est_og3').jqxNumberInput(Show3wat); + $('#brew_mash_efficiency').jqxNumberInput(Show1dec); + $('#brew_preboil_volume,#brew_aboil_volume').jqxNumberInput(Show1dec); + $('#est_pre_vol,#est_a_vol').jqxNumberInput(Show1wat); + $('#brew_preboil_efficiency,#brew_aboil_efficiency,#brew_sparge_temperature,#brew_sparge_volume,#brew_sparge_est').jqxNumberInput(Show1dec); + $('#brew_cooling_to').jqxNumberInput(Show1dec); + $('#brew_sparge_ph').jqxNumberInput(Show2dec); + $('#brew_cooling_method').jqxInput({ theme: theme, width: 180, height: 23 }); + $('#brew_cooling_time,#brew_whirlpool9,#brew_whirlpool7,#brew_whirlpool6,#brew_whirlpool2,#brew_aeration_time,#brew_aeration_speed').jqxNumberInput(Show0dec); + $('#brew_aeration_type').jqxInput({ theme: theme, width: 180, height: 23 }); + $('#brew_fermenter_volume').jqxNumberInput(Show1dec); + $('#brew_fermenter_sg').jqxNumberInput(Show3dec); + $('#brew_fermenter_extrawater,#brew_fermenter_tcloss').jqxNumberInput(Show1dec); + $('#brew_fermenter_ibu,#brew_fermenter_color').jqxNumberInput(Show0dec); + + // Tab 10, Fermentation + $('#brew_fermenter_sg2').jqxTooltip({ content: 'Het behaalde SG in het gistvat, overgenomen van de brouwdag.' }); + $('#primary_start_temp').jqxTooltip({ content: 'De begintemperatuur van de hoofdvergisting.' }); + $('#primary_max_temp').jqxTooltip({ content: 'De hoogst bereikte piek temperatuur tijdens de hoofgvergisting.' }); + $('#primary_end_temp').jqxTooltip({ content: 'De eind temperatuur van de hoofdvergisting.' }); + $('#primary_end_sg').jqxTooltip({ content: 'Het gemeten SG aan het eind van de hoofdvergisting.' }); + $('#primary_svg').jqxTooltip({ content: 'De schijnbare vergisting graad behaald na de hoofdgisting.' }); + $('#primary_end_date').jqxTooltip({ content: 'De eind datum van de hoofdvergisting en eventueel overhevelen.' }); + $('#secondary_end_sg').jqxTooltip({ content: 'Het gemeten SG aan het eind van de navergisting.' }); + $('#secondary_svg').jqxTooltip({ content: 'De schijnbare vergisting graad behaald na de nagisting.' }); + $('#secondary_end_date').jqxTooltip({ content: 'De eind datum van de navergisting en het begin van het lageren.' }); + $('#est_fg3').jqxTooltip({ content: 'Het verwachte eind SG. Dit wordt automatisch berekend.' }); + + $('#primary_end_sg,#secondary_end_sg').jqxNumberInput(Show3dec); + $('#primary_end_date,#secondary_end_date').jqxDateTimeInput(Dateopts); + $('#primary_end_date,#secondary_end_date').jqxDateTimeInput({ disabled: true }); + $('#primary_start_temp,#primary_max_temp,#primary_end_temp,#secondary_temp,#tertiary_temp').jqxNumberInput(Show1dec); + $('#fg').jqxNumberInput(Show3dec); + $('#brew_fermenter_sg2,#est_fg3').jqxNumberInput(Show3dec); + $('#final_abv').jqxNumberInput(Show2dec); + $('#primary_svg,#secondary_svg,#final_svg').jqxNumberInput(Show1dec); + $('#FLog').jqxButton({ template: 'info', width: '150px', theme: theme }); + $('#FLog').click(function() { + // Open log in a new tab. + window.open('log_fermentation.php?code=' + dataRecord.code + '&name=' + dataRecord.name); + }); + $('#ILog').jqxButton({ template: 'info', width: '150px', theme: theme }); + $('#ILog').click(function() { + // Open log in a new tab. + window.open('log_ispindel.php?code=' + dataRecord.code + '&name=' + dataRecord.name); + }); + + // Tab 11, Packaging + // TODO: high gravity packaging, extra water and recalc abv, color and ibu. + $('#package_date').jqxTooltip({ content: 'De verpakkings datum van dit bier.' }); + $('#package_volume').jqxTooltip({ content: 'Het beschikbare volume om te bottelen of op fust te zetten.' }); + $('#package_infuse_amount').jqxTooltip({ content: 'De hoeveelheid water of drank extra toe te voegen.' }); + $('#package_infuse_abv').jqxTooltip({ content: 'De hoeveelheid alcohol in de drank, of 0.0 als het water is.' }); + $('#package_infuse_notes').jqxTooltip({ content: 'Omschrijving van de extra toevoeging.' }); + $('#package_abv').jqxTooltip({ content: 'De uiteindelijke hoeveelheid alcohol volume %.' }); + $('#package_ph').jqxTooltip({ content: 'De gemeten pH vlak voor het verpakken.' }); + $('#st_carb_min2').jqxTooltip({ content: 'Het minimum aanbevolen koolzuur volume voor deze bierstijl.'}); + $('#st_carb_max2').jqxTooltip({ content: 'Het maximum aamnevolen koolzuur volume voor deze bierstijl.'}); + $('#bottle_amount').jqxTooltip({ content: 'De totale hoeveelheid te bottelen bier.' }); + $('#keg_amount').jqxTooltip({ content: 'De totale hoeveelheid op fust te zetten bier.' }); + $('#bottle_carbonation').jqxTooltip({ content: 'Het gewenste CO2 volume in de flessen.' }); + $('#keg_carbonation').jqxTooltip({ content: 'Het gewenste CO2 volume door de suiker in de fusten.' }); + $('#bottle_priming_water,#keg_priming_water').jqxTooltip({ content: 'De hoeveelheid water om de suiker op te lossen.' }); + $('#bottle_pressure').jqxTooltip({ content: 'De maximaal te verwachten druk tijdens het hergisten.' }); + $('#package_date').jqxDateTimeInput(Dateopts); + $('#package_date').jqxDateTimeInput({ disabled: true }); + $('#package_infuse_amount').jqxNumberInput(Show3dec); + $('#package_infuse_notes').jqxInput({ theme: theme, width: 640, height: 23 }); + $('#package_abv').jqxNumberInput(Show2dec); + $('#package_ph').jqxNumberInput(Show2dec); + $('#st_carb_min2,#st_carb_max2').jqxNumberInput(Smal1dec); + $('#package_volume,#package_infuse_abv,#bottle_amount,#keg_amount').jqxNumberInput(Show1dec); + $('#bottle_carbonation,#keg_carbonation').jqxNumberInput(Show2dec); + $('#bottle_priming_sugar').jqxInput({ theme: theme, width: 200, height: 23 }); + $('#keg_priming_sugar').jqxInput({ theme: theme, width: 200, height: 23 }); + $('#bottle_priming_water,#keg_priming_water').jqxNumberInput(Show3dec); + $('#keg_forced_carb').jqxCheckBox({ theme: theme, width: 120, height: 23, disabled: true }); + $('#bottle_priming_amount,#keg_priming_amount,#bottle_priming_total,#bottle_pressure,#keg_priming_total,#keg_pressure').jqxNumberInput(Show1dec); + $('#bottle_abv,#keg_abv').jqxNumberInput(Show2dec); + $('#bottle_carbonation_temp,#keg_carbonation_temp').jqxNumberInput(Show1dec); + $('#CLog').jqxButton({ template: 'info', width: '150px', theme: theme }); + $('#CLog').click(function() { + // Open log in a new tab. + window.open('log_co2pressure.php?code=' + dataRecord.code + '&name=' + dataRecord.name); + }); + + // Tab 12, Tasting + $('#taste_date').jqxTooltip({ content: 'De proef datum van dit bier.' }); + $('#taste_date').jqxDateTimeInput(Dateopts); + $('#taste_date').jqxDateTimeInput({ disabled: true }); + $('#taste_rate').jqxTooltip({ content: 'Het cijfer voor dit bier van 1 tot 10.' }); + $('#taste_rate').jqxNumberInput(Show1dec); + $('#taste_color').jqxTooltip({ content: 'De kleur van het bier.' }); + $('#taste_transparency').jqxTooltip({ content: 'De helderheid van het bier.' }); + $('#taste_head').jqxTooltip({ content: 'Het schuim op het bier.' }); + $('#taste_color,#taste_transparency,#taste_head').jqxInput({ theme: theme, width: 320, height: 23 }); + $('#taste_aroma').jqxTooltip({ content: 'Het aroma van het bier.' }); + $('#taste_taste').jqxTooltip({ content: 'De smaak van het bier.' }); + $('#taste_aftertaste').jqxTooltip({ content: 'De nasmaak van het bier.' }); + $('#taste_mouthfeel').jqxTooltip({ content: 'Het mondgevoelvan het bier.' }); + $('#taste_aroma,#taste_taste,#taste_aftertaste,#taste_mouthfeel').jqxInput({ theme: theme, width: 960, height: 23 }); + $('#taste_notes').jqxTooltip({ content: 'Het oordeel en opmerkingen over dit bier.' }); + $('#taste_notes').jqxInput({ theme: theme, width: 960, height: 100 }); + + $('#jqxTabs').jqxTabs({ + theme: theme, + width: 1280, + height: 660, + autoHeight: false, + position: 'top' + }); + + // Buttons below + $('#Terug').jqxButton({ template: 'primary', width: '80px', theme: theme }); + $('#Terug').bind('click', function() { + window.location.href = my_return; + }); +}); +
--- a/www/prod_edit.php Sat Aug 06 22:02:42 2022 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,931 +0,0 @@ -<?php -require_once($_SERVER['DOCUMENT_ROOT'].'/includes/global.inc.php'); -page_header('Brouw overzicht', 'prod_edit'); -?> - - <div id='jqxTabs'> - <ul> - <li>Algemeen</li> - <li>Apparatuur</li> - <li>Vergistbaar</li> - <li>Hoppen</li> - <li>Diversen</li> - <li>Gist</li> - <li>Maischen</li> - <li>Water</li> - <li>Brouwdag</li> - <li>Vergisten</li> - <li>Verpakken</li> - <li>Proeven</li> - </ul> - - <div> <!-- tab algemeen --> - <div style="overflow: hidden;"> - <table style="width: 100%;"> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Brouw naam:</td> - <td align="left" colspan="3" style="vertical-align: top; padding: 3px;"><input id="name" /></td> - <td style="vertical-align: top; float: right; padding: 3px;">Afgesloten:</td> - <td align="left"><div id="locked"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Brouw code:</td> - <td align="left" style="vertical-align: top; padding: 3px;"><input id="code" /></td> - <td style="vertical-align: top; float: right; padding: 3px;">Start planning:</td> - <td align="left" style="vertical-align: top;"><input readonly="1" id="birth" /></td> - <td style="vertical-align: top; float: right; padding: 3px;">Brouw fase:</td> - <td align="left" style="vertical-align: top; padding: 3px;"><input id="stage" readonly /></td> - </tr> - <tr id='divide_row'> - <td style="vertical-align: top; float: right; padding: 3px;">Splits product:</td> - <td align="left" style="vertical-align: top; padding: 3px;"><input id="divide_type" readonly /></td> - <td style="vertical-align: top; float: right; padding: 3px;">Gesplitst product:</td> - <td align="left" style="vertical-align: top; padding: 3px;"><input id="divide_batch" readonly /></td> - <td style="vertical-align: top; float: right; padding: 3px;">Splits focus:</td> - <td align="left"><div id="d3"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Opmerkingen:</td> - <td colspan="5" style="padding: 3px;"><textarea id="notes"></textarea></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Brouw type:</td> - <td align="left" style="padding: 3px;"><input id="type" readonly /></td> - <td style="vertical-align: top; float: right; padding: 3px;">Brouwzaal rendement:</td> - <td style="padding: 3px;"><div id="efficiency"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;" id="ok_pmpt">Ingredienten aanwezig:</td> - <td align="left"><div id="ok_supplies"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Brouw volume:</td> - <td style="padding: 3px;"><div id="batch_size"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Kooktijd minuten:</td> - <td style="padding: 3px;"><div id="boil_time"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Kook volume:</td> - <td style="padding: 3px;"><div id="boil_size"></div></td> - </tr> - <tr> - <td colspan="6"><hr></td> - </tr> - <tr> - <td></td> - <th>Bierstijl gegevens</th> - <td colspan="4"></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Stijlgids:</td> - <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_guide" /></td> - <td style="vertical-align: top; float: right; padding: 3px;">Bier stijl:</td> - <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_name" /></td> - <td style="vertical-align: top; float: right; padding: 3px;">Bier groep:</td> - <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_letter" /></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Stijl type:</td> - <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_type" /></td> - <td style="vertical-align: top; float: right; padding: 3px;">Categorie:</td> - <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_category" /></td> - <td style="vertical-align: top; float: right; padding: 3px;">Categorie nr:</td> - <td style="padding: 3px;"><div id="st_category_number"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Start SG:</td> - <td style="padding: 3px;"><div style="float: left;" id="est_og"></div><div style="float: left; margin-left: 15px;" id="st_og_min"></div><div style="float: left; margin-left: 5px;" id="st_og_max"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Eind SG:</td> - <td style="padding: 3px;"><div style="float: left;" id="est_fg"></div><div style="float: left; margin-left: 15px;" id="st_fg_min"></div><div style="float: left; margin-left: 5px;" id="st_fg_max"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Alcohol vol.%:</td> - <td style="padding: 3px;"><div style="float: left;" id="est_abv"></div><div style="float: left; margin-left: 15px;" id="st_abv_min"></div><div style="float: left; margin-left: 5px;" id="st_abv_max"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Kleur EBC:</td> - <td style="padding: 3px;"><div style="float: left;" id="est_color"></div><div style="float: left; margin-left: 15px;" id="st_color_min"></div><div style="float: left; margin-left: 5px;" id="st_color_max"></div><div id="bcolor" class='ebccolor'> </div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Kleur methode:</td> - <td style="padding: 3px;"><input id="color_method" readonly /></td> - <td style="vertical-align: top; float: right; padding: 3px;">Koolzuur vol:</td> - <td style="padding: 3px;"><div style="float: left;" id="est_carb"></div><div style="float: left; margin-left: 15px;" id="st_carb_min"></div><div style="float: left; margin-left: 5px;" id="st_carb_max"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Bitterheid IBU:</td> - <td style="padding: 3px;"><div style="float: left;" id="est_ibu"></div><div style="float: left; margin-left: 15px;" id="st_ibu_min"></div><div style="float: left; margin-left: 5px;" id="st_ibu_max"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Bitterheid methode:</td> - <td style="padding: 3px;"><input id="ibu_method" readonly /></td> - <td style="vertical-align: top; float: right; padding: 3px;">Energie-inhoud kcal/l:</td> - <td style="padding: 3px;"><div style="float: left;" id="kcal"></div></td> - </tr> - </table> - <div style="float: right; margin-top: 20px; margin-bottom: 5px;"> - <input style="margin-right: 600px;" type="button" id="Terug" value="Terug" /> - </div> - </div> - </div> - - <div> <!-- Apparatuur --> - <div style="overflow: hidden;"> - <table style="width: 100%;"> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Installatie naam:</td> - <td colspan="3" align="left" style="vertical-align: top; padding: 3px;"><input id="eq_name" readonly /></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Opmerkingen:</td> - <td colspan="3" style="padding: 3px;"><textarea id="eq_notes" readonly></textarea></td> - </tr> - <tr> - <th style="text-align: center;" colspan="2">Maischen</th> - <th style="text-align: center;" colspan="2">Koken</th> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Maischkuip volume L:</td> - <td><div id="eq_tun_volume"></div></td> - <td style="vertical-align: top; float: right;">Kookketel volume L:</td> - <td><div id="eq_kettle_volume"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Maischwater L:</td> - <td><div id="eq_mash_volume"></div></td> - <td style="vertical-align: top; float: right;">Kook volume L:</td> - <td><div id="eq_boil_size"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Maximum moutstort Kg:</td> - <td><div id="eq_mash_max"></div></td> - <td style="vertical-align: top; float: right;">Verdamping per uur L:</td> - <td><div id="eq_evap_rate"></div></td> - </tr> - <tr> - <th style="text-align: center;" colspan="2">Filteren</th> - <td style="vertical-align: top; float: right;">Kooktijd in minuten:</td> - <td><div id="eq_boil_time"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Filter volume L:</td> - <td><div id="eq_lauter_volume"></div></td> - <td style="vertical-align: top; float: right;">Extra water bij koken L:</td> - <td><div id="eq_top_up_kettle"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Filterkuip verlies L:</td> - <td><div id="eq_lauter_deadspace"></div></td> - <td style="vertical-align: top; float: right;">Hopfactor %:</td> - <td><div id="eq_hop_utilization"></div></td> - </tr> - <tr> - <th style="text-align: center;" colspan="2">Koelen</th> - <td style="vertical-align: top; float: right;">Volume eind koken L:</td> - <td><div id="eq_batch_size"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Trub verlies kookketel L:</td> - <td><div id="eq_trub_chiller_loss"></div></td> - <td style="vertical-align: top; float: right;">Brouwzaalrendement %:</td> - <td><div id="eq_efficiency"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Extra water in gistvat:</td> - <td><div id="eq_top_up_water"></div></td> - <td colspan="2"></td> - </tr> - </table> - </div> - </div> - - <div> <!-- tab vergistbaar --> - <div style="overflow: hidden;"> - <table style="width: 100%;"> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Kleur EBC:</td> - <td style="padding: 3px;"><div style="float: left;" id="est_color2"></div><div id="bcolor2" class='ebccolor'> </div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Percentage moutstort:</td> - <td style="padding: 3px;"><div style="float: left;" id="perc_malts"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Begin SG:</td> - <td style="padding: 3px;"><div style="float: left;" id="est_og2"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Percentage suiker:</td> - <td style="padding: 3px;"><div style="float: left;" id="perc_sugars"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Maisch KG:</td> - <td style="padding: 3px;"><div style="float: left;" id="mash_kg"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Percentage cara:</td> - <td style="padding: 3px;"><div style="float: left;" id="perc_cara"></div></td> - </tr> - <tr> - <td colspan="2"> </td> - <td style="vertical-align: top; float: right; padding: 3px;">Lintner totaal:</td> - <td style="padding: 3px;"><div style="float: left;" id="ferm_lintner"></div></td> - </tr> - <tr> - <td align="center" colspan="4"><div id="fermentableGrid"></div></td> - </tr> - </table> - </div> - </div> <!-- tab vergistbaar --> - - <div> <!-- tab hoppen --> - <div style="overflow: hidden;"> - <table style="width: 100%;"> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Bitterheid IBU:</td> - <td style="padding: 3px;"><div id="est_ibu2"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Smaak bijdrage:</td> - <td style="padding: 3px;"><div id="hop_flavour"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Aroma bijdrage:</td> - <td style="padding: 3px;"><div id="hop_aroma"></div></td> - </tr> - <tr> - <td align="center" colspan="6"><div id="hopGrid"></div></td> - </tr> - </table> - </div> - </div> <!-- tab hoppen --> - - <div> <!-- tab misc --> - <div style="overflow: hidden;"> - <table style="width: 100%;"> - <tr><td> </td></tr> - <tr><td align="center"><div id="miscGrid"></div></td></tr> - </table> - </div> - </div> <!-- tab misc --> - - <div> <!-- tab gisten --> - <div style="overflow: hidden;"> - <table style="width: 100%;"> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Verwacht FG en ABV:</td> - <td style="padding: 3px;"><div style="float: left;" id="est_fg2"></div><div style="float: left; margin-left: 10px;" id="est_abv2"></div></td> - <td align="center" colspan="5" rowspan="5"> - <div id="propagator"> - <table style="width: 100%;"> - <caption>Giststarter stappen</caption> - <tr> - <td style="width: 40px; padding: 3px;">Stap</td> - <td align="left" style="vertical-align: top; padding: 3px;">Methode</td> - <td style="width: 120px; padding: 3px;">Volume</td> - <td style="width: 120px; padding: 3px;">Inj. factor</td> - <td style="width: 120px; padding: 3px;">Nieuwe cellen</td> - <td style="width: 120px; padding: 3px;">Totaal cellen</td> - <td style="width: 120px; padding: 3px;">Groei factor</td> - </tr> - <tr> - <td align="center">1</td> - <td><input id="prop1_type" readonly /><div id="r1_pmpt">Niet nodig</div></td> - <td><div id="prop1_volume"></div></td> - <td><div style="float: left;" id="prop1_irate"></div><div style="float: left;" id="r1_irate"></div></td> - <td><div id="prop1_ncells"></div></td> - <td><div style="float: left;" id="prop1_tcells"></div><div style="float: left;" id="r1_tcells"></div></td> - <td><div style="float: left;" id="prop1_growf"></div><div style="float: left;" id="r1_growf"></div></td> - </tr> - <tr> - <td align="center">2</td> - <td><input id="prop2_type" readonly /><div id="r2_pmpt">Niet nodig</div></td> - <td><div id="prop2_volume"></div></td> - <td><div style="float: left;" id="prop2_irate"></div><div style="float: left;" id="r2_irate"></div></td> - <td><div id="prop2_ncells"></div></td> - <td><div style="float: left;" id="prop2_tcells"></div><div style="float: left;" id="r2_tcells"></div></td> - <td><div style="float: left;" id="prop2_growf"></div><div style="float: left;" id="r2_growf"></div></td> - </tr> - <tr> - <td align="center">3</td> - <td><input id="prop3_type" readonly /><div id="r3_pmpt">Niet nodig</div></td> - <td><div id="prop3_volume"></div></td> - <td><div style="float: left;" id="prop3_irate"></div><div style="float: left;" id="r3_irate"></div></td> - <td><div id="prop3_ncells"></div></td> - <td><div style="float: left;" id="prop3_tcells"></div><div style="float: left;" id="r3_tcells"></div></td> - <td><div style="float: left;" id="prop3_growf"></div><div style="float: left;" id="r3_growf"></div></td> - </tr> - <tr> - <td align="center">4</td> - <td><input id="prop4_type" readonly /><div id="r4_pmpt">Niet nodig</div></td> - <td><div id="prop4_volume"></div></td> - <td><div style="float: left;" id="prop4_irate"></div><div style="float: left;" id="r4_irate"></div></td> - <td><div id="prop4_ncells"></div></td> - <td><div style="float: left;" id="prop4_tcells"></div><div style="float: left;" id="r4_tcells"></div></td> - <td><div style="float: left;" id="prop4_growf"></div><div style="float: left;" id="r4_growf"></div></td> - </tr> - </table> - </div> - </td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Gist productie datum:</td> - <td style="padding: 3px;"><div id="yeast_prod_date"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Gist conditie %:</td> - <td style="padding: 3px;"><div id="starter_viability"></div></td> - </tr> - <tr class="primary_dry"> - <td style="vertical-align: top; float: right; padding: 3px;">Gist nodig gram:</td> - <td style="padding: 3px;"><div id="yeast_grams"></div></td> - </tr> - <tr class="primary_dry"> - <td style="vertical-align: top; float: right; padding: 3px;">Ent hoeveelheid gr/hl:</td> - <td style="padding: 3px;"><div id="yeast_gr_hl"></div></td> - </tr> - <tr class="primary_liquid"> - <td style="vertical-align: top; float: right; padding: 3px;">Gistcellen miljard:</td> - <td style="padding: 3px;"><div id="yeast_cells"></div></td> - </tr> - <tr class="primary_liquid"> - <td style="vertical-align: top; float: right; padding: 3px;">Pitch rate:</td> - <td style="padding: 3px;"><div id="yeast_pitchrate"></div></td> - </tr> - <tr class="primary_liquid"> - <td style="vertical-align: top; float: right; padding: 3px;">Cellen nodig miljard:</td> - <td style="padding: 3px;"><div id="need_cells"></div></td> - </tr> - <tr class="primary_liquid"> - <td style="vertical-align: top; float: right; padding: 3px;">Pitch cellen/ml °P:</td> - <td style="padding: 3px;"><div id="plato_cells"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Starter type:</td> - <td style="padding: 3px;"><input id="starter_type" readonly /></td> - <td style="vertical-align: top; float: right; padding: 3px;">Starter SG:</td> - <td style="padding: 3px;"><div id="starter_sg"></div></td> - <td></td> - </tr> - <tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> - <tr><td align="center" colspan="7"><div id="yeastGrid"></div></td></tr> - </table> - </div> - </div> <!-- tab gisten --> - - <div> <!-- tab maischen --> - <div style="overflow: hidden;"> - <table style="width: 100%;"> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Maischchema:</td> - <td colspan="3" align="left" style="vertical-align: top; padding: 3px;"><input id="mash_name" readonly /></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Volume van de maisch L:</td> - <td style="padding: 3px;"><div id="est_mashvol"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Tijdsduur maischen:</td> - <td align="left" style="vertical-align: top; padding: 3px;"><input style="text-align:right" readonly="1" id="est_mashtime" /></td> - </tr> - <tr><td colspan="4"> </td></tr> - <tr><td align="center" colspan="4" style="padding: 3px;"><div id="mashGrid"></div></td></tr> - </table> - </div> - </div> <!-- tab maischen --> - - <div> <!-- tab water --> - <div style="overflow: hidden;"> - <table style="width: 100%;"> - <tr> - <td align="center" colspan="9"> - <div id='water_totals'> - <table style="width: 100%;"> - <caption>Water overzicht</caption> - <tr> - <td align="left" style="vertical-align: top; padding: 3px;">Water profiel</td> - <td style="width: 50px; padding: 3px;">Spoel</td> - <td style="width: 97px; padding: 3px;">Volume</td> - <td style="width: 77px; padding: 3px;">Ca</td> - <td style="width: 77px; padding: 3px;">Mg</td> - <td style="width: 77px; padding: 3px;">HCO3</td> - <td style="width: 77px; padding: 3px;">CaCO3</td> - <td style="width: 77px; padding: 3px;">Na</td> - <td style="width: 77px; padding: 3px;">Cl</td> - <td style="width: 77px; padding: 3px;">SO4</td> - <td style="width: 77px; padding: 3px;">pH</td> - <td style="width: 77px; padding: 3px;">Hardheid</td> - <td style="width: 77px; padding: 3px;">RA</td> - </tr> - <tr> - <td><input readonly="1" id="w1_name" /></td> - <td><div style='margin-left: 10px;' id='w1_button'></div></td> - <td><div id="w1_amount"></div></td> - <td><div id="w1_calcium"></div></td> - <td><div id="w1_magnesium"></div></td> - <td><div id="w1_bicarbonate"></div></td> - <td><div id="w1_total_alkalinity"></div></td> - <td><div id="w1_sodium"></div></td> - <td><div id="w1_chloride"></div></td> - <td><div id="w1_sulfate"></div></td> - <td><div id="w1_ph"></div></td> - <td><div id="w1_hardness"></div></td> - <td><div id="w1_ra"></div></td> - </tr> - <tr> - <td><input readonly="1" id="w2_name" /></td> - <td><div style='margin-left: 10px;' id='w2_button'></div></td> - <td><div id="w2_amount"></div></td> - <td><div id="w2_calcium"></div></td> - <td><div id="w2_magnesium"></div></td> - <td><div id="w2_bicarbonate"></div></td> - <td><div id="w2_total_alkalinity"></div></td> - <td><div id="w2_sodium"></div></td> - <td><div id="w2_chloride"></div></td> - <td><div id="w2_sulfate"></div></td> - <td><div id="w2_ph"></div></td> - <td><div id="w2_hardness"></div></td> - <td><div id="w2_ra"></div></td> - </tr> - <tr> - <td style="vertical-align: top; padding: 3px; float: left;">Gemengd water:</td> - <td><div style='margin-left: 10px;' id='wg_button'></div></td> - <td><div id="wg_amount"></div></td> - <td><div id="wg_calcium"></div></td> - <td><div id="wg_magnesium"></div></td> - <td><div id="wg_bicarbonate"></div></td> - <td><div id="wg_total_alkalinity"></div></td> - <td><div id="wg_sodium"></div></td> - <td><div id="wg_chloride"></div></td> - <td><div id="wg_sulfate"></div></td> - <td><div id="wg_ph"></div></td> - <td><div id="wg_hardness"></div></td> - <td><div id="wg_ra"></div></td> - </tr> - <tr> - <td style="vertical-align: top; padding: 3px; float: left;">Behandeld maisch water:</td> - <td></td> - <td><div></div></td> - <td><div id="wb_calcium"></div></td> - <td><div id="wb_magnesium"></div></td> - <td><div id="wb_bicarbonate"></div></td> - <td><div id="wb_total_alkalinity"></div></td> - <td><div id="wb_sodium"></div></td> - <td><div id="wb_chloride"></div></td> - <td><div id="wb_sulfate"></div></td> - <td><div id="wb_ph"></div></td> - <td><div id="wb_hardness"></div></td> - <td><div id="wb_ra"></div></td> - </tr> - <tr> - <td style="vertical-align: top; padding: 3px; float: left;">Resultaat:</td> - <td></td> - <td><div></div></td> - <td><div id="wr_calcium"></div></td> - <td><div id="wr_magnesium"></div></td> - <td><div id="wr_bicarbonate"></div></td> - <td><div id="wr_total_alkalinity"></div></td> - <td><div id="wr_sodium"></div></td> - <td><div id="wr_chloride"></div></td> - <td><div id="wr_sulfate"></div></td> - <td><div id="wr_ph"></div></td> - <td></td> - <td></td> - </tr> - <tr> - <td style="vertical-align: top; padding: 3px; float: left;">Behandeld spoelwater:</td> - <td></td> - <td><div id="sw_amount"></div></td> - <td><div id="sw_calcium"></div></td> - <td><div id="sw_magnesium"></div></td> - <td><div id="sw_bicarbonate"></div></td> - <td><div id="sw_total_alkalinity"></div></td> - <td><div id="sw_sodium"></div></td> - <td><div id="sw_chloride"></div></td> - <td><div id="sw_sulfate"></div></td> - <td><div id="sw_ph"></div></td> - <td><div id="sw_hardness"></div></td> - <td><div id="sw_ra"></div></td> - </tr> - </table> - </div> - </td> - </tr> - <tr> - <th style="text-align: center;" colspan="3">Brouwzouten</th> - <th colspan="3"></th> - <th style="text-align: center;" colspan="3">Spoelwater</th> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">CaCl2 gr:</td> - <td style="padding: 3px;"><div id="wa_cacl2"></div></td> - <td style="padding: 3px;"><div id="ss_cacl2"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Bitterheidsindex:</td> - <td style="padding: 3px;"><div style="float: left;" id="tgt_bu"></div></td> - <td style="padding: 3px;"><div style="float: left;" id="wr_bu"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Auto bereken:</td> - <td style="padding: 3px;"><div id="calc_acid"></div></td> - <td></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">CaSO4 gr:</td> - <td style="padding: 3px;"><div id="wa_caso4"></div></td> - <td style="padding: 3px;"><div id="ss_caso4"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Richtgetal SO4:Cl:</td> - <td style="padding: 3px;"><div style="float: left;" id="tgt_so4_cl"></div></td> - <td style="padding: 3px;"><div style="float: left;" id="wrt_so4_cl"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;"><div class='c_mashph'>Gewenst maish pH:</div></td> - <td style="padding: 3px;"><div id="mash_ph" class='c_mashph'></div></td> - <td></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">MgSO4 gr:</td> - <td style="padding: 3px;"><div id="wa_mgso4"></div></td> - <td style="padding: 3px;"><div id="ss_mgso4"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Huidig SO4:Cl:</td> - <td style="padding: 3px;"><div style="float: left;" id="got_so4_cl"></div></td> - <td style="padding: 3px;"><div style="float: left;" id="wr_so4_cl"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Aanzuren met:</td> - <td style="padding: 3px;"><input readonly="1" id="wa_acid_name" /></td> - <td style="padding: 3px;"><div style="float: left;" id="wa_acid_perc"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">NaCl gr:</td> - <td style="padding: 3px;"><div id="wa_nacl"></div></td> - <td style="padding: 3px;"><div id="ss_nacl"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Voor koken pH:</td> - <td style="padding: 3px;"><div id="preboil_ph"></div></td> - <td></td> - <td style="vertical-align: top; float: right; padding: 3px;">Zuur hoeveelheid:</td> - <td style="padding: 3px;"><div style="float: left;" id="wa_acid"></div></td> - <td></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">MgCl2 gr:</td> - <td style="padding: 3px;"><div id="wa_mgcl2"></div></td> - <td style="padding: 3px;"><div id="ss_mgcl2"></div></td> - <td colspan="3"></td> - <td style="vertical-align: top; float: right; padding: 3px;">Gewenst spoel pH:</td> - <td style="padding: 3px;"><div id="sparge_ph"></div></td> - <td></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">NaHCO3 gr:</td> - <td style="padding: 3px;"><div id="wa_nahco3"></div></td> - <td colspan="4"></td> - <td style="vertical-align: top; float: right; padding: 3px;">Aanzuren met:</td> - <td style="padding: 3px;"><input readonly="1" id="sparge_acid_type" /></td> - <td style="padding: 3px;"><div id="sparge_acid_perc"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">CaCO3 gr:</td> - <td style="padding: 3px;"><div id="wa_caco3"></div></td> - <td colspan="4"></td> - <td style="vertical-align: top; float: right; padding: 3px;">Zuur hoeveelheid:</td> - <td style="padding: 3px;"><div id="sparge_acid_amount"></div></td> - <td></td> - </tr> - </table> - </div> - </div> <!-- tab water --> - - <div style="overflow: hidden;"> <!-- Brewday --> - <table style="width: 100%;"> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Brouwdag start:</td> - <td align="left" colspan="2" style="vertical-align: top;"><div id="brew_date_start"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Brouwdag eind:</td> - <td align="left" colspan="2" style="vertical-align: top;"><div id="brew_date_end"></div></td> - </tr> - <tr> - <td colspan="6"> </td> - </tr> - <tr> - <th style="text-align: center;" colspan="2">Maischen</th> - <th style="text-align: center;" colspan="4"><div id="brew_pmpt_koken">Koken</div></th> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Maisch pH:</td> - <td><div style="float: left;" id="brew_mash_ph"></div><div style="float: left; margin-left: 10px;" id="est_mash_ph"></div></td> - <td style="vertical-align: top; float: right;">Voor koken pH:</td> - <td><div id="brew_preboil_ph"></div></td> - <td style="vertical-align: top; float: right;">Na koken pH:</td> - <td><div id="brew_aboil_ph"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Maisch SG:</td> - <td><div style="float: left;" id="brew_mash_sg"></div><div style="float: left; margin-left: 10px;" id="est_mash_sg"></div></td> - <td style="vertical-align: top; float: right;">Voor koken SG:</td> - <td><div style="float: left;" id="brew_preboil_sg"></div><div style="float: left; margin-left: 10px;" id="est_pre_sg"></div></td> - <td style="vertical-align: top; float: right;">Na koken SG:</td> - <td><div style="float: left;" id="brew_aboil_sg"></div><div style="float: left; margin-left: 10px;" id="est_og3"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Maisch rendement %:</td> - <td><div id="brew_mash_efficiency"></div></td> - <td style="vertical-align: top; float: right;">Voor koken vol@100°C:</td> - <td><div style="float: left;" id="brew_preboil_volume"></div><div style="float: left; margin-left: 10px;" id="est_pre_vol"></div></td> - <td style="vertical-align: top; float: right;">Na koken vol@100°C:</td> - <td><div style="float: left;" id="brew_aboil_volume"></div><div style="float: left; margin-left: 10px;" id="est_a_vol"></div></td> - </tr> - <tr> - <td colspan="2"> </td> - <td style="vertical-align: top; float: right;">Voor koken rendement %:</td> - <td><div id="brew_preboil_efficiency"></div></td> - <td style="vertical-align: top; float: right;">Na koken rendement %:</td> - <td><div id="brew_aboil_efficiency"></div></td> - </tr> - <tr> - <td colspan="6"> </td> - </tr> - <tr> - <th style="text-align: center;" colspan="2">Spoelen en filteren</th> - <th style="text-align: center;" colspan="4">Koelen en whirlpoolen</th> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Spoelwater °C:</td> - <td><div id="brew_sparge_temperature"></div></td> - <td style="vertical-align: top; float: right;">Whirlpool 85..100°C min:</td> - <td><div id="brew_whirlpool9"></div></td> - <td style="vertical-align: top; float: right;">Koelen tot °C:</td> - <td><div id="brew_cooling_to"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Spoelwater voorraad L:</td> - <td><div id="brew_sparge_volume"></div></td> - <td style="vertical-align: top; float: right;">Whirlpool 72..79°C min:</td> - <td><div id="brew_whirlpool7"></div></td> - <td style="vertical-align: top; float: right;">Koelen met:</td> - <td><input readonly="1" id="brew_cooling_method" /></td> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Spoelwater nodig L:</td> - <td><div id="brew_sparge_est"></div></td> - <td style="vertical-align: top; float: right;">Whirlpool 60..66°C min:</td> - <td><div id="brew_whirlpool6"></div></td> - <td style="vertical-align: top; float: right;">Koelen minuten:</td> - <td><div id="brew_cooling_time"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Spoelwater pH:</td> - <td><div id="brew_sparge_ph"></div></td> - <td style="vertical-align: top; float: right;">Whirlpool koud min:</td> - <td><div id="brew_whirlpool2"></div></td> - <td colspan="2"> </td> - </tr> - <tr> - <td colspan="6"> </td> - </tr> - <tr> - <th style="text-align: center;" colspan="2">Beluchten</th> - <th style="text-align: center;" colspan="4">Naar gistvat</th> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Beluchten met:</td> - <td><input readonly="1" id="brew_aeration_type" /></td> - <td style="vertical-align: top; float: right;">Koeler en trub verlies L:</td> - <td><div id="brew_fermenter_tcloss"></div></td> - <td style="vertical-align: top; float: right;">SG in gistvat:</td> - <td><div id="brew_fermenter_sg"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Beluchten tijd min:</td> - <td><div id="brew_aeration_time"></div></td> - <td style="vertical-align: top; float: right;">Extra water in gistvat L:</td> - <td><div id="brew_fermenter_extrawater"></div></td> - <td style="vertical-align: top; float: right;">Kleur in gistvat EBC:</td> - <td><div style="float: left;" id="brew_fermenter_color"></div><div style="float: left; margin-left: 10px;" id="bcolorf" class='ebccolor'> </div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right;">Beluchten snelheid:</td> - <td><div id="brew_aeration_speed"></div></td> - <td style="vertical-align: top; float: right;">Volume naar gistvat L:</td> - <td><div id="brew_fermenter_volume"></div></td> - <td style="vertical-align: top; float: right;">Bitterheid in gistvat IBU:</td> - <td><div style="float: left;" id="brew_fermenter_ibu"></div></td> - </tr> - </table> - </div> <!-- Brewday --> - - <div> <!-- Vergisten --> - <div style="overflow: hidden;"> - <table style="width: 100%;"> - <tr> - <td style="width: 30%;"> </td> - <td style="width: 20%;"> </td> - <td style="width: 30%;"> </td> - <td style="width: 20%;"> </td> - </tr> - <tr> - <th style="text-align: center;" colspan="4">Hoofdvergisting</th> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Begin vergisting SG:</td> - <td align="left" colspan="3" style="vertical-align: top;"><div id="brew_fermenter_sg2"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Start temperatuur hoofdvergisting °C:</td> - <td align="left" colspan="3" style="vertical-align: top;"><div id="primary_start_temp"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Piek temperatuur hoofdvergisting °C:</td> - <td align="left" colspan="3" style="vertical-align: top;"><div id="primary_max_temp"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Eind temperatuur hoofdvergisting °C:</td> - <td align="left" colspan="3" style="vertical-align: top;"><div id="primary_end_temp"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Eind hoofdvergisting SG:</td> - <td align="left" colspan="3" style="vertical-align: top;"><div id="primary_end_sg"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Eind hoofdvergisting/overhevelen:</td> - <td align="left" style="vertical-align: top;"><div id="primary_end_date"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Schijnbare vergistingsgraad:</td> - <td align="left" style="vertical-align: top;"><div id="primary_svg"></div></td> - </tr> - <tr> - <td colspan="4"><hr></td> - </tr> - <tr> - <th style="text-align: center;" colspan="4">Nagisting</th> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Temperatuur nagisting °C:</td> - <td align="left" colspan="3" style="vertical-align: top;"><div id="secondary_temp"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Eind nagisting SG:</td> - <td align="left" colspan="3" style="vertical-align: top;"><div id="secondary_end_sg"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Eind nagisting/start lageren:</td> - <td align="left" style="vertical-align: top;"><div id="secondary_end_date"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Schijnbare vergistingsgraad %:</td> - <td align="left" style="vertical-align: top;"><div id="secondary_svg"></div></td> - </tr> - <tr> - <td colspan="4"><hr></td> - </tr> - <tr> - <th style="text-align: center;" colspan="4">Lageren</th> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Temperatuur lageren °C:</td> - <td align="left" colspan="3" style="vertical-align: top;"><div id="tertiary_temp"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Het verwachte eind SG:</td> - <td align="left" colspan="3" style="vertical-align: top;"><div id="est_fg3"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Het behaalde eind SG:</td> - <td align="left" colspan="3" style="vertical-align: top;"><div id="fg"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Alcoholgehalte voor hergisting vol.%:</td> - <td align="left" style="vertical-align: top;"><div id="final_abv"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Schijnbare vergistingsgraad %:</td> - <td align="left" style="vertical-align: top;"><div id="final_svg"></div></td> - </tr> - </table> - <div style="float: right; margin-top: 55px; margin-bottom: 5px;"> - <input style="margin-right: 100px;" type="button" id="FLog" value="Klimaatkast log" /> - <input style="margin-right: 475px;" type="button" id="ILog" value="Vergisting log" /> - </div> - </div> - </div> <!-- Vergisten --> - - <div> <!-- Verpakken --> - <div style="overflow: hidden;"> - <table style="width: 100%;"> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Datum:</td> - <td align="left" style="vertical-align: top;"><div id="package_date"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Aanbevolen volume CO2:</td> - <td style="padding: 3px;"><div style="float: left;" id="st_carb_min2"></div><div style="float: left; margin-left: 5px;" id="st_carb_max2"></div></td> - </tr> - <tr> - <td colspan="4"><hr></td> - </tr> - <tr> - <th style="text-align: center;" colspan="4">Verdunnen of infusie</th> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Volume na vergisting L:</td> - <td align="left" colspan="3" style="vertical-align: top;"><div id="package_volume"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Toevoeging Liter:</td> - <td align="left" style="vertical-align: top;"><div id="package_infuse_amount"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Toevoeging ABV %:</td> - <td align="left" style="vertical-align: top;"><div id="package_infuse_abv"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Toevoeging omschrijving:</td> - <td align="left" colspan="3" style="vertical-align: top; padding: 3px;"><input id="package_infuse_notes" /></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Alcohol volume %:</td> - <td align="left" style="vertical-align: top;"><div id="package_abv"></div></td> - <td style="vertical-align: top; float: right;">Bij verpakken pH:</td> - <td align="left" style="vertical-align: top;"><div id="package_ph"></div></td> - </tr> - <tr> - <td colspan="4"><hr></td> - </tr> - <tr> - <th style="text-align: center;" colspan="2">Flessen</th> - <th style="text-align: center;" colspan="2">Fusten</th> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Hoeveelheid Liter:</td> - <td align="left" style="vertical-align: top;"><div id="bottle_amount"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Hoeveelheid Liter:</td> - <td align="left" style="vertical-align: top;"><div id="keg_amount"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Gewenst volume CO2:</td> - <td align="left" style="vertical-align: top;"><div id="bottle_carbonation"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Gewenst volume CO2:</td> - <td align="left" style="vertical-align: top;"><div id="keg_carbonation"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Suiker:</td> - <td align="left" style="vertical-align: top;"><input readonly="1" id="bottle_priming_sugar" /></td> - <td style="vertical-align: top; float: right; padding: 3px;">Suiker:</td> - <td align="left" style="vertical-align: top;"><input readonly="1" id="keg_priming_sugar" /></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Toevoegen suiker g/L:</td> - <td align="left" style="vertical-align: top;"><div id="bottle_priming_amount"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Toevoegen suiker g/L:</td> - <td align="left" style="vertical-align: top;"><div id="keg_priming_amount"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Suiker totaal gram:</td> - <td align="left" style="vertical-align: top;"><div id="bottle_priming_total"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Suiker totaal gram:</td> - <td align="left" style="vertical-align: top;"><div id="keg_priming_total"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Suikeroplossing water L:</td> - <td align="left" style="vertical-align: top;"><div id="bottle_priming_water"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Suikeroplossing water L:</td> - <td align="left" style="vertical-align: top;"><div id="keg_priming_water"></div></td> - </tr> - <tr> - <td colspan="2"></td> - <td style="vertical-align: top; float: right; padding: 3px;">Op druk brengen met CO2:</td> - <td align="left" style="vertical-align: top;"><div id="keg_forced_carb"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Verwachte flesdruk in bar:</td> - <td align="left" style="vertical-align: top;"><div id="bottle_pressure"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Druk op fust bar:</td> - <td align="left" style="vertical-align: top;"><div id="keg_pressure"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Alcoholgehalte flessen vol.%:</td> - <td align="left" style="vertical-align: top;"><div id="bottle_abv"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Alcoholgehalte fusten vol.%:</td> - <td align="left" style="vertical-align: top;"><div id="keg_abv"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Hergisting temperatuur:</td> - <td align="left" style="vertical-align: top;"><div id="bottle_carbonation_temp"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Keg temperatuur:</td> - <td align="left" style="vertical-align: top;"><div id="keg_carbonation_temp"></div></td> - </tr> - </table> - <div style="float: right; margin-top: 20px; margin-bottom: 5px;"> - <input style="margin-right: 575px;" type="button" id="CLog" value="Hergisting log" /> - </div> - </div> - </div> <!-- Verpakken --> - - <div> <!-- Proeven --> - <div style="overflow: hidden;"> - <table style="width: 100%;"> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Datum:</td> - <td align="left" style="vertical-align: top;"><div id="taste_date"></div></td> - <td style="vertical-align: top; float: right; padding: 3px;">Cijfer:</td> - <td align="left" style="vertical-align: top;"><div id="taste_rate"></div></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Kleur:</td> - <td style="padding: 3px;"><textarea id="taste_color" readonly></textarea></td> - <td style="vertical-align: top; float: right; padding: 3px;">Helderheid:</td> - <td style="padding: 3px;"><textarea id="taste_transparency" readonly></textarea></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Schuim:</td> - <td colspan="3" style="padding: 3px;"><textarea id="taste_head" readonly></textarea></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Aroma:</td> - <td colspan="3" style="padding: 3px;"><textarea id="taste_aroma" readonly></textarea></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Smaak:</td> - <td colspan="3" style="padding: 3px;"><textarea id="taste_taste" readonly></textarea></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Nasmaak:</td> - <td colspan="3" style="padding: 3px;"><textarea id="taste_aftertaste" readonly></textarea></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Mondgevoel:</td> - <td colspan="3" style="padding: 3px;"><textarea id="taste_mouthfeel" readonly></textarea></td> - </tr> - <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Oordeel:</td> - <td colspan="3" style="padding: 3px;"><textarea id="taste_notes" readonly></textarea></td> - </tr> - </table> - </div> - </div> <!-- Proeven --> - - </div> <!-- Tabs --> - -<?php -page_footer(); -?>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/www/prod_view.php Sat Aug 06 22:10:28 2022 +0200 @@ -0,0 +1,931 @@ +<?php +require_once($_SERVER['DOCUMENT_ROOT'].'/includes/global.inc.php'); +page_header('Brouw overzicht', 'prod_view'); +?> + + <div id='jqxTabs'> + <ul> + <li>Algemeen</li> + <li>Apparatuur</li> + <li>Vergistbaar</li> + <li>Hoppen</li> + <li>Diversen</li> + <li>Gist</li> + <li>Maischen</li> + <li>Water</li> + <li>Brouwdag</li> + <li>Vergisten</li> + <li>Verpakken</li> + <li>Proeven</li> + </ul> + + <div> <!-- tab algemeen --> + <div style="overflow: hidden;"> + <table style="width: 100%;"> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Brouw naam:</td> + <td align="left" colspan="3" style="vertical-align: top; padding: 3px;"><input id="name" /></td> + <td style="vertical-align: top; float: right; padding: 3px;">Afgesloten:</td> + <td align="left"><div id="locked"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Brouw code:</td> + <td align="left" style="vertical-align: top; padding: 3px;"><input id="code" /></td> + <td style="vertical-align: top; float: right; padding: 3px;">Start planning:</td> + <td align="left" style="vertical-align: top;"><input readonly="1" id="birth" /></td> + <td style="vertical-align: top; float: right; padding: 3px;">Brouw fase:</td> + <td align="left" style="vertical-align: top; padding: 3px;"><input id="stage" readonly /></td> + </tr> + <tr id='divide_row'> + <td style="vertical-align: top; float: right; padding: 3px;">Splits product:</td> + <td align="left" style="vertical-align: top; padding: 3px;"><input id="divide_type" readonly /></td> + <td style="vertical-align: top; float: right; padding: 3px;">Gesplitst product:</td> + <td align="left" style="vertical-align: top; padding: 3px;"><input id="divide_batch" readonly /></td> + <td style="vertical-align: top; float: right; padding: 3px;">Splits focus:</td> + <td align="left"><div id="d3"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Opmerkingen:</td> + <td colspan="5" style="padding: 3px;"><textarea id="notes"></textarea></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Brouw type:</td> + <td align="left" style="padding: 3px;"><input id="type" readonly /></td> + <td style="vertical-align: top; float: right; padding: 3px;">Brouwzaal rendement:</td> + <td style="padding: 3px;"><div id="efficiency"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;" id="ok_pmpt">Ingredienten aanwezig:</td> + <td align="left"><div id="ok_supplies"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Brouw volume:</td> + <td style="padding: 3px;"><div id="batch_size"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Kooktijd minuten:</td> + <td style="padding: 3px;"><div id="boil_time"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Kook volume:</td> + <td style="padding: 3px;"><div id="boil_size"></div></td> + </tr> + <tr> + <td colspan="6"><hr></td> + </tr> + <tr> + <td></td> + <th>Bierstijl gegevens</th> + <td colspan="4"></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Stijlgids:</td> + <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_guide" /></td> + <td style="vertical-align: top; float: right; padding: 3px;">Bier stijl:</td> + <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_name" /></td> + <td style="vertical-align: top; float: right; padding: 3px;">Bier groep:</td> + <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_letter" /></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Stijl type:</td> + <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_type" /></td> + <td style="vertical-align: top; float: right; padding: 3px;">Categorie:</td> + <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_category" /></td> + <td style="vertical-align: top; float: right; padding: 3px;">Categorie nr:</td> + <td style="padding: 3px;"><div id="st_category_number"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Start SG:</td> + <td style="padding: 3px;"><div style="float: left;" id="est_og"></div><div style="float: left; margin-left: 15px;" id="st_og_min"></div><div style="float: left; margin-left: 5px;" id="st_og_max"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Eind SG:</td> + <td style="padding: 3px;"><div style="float: left;" id="est_fg"></div><div style="float: left; margin-left: 15px;" id="st_fg_min"></div><div style="float: left; margin-left: 5px;" id="st_fg_max"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Alcohol vol.%:</td> + <td style="padding: 3px;"><div style="float: left;" id="est_abv"></div><div style="float: left; margin-left: 15px;" id="st_abv_min"></div><div style="float: left; margin-left: 5px;" id="st_abv_max"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Kleur EBC:</td> + <td style="padding: 3px;"><div style="float: left;" id="est_color"></div><div style="float: left; margin-left: 15px;" id="st_color_min"></div><div style="float: left; margin-left: 5px;" id="st_color_max"></div><div id="bcolor" class='ebccolor'> </div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Kleur methode:</td> + <td style="padding: 3px;"><input id="color_method" readonly /></td> + <td style="vertical-align: top; float: right; padding: 3px;">Koolzuur vol:</td> + <td style="padding: 3px;"><div style="float: left;" id="est_carb"></div><div style="float: left; margin-left: 15px;" id="st_carb_min"></div><div style="float: left; margin-left: 5px;" id="st_carb_max"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Bitterheid IBU:</td> + <td style="padding: 3px;"><div style="float: left;" id="est_ibu"></div><div style="float: left; margin-left: 15px;" id="st_ibu_min"></div><div style="float: left; margin-left: 5px;" id="st_ibu_max"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Bitterheid methode:</td> + <td style="padding: 3px;"><input id="ibu_method" readonly /></td> + <td style="vertical-align: top; float: right; padding: 3px;">Energie-inhoud kcal/l:</td> + <td style="padding: 3px;"><div style="float: left;" id="kcal"></div></td> + </tr> + </table> + <div style="float: right; margin-top: 20px; margin-bottom: 5px;"> + <input style="margin-right: 600px;" type="button" id="Terug" value="Terug" /> + </div> + </div> + </div> + + <div> <!-- Apparatuur --> + <div style="overflow: hidden;"> + <table style="width: 100%;"> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Installatie naam:</td> + <td colspan="3" align="left" style="vertical-align: top; padding: 3px;"><input id="eq_name" readonly /></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Opmerkingen:</td> + <td colspan="3" style="padding: 3px;"><textarea id="eq_notes" readonly></textarea></td> + </tr> + <tr> + <th style="text-align: center;" colspan="2">Maischen</th> + <th style="text-align: center;" colspan="2">Koken</th> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Maischkuip volume L:</td> + <td><div id="eq_tun_volume"></div></td> + <td style="vertical-align: top; float: right;">Kookketel volume L:</td> + <td><div id="eq_kettle_volume"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Maischwater L:</td> + <td><div id="eq_mash_volume"></div></td> + <td style="vertical-align: top; float: right;">Kook volume L:</td> + <td><div id="eq_boil_size"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Maximum moutstort Kg:</td> + <td><div id="eq_mash_max"></div></td> + <td style="vertical-align: top; float: right;">Verdamping per uur L:</td> + <td><div id="eq_evap_rate"></div></td> + </tr> + <tr> + <th style="text-align: center;" colspan="2">Filteren</th> + <td style="vertical-align: top; float: right;">Kooktijd in minuten:</td> + <td><div id="eq_boil_time"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Filter volume L:</td> + <td><div id="eq_lauter_volume"></div></td> + <td style="vertical-align: top; float: right;">Extra water bij koken L:</td> + <td><div id="eq_top_up_kettle"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Filterkuip verlies L:</td> + <td><div id="eq_lauter_deadspace"></div></td> + <td style="vertical-align: top; float: right;">Hopfactor %:</td> + <td><div id="eq_hop_utilization"></div></td> + </tr> + <tr> + <th style="text-align: center;" colspan="2">Koelen</th> + <td style="vertical-align: top; float: right;">Volume eind koken L:</td> + <td><div id="eq_batch_size"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Trub verlies kookketel L:</td> + <td><div id="eq_trub_chiller_loss"></div></td> + <td style="vertical-align: top; float: right;">Brouwzaalrendement %:</td> + <td><div id="eq_efficiency"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Extra water in gistvat:</td> + <td><div id="eq_top_up_water"></div></td> + <td colspan="2"></td> + </tr> + </table> + </div> + </div> + + <div> <!-- tab vergistbaar --> + <div style="overflow: hidden;"> + <table style="width: 100%;"> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Kleur EBC:</td> + <td style="padding: 3px;"><div style="float: left;" id="est_color2"></div><div id="bcolor2" class='ebccolor'> </div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Percentage moutstort:</td> + <td style="padding: 3px;"><div style="float: left;" id="perc_malts"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Begin SG:</td> + <td style="padding: 3px;"><div style="float: left;" id="est_og2"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Percentage suiker:</td> + <td style="padding: 3px;"><div style="float: left;" id="perc_sugars"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Maisch KG:</td> + <td style="padding: 3px;"><div style="float: left;" id="mash_kg"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Percentage cara:</td> + <td style="padding: 3px;"><div style="float: left;" id="perc_cara"></div></td> + </tr> + <tr> + <td colspan="2"> </td> + <td style="vertical-align: top; float: right; padding: 3px;">Lintner totaal:</td> + <td style="padding: 3px;"><div style="float: left;" id="ferm_lintner"></div></td> + </tr> + <tr> + <td align="center" colspan="4"><div id="fermentableGrid"></div></td> + </tr> + </table> + </div> + </div> <!-- tab vergistbaar --> + + <div> <!-- tab hoppen --> + <div style="overflow: hidden;"> + <table style="width: 100%;"> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Bitterheid IBU:</td> + <td style="padding: 3px;"><div id="est_ibu2"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Smaak bijdrage:</td> + <td style="padding: 3px;"><div id="hop_flavour"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Aroma bijdrage:</td> + <td style="padding: 3px;"><div id="hop_aroma"></div></td> + </tr> + <tr> + <td align="center" colspan="6"><div id="hopGrid"></div></td> + </tr> + </table> + </div> + </div> <!-- tab hoppen --> + + <div> <!-- tab misc --> + <div style="overflow: hidden;"> + <table style="width: 100%;"> + <tr><td> </td></tr> + <tr><td align="center"><div id="miscGrid"></div></td></tr> + </table> + </div> + </div> <!-- tab misc --> + + <div> <!-- tab gisten --> + <div style="overflow: hidden;"> + <table style="width: 100%;"> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Verwacht FG en ABV:</td> + <td style="padding: 3px;"><div style="float: left;" id="est_fg2"></div><div style="float: left; margin-left: 10px;" id="est_abv2"></div></td> + <td align="center" colspan="5" rowspan="5"> + <div id="propagator"> + <table style="width: 100%;"> + <caption>Giststarter stappen</caption> + <tr> + <td style="width: 40px; padding: 3px;">Stap</td> + <td align="left" style="vertical-align: top; padding: 3px;">Methode</td> + <td style="width: 120px; padding: 3px;">Volume</td> + <td style="width: 120px; padding: 3px;">Inj. factor</td> + <td style="width: 120px; padding: 3px;">Nieuwe cellen</td> + <td style="width: 120px; padding: 3px;">Totaal cellen</td> + <td style="width: 120px; padding: 3px;">Groei factor</td> + </tr> + <tr> + <td align="center">1</td> + <td><input id="prop1_type" readonly /><div id="r1_pmpt">Niet nodig</div></td> + <td><div id="prop1_volume"></div></td> + <td><div style="float: left;" id="prop1_irate"></div><div style="float: left;" id="r1_irate"></div></td> + <td><div id="prop1_ncells"></div></td> + <td><div style="float: left;" id="prop1_tcells"></div><div style="float: left;" id="r1_tcells"></div></td> + <td><div style="float: left;" id="prop1_growf"></div><div style="float: left;" id="r1_growf"></div></td> + </tr> + <tr> + <td align="center">2</td> + <td><input id="prop2_type" readonly /><div id="r2_pmpt">Niet nodig</div></td> + <td><div id="prop2_volume"></div></td> + <td><div style="float: left;" id="prop2_irate"></div><div style="float: left;" id="r2_irate"></div></td> + <td><div id="prop2_ncells"></div></td> + <td><div style="float: left;" id="prop2_tcells"></div><div style="float: left;" id="r2_tcells"></div></td> + <td><div style="float: left;" id="prop2_growf"></div><div style="float: left;" id="r2_growf"></div></td> + </tr> + <tr> + <td align="center">3</td> + <td><input id="prop3_type" readonly /><div id="r3_pmpt">Niet nodig</div></td> + <td><div id="prop3_volume"></div></td> + <td><div style="float: left;" id="prop3_irate"></div><div style="float: left;" id="r3_irate"></div></td> + <td><div id="prop3_ncells"></div></td> + <td><div style="float: left;" id="prop3_tcells"></div><div style="float: left;" id="r3_tcells"></div></td> + <td><div style="float: left;" id="prop3_growf"></div><div style="float: left;" id="r3_growf"></div></td> + </tr> + <tr> + <td align="center">4</td> + <td><input id="prop4_type" readonly /><div id="r4_pmpt">Niet nodig</div></td> + <td><div id="prop4_volume"></div></td> + <td><div style="float: left;" id="prop4_irate"></div><div style="float: left;" id="r4_irate"></div></td> + <td><div id="prop4_ncells"></div></td> + <td><div style="float: left;" id="prop4_tcells"></div><div style="float: left;" id="r4_tcells"></div></td> + <td><div style="float: left;" id="prop4_growf"></div><div style="float: left;" id="r4_growf"></div></td> + </tr> + </table> + </div> + </td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Gist productie datum:</td> + <td style="padding: 3px;"><div id="yeast_prod_date"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Gist conditie %:</td> + <td style="padding: 3px;"><div id="starter_viability"></div></td> + </tr> + <tr class="primary_dry"> + <td style="vertical-align: top; float: right; padding: 3px;">Gist nodig gram:</td> + <td style="padding: 3px;"><div id="yeast_grams"></div></td> + </tr> + <tr class="primary_dry"> + <td style="vertical-align: top; float: right; padding: 3px;">Ent hoeveelheid gr/hl:</td> + <td style="padding: 3px;"><div id="yeast_gr_hl"></div></td> + </tr> + <tr class="primary_liquid"> + <td style="vertical-align: top; float: right; padding: 3px;">Gistcellen miljard:</td> + <td style="padding: 3px;"><div id="yeast_cells"></div></td> + </tr> + <tr class="primary_liquid"> + <td style="vertical-align: top; float: right; padding: 3px;">Pitch rate:</td> + <td style="padding: 3px;"><div id="yeast_pitchrate"></div></td> + </tr> + <tr class="primary_liquid"> + <td style="vertical-align: top; float: right; padding: 3px;">Cellen nodig miljard:</td> + <td style="padding: 3px;"><div id="need_cells"></div></td> + </tr> + <tr class="primary_liquid"> + <td style="vertical-align: top; float: right; padding: 3px;">Pitch cellen/ml °P:</td> + <td style="padding: 3px;"><div id="plato_cells"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Starter type:</td> + <td style="padding: 3px;"><input id="starter_type" readonly /></td> + <td style="vertical-align: top; float: right; padding: 3px;">Starter SG:</td> + <td style="padding: 3px;"><div id="starter_sg"></div></td> + <td></td> + </tr> + <tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> + <tr><td align="center" colspan="7"><div id="yeastGrid"></div></td></tr> + </table> + </div> + </div> <!-- tab gisten --> + + <div> <!-- tab maischen --> + <div style="overflow: hidden;"> + <table style="width: 100%;"> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Maischchema:</td> + <td colspan="3" align="left" style="vertical-align: top; padding: 3px;"><input id="mash_name" readonly /></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Volume van de maisch L:</td> + <td style="padding: 3px;"><div id="est_mashvol"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Tijdsduur maischen:</td> + <td align="left" style="vertical-align: top; padding: 3px;"><input style="text-align:right" readonly="1" id="est_mashtime" /></td> + </tr> + <tr><td colspan="4"> </td></tr> + <tr><td align="center" colspan="4" style="padding: 3px;"><div id="mashGrid"></div></td></tr> + </table> + </div> + </div> <!-- tab maischen --> + + <div> <!-- tab water --> + <div style="overflow: hidden;"> + <table style="width: 100%;"> + <tr> + <td align="center" colspan="9"> + <div id='water_totals'> + <table style="width: 100%;"> + <caption>Water overzicht</caption> + <tr> + <td align="left" style="vertical-align: top; padding: 3px;">Water profiel</td> + <td style="width: 50px; padding: 3px;">Spoel</td> + <td style="width: 97px; padding: 3px;">Volume</td> + <td style="width: 77px; padding: 3px;">Ca</td> + <td style="width: 77px; padding: 3px;">Mg</td> + <td style="width: 77px; padding: 3px;">HCO3</td> + <td style="width: 77px; padding: 3px;">CaCO3</td> + <td style="width: 77px; padding: 3px;">Na</td> + <td style="width: 77px; padding: 3px;">Cl</td> + <td style="width: 77px; padding: 3px;">SO4</td> + <td style="width: 77px; padding: 3px;">pH</td> + <td style="width: 77px; padding: 3px;">Hardheid</td> + <td style="width: 77px; padding: 3px;">RA</td> + </tr> + <tr> + <td><input readonly="1" id="w1_name" /></td> + <td><div style='margin-left: 10px;' id='w1_button'></div></td> + <td><div id="w1_amount"></div></td> + <td><div id="w1_calcium"></div></td> + <td><div id="w1_magnesium"></div></td> + <td><div id="w1_bicarbonate"></div></td> + <td><div id="w1_total_alkalinity"></div></td> + <td><div id="w1_sodium"></div></td> + <td><div id="w1_chloride"></div></td> + <td><div id="w1_sulfate"></div></td> + <td><div id="w1_ph"></div></td> + <td><div id="w1_hardness"></div></td> + <td><div id="w1_ra"></div></td> + </tr> + <tr> + <td><input readonly="1" id="w2_name" /></td> + <td><div style='margin-left: 10px;' id='w2_button'></div></td> + <td><div id="w2_amount"></div></td> + <td><div id="w2_calcium"></div></td> + <td><div id="w2_magnesium"></div></td> + <td><div id="w2_bicarbonate"></div></td> + <td><div id="w2_total_alkalinity"></div></td> + <td><div id="w2_sodium"></div></td> + <td><div id="w2_chloride"></div></td> + <td><div id="w2_sulfate"></div></td> + <td><div id="w2_ph"></div></td> + <td><div id="w2_hardness"></div></td> + <td><div id="w2_ra"></div></td> + </tr> + <tr> + <td style="vertical-align: top; padding: 3px; float: left;">Gemengd water:</td> + <td><div style='margin-left: 10px;' id='wg_button'></div></td> + <td><div id="wg_amount"></div></td> + <td><div id="wg_calcium"></div></td> + <td><div id="wg_magnesium"></div></td> + <td><div id="wg_bicarbonate"></div></td> + <td><div id="wg_total_alkalinity"></div></td> + <td><div id="wg_sodium"></div></td> + <td><div id="wg_chloride"></div></td> + <td><div id="wg_sulfate"></div></td> + <td><div id="wg_ph"></div></td> + <td><div id="wg_hardness"></div></td> + <td><div id="wg_ra"></div></td> + </tr> + <tr> + <td style="vertical-align: top; padding: 3px; float: left;">Behandeld maisch water:</td> + <td></td> + <td><div></div></td> + <td><div id="wb_calcium"></div></td> + <td><div id="wb_magnesium"></div></td> + <td><div id="wb_bicarbonate"></div></td> + <td><div id="wb_total_alkalinity"></div></td> + <td><div id="wb_sodium"></div></td> + <td><div id="wb_chloride"></div></td> + <td><div id="wb_sulfate"></div></td> + <td><div id="wb_ph"></div></td> + <td><div id="wb_hardness"></div></td> + <td><div id="wb_ra"></div></td> + </tr> + <tr> + <td style="vertical-align: top; padding: 3px; float: left;">Resultaat:</td> + <td></td> + <td><div></div></td> + <td><div id="wr_calcium"></div></td> + <td><div id="wr_magnesium"></div></td> + <td><div id="wr_bicarbonate"></div></td> + <td><div id="wr_total_alkalinity"></div></td> + <td><div id="wr_sodium"></div></td> + <td><div id="wr_chloride"></div></td> + <td><div id="wr_sulfate"></div></td> + <td><div id="wr_ph"></div></td> + <td></td> + <td></td> + </tr> + <tr> + <td style="vertical-align: top; padding: 3px; float: left;">Behandeld spoelwater:</td> + <td></td> + <td><div id="sw_amount"></div></td> + <td><div id="sw_calcium"></div></td> + <td><div id="sw_magnesium"></div></td> + <td><div id="sw_bicarbonate"></div></td> + <td><div id="sw_total_alkalinity"></div></td> + <td><div id="sw_sodium"></div></td> + <td><div id="sw_chloride"></div></td> + <td><div id="sw_sulfate"></div></td> + <td><div id="sw_ph"></div></td> + <td><div id="sw_hardness"></div></td> + <td><div id="sw_ra"></div></td> + </tr> + </table> + </div> + </td> + </tr> + <tr> + <th style="text-align: center;" colspan="3">Brouwzouten</th> + <th colspan="3"></th> + <th style="text-align: center;" colspan="3">Spoelwater</th> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">CaCl2 gr:</td> + <td style="padding: 3px;"><div id="wa_cacl2"></div></td> + <td style="padding: 3px;"><div id="ss_cacl2"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Bitterheidsindex:</td> + <td style="padding: 3px;"><div style="float: left;" id="tgt_bu"></div></td> + <td style="padding: 3px;"><div style="float: left;" id="wr_bu"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Auto bereken:</td> + <td style="padding: 3px;"><div id="calc_acid"></div></td> + <td></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">CaSO4 gr:</td> + <td style="padding: 3px;"><div id="wa_caso4"></div></td> + <td style="padding: 3px;"><div id="ss_caso4"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Richtgetal SO4:Cl:</td> + <td style="padding: 3px;"><div style="float: left;" id="tgt_so4_cl"></div></td> + <td style="padding: 3px;"><div style="float: left;" id="wrt_so4_cl"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;"><div class='c_mashph'>Gewenst maish pH:</div></td> + <td style="padding: 3px;"><div id="mash_ph" class='c_mashph'></div></td> + <td></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">MgSO4 gr:</td> + <td style="padding: 3px;"><div id="wa_mgso4"></div></td> + <td style="padding: 3px;"><div id="ss_mgso4"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Huidig SO4:Cl:</td> + <td style="padding: 3px;"><div style="float: left;" id="got_so4_cl"></div></td> + <td style="padding: 3px;"><div style="float: left;" id="wr_so4_cl"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Aanzuren met:</td> + <td style="padding: 3px;"><input readonly="1" id="wa_acid_name" /></td> + <td style="padding: 3px;"><div style="float: left;" id="wa_acid_perc"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">NaCl gr:</td> + <td style="padding: 3px;"><div id="wa_nacl"></div></td> + <td style="padding: 3px;"><div id="ss_nacl"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Voor koken pH:</td> + <td style="padding: 3px;"><div id="preboil_ph"></div></td> + <td></td> + <td style="vertical-align: top; float: right; padding: 3px;">Zuur hoeveelheid:</td> + <td style="padding: 3px;"><div style="float: left;" id="wa_acid"></div></td> + <td></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">MgCl2 gr:</td> + <td style="padding: 3px;"><div id="wa_mgcl2"></div></td> + <td style="padding: 3px;"><div id="ss_mgcl2"></div></td> + <td colspan="3"></td> + <td style="vertical-align: top; float: right; padding: 3px;">Gewenst spoel pH:</td> + <td style="padding: 3px;"><div id="sparge_ph"></div></td> + <td></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">NaHCO3 gr:</td> + <td style="padding: 3px;"><div id="wa_nahco3"></div></td> + <td colspan="4"></td> + <td style="vertical-align: top; float: right; padding: 3px;">Aanzuren met:</td> + <td style="padding: 3px;"><input readonly="1" id="sparge_acid_type" /></td> + <td style="padding: 3px;"><div id="sparge_acid_perc"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">CaCO3 gr:</td> + <td style="padding: 3px;"><div id="wa_caco3"></div></td> + <td colspan="4"></td> + <td style="vertical-align: top; float: right; padding: 3px;">Zuur hoeveelheid:</td> + <td style="padding: 3px;"><div id="sparge_acid_amount"></div></td> + <td></td> + </tr> + </table> + </div> + </div> <!-- tab water --> + + <div style="overflow: hidden;"> <!-- Brewday --> + <table style="width: 100%;"> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Brouwdag start:</td> + <td align="left" colspan="2" style="vertical-align: top;"><div id="brew_date_start"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Brouwdag eind:</td> + <td align="left" colspan="2" style="vertical-align: top;"><div id="brew_date_end"></div></td> + </tr> + <tr> + <td colspan="6"> </td> + </tr> + <tr> + <th style="text-align: center;" colspan="2">Maischen</th> + <th style="text-align: center;" colspan="4"><div id="brew_pmpt_koken">Koken</div></th> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Maisch pH:</td> + <td><div style="float: left;" id="brew_mash_ph"></div><div style="float: left; margin-left: 10px;" id="est_mash_ph"></div></td> + <td style="vertical-align: top; float: right;">Voor koken pH:</td> + <td><div id="brew_preboil_ph"></div></td> + <td style="vertical-align: top; float: right;">Na koken pH:</td> + <td><div id="brew_aboil_ph"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Maisch SG:</td> + <td><div style="float: left;" id="brew_mash_sg"></div><div style="float: left; margin-left: 10px;" id="est_mash_sg"></div></td> + <td style="vertical-align: top; float: right;">Voor koken SG:</td> + <td><div style="float: left;" id="brew_preboil_sg"></div><div style="float: left; margin-left: 10px;" id="est_pre_sg"></div></td> + <td style="vertical-align: top; float: right;">Na koken SG:</td> + <td><div style="float: left;" id="brew_aboil_sg"></div><div style="float: left; margin-left: 10px;" id="est_og3"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Maisch rendement %:</td> + <td><div id="brew_mash_efficiency"></div></td> + <td style="vertical-align: top; float: right;">Voor koken vol@100°C:</td> + <td><div style="float: left;" id="brew_preboil_volume"></div><div style="float: left; margin-left: 10px;" id="est_pre_vol"></div></td> + <td style="vertical-align: top; float: right;">Na koken vol@100°C:</td> + <td><div style="float: left;" id="brew_aboil_volume"></div><div style="float: left; margin-left: 10px;" id="est_a_vol"></div></td> + </tr> + <tr> + <td colspan="2"> </td> + <td style="vertical-align: top; float: right;">Voor koken rendement %:</td> + <td><div id="brew_preboil_efficiency"></div></td> + <td style="vertical-align: top; float: right;">Na koken rendement %:</td> + <td><div id="brew_aboil_efficiency"></div></td> + </tr> + <tr> + <td colspan="6"> </td> + </tr> + <tr> + <th style="text-align: center;" colspan="2">Spoelen en filteren</th> + <th style="text-align: center;" colspan="4">Koelen en whirlpoolen</th> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Spoelwater °C:</td> + <td><div id="brew_sparge_temperature"></div></td> + <td style="vertical-align: top; float: right;">Whirlpool 85..100°C min:</td> + <td><div id="brew_whirlpool9"></div></td> + <td style="vertical-align: top; float: right;">Koelen tot °C:</td> + <td><div id="brew_cooling_to"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Spoelwater voorraad L:</td> + <td><div id="brew_sparge_volume"></div></td> + <td style="vertical-align: top; float: right;">Whirlpool 72..79°C min:</td> + <td><div id="brew_whirlpool7"></div></td> + <td style="vertical-align: top; float: right;">Koelen met:</td> + <td><input readonly="1" id="brew_cooling_method" /></td> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Spoelwater nodig L:</td> + <td><div id="brew_sparge_est"></div></td> + <td style="vertical-align: top; float: right;">Whirlpool 60..66°C min:</td> + <td><div id="brew_whirlpool6"></div></td> + <td style="vertical-align: top; float: right;">Koelen minuten:</td> + <td><div id="brew_cooling_time"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Spoelwater pH:</td> + <td><div id="brew_sparge_ph"></div></td> + <td style="vertical-align: top; float: right;">Whirlpool koud min:</td> + <td><div id="brew_whirlpool2"></div></td> + <td colspan="2"> </td> + </tr> + <tr> + <td colspan="6"> </td> + </tr> + <tr> + <th style="text-align: center;" colspan="2">Beluchten</th> + <th style="text-align: center;" colspan="4">Naar gistvat</th> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Beluchten met:</td> + <td><input readonly="1" id="brew_aeration_type" /></td> + <td style="vertical-align: top; float: right;">Koeler en trub verlies L:</td> + <td><div id="brew_fermenter_tcloss"></div></td> + <td style="vertical-align: top; float: right;">SG in gistvat:</td> + <td><div id="brew_fermenter_sg"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Beluchten tijd min:</td> + <td><div id="brew_aeration_time"></div></td> + <td style="vertical-align: top; float: right;">Extra water in gistvat L:</td> + <td><div id="brew_fermenter_extrawater"></div></td> + <td style="vertical-align: top; float: right;">Kleur in gistvat EBC:</td> + <td><div style="float: left;" id="brew_fermenter_color"></div><div style="float: left; margin-left: 10px;" id="bcolorf" class='ebccolor'> </div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right;">Beluchten snelheid:</td> + <td><div id="brew_aeration_speed"></div></td> + <td style="vertical-align: top; float: right;">Volume naar gistvat L:</td> + <td><div id="brew_fermenter_volume"></div></td> + <td style="vertical-align: top; float: right;">Bitterheid in gistvat IBU:</td> + <td><div style="float: left;" id="brew_fermenter_ibu"></div></td> + </tr> + </table> + </div> <!-- Brewday --> + + <div> <!-- Vergisten --> + <div style="overflow: hidden;"> + <table style="width: 100%;"> + <tr> + <td style="width: 30%;"> </td> + <td style="width: 20%;"> </td> + <td style="width: 30%;"> </td> + <td style="width: 20%;"> </td> + </tr> + <tr> + <th style="text-align: center;" colspan="4">Hoofdvergisting</th> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Begin vergisting SG:</td> + <td align="left" colspan="3" style="vertical-align: top;"><div id="brew_fermenter_sg2"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Start temperatuur hoofdvergisting °C:</td> + <td align="left" colspan="3" style="vertical-align: top;"><div id="primary_start_temp"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Piek temperatuur hoofdvergisting °C:</td> + <td align="left" colspan="3" style="vertical-align: top;"><div id="primary_max_temp"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Eind temperatuur hoofdvergisting °C:</td> + <td align="left" colspan="3" style="vertical-align: top;"><div id="primary_end_temp"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Eind hoofdvergisting SG:</td> + <td align="left" colspan="3" style="vertical-align: top;"><div id="primary_end_sg"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Eind hoofdvergisting/overhevelen:</td> + <td align="left" style="vertical-align: top;"><div id="primary_end_date"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Schijnbare vergistingsgraad:</td> + <td align="left" style="vertical-align: top;"><div id="primary_svg"></div></td> + </tr> + <tr> + <td colspan="4"><hr></td> + </tr> + <tr> + <th style="text-align: center;" colspan="4">Nagisting</th> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Temperatuur nagisting °C:</td> + <td align="left" colspan="3" style="vertical-align: top;"><div id="secondary_temp"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Eind nagisting SG:</td> + <td align="left" colspan="3" style="vertical-align: top;"><div id="secondary_end_sg"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Eind nagisting/start lageren:</td> + <td align="left" style="vertical-align: top;"><div id="secondary_end_date"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Schijnbare vergistingsgraad %:</td> + <td align="left" style="vertical-align: top;"><div id="secondary_svg"></div></td> + </tr> + <tr> + <td colspan="4"><hr></td> + </tr> + <tr> + <th style="text-align: center;" colspan="4">Lageren</th> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Temperatuur lageren °C:</td> + <td align="left" colspan="3" style="vertical-align: top;"><div id="tertiary_temp"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Het verwachte eind SG:</td> + <td align="left" colspan="3" style="vertical-align: top;"><div id="est_fg3"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Het behaalde eind SG:</td> + <td align="left" colspan="3" style="vertical-align: top;"><div id="fg"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Alcoholgehalte voor hergisting vol.%:</td> + <td align="left" style="vertical-align: top;"><div id="final_abv"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Schijnbare vergistingsgraad %:</td> + <td align="left" style="vertical-align: top;"><div id="final_svg"></div></td> + </tr> + </table> + <div style="float: right; margin-top: 55px; margin-bottom: 5px;"> + <input style="margin-right: 100px;" type="button" id="FLog" value="Klimaatkast log" /> + <input style="margin-right: 475px;" type="button" id="ILog" value="Vergisting log" /> + </div> + </div> + </div> <!-- Vergisten --> + + <div> <!-- Verpakken --> + <div style="overflow: hidden;"> + <table style="width: 100%;"> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Datum:</td> + <td align="left" style="vertical-align: top;"><div id="package_date"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Aanbevolen volume CO2:</td> + <td style="padding: 3px;"><div style="float: left;" id="st_carb_min2"></div><div style="float: left; margin-left: 5px;" id="st_carb_max2"></div></td> + </tr> + <tr> + <td colspan="4"><hr></td> + </tr> + <tr> + <th style="text-align: center;" colspan="4">Verdunnen of infusie</th> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Volume na vergisting L:</td> + <td align="left" colspan="3" style="vertical-align: top;"><div id="package_volume"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Toevoeging Liter:</td> + <td align="left" style="vertical-align: top;"><div id="package_infuse_amount"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Toevoeging ABV %:</td> + <td align="left" style="vertical-align: top;"><div id="package_infuse_abv"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Toevoeging omschrijving:</td> + <td align="left" colspan="3" style="vertical-align: top; padding: 3px;"><input id="package_infuse_notes" /></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Alcohol volume %:</td> + <td align="left" style="vertical-align: top;"><div id="package_abv"></div></td> + <td style="vertical-align: top; float: right;">Bij verpakken pH:</td> + <td align="left" style="vertical-align: top;"><div id="package_ph"></div></td> + </tr> + <tr> + <td colspan="4"><hr></td> + </tr> + <tr> + <th style="text-align: center;" colspan="2">Flessen</th> + <th style="text-align: center;" colspan="2">Fusten</th> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Hoeveelheid Liter:</td> + <td align="left" style="vertical-align: top;"><div id="bottle_amount"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Hoeveelheid Liter:</td> + <td align="left" style="vertical-align: top;"><div id="keg_amount"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Gewenst volume CO2:</td> + <td align="left" style="vertical-align: top;"><div id="bottle_carbonation"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Gewenst volume CO2:</td> + <td align="left" style="vertical-align: top;"><div id="keg_carbonation"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Suiker:</td> + <td align="left" style="vertical-align: top;"><input readonly="1" id="bottle_priming_sugar" /></td> + <td style="vertical-align: top; float: right; padding: 3px;">Suiker:</td> + <td align="left" style="vertical-align: top;"><input readonly="1" id="keg_priming_sugar" /></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Toevoegen suiker g/L:</td> + <td align="left" style="vertical-align: top;"><div id="bottle_priming_amount"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Toevoegen suiker g/L:</td> + <td align="left" style="vertical-align: top;"><div id="keg_priming_amount"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Suiker totaal gram:</td> + <td align="left" style="vertical-align: top;"><div id="bottle_priming_total"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Suiker totaal gram:</td> + <td align="left" style="vertical-align: top;"><div id="keg_priming_total"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Suikeroplossing water L:</td> + <td align="left" style="vertical-align: top;"><div id="bottle_priming_water"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Suikeroplossing water L:</td> + <td align="left" style="vertical-align: top;"><div id="keg_priming_water"></div></td> + </tr> + <tr> + <td colspan="2"></td> + <td style="vertical-align: top; float: right; padding: 3px;">Op druk brengen met CO2:</td> + <td align="left" style="vertical-align: top;"><div id="keg_forced_carb"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Verwachte flesdruk in bar:</td> + <td align="left" style="vertical-align: top;"><div id="bottle_pressure"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Druk op fust bar:</td> + <td align="left" style="vertical-align: top;"><div id="keg_pressure"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Alcoholgehalte flessen vol.%:</td> + <td align="left" style="vertical-align: top;"><div id="bottle_abv"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Alcoholgehalte fusten vol.%:</td> + <td align="left" style="vertical-align: top;"><div id="keg_abv"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Hergisting temperatuur:</td> + <td align="left" style="vertical-align: top;"><div id="bottle_carbonation_temp"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Keg temperatuur:</td> + <td align="left" style="vertical-align: top;"><div id="keg_carbonation_temp"></div></td> + </tr> + </table> + <div style="float: right; margin-top: 20px; margin-bottom: 5px;"> + <input style="margin-right: 575px;" type="button" id="CLog" value="Hergisting log" /> + </div> + </div> + </div> <!-- Verpakken --> + + <div> <!-- Proeven --> + <div style="overflow: hidden;"> + <table style="width: 100%;"> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Datum:</td> + <td align="left" style="vertical-align: top;"><div id="taste_date"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Cijfer:</td> + <td align="left" style="vertical-align: top;"><div id="taste_rate"></div></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Kleur:</td> + <td style="padding: 3px;"><textarea id="taste_color" readonly></textarea></td> + <td style="vertical-align: top; float: right; padding: 3px;">Helderheid:</td> + <td style="padding: 3px;"><textarea id="taste_transparency" readonly></textarea></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Schuim:</td> + <td colspan="3" style="padding: 3px;"><textarea id="taste_head" readonly></textarea></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Aroma:</td> + <td colspan="3" style="padding: 3px;"><textarea id="taste_aroma" readonly></textarea></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Smaak:</td> + <td colspan="3" style="padding: 3px;"><textarea id="taste_taste" readonly></textarea></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Nasmaak:</td> + <td colspan="3" style="padding: 3px;"><textarea id="taste_aftertaste" readonly></textarea></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Mondgevoel:</td> + <td colspan="3" style="padding: 3px;"><textarea id="taste_mouthfeel" readonly></textarea></td> + </tr> + <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Oordeel:</td> + <td colspan="3" style="padding: 3px;"><textarea id="taste_notes" readonly></textarea></td> + </tr> + </table> + </div> + </div> <!-- Proeven --> + + </div> <!-- Tabs --> + +<?php +page_footer(); +?>