toji 2.12.0 → 2.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/example/calendar.ipynb +42 -51
  3. data/example/calendar.yaml +6 -6
  4. data/example/calendar_file.ipynb +35 -35
  5. data/example/example_core.rb +850 -230
  6. data/example/kake_ingredient.rb +21 -15
  7. data/example/koji_ingredient.rb +31 -21
  8. data/example/{koji_making.ipynb → koji_progress.ipynb} +14 -14
  9. data/example/{koji_making.rb → koji_progress.rb} +3 -2
  10. data/example/{koji_making.yaml → koji_progress.yaml} +8 -9
  11. data/example/{koji_making_multi.ipynb → koji_progress_multi.ipynb} +21 -22
  12. data/example/{moromi.ipynb → moromi_progress.ipynb} +22 -22
  13. data/example/{moromi.rb → moromi_progress.rb} +3 -2
  14. data/example/{moromi.yaml → moromi_progress.yaml} +0 -0
  15. data/example/moto_progress.ipynb +121 -0
  16. data/example/{moto.rb → moto_progress.rb} +3 -2
  17. data/example/{moto.yaml → moto_progress.yaml} +14 -15
  18. data/example/recipe.rb +44 -32
  19. data/lib/toji.rb +4 -2
  20. data/lib/toji/calendar.rb +12 -12
  21. data/lib/toji/calendar/date_column.rb +8 -8
  22. data/lib/toji/calendar/date_row.rb +6 -6
  23. data/lib/toji/ingredient.rb +6 -2
  24. data/lib/toji/ingredient/alcohol.rb +14 -0
  25. data/lib/toji/ingredient/base.rb +11 -0
  26. data/lib/toji/ingredient/kake.rb +3 -9
  27. data/lib/toji/ingredient/koji.rb +19 -10
  28. data/lib/toji/ingredient/lactic_acid.rb +14 -0
  29. data/lib/toji/ingredient/rice.rb +50 -4
  30. data/lib/toji/ingredient/tanekoji.rb +29 -0
  31. data/lib/toji/ingredient/water.rb +18 -0
  32. data/lib/toji/ingredient/yeast.rb +20 -0
  33. data/lib/toji/processing.rb +18 -0
  34. data/lib/toji/processing/base.rb +7 -0
  35. data/lib/toji/processing/cooled_rice.rb +22 -0
  36. data/lib/toji/processing/cooled_rice_element.rb +8 -0
  37. data/lib/toji/processing/dekoji.rb +22 -0
  38. data/lib/toji/processing/dekoji_element.rb +8 -0
  39. data/lib/toji/processing/kake_processing.rb +7 -0
  40. data/lib/toji/processing/koji_processing.rb +10 -0
  41. data/lib/toji/processing/rice_processing.rb +19 -0
  42. data/lib/toji/processing/soaked_rice.rb +49 -0
  43. data/lib/toji/processing/soaked_rice_element.rb +18 -0
  44. data/lib/toji/processing/steamed_rice.rb +22 -0
  45. data/lib/toji/processing/steamed_rice_element.rb +8 -0
  46. data/lib/toji/product.rb +11 -32
  47. data/lib/toji/product/schedule_factory.rb +74 -0
  48. data/lib/toji/progress.rb +23 -0
  49. data/lib/toji/progress/base_progress.rb +37 -0
  50. data/lib/toji/progress/base_state.rb +39 -0
  51. data/lib/toji/progress/builder.rb +53 -0
  52. data/lib/toji/progress/graph.rb +11 -0
  53. data/lib/toji/{brew → progress}/graph/ab.rb +4 -4
  54. data/lib/toji/{brew → progress}/graph/bmd.rb +2 -2
  55. data/lib/toji/{brew/graph/multi_progress.rb → progress/graph/multi_progress_note.rb} +11 -11
  56. data/lib/toji/{brew/graph/progress.rb → progress/graph/progress_note.rb} +20 -18
  57. data/lib/toji/progress/koji_progress.rb +15 -0
  58. data/lib/toji/progress/koji_state.rb +23 -0
  59. data/lib/toji/{brew/moromi.rb → progress/moromi_progress.rb} +9 -5
  60. data/lib/toji/progress/moromi_state.rb +77 -0
  61. data/lib/toji/progress/moto_progress.rb +15 -0
  62. data/lib/toji/progress/moto_state.rb +31 -0
  63. data/lib/toji/progress/progress.rb +15 -0
  64. data/lib/toji/progress/state.rb +9 -0
  65. data/lib/toji/progress/state/baume_to_nihonshudo.rb +21 -0
  66. data/lib/toji/progress/state/nihonshudo_to_baume.rb +21 -0
  67. data/lib/toji/recipe.rb +53 -39
  68. data/lib/toji/recipe/ab_expect.rb +2 -2
  69. data/lib/toji/recipe/action.rb +2 -2
  70. data/lib/toji/recipe/step.rb +97 -71
  71. data/lib/toji/schedule.rb +5 -0
  72. data/lib/toji/schedule/action_schedule.rb +9 -0
  73. data/lib/toji/{event → schedule}/base.rb +1 -1
  74. data/lib/toji/schedule/kake_schedule.rb +11 -0
  75. data/lib/toji/schedule/koji_schedule.rb +11 -0
  76. data/lib/toji/schedule/rice_schedule.rb +16 -0
  77. data/lib/toji/utils.rb +43 -0
  78. data/lib/toji/version.rb +1 -1
  79. metadata +58 -44
  80. data/lib/toji/brew.rb +0 -18
  81. data/lib/toji/brew/base.rb +0 -55
  82. data/lib/toji/brew/builder.rb +0 -98
  83. data/lib/toji/brew/graph.rb +0 -11
  84. data/lib/toji/brew/koji.rb +0 -11
  85. data/lib/toji/brew/moto.rb +0 -11
  86. data/lib/toji/brew/state.rb +0 -122
  87. data/lib/toji/brew/wrapped_state.rb +0 -109
  88. data/lib/toji/event.rb +0 -5
  89. data/lib/toji/event/action_event.rb +0 -12
  90. data/lib/toji/event/kake_event.rb +0 -13
  91. data/lib/toji/event/koji_event.rb +0 -19
  92. data/lib/toji/event/rice_event.rb +0 -34
  93. data/lib/toji/ingredient/kake/actual.rb +0 -26
  94. data/lib/toji/ingredient/kake/base.rb +0 -18
  95. data/lib/toji/ingredient/kake/expected.rb +0 -40
  96. data/lib/toji/ingredient/koji/actual.rb +0 -29
  97. data/lib/toji/ingredient/koji/actual_fermentable.rb +0 -15
  98. data/lib/toji/ingredient/koji/base.rb +0 -35
  99. data/lib/toji/ingredient/koji/expected.rb +0 -45
  100. data/lib/toji/ingredient/koji/expected_fermentable.rb +0 -15
  101. data/lib/toji/ingredient/koji_rate.rb +0 -16
  102. data/lib/toji/ingredient/rice/actual_steamable.rb +0 -27
  103. data/lib/toji/ingredient/rice/base.rb +0 -40
  104. data/lib/toji/ingredient/rice/expected_steamable.rb +0 -27
  105. data/lib/toji/ingredient/rice_rate.rb +0 -23
  106. data/lib/toji/product/event_factory.rb +0 -70
