www/js/global.js

Wed, 16 Oct 2019 21:05:03 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Wed, 16 Oct 2019 21:05:03 +0200
changeset 514
3c680d1dea35
parent 512
4451af8b6295
child 515
9d771385a8a0
permissions
-rw-r--r--

Added dutch array strings to a global php script. Changed fermentables, hops, yeast and misc inventory scripts to use these strings between the database scripts and javascript scripts. This makes filtering on types strings useable. Added these changes to the product/recipe forum and print exports too.

/*****************************************************************************
 * Copyright (C) 2014-2019
 *
 * Michiel Broek <mbroek at mbse dot eu>
 *
 * This file is part of BrewCloud
 *
 * 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.
 *****************************************************************************/


// dropdownlists arrays

var StageData = [
 { id: 0,  en: 'Plan',        nl: 'Plan' },
 { id: 1,  en: 'Wait',        nl: 'Wacht' },
 { id: 2,  en: 'Brew',        nl: 'Brouwen' },
 { id: 3,  en: 'Primary',     nl: 'Hoofdgisting' },
 { id: 4,  en: 'Secondary',   nl: 'Nagisting' },
 { id: 5,  en: 'Tertiary',    nl: 'Lagering' },
 { id: 6,  en: 'Package',     nl: 'Afvullen' },
 { id: 7,  en: 'Carbonation', nl: 'Hergisten' },
 { id: 8,  en: 'Mature',      nl: 'Rijpen' },
 { id: 9,  en: 'Taste',       nl: 'Proeven' },
 { id: 10, en: 'Ready',       nl: 'Gereed' },
 { id: 11, en: 'Closed',      nl: 'Afgesloten' }
],
StageSource = {
 localdata: StageData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
StageAdapter = new $.jqx.dataAdapter(StageSource),

SplitData = [
 { id: 0, en: 'Not divided',     nl: 'Niet gesplitst',  ok: 100 },
 { id: 1, en: 'After mash',      nl: 'Na maischen',     ok: 2 },
 { id: 2, en: 'After boil',      nl: 'Na koken',        ok: 2 },
 { id: 3, en: 'After cooling',   nl: 'Na koelen',       ok: 2 },
 { id: 4, en: 'After primary',   nl: 'Na hoofdgisting', ok: 3 },
 { id: 5, en: 'After secondary', nl: 'Na nagisting',    ok: 4 },
 { id: 6, en: 'After tertiary',  nl: 'Na lageren',      ok: 5 }
],
SplitSource = {
 localdata: SplitData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }, { name: 'ok' }]
},
SplitAdapter = new $.jqx.dataAdapter(SplitSource),

MaterialData = [
 { id: 0,  en: 'Stainless Steel', nl: 'RVS',       sh: 0.11 },
 { id: 1,  en: 'Aluminium',       nl: 'Aluminium', sh: 0.22 },
 { id: 2,  en: 'Plastics',        nl: 'Kunststof', sh: 0.46 },
 { id: 3,  en: 'Copper',          nl: 'Koper',     sh: 0.092 }
],
MaterialSource = {
 localdata: MaterialData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }, { name: 'sh' }]
},
MaterialAdapter = new $.jqx.dataAdapter(MaterialSource),

