toji 1.1.0 → 1.2.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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/example/koji_making.ipynb +7 -7
  3. data/example/koji_making.rb +5 -5
  4. data/example/koji_recipe.rb +1 -1
  5. data/example/moromi.ipynb +55 -21
  6. data/example/moromi.rb +5 -5
  7. data/example/rice_recipe.rb +2 -2
  8. data/example/shubo.ipynb +6 -6
  9. data/example/shubo.rb +5 -5
  10. data/example/three_step_mashing_recipe.rb +2 -2
  11. data/lib/toji/brew/base.rb +88 -0
  12. data/lib/toji/brew/builder.rb +27 -0
  13. data/lib/toji/brew/graph/ab.rb +85 -0
  14. data/lib/toji/brew/graph/bmd.rb +58 -0
  15. data/lib/toji/brew/graph/progress.rb +142 -0
  16. data/lib/toji/brew/graph.rb +10 -0
  17. data/lib/toji/{product/koji_making.rb → brew/koji.rb} +35 -43
  18. data/lib/toji/{product → brew}/moromi.rb +105 -96
  19. data/lib/toji/brew/shubo.rb +122 -0
  20. data/lib/toji/brew/state.rb +117 -0
  21. data/lib/toji/{product/job_accessor.rb → brew/state_accessor.rb} +4 -4
  22. data/lib/toji/brew/state_record.rb +82 -0
  23. data/lib/toji/brew.rb +21 -0
  24. data/lib/toji/recipe/ingredient/koji/actual.rb +23 -0
  25. data/lib/toji/recipe/ingredient/koji/actual_fermentable.rb +17 -0
  26. data/lib/toji/recipe/ingredient/koji/base.rb +28 -0
  27. data/lib/toji/recipe/ingredient/koji/expected.rb +53 -0
  28. data/lib/toji/recipe/ingredient/koji/expected_fermentable.rb +17 -0
  29. data/lib/toji/recipe/ingredient/koji.rb +21 -0
  30. data/lib/toji/recipe/ingredient/lactic_acid.rb +21 -0
  31. data/lib/toji/recipe/ingredient/rice/actual.rb +20 -0
  32. data/lib/toji/recipe/ingredient/rice/actual_steamable.rb +29 -0
  33. data/lib/toji/recipe/ingredient/rice/base.rb +42 -0
  34. data/lib/toji/recipe/ingredient/rice/expected.rb +48 -0
  35. data/lib/toji/recipe/ingredient/rice/expected_steamable.rb +31 -0
  36. data/lib/toji/recipe/ingredient/rice.rb +21 -0
  37. data/lib/toji/recipe/ingredient/yeast.rb +21 -0
  38. data/lib/toji/recipe/ingredient.rb +11 -0
  39. data/lib/toji/recipe/lactic_acid_rate.rb +17 -0
  40. data/lib/toji/recipe/three_step_mashing.rb +4 -2
  41. data/lib/toji/recipe/yeast_rate.rb +41 -0
  42. data/lib/toji/recipe.rb +3 -0
  43. data/lib/toji/version.rb +1 -1
  44. data/lib/toji.rb +1 -3
  45. metadata +32 -29
  46. data/lib/toji/graph/ab.rb +0 -79
  47. data/lib/toji/graph/bmd.rb +0 -56
  48. data/lib/toji/graph/progress.rb +0 -87
  49. data/lib/toji/graph.rb +0 -8
  50. data/lib/toji/ingredient/koji/actual.rb +0 -21
  51. data/lib/toji/ingredient/koji/actual_fermentable.rb +0 -15
  52. data/lib/toji/ingredient/koji/base.rb +0 -26
  53. data/lib/toji/ingredient/koji/expected.rb +0 -51
  54. data/lib/toji/ingredient/koji/expected_fermentable.rb +0 -15
  55. data/lib/toji/ingredient/koji.rb +0 -19
  56. data/lib/toji/ingredient/rice/actual.rb +0 -18
  57. data/lib/toji/ingredient/rice/actual_steamable.rb +0 -27
  58. data/lib/toji/ingredient/rice/base.rb +0 -40
  59. data/lib/toji/ingredient/rice/expected.rb +0 -46
  60. data/lib/toji/ingredient/rice/expected_steamable.rb +0 -29
  61. data/lib/toji/ingredient/rice.rb +0 -19
  62. data/lib/toji/ingredient/yeast/base.rb +0 -21
  63. data/lib/toji/ingredient/yeast/red_star.rb +0 -30
  64. data/lib/toji/ingredient/yeast.rb +0 -9
  65. data/lib/toji/ingredient.rb +0 -8
  66. data/lib/toji/product/base.rb +0 -74
  67. data/lib/toji/product/job.rb +0 -176
  68. data/lib/toji/product/shubo.rb +0 -130
  69. data/lib/toji/product.rb +0 -11