@@ -1,88 +1,222 @@
1
+ $LOAD_PATH << File.dirname(__FILE__) + "/../lib"
1
2
  require 'toji'
2
3
  require 'securerandom'
3
4
 
4
5
  module Example
5
6
 
6
- module Brew
7
- class State
8
- include Toji::Brew::State
9
- include Toji::Brew::State::BaumeToNihonshudo
7
+ class Product
8
+ include Toji::Product
9
+ include Toji::Product::ScheduleFactory
10
10
 
11
- def self.create(val)
12
- s = new
13
- KEYS.each {|k|
14
- if val.has_key?(k)
15
- s.send("#{k}=", val[k])
16
- end
17
- }
18
- s
19
- end
11
+ attr_accessor :description
12
+ attr_accessor :color
13
+
14
+ def initialize(id, name, description, recipe, base_date, color=nil)
15
+ @id = id
16
+ @name = name
17
+ @description = description
18
+ @recipe = recipe
19
+ @base_date = base_date
20
+ @color = color
20
21
  end
21
22
 
22
- module BrewGenerator
23
- def builder
24
- Toji::Brew::Builder.new(self)
25
- end
23
+ def create_koji_schedule(date:, step_indexes:, kojis:)
24
+ expect = kojis.first.dup
25
+ expect.weight = kojis.map(&:weight).sum
26
26
 
27
- def load_hash(hash)
28
- hash = hash.deep_symbolize_keys
27
+ KojiSchedule.new(
28
+ product: self,
29
+ date: date,
30
+ step_indexes: step_indexes,
31
+ expect: expect,
32
+ )
33
+ end
29
34
 
30
- builder
31
- .add((hash[:states] || []).map{|s| State.create(s)})
32
- .date_line(hash[:date_line] || 0, Toji::Brew::HOUR)
33
- .prefix_day_labels(hash[:prefix_day_labels])
34
- .time_interpolation(nil)
35
- .elapsed_time_interpolation
36
- .build
37
- end
35
+ def create_kake_schedule(date:, step_indexes:, kakes:)
36
+ expect = kakes.first.dup
37
+ expect.weight = kakes.map(&:weight).sum
38
38
 
39
- def load_yaml_file(fname)
40
- hash = YAML.load_file(fname)
41
- load_hash(hash)
42
- end
39
+ KakeSchedule.new(
40
+ product: self,
41
+ date: date,
42
+ step_indexes: step_indexes,
43
+ expect: expect,
44
+ )
43
45
  end
44
46
 
45
- class Base
46
- include Toji::Brew::Base
47
- extend BrewGenerator
47
+ def create_action_schedule(date:, action_index:, action:)
48
+ ActionSchedule.new(
49
+ product: self,
50
+ date: date,
51
+ type: action.type,
52
+ action_index: index,
53
+ )
54
+ end
48
55
 
49
- def initialize
50
- @states = []
51
- @day_offset = 0
52
- @base_time = 0
56
+ def self.create(args)
57
+ if self===args
58
+ args
59
+ elsif Hash===args
60
+ recipe = args.fetch(:recipe)
61
+ if Symbol===recipe
62
+ recipe = Recipe::TEMPLATES.fetch(recipe)
63
+ end
64
+ if args[:scale_rice_total]
65
+ recipe = recipe.scale_rice_total(args[:scale_rice_total])
66
+ end
67
+ if args[:round]
68
+ recipe = recipe.round(args[:round])
69
+ end
70
+
71
+ new(
72
+ args[:id],
73
+ args[:name],
74
+ args[:description],
75
+ recipe,
76
+ args[:base_date],
77
+ args[:color]
78
+ )
79
+ else
80
+ raise "not supported class: #{args.class}"
53
81
  end
54
82
  end
83
+ end
55
84
 
56
- class Koji < Base
57
- include Toji::Brew::Koji
58
- end
59
85
 
