-
Notifications
You must be signed in to change notification settings - Fork 236
/
brew.el
137 lines (105 loc) · 5.44 KB
/
brew.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
(require 'dash)
(defun kg-lbs (kg)
(/ kg 0.45359237))
(defun l-gal (l)
(/ l 3.78541178))
(defun lbs-kg (lbs)
(* lbs 0.45359237))
(defun gal-l (gal)
(* gal 3.78541178))
(defun strike-water-temp (ratio infusion-temp grain-temp)
"Calculate the strike water temperature given the
liters water/kilograms grain ratio, the desired infusion
temperature and the grain temperature"
(+ (* (/ 0.41 ratio) (- infusion-temp grain-temp)) infusion-temp))
(defun infusion-volume (infusion-temp mash-temp grain-weight water-volume addition-temp)
"Calculate the amount of water at temperature ADDITION-TEMP
necessary to add to a mash of GRAIN-WIGHT (kg) and WATER-VOLUME (l)
currently at MASH-TEMP (C) in order to bring it up to INFUSION-TEMP (C)"
(/ (* (- infusion-temp mash-temp) (+ (* 0.41 grain-weight) water-volume)) (- addition-temp infusion-temp)))
(defun infusion-volume-boil (infusion-temp mash-temp grain-weight water-volume)
"Calculate the amount of boiling water necessary to add to a
mash of GRAIN-WAIGHT (kg) and WATER-VOLUME (l) currently at
MASH-TEMP (C) in order to bring it up to INFUSION-TEMP (C)"
(infusion-volume infusion-temp mash-temp grain-weight water-volume 100))
(defun gravity-points (gravity)
"Given a GRAVITY like 1.050, get the number of 'gravity points'
(e.g. 50)"
(* 1000 (- gravity 1)))
(defun wort-gravity (vol weight ppg)
"Given WEIGHT (lbs) amount of fermentable with gravity points PPG,
calculate the specific gravity in a wort of VOL gallons"
(+ 1 (/ (* (/ weight vol) ppg) 1000.0)))
(defun wort-gravity-metric (vol weight ppg)
"Given WEIGHT (kg) amount of fermentable with gravity points PPG,
calculate the specific gravity in a wort of VOL liters"
(wort-gravity (l-gal vol) (kg-lbs weight) ppg))
(defun extract-weight-for-og (vol og ppg)
"Calculate the amount of extract with PPG ppg (gravity points per
lb per gallon) needed for VOL gallons of wort at original gravity OG"
(let ((points (* (gravity-points og) vol)))
(/ points ppg)))
(defun dme-amount-for-og (vol og)
"Given the wort volume VOL in gallons, and an original gravity OG,
calculate the necessary amount of DME in lbs"
(extract-weight-for-og vol og 42))
(defun lme-amount-for-og (vol og)
"Given the wort volume VOL in gallons, and an original gravity OG,
calculate the necessary amount of LME in lbs"
(extract-weight-for-og vol og 36))
(defun extract-kg-for-og (vol og ppg)
"Calculate the weight in kg of extract to reach the desired OG in
a wort of VOL litres."
(lbs-kg (extract-weight-for-og (l-gal vol) og ppg)))
(defun dme-kg-for-og (vol og)
(extract-kg-for-og vol og 42))
(defun lme-kg-for-og (vol og)
(extract-kg-for-og vol og 36))
(defun abv (og fg)
(* (- og fg) 131.25))
(defvar sucrose-ppg 46)
(defun extraction-efficiency (grain-weight wort-volume gravity)
(/ (* (gravity-points gravity) wort-volume) grain-weight))
(defun mash-efficiency (grain-weight wort-volume gravity fgdb)
(/ (extraction-efficiency grain-weight wort-volume gravity) (* fgdb sucrose-ppg)))
(defun extraction-efficiency-metric (grain-weight wort-volume gravity)
(extraction-efficiency (kg-lbs grain-weight) (l-gal wort-volume) gravity))
(defun mash-efficiency-metric (grain-weight wort-volume gravity fgdb)
(mash-efficiency (kg-lbs grain-weight) (l-gal wort-volume) gravity fgdb))
(defun required-grain-weights (wort-volume gravity grains)
"Calculates required weight of individual grains based on a list
of grains where each item is a list of the grain's percentage in
the recipe, its fgdb, and expected efficiency, e.g.:
((0.1 0.7 0.75) ;; CaraPils
(0.1 0.75 0.75) ;; Light Crystal 10L
(0.8 0.8 0.75) ;; Two-row lager malt
)"
(let ((points (* (gravity-points gravity) wort-volume)))
(-map (lambda (grain)
(/ (* points (car grain))
(* (car (cdr grain)) (car (cddr grain)) sucrose-ppg))) grains)))
(defun required-grain-weights-metric (wort-volume gravity grains)
(-map 'lbs-kg (required-grain-weights (l-gal wort-volume) gravity grains)))
;; (required-grain-weights 5 1.050 '((0.74 0.78 0.75) (0.26 0.75 0.75)))
;; (required-grain-weights-metric 18.92 1.050 '((0.74 0.78 0.75) (0.26 0.75 0.75)))
(setq BOIL_TEMP 95)
(defun boil-cold (temp volume cold-temp)
"To create VOLUME liters of TEMP C water, use this many liters
of boiling water, and this many liters of cold water"
(let ((boiling (/ (- (* temp volume) cold-temp) BOIL_TEMP)))
(list (cons (- volume boiling) cold-temp) (cons boiling BOIL_TEMP))))
(defun wort-points (gravity volume)
(* (gravity-points gravity) volume))
(defun wort-points-metric (gravity volume)
(wort-points gravity (l-gal volume)))
(defun wort-volume-at-gravity (gravity volume desired-gravity)
(/ (wort-points gravity volume) (gravity-points desired-gravity)))
(defun mash-schedule (grain-weight grain-temp start-ratio steps)
(let ((strike-temp (strike-water-temp start-ratio (car steps) grain-temp))
(mash-temp (car steps))
(water-volume (* grain-weight start-ratio)))
(-flatten (cons (boil-cold strike-temp water-volume 10.4) (-map (lambda (infusion-temp)
(cons (infusion-volume-boil infusion-temp mash-temp grain-weight water-volume) BOIL_TEMP)) (cdr steps))))))
(defun final-mash-volume (grain-weight grain-temp start-ratio steps)
(-reduce-from (lambda (sum pair) (+ sum (car pair)))
0 (mash-schedule grain-weight grain-temp start-ratio steps)))