toji 2.8.0 → 2.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) 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 +36 -36
  5. data/example/example_core.rb +877 -205
  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 -1
  20. data/lib/toji/calendar.rb +18 -18
  21. data/lib/toji/calendar/date_column.rb +7 -22
  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 -83
  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 +54 -39
  68. data/lib/toji/recipe/ab_expect.rb +2 -2
  69. data/lib/toji/recipe/action.rb +8 -0
  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/schedule/base.rb +9 -0
  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 -40
  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/ingredient/kake/actual.rb +0 -26
  89. data/lib/toji/ingredient/kake/base.rb +0 -18
  90. data/lib/toji/ingredient/kake/expected.rb +0 -40
  91. data/lib/toji/ingredient/koji/actual.rb +0 -29
  92. data/lib/toji/ingredient/koji/actual_fermentable.rb +0 -15
  93. data/lib/toji/ingredient/koji/base.rb +0 -35
  94. data/lib/toji/ingredient/koji/expected.rb +0 -45
  95. data/lib/toji/ingredient/koji/expected_fermentable.rb +0 -15
  96. data/lib/toji/ingredient/koji_rate.rb +0 -16
  97. data/lib/toji/ingredient/rice/actual_steamable.rb +0 -27
  98. data/lib/toji/ingredient/rice/base.rb +0 -40
  99. data/lib/toji/ingredient/rice/expected_steamable.rb +0 -27
  100. data/lib/toji/ingredient/rice_rate.rb +0 -23
  101. data/lib/toji/product/event.rb +0 -13
  102. data/lib/toji/product/rice_event.rb +0 -28
  103. data/lib/toji/product/rice_event_group.rb +0 -19
@@ -1,87 +1,222 @@
1
+ $LOAD_PATH << File.dirname(__FILE__) + "/../lib"
2
+ require 'toji'
1
3
  require 'securerandom'
2
4
 
3
5
  module Example
4
6
 
5
- module Brew
6
- class State
7
- include Toji::Brew::State
8
- include Toji::Brew::State::BaumeToNihonshudo
7
+ class Product
8
+ include Toji::Product
9
+ include Toji::Product::ScheduleFactory
9
10
 
10
- def self.create(val)
11
- s = new
12
- KEYS.each {|k|
13
- if val.has_key?(k)
14
- s.send("#{k}=", val[k])
15
- end
16
- }
17
- s
18
- 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
19
21
  end
20
22
 
21
- module BrewGenerator
22
- def builder
23
- Toji::Brew::Builder.new(self)
24
- end
23
+ def create_koji_schedule(date:, step_indexes:, kojis:)
24
+ expect = kojis.first.dup
25
+ expect.weight = kojis.map(&:weight).sum
25
26
 
26
- def load_hash(hash)
27
- 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
28
34
 
29
- builder
30
- .add((hash[:states] || []).map{|s| State.create(s)})
31
- .date_line(hash[:date_line] || 0, Toji::Brew::HOUR)
32
- .prefix_day_labels(hash[:prefix_day_labels])
33
- .time_interpolation(nil)
34
- .elapsed_time_interpolation
35
- .build
36
- end
35
+ def create_kake_schedule(date:, step_indexes:, kakes:)
36
+ expect = kakes.first.dup
37
+ expect.weight = kakes.map(&:weight).sum
37
38
 
38
- def load_yaml_file(fname)
39
- hash = YAML.load_file(fname)
40
- load_hash(hash)
41
- end
39
+ KakeSchedule.new(
40
+ product: self,
41
+ date: date,
42
+ step_indexes: step_indexes,
43
+ expect: expect,
44
+ )
42
45
  end
43
46
 
44
- class Base
45
- include Toji::Brew::Base
46
- 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
47
55
 
48
- def initialize
49
- @states = []
50
- @day_offset = 0
51
- @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}"
52
81
  end
53
82
  end
83
+ end
54
84
 
55
- class Koji < Base
56
- include Toji::Brew::Koji
57
- end
58
85
 
59
- class Moto < Base
60
- 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
61
96
  end
62
97
 
63
- class Moromi < Base
64
- 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
65
105
  end
66
106
  end