60
- class Moto < Base
61
- include Toji::Brew::Moto
86
+ class Step
87
+ include Toji::Recipe::Step
88
+
89
+ def initialize(kojis: [], kakes: [], waters: [], lactic_acids: [], alcohols: [], yeasts: [])
90
+ @kojis = kojis
91
+ @kakes = kakes
92
+ @waters = waters
93
+ @lactic_acids = lactic_acids
94
+ @alcohols = alcohols
95
+ @yeasts = yeasts
62
96
  end
63
97
 
64
- class Moromi < Base
65
- include Toji::Brew::Moromi
98
+ def initialize_copy(obj)
99
+ @kojis = obj.kojis.deep_dup
100
+ @kakes = obj.kakes.deep_dup
101
+ @waters = obj.waters.deep_dup
102
+ @lactic_acids = obj.lactic_acids.deep_dup
103
+ @alcohols = obj.alcohols.deep_dup
104
+ @yeasts = obj.yeasts.deep_dup
66
105
  end
67
106
  end
68
107
 
108
+ class Koji
109
+ include Toji::Ingredient::Koji
110
+
111
+ def initialize(weight:, brand:, polishing_ratio:, made_in:, year:, soaking_ratio:, steaming_ratio:, cooling_ratio:, tanekojis:, dekoji_ratio:, interval_days:)
112
+ @weight = weight
113
+ @brand = brand
114
+ @polishing_ratio = polishing_ratio
115
+ @made_in = made_in
116
+ @year = year
117
+ @soaking_ratio = soaking_ratio
118
+ @steaming_ratio = steaming_ratio
119
+ @cooling_ratio = cooling_ratio
120
+ @tanekojis = tanekojis.map {|tanekoji|
121
+ tanekoji.koji = self
122
+ tanekoji
123
+ }
124
+ @dekoji_ratio = dekoji_ratio
125
+ @interval_days = interval_days
126
+ end
69
127
 
