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