@@ -1,221 +1,230 @@
1
1
  module Toji
2
- module Product
2
+ module Brew
3
3
  class Moromi < Base
4
4
 
5
5
  TEMPLATES = {
6
6
  default: [
7
- Job.new(
7
+ {
8
8
  time: Time.mktime(2019, 1, 16),
9
- id: :soe,
9
+ mark: :soe,
10
10
  room_temp: 9,
11
11
  temps: [14.8, 11.0],
12
- ),
13
- Job.new(
12
+ },
13
+ {
14
14
  time: Time.mktime(2019, 1, 17),
15
15
  room_temp: 9,
16
16
  temps: 14.3,
17
- ),
18
- Job.new(
17
+ },
18
+ {
19
19
  time: Time.mktime(2019, 1, 18),
20
20
  room_temp: 8.5,
21
21
  temps: 11.3,
22
- ),
23
- Job.new(
22
+ },
23
+ {
24
24
  time: Time.mktime(2019, 1, 19),
25
- id: :naka,
25
+ mark: :naka,
26
26
  room_temp: 9,
27
27
  temps: [6.9, 10.6],
28
- ),
29
- Job.new(
28
+ },
29
+ {
30
30
  time: Time.mktime(2019, 1, 20),
31
- id: :tome,
31
+ mark: :tome,
32
32
  room_temp: 6,
33
33
  temps: [7.5, 8.0],
34
- ),
35
- Job.new(
34
+ },
35
+ {
36
36
  time: Time.mktime(2019, 1, 21),
37
37
  room_temp: 7,
38
38
  temps: 9.1,
39
- ),
40
- Job.new(
39
+ },
40
+ {
41
41
  time: Time.mktime(2019, 1, 22),
42
42
  room_temp: 7,
43
43
  temps: 10.4,
44
- ),
45
- Job.new(
44
+ },
45
+ {
46
46
  time: Time.mktime(2019, 1, 23),
47
47
  room_temp: 8,
48
48
  temps: 11.9,
49
49
  baume: 8.6,
50
- ),
51
- Job.new(
50
+ },
51
+ {
52
52
  time: Time.mktime(2019, 1, 24),
53
53
  room_temp: 8,
54
54
  temps: 12.3,
55
55
  baume: 8.0,
56
56
  alcohol: 4.8,
57
- ),
58
- Job.new(
57
+ },
58
+ {
59
59
  time: Time.mktime(2019, 1, 25),
60
60
  room_temp: 7.5,
61
61
  temps: 13.1,
62
62
  baume: 7.2,
63
63
  alcohol: 6.75,
64
- ),
65
- Job.new(
64
+ },
65
+ {
66
66
  time: Time.mktime(2019, 1, 26),
67
67
  room_temp: 7.5,
68
68
  temps: 13.1,
69
69
  baume: 5.8,
70
70
  alcohol: 7.992,
71
- ),
72
- Job.new(
71
+ },
72
+ {
73
73
  time: Time.mktime(2019, 1, 27),
74
74
  room_temp: 7.5,
75
75
  temps: 12.9,
76
76
  baume: 4.8,
77
- ),
78
- Job.new(
77
+ },
78
+ {
79
79
  time: Time.mktime(2019, 1, 28),
80
80
  room_temp: 7.0,
81
81
  temps: 12.8,
82
82
  baume: 4.0,
83
83
  alcohol: 10.7,
84
- ),
85
- Job.new(
84
+ },
85
+ {
86
86
  time: Time.mktime(2019, 1, 29),
87
87
  room_temp: 8.0,
88
88
  temps: 12.9,
89
89
  baume: 3.4,
90
90
  alcohol: 11.6,
91
- ),
92
- Job.new(
91
+ },
92
+ {
93
93
  time: Time.mktime(2019, 1, 30),
94
94
  room_temp: 8.0,
95
95
  temps: 12.6,
96
96
  nihonshudo: -27,
97
97
  alcohol: 12.7,
98
- ),
99
- Job.new(
98
+ },
99
+ {
100
100
  time: Time.mktime(2019, 1, 31),
101
101
  room_temp: 7.0,
102
102
  temps: 12.0,
103
103
  nihonshudo: -21,
104
104
  alcohol: 13.7,
105
- ),
106
- Job.new(
105
+ },
106
+ {
107
107
  time: Time.mktime(2019, 2, 1),
108
108
  room_temp: 7.0,
109
109
  temps: 11.2,
110
110
  nihonshudo: -17,
111
- ),
112
- Job.new(
111
+ },
112
+ {
113
113
  time: Time.mktime(2019, 2, 2),
114
114
  room_temp: 6.5,
115
115
  temps: 10.2,
116
116
  nihonshudo: -13,
117
- ),
118
- Job.new(
117
+ },
118
+ {
119
119
  time: Time.mktime(2019, 2, 3),
120
120
  room_temp: 7.0,
121
121
  temps: 9.7,
122
- ),
123
- Job.new(
122
+ },
123
+ {
124
124
  time: Time.mktime(2019, 2, 4),
125
125
  room_temp: 8.0,
126
126
  temps: 9.8,
127
127
  nihonshudo: -8,
128
128
  alcohol: 16.0,
129
- ),
130
- Job.new(
129
+ },
130
+ {
131
131
  time: Time.mktime(2019, 2, 5),
132
132
  room_temp: 6.0,
133
133
  temps: 9.1,
134
134
  nihonshudo: -5,
135
- ),
136
- Job.new(
135
+ },
136
+ {
137
137
  time: Time.mktime(2019, 2, 6),
138
138
  room_temp: 5.0,
139
139
  temps: 8.4,
140
140
  nihonshudo: -3,
141
141
  alcohol: 16.3,
142
- ),
143
- Job.new(
142
+ },
143
+ {
144
144
  time: Time.mktime(2019, 2, 7),
145
145
  room_temp: 5.0,
146
146
  temps: 8.1,
147
147
  nihonshudo: -2,
148
- ),
149
- Job.new(
148
+ },
149
+ {
150
150
  time: Time.mktime(2019, 2, 8),
151
151
  room_temp: 7.0,
152
152
  temps: 8.3,
153
153
  nihonshudo: 0,
154
- ),
155
- Job.new(
154
+ },
155
+ {
156
156
  time: Time.mktime(2019, 2, 9),
157
157
  room_temp: 6.0,
158
158
  temps: 8.1,
159
- ),
159
+ },
160
160
  ],
161
161
  }