70
- class Step
71
- include Toji::Recipe::Step
72
- attr_accessor :name
73
-
74
- def self.create(name:, kake: 0, koji: 0, water: 0, lactic_acid: 0, alcohol: 0, yeast: 0, koji_interval_days: 0, kake_interval_days: 0)
75
- new.tap {|o|
76
- o.name = name
77
- o.kake = kake.to_f
78
- o.koji = koji.to_f
79
- o.water = water.to_f
80
- o.lactic_acid = lactic_acid.to_f
81
- o.alcohol = alcohol.to_f
82
- o.yeast = yeast.to_f
83
- o.koji_interval_days = koji_interval_days.to_i
84
- o.kake_interval_days = kake_interval_days.to_i
128
+ def initialize_copy(obj)
129
+ @weight = obj.weight.dup
130
+ @brand = obj.brand.dup
131
+ @polishing_ratio = obj.polishing_ratio.dup
132
+ @made_in = obj.made_in.dup
133
+ @year = obj.year.dup
134
+ @soaking_ratio = obj.soaking_ratio.dup
135
+ @steaming_ratio = obj.steaming_ratio.dup
136
+ @cooling_ratio = obj.cooling_ratio.dup
137
+
138
+ @tanekojis = obj.tanekojis.map {|tanekoji|
139
+ tanekoji = tanekoji.dup
140
+ tanekoji.koji = self
141
+ tanekoji
85
142
  }
143
+
144
+ @dekoji_ratio = obj.dekoji_ratio.dup
145
+ @interval_days = obj.interval_days.dup
146
+ end
147
+ end
148
+
149
+ class Tanekoji
150
+ include Toji::Ingredient::Tanekoji
151
+
152
+ attr_accessor :koji
153
+
154
+ def initialize(koji: nil, brand:, ratio:)
155
+ @brand = brand
156
+ @ratio = ratio
157
+ end
158
+
159
+ def initialize_copy(obj)
160
+ @brand = obj.brand.dup
161
+ @ratio = obj.ratio.dup
162
+ end
163
+ end
164
+
165
+ class Kake
166
+ include Toji::Ingredient::Kake
167
+
168
+ def initialize(weight:, brand:, polishing_ratio:, made_in:, year:, soaking_ratio:, steaming_ratio:, cooling_ratio:, interval_days:)
169
+ @weight = weight
170
+ @brand = brand
171
+ @polishing_ratio = polishing_ratio
172
+ @made_in = made_in
173
+ @year = year
174
+ @soaking_ratio = soaking_ratio
175
+ @steaming_ratio = steaming_ratio
176
+ @cooling_ratio = cooling_ratio
177
+ @interval_days = interval_days
178
+ end
179
+ end
180
+
181
+ class Water
182
+ include Toji::Ingredient::Water
183
+
184
+ def initialize(weight:)
185
+ @weight = weight
186
+ end
187
+ end
188
+
189
+ class LacticAcid
190
+ include Toji::Ingredient::LacticAcid
191
+
192
+ def initialize(weight:)
193
+ @weight = weight
194
+ end
195
+ end
196
+
197
+ class Alcohol
198
+ include Toji::Ingredient::Alcohol
199
+
200
+ def initialize(weight:)
201
+ @weight = weight
202
+ end
203
+ end
204
+
205
+ class Yeast
206
+ include Toji::Ingredient::Yeast
207
+
208
+ def initialize(weight:)
209
+ @weight = weight
210
+ end
211
+ end
212
+
213
+
214
+ class Action
215
+ include Toji::Recipe::Action
216
+
217
+ def initialize(type:, interval_days:)
218
+ @type = type
219
+ @interval_days = interval_days
86
220
  end
87
221
  end
88
222
 
@@ -90,14 +224,12 @@ module Example
90
224
  class Recipe
91
225
  include Toji::Recipe
92
226
 
93
- def initialize
94
- @steps = []
227
+ def initialize(steps)
228
+ @steps = steps
95
229
  end
96
230
 
97
- def self.create(steps)
98
- new.tap {|o|
99
- o.steps = steps
100
- }
231
+ def initialize_copy(obj)
232
+ @steps = obj.steps.deep_dup
101
233
  end
102
234
 
103
235
  # 乳酸は汲水100L当たり比重1.21の乳酸(90%乳酸と称される)を650〜720ml添加する。
@@ -109,135 +241,563 @@ module Example
109
241
  TEMPLATES = {
110
242
  # 酒造教本による標準型仕込配合
111
243
  # 出典: 酒造教本 P97
112
- sokujo_textbook: create(
244
+ sokujo_textbook: new(
113
245
  [
114
- Step.create(
115
- name: :moto,
116
- kake: 45,
117
- koji: 20,
118
- water: 70,
119
- lactic_acid: 70/100.0*0.685,
120
- yeast: (45+20)/100.0*1.5,
121
- koji_interval_days: 0,
122
- kake_interval_days: 5,
246
+ Step.new(
247
+ kojis: [
248
+ Koji.new(
249
+ weight: 20,
250
+ brand: :yamadanishiki,
251
+ polishing_ratio: 0.55,
252
+ made_in: :hyogo,
253
+ year: 2020,
254
+ soaking_ratio: 0.33,
255
+ steaming_ratio: 0.41,
256
+ cooling_ratio: 0.33,
257
+ tanekojis: [
258
+ Tanekoji.new(
259
+ brand: :byakuya,
260
+ ratio: 0.001,
261
+ ),
262
+ ],
263
+ dekoji_ratio: 0.18,
264
+ interval_days: 0,
265
+ ),
266
+ ],
267
+ kakes: [
268
+ Kake.new(
269
+ weight: 45,
270
+ brand: :yamadanishiki,
271
+ polishing_ratio: 0.55,
272
+ made_in: :hyogo,
273
+ year: 2020,
274
+ soaking_ratio: 0.33,
275
+ steaming_ratio: 0.41,
276
+ cooling_ratio: 0.33,
277
+ interval_days: 5,
278
+ ),
279
+ ],
280
+ waters: [
281
+ Water.new(
282
+ weight: 70,
283
+ ),
284
+ ],
285
+ lactic_acids: [
286
+ LacticAcid.new(
287
+ weight: 70/100.0*0.685,
288
+ ),
289
+ ],
290
+ yeasts: [
291
+ Yeast.new(
292
+ weight: (45+20)/100.0*1.5,
293
+ ),
294
+ ]
123
295
  ),
124
- Step.create(
125
- name: :soe,
126
- kake: 100,
127
- koji: 40,
128
- water: 130,
129
- koji_interval_days: 14,
130
- kake_interval_days: 15,
296
+ Step.new(
297
+ kojis: [
298
+ Koji.new(
299
+ weight: 40,
300
+ brand: :yamadanishiki,
301
+ polishing_ratio: 0.55,
302
+ made_in: :hyogo,
303
+ year: 2020,
304
+ soaking_ratio: 0.33,
305
+ steaming_ratio: 0.41,
306
+ cooling_ratio: 0.33,
307
+ tanekojis: [
308
+ Tanekoji.new(
309
+ brand: :byakuya,
310
+ ratio: 0.001,
311
+ ),
312
+ ],
313
+ dekoji_ratio: 0.18,
314
+ interval_days: 14,
315
+ ),
316
+ ],
317
+ kakes: [
318
+ Kake.new(
319
+ weight: 100,
320
+ brand: :yamadanishiki,
321
+ polishing_ratio: 0.55,
322
+ made_in: :hyogo,
323
+ year: 2020,
324
+ soaking_ratio: 0.33,
325
+ steaming_ratio: 0.41,
326
+ cooling_ratio: 0.33,
327
+ interval_days: 20,
328
+ ),
329
+ ],
330
+ waters: [
331
+ Water.new(
332
+ weight: 130,
333
+ ),
334
+ ],
131
335
  ),
132
- Step.create(
133
- name: :naka,
134
- kake: 215,
135
- koji: 60,
136
- water: 330,
137
- koji_interval_days: 0,
138
- kake_interval_days: 2,
336
+ Step.new(
337
+ kojis: [
338
+ Koji.new(
339
+ weight: 60,
340
+ brand: :yamadanishiki,
341
+ polishing_ratio: 0.55,
342
+ made_in: :hyogo,
343
+ year: 2020,
344
+ soaking_ratio: 0.33,
345
+ steaming_ratio: 0.41,
346
+ cooling_ratio: 0.33,
347
+ tanekojis: [
348
+ Tanekoji.new(
349
+ brand: :byakuya,
350
+ ratio: 0.001,
351
+ ),
352
+ ],
353
+ dekoji_ratio: 0.18,
354
+ interval_days: 14,
355
+ ),
356
+ ],
357
+ kakes: [
358
+ Kake.new(
359
+ weight: 215,
360
+ brand: :yamadanishiki,
361
+ polishing_ratio: 0.55,
362
+ made_in: :hyogo,
363
+ year: 2020,
364
+ soaking_ratio: 0.33,
365
+ steaming_ratio: 0.41,
366
+ cooling_ratio: 0.33,
367
+ interval_days: 22,
368
+ ),
369
+ ],
370
+ waters: [
371
+ Water.new(
372
+ weight: 330,
373
+ ),
374
+ ],
139
375
  ),
140
- Step.create(
141
- name: :tome,
142
- kake: 360,
143
- koji: 80,
144
- water: 630,
145
- koji_interval_days: 0,
146
- kake_interval_days: 1,
376
+ Step.new(
377
+ kojis: [
378
+ Koji.new(
379
+ weight: 80,
380
+ brand: :yamadanishiki,
381
+ polishing_ratio: 0.55,
382
+ made_in: :hyogo,
383
+ year: 2020,
384
+ soaking_ratio: 0.33,
385
+ steaming_ratio: 0.41,
386
+ cooling_ratio: 0.33,
387
+ tanekojis: [
388
+ Tanekoji.new(
389
+ brand: :byakuya,
390
+ ratio: 0.001,
391
+ ),
392
+ ],
393
+ dekoji_ratio: 0.18,
394
+ interval_days: 14,
395
+ ),
396
+ ],
397
+ kakes: [
398
+ Kake.new(
399
+ weight: 360,
400
+ brand: :yamadanishiki,
401
+ polishing_ratio: 0.55,
402
+ made_in: :hyogo,
403
+ year: 2020,
404
+ soaking_ratio: 0.33,
405
+ steaming_ratio: 0.41,
406
+ cooling_ratio: 0.33,
407
+ interval_days: 23,
408
+ ),
409
+ ],
410
+ waters: [
411
+ Water.new(
412
+ weight: 630,
413
+ ),
414
+ ],
147
415
  ),
148
- Step.create(
149
- name: :yodan,
150
- kake: 80,
151
- water: 120,
152
- kake_interval_days: 25,
416
+ Step.new(
417
+ kakes: [
418
+ Kake.new(
419
+ weight: 80,
420
+ brand: :yamadanishiki,
421
+ polishing_ratio: 0.55,
422
+ made_in: :hyogo,
423
+ year: 2020,
424
+ soaking_ratio: 0.33,
425
+ steaming_ratio: 0.41,
426
+ cooling_ratio: 0.33,
427
+ interval_days: 48,
428
+ ),
429
+ ],
430
+ waters: [
431
+ Water.new(
432
+ weight: 120,
433
+ ),
434
+ ],
153
435
  ),
154
436
  ].map(&:freeze).freeze
155
437
  ).freeze,
156
438
  # 灘における仕込配合の平均値
157
439
  # 出典: http://www.nada-ken.com/main/jp/index_shi/234.html
158
- sokujo_nada: create(
440
+ sokujo_nada: new(
159
441
  [
160
- Step.create(
161
- name: :moto,
162
- kake: 93,
163
- koji: 47,
164
- water: 170,
165
- lactic_acid: 170/100.0*0.685,
166
- yeast: (93+47)/100.0*1.5,
167
- koji_interval_days: 0,
168
- kake_interval_days: 5,
442
+ Step.new(
443
+ kojis: [
444
+ Koji.new(
445
+ weight: 47,
446
+ brand: :yamadanishiki,
447
+ polishing_ratio: 0.55,
448
+ made_in: :hyogo,
449
+ year: 2020,
450
+ soaking_ratio: 0.33,
451
+ steaming_ratio: 0.41,
452
+ cooling_ratio: 0.33,
453
+ tanekojis: [
454
+ Tanekoji.new(
455
+ brand: :byakuya,
456
+ ratio: 0.001,
457
+ ),
458
+ ],
459
+ dekoji_ratio: 0.18,
460
+ interval_days: 0,
461
+ ),
462
+ ],
463
+ kakes: [
464
+ Kake.new(
465
+ weight: 93,
466
+ brand: :yamadanishiki,
467
+ polishing_ratio: 0.55,
468
+ made_in: :hyogo,
469
+ year: 2020,
470
+ soaking_ratio: 0.33,
471
+ steaming_ratio: 0.41,
472
+ cooling_ratio: 0.33,
473
+ interval_days: 5,
474
+ ),
475
+ ],
476
+ waters: [
477
+ Water.new(
478
+ weight: 170,
479
+ ),
480
+ ],
481
+ lactic_acids: [
482
+ LacticAcid.new(
483
+ weight: 170/100.0*0.685,
484
+ ),
485
+ ],
486
+ yeasts: [
487
+ Yeast.new(
488
+ weight: (93+47)/100.0*1.5,
489
+ ),
490
+ ],
169
491
  ),
170
- Step.create(
171
- name: :soe,
172
- kake: 217,
173
- koji: 99,
174
- water: 270,
175
- koji_interval_days: 14,
176
- kake_interval_days: 15,
492
+ Step.new(
493
+ kojis: [
494
+ Koji.new(
495
+ weight: 99,
496
+ brand: :yamadanishiki,
497
+ polishing_ratio: 0.55,
498
+ made_in: :hyogo,
499
+ year: 2020,
500
+ soaking_ratio: 0.33,
501
+ steaming_ratio: 0.41,
502
+ cooling_ratio: 0.33,
503
+ tanekojis: [
504
+ Tanekoji.new(
505
+ brand: :byakuya,
506
+ ratio: 0.001,
507
+ ),
508
+ ],
509
+ dekoji_ratio: 0.18,
510
+ interval_days: 14,
511
+ ),
512
+ ],
513
+ kakes: [
514
+ Kake.new(
515
+ weight: 217,
516
+ brand: :yamadanishiki,
517
+ polishing_ratio: 0.55,
518
+ made_in: :hyogo,
519
+ year: 2020,
520
+ soaking_ratio: 0.33,
521
+ steaming_ratio: 0.41,
522
+ cooling_ratio: 0.33,
523
+ interval_days: 20,
524
+ ),
525
+ ],
526
+ waters: [
527
+ Water.new(
528
+ weight: 270,
529
+ ),
530
+ ],
177
531
  ),
178
- Step.create(
179
- name: :naka,
180
- kake: 423,
181
- koji: 143,
182
- water: 670,
183
- koji_interval_days: 0,
184
- kake_interval_days: 2,
532
+ Step.new(
533
+ kojis: [
534
+ Koji.new(
535
+ weight: 143,
536
+ brand: :yamadanishiki,
537
+ polishing_ratio: 0.55,
538
+ made_in: :hyogo,
539
+ year: 2020,
540
+ soaking_ratio: 0.33,
541
+ steaming_ratio: 0.41,
542
+ cooling_ratio: 0.33,
543
+ tanekojis: [
544
+ Tanekoji.new(
545
+ brand: :byakuya,
546
+ ratio: 0.001,
547
+ ),
548
+ ],
549
+ dekoji_ratio: 0.18,
550
+ interval_days: 14,
551
+ ),
552
+ ],
553
+ kakes: [
554
+ Kake.new(
555
+ weight: 423,
556
+ brand: :yamadanishiki,
557
+ polishing_ratio: 0.55,
558
+ made_in: :hyogo,
559
+ year: 2020,
560
+ soaking_ratio: 0.33,
561
+ steaming_ratio: 0.41,
562
+ cooling_ratio: 0.33,
563
+ interval_days: 22,
564
+ ),
565
+ ],
566
+ waters: [
567
+ Water.new(
568
+ weight: 670,
569
+ ),
570
+ ],
185
571
  ),
186
- Step.create(
187
- name: :tome,
188
- kake: 813,
189
- koji: 165,
190
- water: 1330,
191
- koji_interval_days: 0,
192
- kake_interval_days: 1,
572
+ Step.new(
573
+ kojis: [
574
+ Koji.new(
575
+ weight: 165,
576
+ brand: :yamadanishiki,
577
+ polishing_ratio: 0.55,
578
+ made_in: :hyogo,
579
+ year: 2020,
580
+ soaking_ratio: 0.33,
581
+ steaming_ratio: 0.41,
582
+ cooling_ratio: 0.33,
583
+ tanekojis: [
584
+ Tanekoji.new(
585
+ brand: :byakuya,
586
+ ratio: 0.001,
587
+ ),
588
+ ],
589
+ dekoji_ratio: 0.18,
590
+ interval_days: 14,
591
+ ),
592
+ ],
593
+ kakes: [
594
+ Kake.new(
595
+ weight: 813,
596
+ brand: :yamadanishiki,
597
+ polishing_ratio: 0.55,
598
+ made_in: :hyogo,
599
+ year: 2020,
600
+ soaking_ratio: 0.33,
601
+ steaming_ratio: 0.41,
602
+ cooling_ratio: 0.33,
603
+ interval_days: 23,
604
+ ),
605
+ ],
606
+ waters: [
607
+ Water.new(
608
+ weight: 1330,
609
+ ),
610
+ ],
193
611
  ),
194
- Step.create(
195
- name: :alcohol,
196
- alcohol: 900
612
+ Step.new(
613
+ alcohols: [
614
+ Alcohol.new(
615
+ weight: 900,
616
+ ),
617
+ ],
197
618
  ),
198
619
  ].map(&:freeze).freeze
199
620
  ).freeze,
200
621
  # 簡易酒母省略仕込
201
622
  # 出典: https://www.jstage.jst.go.jp/article/jbrewsocjapan1915/60/11/60_11_999/_article/-char/ja/
202
- simple_sokujo_himeno: create(
623
+ simple_sokujo_himeno: new(
203
624
  [
204
- Step.create(
205
- name: :moto,
206
- kake: 0,
207
- koji: 70,
208
- water: 245,
209
- lactic_acid: 1.6,
210
- yeast: 5,
211
- koji_interval_days: 0,
212
- kake_interval_days: 6,
625
+ Step.new(
626
+ kojis: [
627
+ Koji.new(
628
+ weight: 70,
629
+ brand: :yamadanishiki,
630
+ polishing_ratio: 0.55,
631
+ made_in: :hyogo,
632
+ year: 2020,
633
+ soaking_ratio: 0.33,
634
+ steaming_ratio: 0.41,
635
+ cooling_ratio: 0.33,
636
+ tanekojis: [
637
+ Tanekoji.new(
638
+ brand: :byakuya,
639
+ ratio: 0.001,
640
+ ),
641
+ ],
642
+ dekoji_ratio: 0.18,
643
+ interval_days: 0,
644
+ ),
645
+ ],
646
+ kakes: [
647
+ Kake.new(
648
+ weight: 0,
649
+ brand: :yamadanishiki,
650
+ polishing_ratio: 0.55,
651
+ made_in: :hyogo,
652
+ year: 2020,
653
+ soaking_ratio: 0.33,
654
+ steaming_ratio: 0.41,
655
+ cooling_ratio: 0.33,
656
+ interval_days: 6,
657
+ ),
658
+ ],
659
+ waters: [
660
+ Water.new(
661
+ weight: 245,
662
+ ),
663
+ ],
664
+ lactic_acids: [
665
+ LacticAcid.new(
666
+ weight: 1.6,
667
+ ),
668
+ ],
669
+ yeasts: [
670
+ Yeast.new(
671
+ weight: 5,
672
+ ),
673
+ ],
213
674
  ),
214
- Step.create(
215
- name: :soe,
216
- kake: 130,
217
- koji: 0,
218
- water: 0,
219
- koji_interval_days: 0,
220
- kake_interval_days: 1,
675
+ Step.new(
676
+ kojis: [
677
+ Koji.new(
678
+ weight: 0,
679
+ brand: :yamadanishiki,
680
+ polishing_ratio: 0.55,
681
+ made_in: :hyogo,
682
+ year: 2020,
683
+ soaking_ratio: 0.33,
684
+ steaming_ratio: 0.41,
685
+ cooling_ratio: 0.33,
686
+ tanekojis: [
687
+ Tanekoji.new(
688
+ brand: :byakuya,
689
+ ratio: 0.001,
690
+ ),
691
+ ],
692
+ dekoji_ratio: 0.18,
693
+ interval_days: 0,
694
+ ),
695
+ ],
696
+ kakes: [
697
+ Kake.new(
698
+ weight: 130,
699
+ brand: :yamadanishiki,
700
+ polishing_ratio: 0.55,
701
+ made_in: :hyogo,
702
+ year: 2020,
703
+ soaking_ratio: 0.33,
704
+ steaming_ratio: 0.41,
705
+ cooling_ratio: 0.33,
706
+ interval_days: 7,
707
+ ),
708
+ ],
709
+ waters: [
710
+ Water.new(
711
+ weight: 0,
712
+ ),
713
+ ],
221
714
  ),
222
- Step.create(
223
- name: :naka,
224
- kake: 300,
225
- koji: 100,
226
- water: 400,
227
- koji_interval_days: 0,
228
- kake_interval_days: 2,
715
+ Step.new(
716
+ kojis: [
717
+ Koji.new(
718
+ weight: 100,
719
+ brand: :yamadanishiki,
720
+ polishing_ratio: 0.55,
721
+ made_in: :hyogo,
722
+ year: 2020,
723
+ soaking_ratio: 0.33,
724
+ steaming_ratio: 0.41,
725
+ cooling_ratio: 0.33,
726
+ tanekojis: [
727
+ Tanekoji.new(
728
+ brand: :byakuya,
729
+ ratio: 0.001,
730
+ ),
731
+ ],
732
+ dekoji_ratio: 0.18,
733
+ interval_days: 0,
734
+ ),
735
+ ],
736
+ kakes: [
737
+ Kake.new(
738
+ weight: 300,
739
+ brand: :yamadanishiki,
740
+ polishing_ratio: 0.55,
741
+ made_in: :hyogo,
742
+ year: 2020,
743
+ soaking_ratio: 0.33,
744
+ steaming_ratio: 0.41,
745
+ cooling_ratio: 0.33,
746
+ interval_days: 9,
747
+ ),
748
+ ],
749
+ waters: [
750
+ Water.new(
751
+ weight: 400,
752
+ ),
753
+ ],
229
754
  ),
230
- Step.create(
231
- name: :tome,
232
- kake: 490,
233
- koji: 110,
234
- water: 800,
235
- koji_interval_days: 0,
236
- kake_interval_days: 1,
755
+ Step.new(
756
+ kojis: [
757
+ Koji.new(
758
+ weight: 110,
759
+ brand: :yamadanishiki,
760
+ polishing_ratio: 0.55,
761
+ made_in: :hyogo,
762
+ year: 2020,
763
+ soaking_ratio: 0.33,
764
+ steaming_ratio: 0.41,
765
+ cooling_ratio: 0.33,
766
+ tanekojis: [
767
+ Tanekoji.new(
768
+ brand: :byakuya,
769
+ ratio: 0.001,
770
+ ),
771
+ ],
772
+ dekoji_ratio: 0.18,
773
+ interval_days: 0,
774
+ ),
775
+ ],
776
+ kakes: [
777
+ Kake.new(
778
+ weight: 490,
779
+ brand: :yamadanishiki,
780
+ polishing_ratio: 0.55,
781
+ made_in: :hyogo,
782
+ year: 2020,
783
+ soaking_ratio: 0.33,
784
+ steaming_ratio: 0.41,
785
+ cooling_ratio: 0.33,
786
+ interval_days: 10,
787
+ ),
788
+ ],
789
+ waters: [
790
+ Water.new(
791
+ weight: 800,
792
+ ),
793
+ ],
237
794
  ),
238
- Step.create(
239
- name: :yodan,
240
- water: 255
795
+ Step.new(
796
+ waters: [
797
+ Water.new(
798
+ weight: 255,
799
+ ),
800
+ ],
241
801
  ),
242
802
  ].map(&:freeze).freeze
243
803
  ).freeze,
@@ -245,97 +805,157 @@ module Example
245
805
  end
246
806
 
247
807
 
248
- class KojiEvent
249
- include Toji::Event::KojiEvent
808
+ class KojiSchedule
809
+ include Toji::Schedule::KojiSchedule
250
810
 
251
- def initialize(product:, date:, group_index:, indexes:, raw:)
811
+ def initialize(product:, date:, step_indexes:, expect:)
252
812
  @product = product
253
813
  @date = date
254
- @group_index = group_index
255
- @indexes = indexes
256
- @raw = raw
814
+ @step_indexes = step_indexes
815
+ @expect = expect
257
816
  end
258
817
  end
259
818
 
819
+ class KakeSchedule
820
+ include Toji::Schedule::KakeSchedule
260
821
 
261
- class KakeEvent
262
- include Toji::Event::KakeEvent
263
-
264
- def initialize(product:, date:, group_index:, indexes:, raw:)
822
+ def initialize(product:, date:, step_indexes:, expect:)
265
823
  @product = product
266
824
  @date = date
267
- @group_index = group_index
268
- @indexes = indexes
269
- @raw = raw
825
+ @step_indexes = step_indexes
826
+ @expect = expect
270
827
  end
271
828
  end
272
829
 
830
+ class ActionSchedule
831
+ include Toji::Schedule::ActionSchedule
273
832
 
274
- class ActionEvent
275
- include Toji::Event::ActionEvent
276
-
277
- def initialize(product:, date:, type:, index:)
833
+ def initialize(product:, date:, type:, action_index:)
278
834
  @product = product
279
835
  @date = date
280
836
  @type = type
281
- @index = index
837
+ @action_index = action_index
282
838
  end
283
839
  end
284
840
 
285
841
 
286
- class Product
287
- include Toji::Product
288
- include Toji::Product::EventFactory
842
+ module Progress
843
+ module ProgressGenerator
844
+ def load_hash(hash)
845
+ hash = hash.deep_symbolize_keys
289
846
 
290
- attr_accessor :description
291
- attr_accessor :color
847
+ builder
848
+ .add(hash[:states] || [])
849
+ .date_line(hash[:date_line] || 0, Toji::Progress::HOUR)
850
+ .prefix_day_labels(hash[:prefix_day_labels])
851
+ .build
852
+ end
292
853
 
293
- def initialize(id, name, description, recipe, base_date, color=nil)
294
- @id = id
295
- @name = name
296
- @description = description
297
- @recipe = recipe
298
- @base_date = base_date
299
- @color = color
854
+ def load_yaml_file(fname)
855
+ hash = YAML.load_file(fname)
856
+ load_hash(hash)
857
+ end
300
858
  end
301
859
 
302
- def create_koji_event(date:, group_index:, indexes:, raw:)
303
- KojiEvent.new(product: self, date: date, group_index: group_index, indexes: indexes, raw: raw)
860
+ class KojiProgress
861
+ include Toji::Progress::KojiProgress
862
+ extend ProgressGenerator
863
+
864
+ attr_accessor :states
865
+ attr_accessor :date_line
866
+
867
+ def self.builder
868
+ Toji::Progress::Builder.new(KojiProgress, KojiState)
869
+ end
304
870
  end
305
871
 
306
- def create_kake_event(date:, group_index:, indexes:, raw:)
307
- KakeEvent.new(product: self, date: date, group_index: group_index, indexes: indexes, raw: raw)
872
+ class KojiState
873
+ include Toji::Progress::KojiState
874
+
875
+ def self.create(args)
876
+ new.tap {|s|
877
+ s.progress = args[:progress]
878
+ s.time = args[:time].to_time
879
+ s.mark = args[:mark]
880
+ s.temps = [args[:temps]].flatten.compact
881
+ s.preset_temp = args[:preset_temp]
882
+ s.room_temp = args[:room_temp]
883
+ s.room_psychrometry = args[:room_psychrometry]
884
+ s.note = args[:note]
885
+ }
886
+ end
308
887
  end
309
888
 
310
- def create_action_event(date:, type:, index:)
311
- ActionEvent.new(product: self, date: date, type: type, index: index)
889
+ class MotoProgress
890
+ include Toji::Progress::MotoProgress
891
+ extend ProgressGenerator
892
+
893
+ attr_accessor :states
894
+ attr_accessor :date_line
895
+
896
+ def self.builder
897
+ Toji::Progress::Builder.new(MotoProgress, MotoState)
898
+ end
312
899
  end
313
900
 
314
- def self.create(args)
315
- if self===args
316
- args
317
- elsif Hash===args
318
- recipe = args.fetch(:recipe)
319
- if Symbol===recipe
320
- recipe = Recipe::TEMPLATES.fetch(recipe)
321
- end
322
- if args[:scale]
323
- recipe = recipe.scale(args[:scale])
324
- end
325
- if args[:round]
326
- recipe = recipe.round(args[:round])
327
- end
901
+ class MotoState
902
+ include Toji::Progress::MotoState
903
+
904
+ def self.create(args)
905
+ new.tap {|s|
906
+ s.progress = args[:progress]
907
+ s.time = args[:time].to_time
908
+ s.mark = args[:mark]
909
+ s.temps = [args[:temps]].flatten.compact
910
+ s.preset_temp = args[:preset_temp]
911
+ s.room_temp = args[:room_temp]
912
+ s.room_psychrometry = args[:room_psychrometry]
913
+ s.baume = args[:baume]
914
+ s.acid = args[:acid]
915
+ s.warmings = [args[:warmings]].flatten.compact
916
+ s.note = args[:note]
917
+ }
918
+ end
919
+ end
328
920
 
329
- new(
330
- args[:id],
331
- args[:name],
332
- args[:description],
333
- recipe,
334
- args[:base_date],
335
- args[:color]
336
- )
337
- else
338
- raise "not supported class: #{args.class}"
921
+
922
+ class MoromiProgress
923
+ include Toji::Progress::MoromiProgress
924
+ extend ProgressGenerator
925
+
926
+ attr_accessor :states
927
+ attr_accessor :date_line
928
+ attr_accessor :prefix_day_labels
929
+
930
+ def self.builder
931
+ Toji::Progress::Builder.new(MoromiProgress, MoromiState)
932
+ end
933
+ end
934
+
935
+ class MoromiState
936
+ include Toji::Progress::MoromiState
937
+ include Toji::Progress::State::BaumeToNihonshudo
938
+
939
+ def self.create(args)
940
+ new.tap {|s|
941
+ s.progress = args[:progress]
942
+ s.time = args[:time].to_time
943
+ s.mark = args[:mark]
944
+ s.temps = [args[:temps]].flatten.compact
945
+ s.preset_temp = args[:preset_temp]
946
+ s.room_temp = args[:room_temp]
947
+ s.room_psychrometry = args[:room_psychrometry]
948
+ if args[:baume]
949
+ s.baume = args[:baume]
950
+ else
951
+ s.nihonshudo = args[:nihonshudo]
952
+ end
953
+ s.acid = args[:acid]
954
+ s.amino_acid = args[:amino_acid]
955
+ s.alcohol = args[:alcohol]
956
+ s.warmings = [args[:warmings]].flatten.compact
957
+ s.note = args[:note]
958
+ }
339
959
  end
340
960
  end
341
961
  end