FermentableTypeData = [
 { id: 0, en: 'Grain',       nl: 'Mout' },
 { id: 1, en: 'Sugar',       nl: 'Suiker' },
 { id: 2, en: 'Extract',     nl: 'Vloeibaar extract' },
 { id: 3, en: 'Dry extract', nl: 'Droog extract' },
 { id: 4, en: 'Adjunct',     nl: 'Ongemout graan' }
],
FermentableTypeSource = {
 localdata: FermentableTypeData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
FermentableTypeAdapter = new $.jqx.dataAdapter(FermentableTypeSource),

GrainTypeData = [
 { id: 0, en: 'Base',      nl: 'Basismout' },
 { id: 1, en: 'Roast',     nl: 'Geroosterde mout' },
 { id: 2, en: 'Crystal',   nl: 'Cara- of crystalmout' },
 { id: 3, en: 'Kilned',    nl: 'Geƫeste mout'},
 { id: 4, en: 'Sour malt', nl: 'Zuurmout' },
 { id: 5, en: 'Special',   nl: 'Speciale mout' },
 { id: 6, en: 'No malt',   nl: 'Geen mout' }
],
GrainTypeSource = {
 localdata: GrainTypeData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
GrainTypeAdapter = new $.jqx.dataAdapter(GrainTypeSource),

AddedData = [
 { id: 0, en: 'Mash', nl: 'Maischen' },
 { id: 1, en: 'Boil', nl: 'Koken' },
 { id: 2, en: 'Fermentation', nl: 'Vergisten' },
 { id: 3, en: 'Lagering', nl: 'Nagisten/lageren' },
 { id: 4, en: 'Bottle', nl: 'Bottelen' },
 { id: 5, en: 'Kegs', nl: 'Fust' }
],
AddedSource = {
 localdata: AddedData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
AddedAdapter = new $.jqx.dataAdapter(AddedSource),

HopTypeData = [
 { id: 0, en: 'Bittering', nl: 'Bitterhop' },
 { id: 1, en: 'Aroma',     nl: 'Aromahop' },
 { id: 2, en: 'Both',      nl: 'Beide' }
],
HopTypeSource = {
 localdata: HopTypeData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
HopTypeAdapter = new $.jqx.dataAdapter(HopTypeSource),

HopFormData = [
 { id: 0, en: 'Pellet',   nl: 'Pellets' },
 { id: 1, en: 'Plug',     nl: 'Plugs' },
 { id: 2, en: 'Leaf',     nl: 'Bloemen' },
 { id: 3, en: 'Leaf wet', nl: 'Hop nat' },
 { id: 4, en: 'Cryo',     nl: 'Cryo' }
],
HopFormSource = {
 localdata: HopFormData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
HopFormAdapter = new $.jqx.dataAdapter(HopFormSource),

HopUseData = [
 { id: 0, en: 'Mash',       nl: 'Maischhop' },
 { id: 1, en: 'First wort', nl: 'First wort' },
 { id: 2, en: 'Boil',       nl: 'Koken' },
 { id: 3, en: 'Aroma',      nl: 'Vlamuit' },
 { id: 4, en: 'Whirlpool',  nl: 'Whirlpool' },
 { id: 5, en: 'Dry hop',    nl: 'Koudhop' }
],
HopUseSource = {
 localdata: HopUseData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
HopUseAdapter = new $.jqx.dataAdapter(HopUseSource),

YeastTypeData = [
 { id: 0, en: 'Lager',     nl: 'Ondergist' },
 { id: 1, en: 'Ale',       nl: 'Bovengist' },
 { id: 2, en: 'Wheat',     nl: 'Tarwegist' },
 { id: 3, en: 'Wine',      nl: 'Wijngist' },
 { id: 4, en: 'Champagne', nl: 'Champagnegist' },
 { id: 5, en: 'Brett',     nl: 'Brett' },
 { id: 6, en: 'Kveik',     nl: 'Kveik' },
 { id: 7, en: 'Hybrid',    nl: 'Hybride' }
// { id: 8, en: 'Mixed',     nl: 'Mixed' },
// { id: 9, en: 'Spontaneous', nl: 'Spontaan' },
// { id: 10, en: 'Other',       nl: 'Overig' }
],
YeastTypeSource = {
 localdata: YeastTypeData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
YeastTypeAdapter = new $.jqx.dataAdapter(YeastTypeSource),

YeastFormData = [
 { id: 0, en: 'Liquid',  nl: 'Vloeibaar',    cells: 100000000000 },
 { id: 1, en: 'Dry',     nl: 'Droog',        cells: 15000000000 },
 { id: 2, en: 'Slant',   nl: 'Schuine buis', cells: 1700000000 },
 { id: 3, en: 'Culture', nl: 'Slurry',       cells: 1700000000 },
 { id: 4, en: 'Frozen',  nl: 'Ingevroren',   cells: 1700000000 },
 { id: 5, en: 'Bottle',  nl: 'Depot',        cells: 1700000000 }
],
YeastFormSource = {
 localdata: YeastFormData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }, { name: 'cells' }]
},
YeastFormAdapter = new $.jqx.dataAdapter(YeastFormSource),

YeastUseData = [
 { id: 0, en: 'Primary',   nl: 'Hoofdgisting' },
 { id: 1, en: 'Secondary', nl: 'Nagisting' },
 { id: 2, en: 'Tertiary',  nl: 'Lagering' },
 { id: 3, en: 'Bottle',    nl: 'Bottelen' }
],
YeastUseSource = {
 localdata: YeastUseData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }, { name: 'cells' }]
},
YeastUseAdapter = new $.jqx.dataAdapter(YeastUseSource),

FlocculationData = [
 { id: 0, en: 'Low',       nl: 'Laag' },
 { id: 1, en: 'Medium',    nl: 'Medium' },
 { id: 2, en: 'High',      nl: 'Hoog' },
 { id: 3, en: 'Very high', nl: 'Zeer hoog' }
],
FlocculationSource = {
 localdata: FlocculationData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
FlocculationAdapter = new $.jqx.dataAdapter(FlocculationSource),

ZymocideData = [
 { id: 0, en: 'None', nl: 'Niet' },
 { id: 1, en: 'K1',   nl: 'K1' },
 { id: 2, en: 'K2',   nl: 'K2' },
 { id: 3, en: 'K28',  nl: 'K28' },
 { id: 4, en: 'Klus', nl: 'Klus' }
],
ZymocideSource = {
 localdata: ZymocideData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
ZymocideAdapter = new $.jqx.dataAdapter(ZymocideSource),

StarterTypeData = [
 { id: 0, en: 'Stirred', nl: 'Geroerd' },
 { id: 1, en: 'Shaken',  nl: 'Geschud' },
 { id: 2, en: 'Simple',  nl: 'Simpel' }
],
StarterTypeSource = {
 localdata: StarterTypeData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
StarterTypeAdapter = new $.jqx.dataAdapter(StarterTypeSource),

MiscTypeData = [
 { id: 0, en: 'Spice',          nl: 'Specerij' },
 { id: 1, en: 'Herb',           nl: 'Kruid' },
 { id: 2, en: 'Flavor',         nl: 'Smaakstof' },
 { id: 3, en: 'Fining',         nl: 'Klaringsmiddel' },
 { id: 4, en: 'Water agent',    nl: 'Brouwzout' },
 { id: 5, en: 'Yeast nutrient', nl: 'Gistvoeding' },
 { id: 6, en: 'Other',          nl: 'Anders' }
],
MiscTypeSource = {
 localdata: MiscTypeData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
MiscTypeAdapter = new $.jqx.dataAdapter(MiscTypeSource),

MiscUseData = [
 { id: 0, en: 'Starter',   nl: 'Starter' },
 { id: 1, en: 'Mash',      nl: 'Maischen' },
 { id: 2, en: 'Boil',      nl: 'Koken' },
 { id: 3, en: 'Primary',   nl: 'Hoofdvergisting' },
 { id: 4, en: 'Secondary', nl: 'Nagisting/lagering' },
 { id: 5, en: 'Bottling',  nl: 'Bottelen' }
],
MiscUseSource = {
 localdata: MiscUseData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
MiscUseAdapter = new $.jqx.dataAdapter(MiscUseSource),

StyleTypeData = [
 { id: 0, en: 'Lager', nl: 'Ondergistend bier' },
 { id: 1, en: 'Ale',   nl: 'Bovengistend bier' },
 { id: 2, en: 'Mead',  nl: 'Mede' },
 { id: 3, en: 'Wheat', nl: 'Tarwebier' },
 { id: 4, en: 'Mixed', nl: 'Gemengd' },
 { id: 5, en: 'Cider', nl: 'Cider' }
],
StyleTypeSource = {
 localdata: StyleTypeData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
StyleTypeAdapter = new $.jqx.dataAdapter(StyleTypeSource),

MashStepTypeData = [
 { id: 0, en: 'Infusion',    nl: 'Infusie' },
 { id: 1, en: 'Temperature', nl: 'Verwarming' },
 { id: 2, en: 'Decoction',   nl: 'Decoctie' }
],
MashStepTypeSource = {
 localdata: MashStepTypeData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
MashStepTypeAdapter = new $.jqx.dataAdapter(MashStepTypeSource),

RecipeTypeData = [
 { id: 0, en: 'Extract',      nl: 'Extract' },
 { id: 1, en: 'Partial Mash', nl: 'Deelmaisch' },
 { id: 2, en: 'All Grain',    nl: 'Mout' }
],
RecipeTypeSource = {
 localdata: RecipeTypeData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
RecipeTypeAdapter = new $.jqx.dataAdapter(RecipeTypeSource),

IBUmethodData = [
 { id: 0, en: 'Tinseth', nl: 'Tinseth' },
 { id: 1, en: 'Rager',   nl: 'Rager' },
 { id: 2, en: 'Daniels', nl: 'Daniels' }
// { id: 3, en: 'Garetz',  nl: 'Garetz' }, // Not yet supported.
// { id: 4, en: 'Mosher',  nl: 'Mosher' },
// { id: 5, en: 'Noonan',  nl: 'Noonan' }
],
IBUmethodSource = {
 localdata: IBUmethodData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
IBUmethodAdapter = new $.jqx.dataAdapter(IBUmethodSource),

ColorMethodData = [
 { id: 0, en: 'Morey',       nl: 'Morey' },
 { id: 1, en: 'Mosher',      nl: 'Mosher' },
 { id: 2, en: 'Daniels',     nl: 'Daniels' },
 { id: 3, en: 'Halberstadt', nl: 'Halberstadt' },
 { id: 4, en: 'Naudts',      nl: 'Naudts' }
],
ColorMethodSource = {
 localdata: ColorMethodData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
ColorMethodAdapter = new $.jqx.dataAdapter(ColorMethodSource),

CoolingTypeData = [
 { id: 0, en: '-',                   nl: '-' },
 { id: 1, en: 'Emersion chiller',    nl: 'Dompelkoeler' },
 { id: 2, en: 'Counterflow chiller', nl: 'Tegenstroomkoeler' },
 { id: 3, en: 'Au bain marie',       nl: 'Au bain marie' },
 { id: 4, en: 'Natural',             nl: 'Laten afkoelen' }
],
CoolingTypeSource = {
 localdata: CoolingTypeData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
CoolingTypeAdapter = new $.jqx.dataAdapter(CoolingTypeSource),

AerationTypeData = [
 { id: 0, en: 'None',   nl: 'Geen' },
 { id: 1, en: 'Air',    nl: 'Lucht' },
 { id: 2, en: 'Oxygen', nl: 'Zuurstof' }
],
AerationTypeSource = {
 localdata: AerationTypeData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
AerationTypeAdapter = new $.jqx.dataAdapter(AerationTypeSource),

AcidTypeData = [
 { id: 0, en: 'Lactic',       nl: 'Melkzuur' },
 { id: 1, en: 'Hydrochloric', nl: 'Zoutzuur' },
 { id: 2, en: 'Phosphoric',   nl: 'Fosforzuur' },
 { id: 3, en: 'Sulfuric',     nl: 'Zwavelzuur' }
],
AcidTypeSource = {
 localdata: AcidTypeData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
AcidTypeAdapter = new $.jqx.dataAdapter(AcidTypeSource),

BaseTypeData = [
 { id: 0, en: 'Sodiumbicarbonate', nl: 'NaHCO3' },
 { id: 1, en: 'Sodiumcarbonate',   nl: 'Na2CO3' },
 { id: 2, en: 'Calciumcarbonate',  nl: 'CaCO3' },
 { id: 3, en: 'Calciumhydroxide',  nl: 'Ca(OH)2' }
],
BaseTypeSource = {
 localdata: BaseTypeData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
BaseTypeAdapter = new $.jqx.dataAdapter(BaseTypeSource),

SpargeSourceData = [
 { id: 0, en: 'Source 1', nl: 'Bron 1' },
 { id: 1, en: 'Source 2', nl: 'Bron 2' },
 { id: 2, en: 'Mixed',    nl: 'Gemengd' }
],
SpargeSourceSource = {
 localdata: SpargeSourceData,
 datatype: 'array',
 datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
},
SpargeSourceAdapter = new $.jqx.dataAdapter(SpargeSourceSource),


// options for editors

Show1wat = { inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 1, readOnly: true },
Show2wat = { inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 2, readOnly: true },
Show3wat = { inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 3, readOnly: true },
Smal0dec = { inputMode: 'simple', theme: theme, width: 50, height: 23, decimalDigits: 0, readOnly: true },
Smal1dec = { inputMode: 'simple', theme: theme, width: 50, height: 23, decimalDigits: 1, readOnly: true },
Show0dec = { inputMode: 'simple', theme: theme, width: 90, height: 23, readOnly: true, decimalDigits: 0 },
Show1dec = { inputMode: 'simple', theme: theme, width: 90, height: 23, readOnly: true, decimalDigits: 1 },
Show2dec = { inputMode: 'simple', theme: theme, width: 90, height: 23, readOnly: true, decimalDigits: 2 },
Show3dec = { inputMode: 'simple', theme: theme, width: 90, height: 23, readOnly: true, decimalDigits: 3 },
  SGopts = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 0.990, max: 1.199, decimalDigits: 3, spinButtons: true },
Spin1dec = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 0, decimalDigits: 1, spinButtons: true },
Spin2dec = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 0, decimalDigits: 2, spinButtons: true },
Spin3dec = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 0, decimalDigits: 3, spinButtons: true },
  SpinpH = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 1, max: 14, decimalDigits: 1, spinButtons: true },
 Spin2pH = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 1, max: 14, decimalDigits: 2, spinButtons: true },
  YeastT = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 0, max: 50, decimalDigits: 1, spinButtons: true },
  PosInt = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 0, decimalDigits: 0, spinButtons: true },
Perc1dec = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 0, max: 100, decimalDigits: 1, spinButtons: true },
   Perc0 = { inputMode: 'simple', theme: theme, width: 110, height: 23, min: 0, max: 100, decimalDigits: 0, spinButtons: true },
Dateopts = {
 theme: theme, width: 150, height: 23, allowNullDate: true, todayString: 'Vandaag', clearString: 'Wissen', showFooter: true,
 formatString: 'yyyy-MM-dd', enableBrowserBoundsDetection: true
},
DateTimeopts = {
 theme: theme, width: 230, height: 23, allowNullDate: true, todayString: 'Vandaag', clearString: 'Wissen', showFooter: true,
 formatString: 'yyyy-MM-dd HH:mm:ss', enableBrowserBoundsDetection: true, showTimeButton: true
},


sugardensity = 1.611, //kg/l in solution

// Styles dropdown list
stylesSource = {
 datatype: 'json',
 datafields: [
  { name: 'record', type: 'number' },
  { name: 'name', type: 'string' },
  { name: 'category', type: 'string' },
  { name: 'category_number', type: 'number' },
  { name: 'style_letter', type: 'string' },
  { name: 'style_guide', type: 'string' },
  { name: 'type', type: 'int' },
  { name: 'og_min', type: 'float' },
  { name: 'og_max', type: 'float' },
  { name: 'fg_min', type: 'float' },
  { name: 'fg_max', type: 'float' },
  { name: 'ibu_min', type: 'float' },
  { name: 'ibu_max', type: 'float' },
  { name: 'color_min', type: 'float' },
  { name: 'color_max', type: 'float' },
  { name: 'carb_min', type: 'float' },
  { name: 'carb_max', type: 'float' },
  { name: 'abv_min', type: 'float' },
  { name: 'abv_max', type: 'float' },
  { name: 'notes', type: 'string' },
  { name: 'profile', type: 'string' },
  { name: 'ingredients', type: 'string' },
  { name: 'examples', type: 'string' }
 ],
 url: 'includes/db_profile_styles.php'
},
styleslist = new $.jqx.dataAdapter(stylesSource),

// Equipemnt dropdown list
equipmentSource = {
 datatype: 'json',
 datafields: [
  { name: 'name', type: 'string' },
  { name: 'boil_size', type: 'float' },
  { name: 'batch_size', type: 'float' },
  { name: 'tun_volume', type: 'float' },
  { name: 'tun_weight', type: 'float' },
  { name: 'tun_specific_heat', type: 'float' },
  { name: 'tun_material', type: 'int' },
  { name: 'tun_height', type: 'float' },
  { name: 'top_up_water', type: 'float' },
  { name: 'trub_chiller_loss', type: 'float' },
  { name: 'evap_rate', type: 'float' },
  { name: 'boil_time', type: 'float' },
  { name: 'calc_boil_volume', type: 'int' },
  { name: 'top_up_kettle', type: 'float' },
  { name: 'hop_utilization', type: 'float' },
  { name: 'notes', type: 'string' },
  { name: 'lauter_volume', type: 'float' },
  { name: 'lauter_height', type: 'float' },
  { name: 'lauter_deadspace', type: 'float' },
  { name: 'kettle_volume', type: 'float' },
  { name: 'kettle_height', type: 'float' },
  { name: 'mash_volume', type: 'float' },
  { name: 'mash_max', type: 'float' },
  { name: 'efficiency', type: 'float' }
 ],
 url: 'includes/db_inventory_equipments.php'
},
equipmentlist = new $.jqx.dataAdapter(equipmentSource),

// dropdownlist datasource from inventory_fermentables
fermentableInvSource = {
 datatype: 'json',
 datafields: [
  { name: 'record', type: 'number' },
  { name: 'name', type: 'string' },
  { name: 'type', type: 'int' },
  { name: 'yield', type: 'float' },
  { name: 'color', type: 'float' },
  { name: 'add_after_boil', type: 'int' },
  { name: 'origin', type: 'string' },
  { name: 'supplier', type: 'string' },
  { name: 'coarse_fine_diff', type: 'float' },
  { name: 'moisture', type: 'float' },
  { name: 'diastatic_power', type: 'float' },
  { name: 'protein', type: 'float' },
  { name: 'dissolved_protein', type: 'float' },
  { name: 'max_in_batch', type: 'float' },
  { name: 'recommend_mash', type: 'int' },
  { name: 'graintype', type: 'int' },
  { name: 'di_ph', type: 'float' },
  { name: 'acid_to_ph_57', type: 'float' },
  { name: 'inventory', type: 'float' },
  { name: 'cost', type: 'float' }
 ],
 url: 'getfermentablesources.php'
},
fermentableinstock = false,
fermentablelist = new $.jqx.dataAdapter(fermentableInvSource, {
 beforeLoadComplete: function(records) {
  var row, i, data = new Array();
  for (i = 0; i < records.length; i++) {
   row = records[i];
   if (row.inventory || ! fermentableinstock)
    data.push(row);
  }
  return data;
 },
 loadError: function(jqXHR, status, error) {
  console.log(status + ' ' + error);
 },
}),
fermentablesugars = new $.jqx.dataAdapter(fermentableInvSource, {
 beforeLoadComplete: function(records) {
  var row, i, data = new Array();
  for (i = 0; i < records.length; i++) {
   row = records[i];
   if (row.type == 1 || row.type == 3) // Sugars or dry extract
    data.push(row);
  }
  return data;
 },
 loadError: function(jqXHR, status, error) {
  console.log(status + ' ' + error);
 },
}),

// dropdownlist datasource from inventory_hops
hopInvSource = {
 datatype: 'json',
 datafields: [
  { name: 'record', type: 'number' },
  { name: 'name', type: 'string' },
  { name: 'origin', type: 'string' },
  { name: 'type', type: 'int' },
  { name: 'alpha', type: 'float' },
  { name: 'beta', type: 'float' },
  { name: 'humulene', type: 'float' },
  { name: 'caryophyllene', type: 'float' },
  { name: 'cohumulone', type: 'float' },
  { name: 'myrcene', type: 'float' },
  { name: 'hsi', type: 'float' },
  { name: 'useat', type: 'int' },
  { name: 'form', type: 'int' },
  { name: 'total_oil', type: 'float' },
  { name: 'inventory', type: 'float' },
  { name: 'cost', type: 'float' }
 ],
 url: 'gethopsources.php'
},
hopinstock = false,
hoplist = new $.jqx.dataAdapter(hopInvSource, {
 beforeLoadComplete: function(records) {
  var row, i, data = new Array();
  for (i = 0; i < records.length; i++) {
   row = records[i];
   if (row.inventory || ! hopinstock)
    data.push(row);
  }
  return data;
 },
 loadError: function(jqXHR, status, error) {
  console.log(status + ' ' + error);
 },
}),

// dropdownlist datasource from inventory_miscs
miscInvSource = {
 datatype: 'json',
 datafields: [
  { name: 'record', type: 'number' },
  { name: 'name', type: 'string' },
  { name: 'type', type: 'int' },
  { name: 'use_use', type: 'int' },
  { name: 'amount_is_weight', type: 'int' },
  { name: 'time', type: 'float' },
  { name: 'inventory', type: 'float' },
  { name: 'cost', type: 'float' }
 ],
 url: 'getmiscsources.php'
},
miscinstock = false,
misclist = new $.jqx.dataAdapter(miscInvSource, {
 beforeLoadComplete: function(records) {
  var row, i, data = new Array();
  for (i = 0; i < records.length; i++) {
   row = records[i];
    if (row.inventory || ! miscinstock)
     data.push(row);
  }
  return data;
 },
 loadError: function(jqXHR, status, error) {
  console.log(status + ' ' + error);
 },
}),

// dropdownlist datasource from inventory_yeasts
yeastInvSource = {
 datatype: 'json',
 datafields: [
  { name: 'record', type: 'number' },
  { name: 'name', type: 'string' },
  { name: 'type', type: 'int' },
  { name: 'form', type: 'int' },
  { name: 'laboratory', type: 'string' },
  { name: 'product_id', type: 'string' },
  { name: 'min_temperature', type: 'float' },
  { name: 'max_temperature', type: 'float' },
  { name: 'flocculation', type: 'int' },
  { name: 'attenuation', type: 'float' },
  { name: 'cells', type: 'float' },
  { name: 'inventory', type: 'float' },
  { name: 'cost', type: 'float' },
  { name: 'tolerance', type: 'float' }
 ],
 url: 'getyeastsources.php'
},
yeastinstock = false,
yeastlist = new $.jqx.dataAdapter(yeastInvSource, {
 beforeLoadComplete: function(records) {
  var row, i, data = new Array();
  for (i = 0; i < records.length; i++) {
   row = records[i];
   if (row.inventory || ! yeastinstock)
    data.push(row);
  }
  return data;
 },
 loadError: function(jqXHR, status, error) {
  console.log(status + ' ' + error);
 },
}),

// dropdownlist datasource from inventory_waters
waterInvSource = {
 datatype: 'json',
 datafields: [
  { name: 'record', type: 'number' },
  { name: 'name', type: 'string' },
  { name: 'unlimited_stock', type: 'int' },
  { name: 'calcium', type: 'float' },
  { name: 'sulfate', type: 'float' },
  { name: 'chloride', type: 'float' },
  { name: 'sodium', type: 'float' },
  { name: 'magnesium', type: 'float' },
  { name: 'ph', type: 'float' },
  { name: 'total_alkalinity', type: 'float' },
  { name: 'inventory', type: 'float' },
  { name: 'cost', type: 'float' },
 ],
 url: 'getwatersources.php'
},
waterinstock = false,
waterlist = new $.jqx.dataAdapter(waterInvSource, {
 beforeLoadComplete: function(records) {
  var data, i, row;
  data = new Array();
  for (i = 0; i < records.length; i++) {
   row = records[i];
   if (row.inventory || row.unlimited_stock || ! waterinstock)
    data.push(row);
  }
  return data;
 },
 loadError: function(jqXHR, status, error) {
  console.log(status + ' ' + error);
 },
}),

// dropdownlist datasource from profile_water
waterProfileSource = {
 datatype: 'json',
 datafields: [
  { name: 'record', type: 'number' },
  { name: 'name', type: 'string' },
  { name: 'calcium', type: 'float' },
  { name: 'bicarbonate', type: 'float' },
  { name: 'sulfate', type: 'float' },
  { name: 'chloride', type: 'float' },
  { name: 'sodium', type: 'float' },
  { name: 'magnesium', type: 'float' },
  { name: 'ph', type: 'float' },
  { name: 'total_alkalinity', type: 'float' },
 ],
 url: 'includes/db_profile_water.php'
},
waterprofiles = new $.jqx.dataAdapter(waterProfileSource),

// dropdownlist datasource from profile_mash
mashProfileSource = {
 datatype: 'json',
 datafields: [
  { name: 'record', type: 'number' },
  { name: 'name', type: 'string' },
  { name: 'steps', type: 'array' }
 ],
 url: 'includes/db_profile_mash.php'
},
mashlist = new $.jqx.dataAdapter(mashProfileSource),



/*
 * From "Rekenen aan bier" by Hans Halberstadt.
 */
K1s = 0.384, K1a = -0.177, K1e = 0.241, K1g = 0.247, Ks = 0.1415, Ka1 = 0.058, Ka2 = 0.078, Ke = 0.174, Kg = 0.109;

// =E2/E6+(E3/E6)*$B$24/$B$23+(E3/E6)*(E3/E6)*$B$25/$B$23+E4/E6*$B$26/$B$23+E5/E6*$B$27/$B$23
// For Brix
function A(sugar, volume, alc, eiwit, glycerol) {

 var vol, A;

 vol = volume * 1000;
 A = sugar / vol + (alc / vol) * Ka1 / Ks + (alc / vol) * (alc / vol) * Ka2 / Ks + eiwit / vol * Ke / Ks + glycerol / vol * Kg / Ks;
 console.log('A(' + sugar + ',' + volume + ',' + alc + ',' + eiwit + ',' + glycerol + '):' + A);
 return A;
}

// =E2/E6+(E3/E6)*$B$20/$B$19+E4/E6*$B$21/$B$19+E5/E6*$B$22/$B$19
// for Plato
function B(sugar, volume, alc, eiwit, glycerol) {

 var vol, B;

 vol = volume * 1000;
 B = sugar / vol + (alc / vol) * K1a / K1s + eiwit / vol * K1e / K1s + glycerol / vol * K1g / K1s;
 console.log('B(' + sugar + ',' + volume + ',' + alc + ',' + eiwit + ',' + glycerol + '):' + B);
 return B;
}



$(document).ready(function() {

 $('#jqxMenu').jqxMenu({
  width: 1280,
  height: '30px',
  autoOpen: false,
  clickToOpen: true,
  theme: theme
 });
 $('#jqxWidget').css('visibility', 'visible');

});



function Round(n, d) {
 for (var i = 0, m = 1; i < d; i++, m *= 10);
 return Math.round(n * m) / m;
}



function ebc_to_srm(ebc) {
 var srm = -1.32303E-12 * Math.pow(ebc, 4) - 0.00000000291515 * Math.pow(ebc, 3) + 0.00000818515 * Math.pow(ebc, 2) + 0.372038 * ebc + 0.596351;
 if (srm < 0)
  srm = 0;
 return srm;
}



function srm_to_ebc(srm) {
 var ebc = Math.round(0.000000000176506 * Math.pow(srm, 4) + 0.000000154529 * Math.pow(srm, 3) - 0.000159428 * Math.pow(srm, 2) + 2.68837 * srm - 1.6004);
 if (ebc < 0)
  ebc = 0;
 return ebc;
}



/* Return incremented color by the boil and yeast.
 * https://www.hobbybrouwen.nl/forum/index.php/topic,19020.msg281132.html#msg281132 */
function get_kt(ebc) {

 var kt = 1;
 if (ebc < 3)
  kt = 3.5;
 else if (ebc < 6)
  kt = 3;
 else if (ebc < 8)
  kt = 2.75;
 else if (ebc < 10)
  kt = 2.5;
 else if (ebc < 20)
  kt = 1.8;
 else if (ebc < 30)
  kt = 1.6;
 else if (ebc < 60)
  kt = 1.3;
 else if (ebc < 100)
  kt = 1.2;
 else if (ebc < 300)
  kt = 1.1;
 return kt;
}



function abvol(og, fg) {
 if (((og - fg) < 0) || (fg < 0.9))
  return 0;
 var factor = og * 3157 * Math.pow(10, -5) + 9.716 * Math.pow(10, -2);
 return (og * 1000 - fg * 1000) * factor;
}



/* Kleurwerking naar SRM. Niet voor Halberstadt, Naudts */
function kw_to_srm(colormethod, c) {
 if (colormethod == 0)
  return 1.4922 * Math.pow(c, 0.6859); //Morey
 if (colormethod == 1)
  return 0.3 * c + 4.7; //Mosher
 if (colormethod == 2)
  return 0.2 * c + 8.4; //Daniels
 return 0; //Halberstadt,Naudts
}



function kw_to_ebc(colormethod, c) {
 return srm_to_ebc(kw_to_srm(colormethod, c));
}



/*
 * Berekeningen uit https://www.hobbybrouwen.nl/forum/index.php/topic,6079.msg69464.html#msg69464
 */
function toIBU(Use, Form, SG, Volume, Amount, Boiltime, Alpha, Method) {

 var gravity, liters, alpha, mass, time, fmoment = 1.0, pfactor = 1.0, ibu = 0, boilfactor, sgfactor,
     AddedAlphaAcids, Bigness_factor, BoilTime_factor, utiisation;

 gravity = parseFloat(SG);
 liters = parseFloat(Volume);
 alpha = parseFloat(Alpha) / 100;
 mass = parseFloat(Amount) * 1000;
 time = parseFloat(Boiltime);

 if ((Use == 3) || (Use == 4) || (Use == 5)) { // Aroma, Whirlpool or Dry hop.
  fmoment = 0.0;
 } else if (Use == 0) { // Mash
  fmoment += my_factor_mashhop / 100; // Brouwhulp
 } else if (Use == 1) { // First wort
  fmoment += my_factor_fwh / 100; // Brouwhulp, Louis, Ozzie
 }

 if (Form == 0) { // Pellet
  pfactor += my_factor_pellet / 100;
 } else if (Form == 1) { // Plug
  pfactor += my_factor_plug / 100;
 } else if (Form == 3) { // Wet leaf
  pfactor += my_factor_wethop / 100; // From https://github.com/chrisgilmerproj/brewday/blob/master/brew/constants.py
 } else if (Form == 4) { // Cryo hop
  pfactor += my_factor_cryohop / 100;
 }

 if (Method == 0) { // Tinseth
  /* http://realbeer.com/hops/research.html */
  AddedAlphaAcids = (alpha * mass * 1000) / liters;
  Bigness_factor = 1.65 * Math.pow(0.000125, gravity - 1);
  BoilTime_factor = ((1 - Math.exp(-0.04 * time)) / 4.15);
  utiisation = Bigness_factor * BoilTime_factor;
  ibu = Round(utiisation * AddedAlphaAcids * fmoment * pfactor, 1);
 }
 if (Method == 2) { // Daniels
  if (Form == 2) // Leaf
   boilfactor = -(0.0041 * time * time) + (0.6162 * time) + 1.5779;
  else
   boilfactor = -(0.0051 * time * time) + (0.7835 * time) + 1.9348;
  if (gravity < 1050)
   sgfactor = 0;
  else
   sgfactor = (gravity - 1050) / 200;
  ibu = Round(fmoment * ((mass * (alpha * 100) * boilfactor * 0.1) / (liters * (1 + sgfactor))), 1);
 }
 if (Method == 1) { // Rager
  boilfactor = fmoment * 18.11 + 13.86 * Math.tanh((time * 31.32) / 18.27);
  if (gravity < 1050)
   sgfactor = 0;
  else
   sgfactor = (gravity - 1050) / 200;
  ibu = Round((mass * (alpha * 100) * boilfactor * 0.1) / (liters * (1 + sgfactor)), 1);
 }

 //console.log("toIBU("+Use+","+Form+","+SG+","+Volume+","+Amount+","+Boiltime+","+Alpha+","+Method+"):"+ibu+" fm:"+fmoment+" pf:"+pfactor);
 return ibu;
}



function ebc_to_color(ebc) {
 return srm_to_color(ebc_to_srm(ebc));
}



function srm_to_color(srm) {
 var i, R, G, B, color, result;

 i = Math.round(srm * 10);
 if (i < 0)
  i = 0;
 if (i > 299)
  i = 299;

 /* Table copied from Brouwhulp/BrewBuddy */

 R = [
 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, //0
 250, 250, 250, 250, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, //2
 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, //4
 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 200, 199, 199, 198, 198, //6
 197, 197, 196, 196, 195, 195, 194, 194, 193, 193, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, //8
 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, //10
 192, 192, 192, 192, 192, 192, 192, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, //12
 179, 178, 177, 175, 174, 172, 171, 169, 168, 167, 195, 164, 162, 161, 159, 158, 157, 155, 154, 152, //14
 151, 149, 148, 147, 145, 144, 142, 141, 139, 138, 137, 135, 134, 132, 131, 129, 128, 127, 125, 124, //16
 122, 121, 119, 118, 117, 115, 114, 112, 111, 109, 108, 107, 105, 104, 102, 101, 99, 98, 97, 95, //18
 94, 92, 91, 89, 88, 87, 85, 84, 82, 81, 79, 78, 77, 75, 74, 72, 71, 69, 68, 67, //20
 65, 64, 62, 61, 59, 58, 57, 55, 54, 52, 51, 49, 48, 47, 45, 44, 43, 41, 39, 38, //22
 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, //24
 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, //26
 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8];

 G = [
 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
 250, 250, 250, 250, 250, 250, 249, 248, 247, 246, 245, 244, 242, 240, 238, 236, 234, 232, 230, 228,
 226, 224, 222, 220, 218, 216, 214, 212, 210, 208, 206, 204, 202, 200, 198, 196, 194, 192, 190, 188,
 186, 184, 182, 180, 178, 176, 174, 172, 170, 168, 166, 164, 162, 160, 158, 156, 154, 152, 150, 148,
 146, 144, 142, 141, 140, 139, 139, 138, 137, 136, 136, 135, 134, 133, 133, 132, 131, 130, 130, 129,
 128, 127, 127, 126, 125, 124, 124, 123, 122, 121, 121, 120, 119, 118, 118, 117, 116, 115, 115, 114,
 113, 112, 112, 111, 110, 109, 109, 108, 107, 106, 106, 105, 104, 103, 103, 102, 101, 100, 100, 99,
 98, 97, 97, 96, 95, 94, 94, 93, 92, 91, 91, 90, 89, 88, 88, 87, 86, 85, 85, 84,
 83, 82, 82, 81, 80, 79, 78, 77, 76, 75, 75, 74, 73, 72, 72, 71, 70, 69, 69, 68,
 67, 66, 66, 65, 64, 63, 63, 62, 61, 60, 60, 59, 58, 57, 57, 56, 55, 54, 54, 53,
 52, 51, 51, 50, 49, 48, 48, 47, 46, 45, 45, 44, 43, 42, 42, 41, 40, 39, 39, 38,
 37, 36, 36, 35, 34, 33, 33, 32, 31, 30, 30, 29, 28, 27, 27, 26, 25, 24, 24, 23,
 22, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 17, 17, 17, 16, 16,
 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 9,
 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3];

 B = [
 210, 204, 199, 193, 188, 182, 177, 171, 166, 160, 155, 149, 144, 138, 133, 127, 122, 116, 111, 105,
 100, 94, 89, 83, 78, 72, 67, 61, 56, 50, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47,
 47, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51, 52, 52, 52,
 52, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56,
 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
 56, 56, 56, 55, 55, 55, 55, 54, 54, 54, 54, 53, 53, 53, 53, 52, 52, 52, 52, 51,
 51, 51, 51, 50, 50, 50, 50, 49, 49, 48, 47, 47, 46, 45, 45, 44, 43, 43, 42, 41,
 41, 40, 39, 39, 38, 37, 37, 36, 35, 34, 33, 32, 31, 29, 28, 27, 26, 25, 24, 23,
 21, 20, 19, 18, 17, 16, 15, 13, 12, 11, 10, 9, 8, 9, 9, 10, 10, 11, 11, 12,
 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22,
 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 17, 17, 17, 17, 16, 16, 15, 15,
 15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 9, 8,
 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2];

 color = R[i] * 65536 + G[i] * 256 + B[i];
 result = color.toString(16).toUpperCase();
 if (result.length < 6)
  result = '0' + result;
 return '#' + result;
}



function sg_to_plato(sg) {
 return ((135.997 * sg - 630.272) * sg + 1111.14) * sg - 616.868;
}



function plato_to_sg(plato) {
 return 1 + (plato / (258.6 - ((plato / 258.2) * 227.1)));
}



function brix_to_sg(brix) {
 if (my_brix_correction > 0)
  return plato_to_sg(brix / my_brix_correction);
 else
  return plato_to_sg(brix);
}



function sg_to_brix(sg) {
 return sg_to_plato(sg) * my_brix_correction;
}



function estimate_sg(sugars, batch_size) {

 var plato, sg, i;

 plato = 100 * sugars / batch_size;
 sg = plato_to_sg(plato);
 for (i = 0; i < 20; i++) {
  if (sg > 0)
   plato = 100 * sugars / (batch_size * sg);
  sg = plato_to_sg(plato);
 }
 return Round(sg, 4);
}



function estimate_fg(percSugar, percCara, WGratio, TotTme, Temp, attenuation, og) {

 var BD, AttBeer, fg;

 if (percSugar > 40)
  percSugar = 0;
 if (percCara > 50)
  percCara = 0;
 if ((WGratio > 0) && (TotTme > 0)) {
  BD = WGratio;
  if (BD < 2)
   BD = 2;
  if (BD > 5.5)
   BD = 5.5;
  if (Temp < 60)
   Temp = 60;
  if (Temp > 72)
   Temp = 72;
 } else {
  BD = 3.5;
  Temp = 67;
  TotTme = 75;
 }
 if (attenuation < 30)
  attenuation = 77;

 // 0.00825 Attenuation factor yeast
 // 0.00817 Attenuation factor water/grain ration
 // -0.00684 Attenuation factor mash temperature
 // 0.00026 Attenuation factor total mash time  (at some places this is 0.0026 this is wrong!)
 // -0.00356 Attenuation factor percentage crystal malt
 // 0.00553 Attenuation factor percentage simple sugars
 // 0.547 Attenuation factor constant
 AttBeer = 0.00825 * attenuation + 0.00817 * BD - 0.00684 * Temp + 0.00026 * TotTme - 0.00356 * percCara + 0.00553 * percSugar + 0.547;
 fg = Round(1 + (1 - AttBeer) * (og - 1), 4);

 //console.log('estimate_fg(' + percSugar + ',' + percCara + ',' + BD + ',' + TotTme + ',' +
 //            Temp + ',' + attenuation + ',' + og + ') AttBeer:' + AttBeer + ' fg:' + fg);
 return fg;
}



function CalcFrac(TpH, pK1, pK2, pK3) {

 var r1d, r2d, r3d, dd, f2d, f3d, f4d;

 r1d = Math.pow(10, TpH - pK1);
 r2d = Math.pow(10, TpH - pK2);
 r3d = Math.pow(10, TpH - pK3);
 dd = 1 / (1 + r1d + r1d * r2d + r1d * r2d * r3d);
 f2d = r1d * dd;
 f3d = r1d * r2d * dd;
 f4d = r1d * r2d * r3d * dd;
 return f2d + 2 * f3d + 3 * f4d;
}



function lintner_to_kolbach(lintner) {
 return (3.5 * lintner) - 16;
}


function kolbach_to_lintner(kolbach) {
 return (kolbach + 16) / 3.5;
}

mercurial