162
162
 
163
+ DAY_LABELS = {
164
+ default: [:soe, :odori, :naka, :tome].freeze,
165
+ moto1: [:moto, :soe, :odori, :naka, :tome].freeze,
166
+ odori2: [:soe, :odori, :odori, :naka, :tome].freeze,
167
+ }.freeze
163
168
 
164
- job_reader :moto
165
- job_reader :soe
166
- job_reader :naka
167
- job_reader :tome
169
+ state_reader :moto
170
+ state_reader :soe
171
+ state_reader :naka
172
+ state_reader :tome
173
+ state_reader :yodan
168
174
 
169
- def initialize(jobs=[], date_line: 0, day_labels: nil)
170
- super(jobs, date_line: date_line)
175
+ attr_writer :prefix_day_labels
171
176
 
172
- if day_labels
173
- @day_labels = [day_labels].flatten
174
- end
175
- end
176
-
177
- def moromi_days
178
- if @day_labels
179
- days - @day_labels.length
180
- else
181
- tome = self[:tome]
182
- if tome
183
- tome_day = (tome.elapsed_time.to_f / Job::DAY).floor + 1
184
- days - tome_day
185
- end
186
- end
187
- end
188
-
189
- def day_labels
190
- if @day_labels
191
- @day_labels + moromi_days.times.map{|i| i+2}
177
+ def prefix_day_labels
178
+ if @prefix_day_labels
179
+ @prefix_day_labels
180
+ elsif !self[:soe] && !self[:tome]
181
+ nil
192
182
  else