67
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
68
127
 
69
- class Step
70
- include Toji::Recipe::Step
71
- attr_accessor :name
72
-
73
- 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)
74
- new.tap {|o|
75
- o.name = name
76
- o.kake = kake.to_f
77
- o.koji = koji.to_f
78
- o.water = water.to_f
79
- o.lactic_acid = lactic_acid.to_f
80
- o.alcohol = alcohol.to_f
81
- o.yeast = yeast.to_f
82
- o.koji_interval_days = koji_interval_days.to_i
83
- 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
84
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
85
220
  end
86
221
  end
87
222
 
@@ -89,14 +224,12 @@ module Example
89
224
  class Recipe
90
225
  include Toji::Recipe
91
226
 
92
- def initialize
93
- @steps = []
227
+ def initialize(steps)
228
+ @steps = steps
94
229
  end
95
230
 
96
- def self.create(steps)
97
- new.tap {|o|
98
- o.steps = steps
99
- }
231
+ def initialize_copy(obj)
232
+ @steps = obj.steps.deep_dup
100
233
  end
101
234
 
102
235
  # 乳酸は汲水100L当たり比重1.21の乳酸(90%乳酸と称される)を650〜720ml添加する。
@@ -108,135 +241,563 @@ module Example
108
241
  TEMPLATES = {
109
242
  # 酒造教本による標準型仕込配合
110
243
  # 出典: 酒造教本 P97
111
- sokujo_textbook: create(
244
+ sokujo_textbook: new(
112
245
  [
113
- Step.create(
114
- name: :moto,
115
- kake: 45,
116
- koji: 20,
117
- water: 70,
118
- lactic_acid: 70/100.0*0.685,
119
- yeast: (45+20)/100.0*1.5,
120
- koji_interval_days: 0,
121
- 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
+ ]
122
295
  ),
123
- Step.create(
124
- name: :soe,
125
- kake: 100,
126
- koji: 40,
127
- water: 130,
128
- koji_interval_days: 14,
129
- 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
+ ],
130
335
  ),
131
- Step.create(
132
- name: :naka,
133
- kake: 215,
134
- koji: 60,
135
- water: 330,
136
- koji_interval_days: 0,
137
- 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
+ ],
138
375
  ),
139
- Step.create(
140
- name: :tome,
141
- kake: 360,
142
- koji: 80,
143
- water: 630,
144
- koji_interval_days: 0,
145
- 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
+ ],
146
415
  ),
147
- Step.create(
148
- name: :yodan,
149
- kake: 80,
150
- water: 120,
151
- 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
+ ],
152
435
  ),
153
436
  ].map(&:freeze).freeze
154
437
  ).freeze,
155
438
  # 灘における仕込配合の平均値
156
439
  # 出典: http://www.nada-ken.com/main/jp/index_shi/234.html
157
- sokujo_nada: create(
440
+ sokujo_nada: new(
158
441
  [
159
- Step.create(
160
- name: :moto,
161
- kake: 93,
162
- koji: 47,
163
- water: 170,
164
- lactic_acid: 170/100.0*0.685,
165
- yeast: (93+47)/100.0*1.5,
166
- koji_interval_days: 0,
167
- 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
+ ],
168
491
  ),
169
- Step.create(
170
- name: :soe,
171
- kake: 217,
172
- koji: 99,
173
- water: 270,
174
- koji_interval_days: 14,
175
- 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
+ ],
176
531
  ),
177
- Step.create(
178
- name: :naka,
179
- kake: 423,
180
- koji: 143,
181
- water: 670,
182
- koji_interval_days: 0,
183
- 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
+ ],
184
571
  ),
185
- Step.create(
186
- name: :tome,
187
- kake: 813,
188
- koji: 165,
189
- water: 1330,
190
- koji_interval_days: 0,
191
- 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
+ ],
192
611
  ),
193
- Step.create(
194
- name: :alcohol,
195
- alcohol: 900
612
+ Step.new(
613
+ alcohols: [
614
+ Alcohol.new(
615
+ weight: 900,
616
+ ),
617
+ ],
196
618
  ),
197
619
  ].map(&:freeze).freeze
