brewser 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ class BeerXML2 < Brewser::Engine
2
+
3
+ require 'nokogiri'
4
+
5
+ class << self
6
+
7
+ def acceptable?(q)
8
+ Nokogiri::XML(q){|config| config.noblanks }.remove_namespaces!.xpath("//version").inner_text.to_i == 2 ? true : false
9
+ # @TODO Add XSD Validation here
10
+ end
11
+
12
+ def deserialize(string_or_io)
13
+ results = parse_xml(string_or_io)
14
+ puts results.inspect
15
+ return results
16
+ end
17
+
18
+ def serialize(brewser_model)
19
+ end
20
+
21
+ def parse_xml(string_or_io)
22
+ raise NotImplemented, "BeerXML2 support is not implemented yet"
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+
@@ -0,0 +1,20 @@
1
+ class BrewSON < Brewser::Engine
2
+
3
+ class << self
4
+
5
+ def acceptable?(q)
6
+ return q.valid_json?
7
+ end
8
+
9
+ def deserialize(string_or_io)
10
+ end
11
+
12
+ def serialize(brewser_model)
13
+ brewser_model.deep_json
14
+ end
15
+
16
+ end
17
+
18
+ end
19
+
20
+
@@ -0,0 +1,424 @@
1
+ class ProMashRec < Brewser::Engine
2
+
3
+ class << self
4
+
5
+ def acceptable?(q)
6
+ return true
7
+ end
8
+
9
+ def deserialize(io)
10
+ object = ProMashRec::Recipe.new
11
+ object.from_promash(io)
12
+ return object
13
+ end
14
+
15
+ end
16
+
17
+ module ::Loader
18
+
19
+ require 'bindata'
20
+
21
+ class RecEntry < BinData::Record
22
+ endian :little
23
+ end
24
+
25
+ class Hop < RecEntry
26
+ string :name, :length => 55, :trim_padding => true
27
+ float :alpha_acids
28
+ float :beta_acids
29
+ int8 :noble
30
+ float :cohumulone
31
+ float :myrcene
32
+ float :humulene
33
+ float :caryphylene
34
+ int8 :type
35
+ int8 :form
36
+ float :storage_factor
37
+ string :taste_notes, :length => 155, :trim_padding => true
38
+ string :origin, :length => 55, :trim_padding => true
39
+ string :best_for, :length => 155, :trim_padding => true
40
+ string :substitutes, :length => 155, :trim_padding => true
41
+ skip length: 10
42
+ float :storage_temp_c
43
+ float :actual_alpha_acids
44
+ int8 :flag
45
+ float :amount
46
+ int16 :time
47
+ float :ibus
48
+ end
49
+
50
+ class Fermentable < RecEntry
51
+ string :name, :length => 110, :trim_padding => true
52
+ string :origin, :length => 55, :trim_padding => true
53
+ int8 :type
54
+ int8 :form
55
+ float :potential
56
+ float :color
57
+ float :moisture_content
58
+ float :max_in_batch
59
+ float :diastatic_power
60
+ float :percent_protein
61
+ float :percent_tsn
62
+ string :uses, :length => 155, :trim_padding => true
63
+ string :comments, :length => 155, :trim_padding => true
64
+ skip length: 8
65
+ float :dry_basis_fg
66
+ float :dry_basis_cg
67
+ float :amount
68
+ float :extract
69
+ end
70
+
71
+ class Additive < RecEntry
72
+ string :name, :length => 55, :trim_padding => true
73
+ int8 :type
74
+ int16 :time
75
+ skip length: 2
76
+ int8 :added_when
77
+ int8 :time_in
78
+ int8 :amount_unit
79
+ skip length: 4
80
+ string :uses, :length => 255, :trim_padding => true
81
+ string :comments, :length => 255, :trim_padding => true
82
+ float :amount
83
+ skip length: 8
84
+ end
85
+
86
+ class Yeast < RecEntry
87
+ string :name, :length => 55, :trim_padding => true
88
+ string :supplier, :length => 55, :trim_padding => true
89
+ string :catalog, :length => 26, :trim_padding => true
90
+ string :flavor_note, :length => 155, :trim_padding => true
91
+ string :comment, :length => 155, :trim_padding => true
92
+ skip length: 9
93
+ int32 :aa_low
94
+ int32 :aa_high
95
+ float :optimum_temp
96
+ skip length: 6
97
+ end
98
+
99
+ class WaterProfile < RecEntry
100
+ string :name, :length => 27, :trim_padding => true
101
+ float :calcium
102
+ float :magnesium
103
+ float :sodium
104
+ float :unknown
105
+ float :sulfate
106
+ float :chloride
107
+ float :bicarbonate
108
+ float :ph
109
+ string :comments, :length => 155, :trim_padding => true
110
+ skip length: 8
111
+ end
112
+
113
+ class MashStep < RecEntry
114
+ string :name, :length => 255, :trim_padding => true
115
+ int8 :type
116
+ int32 :start_temp
117
+ int32 :stop_temp
118
+ int32 :step_temp
119
+ int32 :rest_time
120
+ int32 :step_time
121
+ float :thickness
122
+ float :amount
123
+ skip length: 8
124
+ end
125
+
126
+ class MashSchedule < RecEntry
127
+ int32 :_steps_count
128
+ int32 :grain_temp
129
+ skip length: 4
130
+ array :mash_steps, :type => :mash_step, :read_until => lambda { index == 50 }
131
+ string :name, :length => 256, :trim_padding => true
132
+ end
133
+
134
+ class SimpleSchedule < RecEntry
135
+ int32 :num_steps
136
+ skip length: 5
137
+ int32 :acid_rest_temp
138
+ int32 :acid_rest_time
139
+ int32 :protein_rest_temp
140
+ int32 :protein_rest_time
141
+ int32 :int_rest_temp
142
+ int32 :int_rest_time
143
+ int32 :sac_rest_temp
144
+ int32 :sac_rest_time
145
+ int32 :mash_out_temp
146
+ int32 :mash_out_time
147
+ int32 :sparge_temp
148
+ int32 :sparge_time
149
+ float :mash_volume
150
+ skip length: 1
151
+ end
152
+
153
+ class Style < RecEntry
154
+ string :category, :length => 55, :trim_padding => true
155
+ string :sub_category, :length => 55, :trim_padding => true
156
+ int8 :_type
157
+ float :min_og
158
+ float :max_og
159
+ float :min_fg
160
+ float :max_fg
161
+ float :min_abv
162
+ float :max_abv
163
+ float :min_ibu
164
+ float :max_ibu
165
+ float :min_color
166
+ float :max_color
167
+ string :color_note, :length => 155, :trim_padding => true
168
+ string :malt_note, :length => 155, :trim_padding => true
169
+ string :hop_note, :length => 155, :trim_padding => true
170
+ string :yeast_note, :length => 155, :trim_padding => true
171
+ string :examples, :length => 255, :trim_padding => true
172
+ int16 :category_number
173
+ string :sub_category_letter, :length => 2, :trim_padding => true
174
+ int8 :_guideline
175
+ end
176
+
177
+ class Recipe < RecEntry
178
+ string :title, :length => 85, :trim_padding => true
179
+ int32 :_hops_count
180
+ int32 :_fermentables_count
181
+ int32 :_additives_count
182
+ float :recipe_volume
183
+ float :boil_volume
184
+ float :estimated_og
185
+ float :estimated_ibu
186
+ float :recipe_efficiency
187
+ int32 :boil_time
188
+ int32 :_recipe_type
189
+ int8 :_brew_method
190
+ style :style
191
+ array :hops, :type => :hop, :initial_length => :_hops_count
192
+ array :fermentables, :type => :fermentable, :initial_length => :_fermentables_count
193
+ array :additives, :type => :additive, :initial_length => :_additives_count
194
+ yeast :yeast
195
+ water_profile :water_profile
196
+ simple_schedule :simple_schedule
197
+ string :notes, :length => 4029, :trim_padding => true
198
+ string :awards, :length => 3693, :trim_padding => true
199
+ mash_schedule :mash_schedule
200
+ end
201
+ end
202
+
203
+ end
204
+
205
+
206
+ class ProMashRec::Hop < Brewser::Hop
207
+
208
+ @@hop_types = {0 => "Both", 1 => "Bittering", 2 => "Aroma"}
209
+ @@hop_forms = {1 => "Whole", 3 => "Whole", 21 => "Pellet", 23 => "Pellet", 11 => "Plug"}
210
+
211
+ # Pellet 21, 23
212
+ def from_promash(hop,time)
213
+ self.name = hop.name.split("\x00")[0]
214
+ self.origin = hop.origin.split("\x00")[0]
215
+ self.alpha_acids = hop.alpha_acids
216
+ self.beta_acids = hop.beta_acids
217
+ self.type = @@hop_types[hop.type]
218
+ self.form = @@hop_forms[hop.form]
219
+ self.amount = "#{hop.amount} oz".u
220
+ self.time = "#{hop.time} min".u
221
+ self.storageability = hop.storage_factor
222
+ self.humulene = hop.humulene
223
+ self.caryophyllene = hop.caryphylene
224
+ self.cohumulone = hop.cohumulone
225
+ self.myrcene = hop.myrcene
226
+ if hop.time.to_i >= 0 and hop.time.to_i <= time
227
+ self.added_when = "Boil"
228
+ elsif hop.time.to_i == time+1
229
+ self.added_when = "FWH"
230
+ elsif hop.time.to_i == time+2
231
+ self.added_when = "Mash"
232
+ else
233
+ self.added_when = "Dry"
234
+ end
235
+
236
+ return self
237
+ end
238
+
239
+ end
240
+
241
+ class ProMashRec::Fermentable < Brewser::Fermentable
242
+
243
+ @@ferm_types = {0 => { 0 => "Grain", 1 => "Dry Extract", 2 => "Sugar", 3 => "Adjunct"},
244
+ 1 => { 0 => "Grain", 1 => "Extract", 2 => "Sugar", 3 => "Adjunct"}}
245
+
246
+ def from_promash(ferm)
247
+ self.name = ferm.name.split("\x00")[0]
248
+ self.origin = ferm.origin.split("\x00")[0]
249
+ self.type = @@ferm_types[ferm.form][ferm.type]
250
+ self.potential = ferm.potential.round(3)
251
+ self.color = ferm.color
252
+ self.amount = "#{ferm.amount} lbs".u
253
+ self.diastatic_power = ferm.diastatic_power
254
+ self.max_in_batch = ferm.max_in_batch
255
+ self.moisture = ferm.moisture_content
256
+
257
+ return self
258
+ end
259
+
260
+ end
261
+
262
+ class ProMashRec::Additive < Brewser::Additive
263
+
264
+ @@additive_types = { 0 => "Spice", 1 => "Fruit", 2 => "Flavor", 3 => "Other", 4 => "Fining", 5 => "Herb" }
265
+ @@added_whens = { 0 => "Boil", 1 => "Primary", 2 => "Mash" }
266
+ @@additive_unit = { 0 => "oz", 1 => "g", 2 => "lb", 3 => "tsp", 4 => "tbsp", 5 => "cups", 6 => "each" }
267
+ @@additive_time = { 0 => "days", 1 => "min" }
268
+
269
+ def from_promash(add)
270
+ self.name = add.name.split("\x00")[0]
271
+ self.type = @@additive_types[add.type]
272
+ self.added_when = @@added_whens[add.added_when]
273
+ self.time = "#{add.time} #{@@additive_time[add.time_in]}".u
274
+ self.amount = "#{add.amount} #{@@additive_unit[add.amount_unit]}".u
275
+ self.use_for = add.uses
276
+
277
+ return self
278
+ end
279
+
280
+ end
281
+
282
+ class ProMashRec::Yeast < Brewser::Yeast
283
+
284
+ def from_promash(y)
285
+ self.name = y.name.split("\x00")[0]
286
+ self.supplier = y.supplier
287
+ self.catalog = y.catalog
288
+ self.attenuation = (y.aa_high + y.aa_low)/2
289
+ self.min_temperature = self.max_temperature = "#{y.optimum_temp} dF".u
290
+ self.description = y.comment
291
+ self.amount = "1 each".u
292
+
293
+ return self
294
+ end
295
+
296
+ end
297
+
298
+ class ProMashRec::MashStep < Brewser::MashStep
299
+
300
+ def from_simple(idx, name, rest_temp, rest_time)
301
+ self.index = idx
302
+ self.name = name
303
+ self.rest_temperature = rest_temp.u
304
+ self.rest_time = rest_time.u
305
+
306
+ return self
307
+ end
308
+
309
+ end
310
+
311
+ class ProMashRec::MashSchedule < Brewser::MashSchedule
312
+
313
+ def from_promash(mash)
314
+
315
+ return self
316
+ end
317
+
318
+ end
319
+
320
+ class ProMashRec::SimpleSchedule < Brewser::MashSchedule
321
+
322
+ def from_promash(mash)
323
+ self.name = "Simple"
324
+ ["acid_rest", "protein_rest", "int_rest", "sac_rest", "mash_out", "sparge"].each do |step, index|
325
+ next if mash.send("#{step}_temp")==0
326
+ self.mash_steps.push ProMashRec::MashStep.new.from_simple(index, "#{step.gsub("_"," ").capitalize}", "#{mash.send("#{step}_temp")} dF",
327
+ "#{mash.send("#{step}_time")} min")
328
+ end
329
+ return self
330
+ end
331
+
332
+ end
333
+
334
+ class ProMashRec::FermentationStep < Brewser::FermentationStep
335
+ # Not support in ProMash REC files
336
+ end
337
+
338
+ class ProMashRec::FermentationSchedule < Brewser::FermentationSchedule
339
+ # Not supported in ProMash REC files
340
+ end
341
+
342
+ class ProMashRec::WaterProfile < Brewser::WaterProfile
343
+
344
+ def from_promash(water)
345
+ self.name = water.name.split("\x00")[0]
346
+ self.calcium = water.calcium
347
+ self.magnesium = water.magnesium
348
+ self.sodium = water.sodium
349
+ self.chloride = water.chloride
350
+ self.sulfates = water.sulfate
351
+ self.bicarbonate = water.bicarbonate
352
+ self.ph = water.ph.round(2)
353
+
354
+ return self
355
+ end
356
+
357
+ end
358
+
359
+ class ProMashRec::Style < Brewser::Style
360
+
361
+ @@style_guides = { 0 => "AHA", 1 => "BJCP" }
362
+ @@style_types = { 0 => "Ale", 1 => "Lager", 2 => "Cider", 3 => "Mead", 5 => "Hybrid"}
363
+
364
+ def from_promash(style)
365
+ self.name = style.sub_category.split("\x00")[0]
366
+ self.category = style.category.split("\x00")[0]
367
+ self.category_number = style.category_number
368
+ self.style_letter = style.sub_category_letter
369
+ self.style_guide = @@style_guides[style._guideline]
370
+ self.type = @@style_types[style._type]
371
+ self.og_min = style.min_og
372
+ self.og_max = style.max_og
373
+ self.fg_min = style.min_fg
374
+ self.fg_max = style.max_fg
375
+ self.ibu_min = style.min_ibu
376
+ self.ibu_max = style.max_ibu
377
+ self.color_min = style.min_color
378
+ self.color_max = style.max_color
379
+ self.examples = style.examples
380
+
381
+ return self
382
+ end
383
+
384
+ end
385
+
386
+ class ProMashRec::Recipe < Brewser::Recipe
387
+
388
+ @@recipe_types = { 0 => "Other", 15 => "Lager", 25 => "Hybrid", 30 => "Ale" }
389
+ @@brew_methods = { 0 => "All Grain", 1 => "Partial Mash", 2 => "Extract" }
390
+
391
+ def from_promash(data)
392
+ rec = Loader::Recipe.read(data)
393
+ self.name = rec.title.split("\x00")[0]
394
+ self.method = @@brew_methods[rec._brew_method]
395
+ self.recipe_volume = "#{rec.recipe_volume} gal".u
396
+ self.boil_volume = "#{rec.boil_volume} gal".u
397
+ self.boil_time = "#{rec.boil_time} min".u
398
+ self.estimated_og = (1+rec.estimated_og/1000).round(3)
399
+ self.estimated_ibu = rec.estimated_ibu.round(1)
400
+ self.recipe_efficiency = rec.recipe_efficiency*100
401
+ self.style = ProMashRec::Style.new.from_promash(rec.style)
402
+ rec.hops.each do |hop|
403
+ self.hops.push ProMashRec::Hop.new.from_promash(hop,rec.boil_time.to_i)
404
+ end
405
+ rec.fermentables.each do |fermentable|
406
+ self.fermentables.push ProMashRec::Fermentable.new.from_promash(fermentable)
407
+ end
408
+ rec.additives.each do |additive|
409
+ self.additives.push ProMashRec::Additive.new.from_promash(additive)
410
+ end
411
+ self.yeasts.push ProMashRec::Yeast.new.from_promash(rec.yeast)
412
+ self.water_profile = ProMashRec::WaterProfile.new.from_promash(rec.water_profile)
413
+ if rec.simple_schedule.num_steps > 0
414
+ self.mash_schedule = ProMashRec::SimpleSchedule.new.from_promash(rec.simple_schedule)
415
+ else
416
+ self.mash_schedule = ProMashRec::MashSchedule.new.from_promash(rec.mash_schedule)
417
+ end
418
+ self.description = rec.notes
419
+ self.type = self.style.type
420
+ #puts rec.snapshot
421
+ return self
422
+ end
423
+
424
+ end