193
- texts = Array.new(days)
194
- [:soe, :naka, :tome].each {|id|
195
- j = select{|j| j.id==id}.first
196
- if j
197
- i = ((j.elapsed_time + day_offset) / Job::DAY.to_f).floor
198
- texts[i] = id
183
+ labels = []
184
+ [:soe, :naka, :tome].each {|mark|
185
+ s = self[mark]
186
+ if s
187
+ i = s.day - 1
188
+ labels[i] = mark
199
189
  end
200
190
  }
201
191
 
202
- soe_i = texts.index(:soe)
203
- tome_i = texts.index(:tome)
204
- moromi_day = 1
205
- texts.map.with_index {|text,i|
206
- if text
207
- text
192
+ soe_i = labels.index(:soe)
193
+ labels.map.with_index {|label,i|
194
+ if label
195
+ label
208
196
  elsif !soe_i || i<soe_i
209
197
  :moto
210
- elsif !tome_i || i<tome_i
211
- :odori
212
198
  else
213
- moromi_day += 1
199
+ :odori
214
200
  end
215
201
  }
216
202
  end
217
203
  end
218
204
 
205
+ def moromi_tome_day
206
+ prefix_day_labels&.length
207
+ end
208
+
209
+ def moromi_days
210
+ _tome_day = moromi_tome_day
211
+ _days = self.days
212
+
213
+ if _tome_day && _tome_day<_days
214
+ _days - _tome_day + 1
215
+ end
216
+ end
217
+
218
+ def day_labels
219
+ _prefix = prefix_day_labels
220
+
221
+ if _prefix
222
+ _prefix + moromi_days.times.map{|i| i+2}
223
+ else
224
+ self.days.times.map{|i| i+1}
225
+ end
226
+ end
227
+
219
228
  def progress(enable_annotations: true)
220
229
  Graph::Progress.new(self, enable_annotations: enable_annotations)
221
230
  end
@@ -229,7 +238,7 @@ module Toji
229
238
  end
230
239
 
231
240
  def self.template(key=:default)
232
- new(TEMPLATES[key])
241
+ create(TEMPLATES[key])
233
242
  end
234
243
  end
235
244
  end
@@ -0,0 +1,122 @@
1
+ module Toji
2
+ module Brew
3
+ class Shubo < Base
4
+
5
+ TEMPLATES = {
6
+ default: [
7
+ {
8
+ elapsed_time: 0 * Brew::DAY,
9
+ mark: :mizukoji,
10
+ temps: 12.0,
11
+ acid: 13.0,
12
+ },
13
+ {
14
+ elapsed_time: 0 * Brew::DAY + 1 * Brew::HOUR,
15
+ mark: :shikomi,
16
+ temps: 20.0,
17
+ acid: 13.0,
18
+ },
19
+ {
20
+ elapsed_time: 1 * Brew::DAY,
21
+ mark: :utase,
22
+ temps: 14.0,
23
+ baume: 15.0,
24
+ acid: 13.0,
25
+ },
26
+ {
27
+ elapsed_time: 2 * Brew::DAY,
28
+ temps: [8.0, 11.0],
29
+ baume: 16.0,
30
+ acid: 13.0,
31
+ warming: WARM_DAKI,
32
+ },
33
+ {
34
+ elapsed_time: 3 * Brew::DAY,
35
+ temps: [10.0, 13.0],
36
+ baume: 16.5,
37
+ acid: 13.5,
38
+ warming: WARM_DAKI,
39
+ },
40
+ {
41
+ elapsed_time: 4 * Brew::DAY,
42
+ temps: [12.0, 15.0],
43
+ baume: 17.0,
44
+ acid: 13.5,
45
+ warming: WARM_DAKI,
46
+ },
47
+ {
48
+ elapsed_time: 5 * Brew::DAY,
49
+ temps: 14.0,
50
+ baume: 17.0,
51
+ acid: 14.0,
52
+ warming: WARM_ANKA,
53
+ },
54
+ {
55
+ elapsed_time: 6 * Brew::DAY,
56
+ temps: 20.0,
57
+ baume: 17.0,
58
+ acid: 14.5,
59
+ warming: WARM_ANKA,
60
+ },
61
+ {
62
+ elapsed_time: 7 * Brew::DAY,
63
+ temps: 20.0,
64
+ baume: 14.0,
65
+ acid: 15.5,
66
+ },
67
+ {
68
+ elapsed_time: 8 * Brew::DAY,
69
+ temps: 20.0,
70
+ baume: 12.0,
71
+ acid: 16.0,
72
+ },
73
+ {
74
+ elapsed_time: 9 * Brew::DAY,
75
+ mark: :wake,
76
+ temps: 20.0,
77
+ baume: 9.0,
78
+ acid: 16.0,
79
+ },
80
+ {
81
+ elapsed_time: 10 * Brew::DAY,
82
+ temps: 15.0,
83
+ baume: 8.0,
84
+ acid: 16.5,
85
+ },
86
+ {
87
+ elapsed_time: 11 * Brew::DAY,
88
+ temps: 12.0,
89
+ baume: 7.0,
90
+ acid: 17.0,
91
+ },
92
+ {
93
+ elapsed_time: 12 * Brew::DAY,
94
+ temps: 10.0,
95
+ baume: 6.0,
96
+ acid: 17.5,
97
+ },
98
+ {
99
+ elapsed_time: 13 * Brew::DAY,
100
+ temps: 9.0,
101
+ baume: 5.0,
102
+ acid: 17.5,
103
+ },
104
+ ],
105
+ }
106
+
107
+
108
+ state_reader :mizukoji
109
+ state_reader :shikomi
110
+ state_reader :utase
111
+ state_reader :wake
112
+
113
+ def progress(enable_annotations: true)
114
+ Graph::Progress.new(self, enable_annotations: enable_annotations)
115
+ end
116
+
117
+ def self.template(key=:default)
118
+ create(TEMPLATES[key])
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,117 @@
1
+ require 'forwardable'
2
+
3
+ module Toji
4
+ module Brew
5
+ class State
6
+ extend Forwardable
7
+
8
+ attr_accessor :elapsed_time
9
+ attr_accessor :time
10
+ attr_accessor :day_label
11
+ attr_reader :record
12
+ attr_reader :brew
13
+
14
+ def_delegators :@record, :mark
15
+ def_delegators :@record, :temps
16
+ def_delegators :@record, :preset_temp
17
+ def_delegators :@record, :room_temp
18
+ def_delegators :@record, :room_psychrometry
19
+ def_delegators :@record, :acid
20
+ def_delegators :@record, :amino_acid
21
+ def_delegators :@record, :alcohol
22
+ def_delegators :@record, :warming
23
+ def_delegators :@record, :warmings
24
+ def_delegators :@record, :note
25
+
26
+ def_delegators :@record, :has_keys
27
+
28
+ def initialize(elapsed_time, record, brew)
29
+ @elapsed_time = elapsed_time
30
+ @record = record
31
+ @brew = brew
32
+ end
33
+
34
+ def has_keys
35
+ result = [:elapsed_time, :time, :day, :day_label, :display_time]
36
+ keys = [:moromi_day, :display_baume, :bmd] + StateRecord::KEYS
37
+
38
+ result += keys.select {|k|
39
+ !!send(k)
40
+ }
41
+ end
42
+
43
+ def day
44
+ ((elapsed_time_with_offset.to_f + 1) / DAY).ceil
45
+ end
46
+
47
+ def day_label
48
+ @brew.day_labels[day - 1]
49
+ end
50
+
51
+ def elapsed_time_with_offset
52
+ @elapsed_time + @brew.day_offset
53
+ end
54
+
55
+ def baume
56
+ if @record.baume
57
+ @record.baume
58
+ elsif @record.nihonshudo
59
+ @record.nihonshudo * -0.1
60
+ end
61
+ end
62
+
63
+ def nihonshudo
64
+ if @record.nihonshudo
65
+ @record.nihonshudo
66
+ elsif @record.baume
67
+ @record.baume * -10
68
+ end
69
+ end
70
+
71
+ def display_baume
72
+ if @record.baume || @record.nihonshudo
73
+ b = baume
74
+ if b<3.0
75
+ nihonshudo
76
+ else
77
+ b
78
+ end
79
+ end
80
+ end
81
+
82
+ def display_time(format="%m/%d %H:%M")
83
+ if @time
84
+ @time.strftime(format)
85
+ else
86
+ Time.at(@elapsed_time).strftime(format)
87
+ end
88
+ end
89
+
90
+ def moromi_day
91
+ _tome_day = @brew.moromi_tome_day
92
+ _now_day = day
93
+
94
+ if _tome_day && _tome_day < _now_day
95
+ _now_day - _tome_day + 1
96
+ end
97
+ end
98
+
99
+ def bmd
100
+ _moromi_day = moromi_day
101
+ _baume = baume
102
+
103
+ if _moromi_day && _baume
104
+ _moromi_day * _baume
105
+ end
106
+ end
107
+
108
+ def expected_alcohol(target_alc, target_nihonshudo, coef)
109
+ _baume = baume
110
+
111
+ if _baume
112
+ target_alc - (_baume - target_nihonshudo * -0.1) * coef
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -1,10 +1,10 @@
1
1
  module Toji
2
- module Product
3
- module JobAccessor
4
- def job_reader(*args)
2
+ module Brew
3
+ module StateAccessor
4
+ def state_reader(*args)
5
5
  args.each {|arg|
6
6
  define_method(arg) {
7
- self[arg]
7
+ @data[arg]
8
8
  }
9
9
  }
10
10
  end
@@ -0,0 +1,82 @@
1
+ module Toji
2
+ module Brew
3
+ class StateRecord
4
+ KEYS = [
5
+ :time,
6
+ :elapsed_time,
7
+ :mark,
8
+ :temps,
9
+ :preset_temp,
10
+ :room_temp,
11
+ :room_psychrometry,
12
+ :baume,
13
+ :nihonshudo,
14
+ :acid,
15
+ :amino_acid,
16
+ :alcohol,
17
+ :warming,
18
+ :note,
19
+ ].freeze
20
+
21
+ RO_KEYS = [
22
+ :warmings,
23
+ ].freeze
24
+
25
+ attr_accessor :time
26
+ attr_accessor :elapsed_time
27
+ attr_accessor :mark
28
+ attr_accessor :temps
29
+
30
+ attr_accessor :preset_temp
31
+ attr_accessor :room_temp
32
+ attr_accessor :room_psychrometry
33
+
34
+ attr_accessor :baume
35
+ attr_accessor :nihonshudo
36
+ attr_accessor :acid
37
+ attr_accessor :amino_acid
38
+ attr_accessor :alcohol
39
+
40
+ attr_accessor :warming
41
+ attr_accessor :note
42
+
43
+ def temps=(val)
44
+ @temps = [val].flatten.select{|t| t}
45
+ end
46
+
47
+ def warmings
48
+ result = []
49
+ if @warming & WARM_DAKI
50
+ result << :daki
51
+ end
52
+ if @warming & WARM_ANKA
53
+ result << :anka
54
+ end
55
+ if @warming & WARM_MAT
56
+ result << :mat
57
+ end
58
+ result
59
+ end
60
+
61
+ def self.create(r)
62
+ if StateRecord===r
63
+ r
64
+ elsif State==r
65
+ r.record
66
+ elsif Hash===r
67
+ record = new
68
+ KEYS.each {|k|
69
+ record.send("#{k}=", r[k])
70
+ }
71
+ record
72
+ else
73
+ record = new
74
+ KEYS.each {|k|
75
+ record.send("#{k}=", r.send(k))
76
+ }
77
+ record
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
data/lib/toji/brew.rb ADDED
@@ -0,0 +1,21 @@
1
+ module Toji
2
+ module Brew
3
+ HOUR = 60 * 60
4
+ DAY = 24 * HOUR
5
+
6
+ WARM_DAKI = 1
7
+ WARM_ANKA = 1<<1
8
+ WARM_MAT = 1<<2
9
+ end
10
+ end
11
+
12
+ require 'toji/brew/state_accessor'
13
+ require 'toji/brew/base'
14
+ require 'toji/brew/state'
15
+ require 'toji/brew/state_record'
16
+ require 'toji/brew/builder'
17
+ require 'toji/brew/graph'
18
+
19
+ require 'toji/brew/koji'
20
+ require 'toji/brew/shubo'
21
+ require 'toji/brew/moromi'