198
620
  ).freeze,
199
621
  # 簡易酒母省略仕込
200
622
  # 出典: https://www.jstage.jst.go.jp/article/jbrewsocjapan1915/60/11/60_11_999/_article/-char/ja/
201
- simple_sokujo_himeno: create(
623
+ simple_sokujo_himeno: new(
202
624
  [
203
- Step.create(
204
- name: :moto,
205
- kake: 0,
206
- koji: 70,
207
- water: 245,
208
- lactic_acid: 1.6,
209
- yeast: 5,
210
- koji_interval_days: 0,
211
- 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
+ ],
212
674
  ),
213
- Step.create(
214
- name: :soe,
215
- kake: 130,
216
- koji: 0,
217
- water: 0,
218
- koji_interval_days: 0,
219
- 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
+ ],
220
714
  ),
221
- Step.create(
222
- name: :naka,
223
- kake: 300,
224
- koji: 100,
225
- water: 400,
226
- koji_interval_days: 0,
227
- 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
+ ],
228
754
  ),
229
- Step.create(
230
- name: :tome,
231
- kake: 490,
232
- koji: 110,
233
- water: 800,
234
- koji_interval_days: 0,
235
- 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
+ ],
236
794
  ),
237
- Step.create(
238
- name: :yodan,
239
- water: 255
795
+ Step.new(
796
+ waters: [
797
+ Water.new(
798
+ weight: 255,
799
+ ),
800
+ ],
240
801
  ),
241
802
  ].map(&:freeze).freeze
242
803
  ).freeze,
@@ -244,46 +805,157 @@ module Example
244
805
  end
245
806
 
246
807
 
247
- class Product
248
- include Toji::Product
808
+ class KojiSchedule
809
+ include Toji::Schedule::KojiSchedule
249
810
 
250
- attr_accessor :description
251
- attr_accessor :color
811
+ def initialize(product:, date:, step_indexes:, expect:)
812
+ @product = product
813
+ @date = date
814
+ @step_indexes = step_indexes
815
+ @expect = expect
816
+ end
817
+ end
252
818
 
253
- def initialize(reduce_key, name, description, recipe, base_date, color=nil)
254
- @reduce_key = reduce_key || SecureRandom.uuid
255
- @name = name
256
- @description = description
257
- @recipe = recipe
258
- @base_date = base_date
259
- @color = color
819
+ class KakeSchedule
820
+ include Toji::Schedule::KakeSchedule
821
+
822
+ def initialize(product:, date:, step_indexes:, expect:)
823
+ @product = product
824
+ @date = date
825
+ @step_indexes = step_indexes
826
+ @expect = expect
260
827
  end
828
+ end
261
829
 
262
- def self.create(args)
263
- if self===args
264
- args
265
- elsif Hash===args
266
- recipe = args.fetch(:recipe)
267
- if Symbol===recipe
268
- recipe = Recipe::TEMPLATES.fetch(recipe)
269
- end
270
- if args[:scale]
271
- recipe = recipe.scale(args[:scale])
272
- end
273
- if args[:round]
274
- recipe = recipe.round(args[:round])
275
- end
830
+ class ActionSchedule
831
+ include Toji::Schedule::ActionSchedule
276
832
 
277
- new(
278
- args[:id],
279
- args[:name],
280
- args[:description],
281
- recipe,
282
- args[:base_date],
283
- args[:color]
284
- )
285
- else
286
- raise "not supported class: #{args.class}"
833
+ def initialize(product:, date:, type:, action_index:)
834
+ @product = product
835
+ @date = date
836
+ @type = type
837
+ @action_index = action_index
838
+ end
839
+ end
840
+
841
+
842
+ module Progress
843
+ module ProgressGenerator
844
+ def load_hash(hash)
845
+ hash = hash.deep_symbolize_keys
846
+
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
853
+
854
+ def load_yaml_file(fname)
855
+ hash = YAML.load_file(fname)
856
+ load_hash(hash)
857
+ end
858
+ end
859
+
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
870
+ end
871
+
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
887
+ end
888
+
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
899
+ end
900
+
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
920
+
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
+ }
287
959
  end
288
960
  end
289
961
  end