toji 1.6.8 → 2.3.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.
- checksums.yaml +4 -4
- data/example/calendar.ipynb +383 -0
- data/example/{schedule.yaml → calendar.yaml} +6 -30
- data/example/calendar_file.ipynb +338 -0
- data/example/example_core.rb +354 -0
- data/example/kake_ingredient.rb +26 -0
- data/example/{koji_recipe.rb → koji_ingredient.rb} +1 -2
- data/example/koji_making.ipynb +16 -15
- data/example/koji_making.rb +2 -1
- data/example/koji_making.yaml +10 -9
- data/example/koji_making_multi.ipynb +27 -61
- data/example/moromi.ipynb +25 -24
- data/example/moromi.rb +1 -0
- data/example/moromi.yaml +10 -4
- data/example/recipe.rb +75 -0
- data/example/shubo.ipynb +15 -14
- data/example/shubo.rb +2 -1
- data/example/shubo.yaml +12 -11
- data/lib/toji.rb +3 -1
- data/lib/toji/brew.rb +4 -3
- data/lib/toji/brew/base.rb +8 -92
- data/lib/toji/brew/builder.rb +77 -6
- data/lib/toji/brew/graph/bmd.rb +1 -2
- data/lib/toji/brew/graph/multi_progress.rb +0 -121
- data/lib/toji/brew/graph/progress.rb +17 -52
- data/lib/toji/brew/koji.rb +2 -11
- data/lib/toji/brew/moromi.rb +4 -37
- data/lib/toji/brew/shubo.rb +2 -6
- data/lib/toji/brew/state.rb +90 -103
- data/lib/toji/brew/wrapped_state.rb +136 -0
- data/lib/toji/calendar.rb +123 -0
- data/lib/toji/{schedule → calendar}/date_column.rb +3 -6
- data/lib/toji/{schedule → calendar}/date_row.rb +6 -6
- data/lib/toji/ingredient.rb +10 -0
- data/lib/toji/ingredient/kake.rb +17 -0
- data/lib/toji/ingredient/kake/actual.rb +26 -0
- data/lib/toji/ingredient/kake/base.rb +18 -0
- data/lib/toji/ingredient/kake/expected.rb +40 -0
- data/lib/toji/ingredient/koji.rb +19 -0
- data/lib/toji/ingredient/koji/actual.rb +29 -0
- data/lib/toji/ingredient/koji/actual_fermentable.rb +15 -0
- data/lib/toji/ingredient/koji/base.rb +35 -0
- data/lib/toji/ingredient/koji/expected.rb +45 -0
- data/lib/toji/ingredient/koji/expected_fermentable.rb +15 -0
- data/lib/toji/{recipe → ingredient}/koji_rate.rb +1 -1
- data/lib/toji/ingredient/rice.rb +10 -0
- data/lib/toji/ingredient/rice/actual_steamable.rb +27 -0
- data/lib/toji/ingredient/rice/base.rb +40 -0
- data/lib/toji/ingredient/rice/expected_steamable.rb +27 -0
- data/lib/toji/ingredient/rice_rate.rb +23 -0
- data/lib/toji/product.rb +65 -0
- data/lib/toji/{schedule/product_event.rb → product/event.rb} +4 -4
- data/lib/toji/recipe.rb +111 -5
- data/lib/toji/recipe/step.rb +49 -64
- data/lib/toji/version.rb +1 -1
- metadata +33 -39
- data/example/rice_recipe.rb +0 -28
- data/example/schedule.ipynb +0 -393
- data/example/schedule_file.ipynb +0 -337
- data/example/three_step_mashing_recipe.rb +0 -67
- data/lib/toji/brew/state_accessor.rb +0 -13
- data/lib/toji/brew/state_record.rb +0 -72
- data/lib/toji/recipe/ingredient.rb +0 -10
- data/lib/toji/recipe/ingredient/koji.rb +0 -21
- data/lib/toji/recipe/ingredient/koji/actual.rb +0 -32
- data/lib/toji/recipe/ingredient/koji/actual_fermentable.rb +0 -17
- data/lib/toji/recipe/ingredient/koji/base.rb +0 -37
- data/lib/toji/recipe/ingredient/koji/expected.rb +0 -48
- data/lib/toji/recipe/ingredient/koji/expected_fermentable.rb +0 -17
- data/lib/toji/recipe/ingredient/rice.rb +0 -21
- data/lib/toji/recipe/ingredient/rice/actual.rb +0 -29
- data/lib/toji/recipe/ingredient/rice/actual_steamable.rb +0 -29
- data/lib/toji/recipe/ingredient/rice/base.rb +0 -51
- data/lib/toji/recipe/ingredient/rice/expected.rb +0 -43
- data/lib/toji/recipe/ingredient/rice/expected_steamable.rb +0 -31
- data/lib/toji/recipe/ingredient/yeast.rb +0 -21
- data/lib/toji/recipe/rice_rate.rb +0 -10
- data/lib/toji/recipe/rice_rate/base.rb +0 -21
- data/lib/toji/recipe/rice_rate/cooked.rb +0 -67
- data/lib/toji/recipe/rice_rate/steamed.rb +0 -30
- data/lib/toji/recipe/three_step_mashing.rb +0 -274
- data/lib/toji/recipe/yeast_rate.rb +0 -41
- data/lib/toji/schedule.rb +0 -11
- data/lib/toji/schedule/calendar.rb +0 -139
- data/lib/toji/schedule/date_interval_enumerator.rb +0 -45
- data/lib/toji/schedule/product.rb +0 -117
@@ -1,67 +0,0 @@
|
|
1
|
-
module Toji
|
2
|
-
module Recipe
|
3
|
-
module RiceRate
|
4
|
-
class Cooked
|
5
|
-
include Base
|
6
|
-
|
7
|
-
# 炊飯器を使う場合
|
8
|
-
#
|
9
|
-
# 浸漬。
|
10
|
-
# 25〜30分くらい浸漬させないと中心部まで水を吸わない。
|
11
|
-
# => 吸水歩合 約1.30。
|
12
|
-
#
|
13
|
-
# 炊飯。
|
14
|
-
# 吸水と炊く用の水を合わせて歩合1.50くらいにしないと中心部まで火が通らない、且つ側面が焦げる。
|
15
|
-
# 圧力がかかる熟成炊きみたいな長めの炊飯が良い。
|
16
|
-
# => 蒸米歩合 約1.40。
|
17
|
-
#
|
18
|
-
# 白米の60%の水で炊くと蒸米吸水率はだいたい38%くらいになる
|
19
|
-
# 炊飯、放冷の過程で水分のうち36%程度は蒸発する
|
20
|
-
#
|
21
|
-
# 放冷。
|
22
|
-
# 歩合1.36〜1.37くらいになる。
|
23
|
-
# 更に歩合を下げたければ炊飯までは同じで、放冷に注力するのが良い。
|
24
|
-
|
25
|
-
# 重量推移の例
|
26
|
-
#
|
27
|
-
# 浸漬
|
28
|
-
# before
|
29
|
-
# 白米(無洗米コシヒカリ) 100g
|
30
|
-
# after
|
31
|
-
# 吸水後白米 130g
|
32
|
-
# (吸水歩合 30%)
|
33
|
-
#
|
34
|
-
# 炊飯
|
35
|
-
# before
|
36
|
-
# 吸水後白米 130g
|
37
|
-
# 炊飯用水 20g
|
38
|
-
# (吸水歩合+炊飯水率 50%)
|
39
|
-
# after
|
40
|
-
# 炊飯米 140g
|
41
|
-
# (炊飯米吸水率 40%)
|
42
|
-
#
|
43
|
-
# 放冷
|
44
|
-
# before
|
45
|
-
# 炊飯米 140g
|
46
|
-
# after
|
47
|
-
# 放冷後炊飯米 136g
|
48
|
-
# (放冷後炊飯米吸水率 36%)
|
49
|
-
|
50
|
-
def initialize(soaked_rate, before_steaming_rate, steamed_rate, cooled_rate)
|
51
|
-
@soaked_rate = soaked_rate
|
52
|
-
@before_steaming_rate = before_steaming_rate
|
53
|
-
@steamed_rate = steamed_rate
|
54
|
-
@cooled_rate = cooled_rate
|
55
|
-
end
|
56
|
-
|
57
|
-
|
58
|
-
DEFAULT = new(0.30, 0.5, 0.40, 0.36)
|
59
|
-
end
|
60
|
-
|
61
|
-
|
62
|
-
def self.cooked(soaked_rate, before_steaming_rate, steamed_rate, cooled_rate)
|
63
|
-
Cooked.new(soaked_rate, before_steaming_rate, steamed_rate, cooled_rate)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module Toji
|
2
|
-
module Recipe
|
3
|
-
module RiceRate
|
4
|
-
class Steamed
|
5
|
-
include Base
|
6
|
-
|
7
|
-
def initialize(soaked_rate, before_steaming_rate, steamed_rate, cooled_rate)
|
8
|
-
@soaked_rate = soaked_rate
|
9
|
-
@before_steaming_rate = before_steaming_rate
|
10
|
-
@steamed_rate = steamed_rate
|
11
|
-
@cooled_rate = cooled_rate
|
12
|
-
end
|
13
|
-
|
14
|
-
def before_steaming_rate
|
15
|
-
@before_steaming_rate || begin
|
16
|
-
@soaked_rate - 0.04
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
|
21
|
-
DEFAULT = new(0.33, nil, 0.41, 0.33)
|
22
|
-
end
|
23
|
-
|
24
|
-
|
25
|
-
def self.steamed(soaked_rate, before_steaming_rate, steamed_rate, cooled_rate)
|
26
|
-
Steamed.new(soaked_rate, before_steaming_rate, steamed_rate, cooled_rate)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,274 +0,0 @@
|
|
1
|
-
module Toji
|
2
|
-
module Recipe
|
3
|
-
class ThreeStepMashing
|
4
|
-
|
5
|
-
attr_reader :steps
|
6
|
-
attr_reader :yeast
|
7
|
-
|
8
|
-
attr_accessor :moto_days
|
9
|
-
attr_accessor :odori_days
|
10
|
-
|
11
|
-
def initialize(steps, yeast_rate, moto_days: 1, odori_days: 1)
|
12
|
-
@steps = steps
|
13
|
-
|
14
|
-
@yeast_rate = yeast_rate
|
15
|
-
weight_total = @steps.map(&:weight_total).sum
|
16
|
-
@yeast = Ingredient::Yeast.new(weight_total, rate: yeast_rate)
|
17
|
-
|
18
|
-
@moto_days = moto_days
|
19
|
-
@odori_days = odori_days
|
20
|
-
end
|
21
|
-
|
22
|
-
def scale(rice_total, yeast_rate=@yeast_rate)
|
23
|
-
rate = rice_total / @steps.map(&:rice_total).sum
|
24
|
-
new_steps = @steps.map {|step|
|
25
|
-
step * rate
|
26
|
-
}
|
27
|
-
|
28
|
-
self.class.new(new_steps, yeast_rate, moto_days: @moto_days, odori_days: @odori_days)
|
29
|
-
end
|
30
|
-
|
31
|
-
def round(ndigit=0, half: :up)
|
32
|
-
new_steps = @steps.map {|step|
|
33
|
-
step.round(ndigit, half: half)
|
34
|
-
}
|
35
|
-
self.class.new(new_steps, @yeast_rate, moto_days: @moto_days, odori_days: @odori_days)
|
36
|
-
end
|
37
|
-
|
38
|
-
# 内容量の累計
|
39
|
-
def cumulative_weight_totals
|
40
|
-
weight_total = @steps.map(&:weight_total)
|
41
|
-
|
42
|
-
weight_total.map.with_index {|x,i|
|
43
|
-
weight_total[0..i].inject(:+)
|
44
|
-
}
|
45
|
-
end
|
46
|
-
|
47
|
-
# 総米の累計
|
48
|
-
def cumulative_rice_totals
|
49
|
-
rice_total = @steps.map(&:rice_total)
|
50
|
-
|
51
|
-
rice_total.map.with_index {|x,i|
|
52
|
-
rice_total[0..i].inject(&:+)
|
53
|
-
}
|
54
|
-
end
|
55
|
-
|
56
|
-
# 酒母歩合の累計
|
57
|
-
def cumulative_shubo_rates
|
58
|
-
rice_total = @steps.map(&:rice_total)
|
59
|
-
shubo = rice_total[0]
|
60
|
-
|
61
|
-
rice_total.map.with_index {|x,i|
|
62
|
-
shubo / rice_total[0..i].inject(&:+)
|
63
|
-
}
|
64
|
-
end
|
65
|
-
|
66
|
-
# 酒母歩合
|
67
|
-
#
|
68
|
-
# 7%が標準である
|
69
|
-
# 汲水歩合が大きい高温糖化酒母では6%程度である
|
70
|
-
#
|
71
|
-
# 出典: 酒造教本 P96
|
72
|
-
def shubo_rate
|
73
|
-
cumulative_shubo_rates.last || 0.0
|
74
|
-
end
|
75
|
-
|
76
|
-
# 白米比率
|
77
|
-
#
|
78
|
-
# 発酵型と白米比率
|
79
|
-
# 発酵の型 酒母 添 仲 留 特徴
|
80
|
-
# 湧き進め型 1 2 4 6 短期醪、辛口、軽快な酒質
|
81
|
-
# 湧き抑え型 1 2 4 7 長期醪、甘口、おだやかな酒質
|
82
|
-
#
|
83
|
-
# 出典: 酒造教本 P95
|
84
|
-
def rice_rates
|
85
|
-
@steps.map {|step|
|
86
|
-
step.rice_total / @steps[0].rice_total
|
87
|
-
}
|
88
|
-
end
|
89
|
-
|
90
|
-
def to_h
|
91
|
-
{
|
92
|
-
steps: steps.map(&:to_h),
|
93
|
-
cumulative_rice_totals: cumulative_rice_totals,
|
94
|
-
cumulative_shubo_rates: cumulative_shubo_rates,
|
95
|
-
shubo_rate: shubo_rate,
|
96
|
-
rice_rates: rice_rates,
|
97
|
-
}
|
98
|
-
end
|
99
|
-
|
100
|
-
def table_data
|
101
|
-
headers = [""] + @steps.map(&:name) + [:total]
|
102
|
-
keys = [:rice_total, :rice, :koji, :alcohol, :water, :lactic_acid]
|
103
|
-
|
104
|
-
cells = [keys]
|
105
|
-
cells += @steps.map {|step|
|
106
|
-
[step.rice_total, step.rice, step.koji, step.alcohol, step.water, step.lactic_acid]
|
107
|
-
}
|
108
|
-
cells << keys.map {|key|
|
109
|
-
@steps.map(&key).compact.sum
|
110
|
-
}
|
111
|
-
|
112
|
-
cells = cells.map {|cell|
|
113
|
-
cell.map {|c|
|
114
|
-
if Ingredient::Rice::Base===c
|
115
|
-
c = c.raw
|
116
|
-
end
|
117
|
-
|
118
|
-
case c
|
119
|
-
when NilClass
|
120
|
-
""
|
121
|
-
when 0
|
122
|
-
""
|
123
|
-
else
|
124
|
-
c
|
125
|
-
end
|
126
|
-
}
|
127
|
-
}
|
128
|
-
|
129
|
-
{header: headers, rows: cells.transpose}
|
130
|
-
end
|
131
|
-
|
132
|
-
def table
|
133
|
-
data = table_data
|
134
|
-
|
135
|
-
Plotly::Plot.new(
|
136
|
-
data: [{
|
137
|
-
type: :table,
|
138
|
-
header: {
|
139
|
-
values: data[:header]
|
140
|
-
},
|
141
|
-
cells: {
|
142
|
-
values: data[:rows].transpose
|
143
|
-
},
|
144
|
-
}],
|
145
|
-
layout: {
|
146
|
-
}
|
147
|
-
)
|
148
|
-
end
|
149
|
-
|
150
|
-
|
151
|
-
# 乳酸は汲水100L当たり比重1.21の乳酸(90%乳酸と称される)を650〜720ml添加する。
|
152
|
-
# ここでは間をとって685mlとする
|
153
|
-
#
|
154
|
-
# 出典: 酒造教本 P38
|
155
|
-
TEMPLATES = {
|
156
|
-
# 酒造教本による標準型仕込配合
|
157
|
-
# 出典: 酒造教本 P97
|
158
|
-
sokujo_textbook: new(
|
159
|
-
[
|
160
|
-
Step.new(
|
161
|
-
name: :moto,
|
162
|
-
rice: 45,
|
163
|
-
koji: 20,
|
164
|
-
water: 70,
|
165
|
-
lactic_acid: 70*6.85/1000
|
166
|
-
),
|
167
|
-
Step.new(
|
168
|
-
name: :soe,
|
169
|
-
rice: 100,
|
170
|
-
koji: 40,
|
171
|
-
water: 130
|
172
|
-
),
|
173
|
-
Step.new(
|
174
|
-
name: :naka,
|
175
|
-
rice: 215,
|
176
|
-
koji: 60,
|
177
|
-
water: 330
|
178
|
-
),
|
179
|
-
Step.new(
|
180
|
-
name: :tome,
|
181
|
-
rice: 360,
|
182
|
-
koji: 80,
|
183
|
-
water: 630
|
184
|
-
),
|
185
|
-
Step.new(
|
186
|
-
name: :yodan,
|
187
|
-
rice: 80,
|
188
|
-
water: 120
|
189
|
-
),
|
190
|
-
],
|
191
|
-
YeastRate::RED_STAR,
|
192
|
-
moto_days: 14,
|
193
|
-
odori_days: 1,
|
194
|
-
),
|
195
|
-
# 灘における仕込配合の平均値
|
196
|
-
# 出典: http://www.nada-ken.com/main/jp/index_shi/234.html
|
197
|
-
sokujo_nada: new(
|
198
|
-
[
|
199
|
-
Step.new(
|
200
|
-
name: :moto,
|
201
|
-
rice: 93,
|
202
|
-
koji: 47,
|
203
|
-
water: 170,
|
204
|
-
lactic_acid: 170*6.85/1000
|
205
|
-
),
|
206
|
-
Step.new(
|
207
|
-
name: :soe,
|
208
|
-
rice: 217,
|
209
|
-
koji: 99,
|
210
|
-
water: 270
|
211
|
-
),
|
212
|
-
Step.new(
|
213
|
-
name: :naka,
|
214
|
-
rice: 423,
|
215
|
-
koji: 143,
|
216
|
-
water: 670
|
217
|
-
),
|
218
|
-
Step.new(
|
219
|
-
name: :tome,
|
220
|
-
rice: 813,
|
221
|
-
koji: 165,
|
222
|
-
water: 1330
|
223
|
-
),
|
224
|
-
Step.new(
|
225
|
-
name: :alcohol,
|
226
|
-
alcohol: 900
|
227
|
-
),
|
228
|
-
],
|
229
|
-
YeastRate::RED_STAR,
|
230
|
-
moto_days: 14,
|
231
|
-
odori_days: 1,
|
232
|
-
),
|
233
|
-
# 簡易酒母省略仕込
|
234
|
-
# 出典: https://www.jstage.jst.go.jp/article/jbrewsocjapan1915/60/11/60_11_999/_article/-char/ja/
|
235
|
-
simple_sokujo_himeno: new(
|
236
|
-
[
|
237
|
-
Step.new(
|
238
|
-
name: :moto,
|
239
|
-
rice: 0,
|
240
|
-
koji: 70,
|
241
|
-
water: 245,
|
242
|
-
lactic_acid: 1.6
|
243
|
-
),
|
244
|
-
Step.new(
|
245
|
-
name: :soe,
|
246
|
-
rice: 130,
|
247
|
-
koji: 0,
|
248
|
-
water: 0
|
249
|
-
),
|
250
|
-
Step.new(
|
251
|
-
name: :naka,
|
252
|
-
rice: 300,
|
253
|
-
koji: 100,
|
254
|
-
water: 400
|
255
|
-
),
|
256
|
-
Step.new(
|
257
|
-
name: :tome,
|
258
|
-
rice: 490,
|
259
|
-
koji: 110,
|
260
|
-
water: 800
|
261
|
-
),
|
262
|
-
Step.new(
|
263
|
-
name: :yodan,
|
264
|
-
water: 255
|
265
|
-
),
|
266
|
-
],
|
267
|
-
YeastRate::RED_STAR,
|
268
|
-
moto_days: 1,
|
269
|
-
odori_days: 2,
|
270
|
-
),
|
271
|
-
}.freeze
|
272
|
-
end
|
273
|
-
end
|
274
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
module Toji
|
2
|
-
module Recipe
|
3
|
-
class YeastRate
|
4
|
-
|
5
|
-
# 1リットル醸造のために必要な酵母の量
|
6
|
-
attr_reader :yeast_rate
|
7
|
-
|
8
|
-
# 乾燥酵母を戻すのに必要な水の量
|
9
|
-
attr_reader :water_rate
|
10
|
-
|
11
|
-
def initialize(yeast_rate, water_rate)
|
12
|
-
@yeast_rate = yeast_rate
|
13
|
-
@water_rate = water_rate
|
14
|
-
end
|
15
|
-
|
16
|
-
# RedStar酵母
|
17
|
-
#
|
18
|
-
# 容量 5g
|
19
|
-
# 醸造可能量 20〜23L
|
20
|
-
#
|
21
|
-
# ドライイーストは、生イーストの保存性を高めるために、その水分を大部分除いたものです。
|
22
|
-
# 使用時にはイーストの10倍以上の30-35℃の無菌のお湯(ミネラルウオーターや湯冷まし)で20-25分程度なじませてください。
|
23
|
-
# これにより水分を再吸収させると同 時に発酵力を回復させ、生イーストの状態にもどします。
|
24
|
-
# このときの温湯の温度が、イーストの発酵力に影響します
|
25
|
-
RED_STAR = new(5.0 / 20.0, 10.0)
|
26
|
-
|
27
|
-
# 酒粕
|
28
|
-
#
|
29
|
-
# 以下の計算式を用いて酒粕にどの程度水を足せば醪時点での緩さになるかを算出する。
|
30
|
-
# 計算が面倒なので麹歩合は無視して蒸米時点での重量とする。
|
31
|
-
# (白米重量 * 蒸米歩合 + 白米重量 * 汲水歩合) / (粕歩合 * 100) - 1
|
32
|
-
#
|
33
|
-
# 蒸米歩合135%、汲水歩合130%、粕歩合30%の場合、酒粕に対して7.833倍の水を足せば理論上醪と同じ緩さになる。
|
34
|
-
# (100 * 1.35 + 100 * 1.3) / (0.3 * 100) - 1
|
35
|
-
# => 7.833333333333334
|
36
|
-
#
|
37
|
-
# しかし櫂入れ出来る程度の緩さになれば良いのではないだろうか。
|
38
|
-
SAKE_LEES = new(5.0, 3.0)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
data/lib/toji/schedule.rb
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
require 'toji/schedule/calendar'
|
2
|
-
require 'toji/schedule/product'
|
3
|
-
require 'toji/schedule/product_event'
|
4
|
-
require 'toji/schedule/date_row'
|
5
|
-
require 'toji/schedule/date_column'
|
6
|
-
require 'toji/schedule/date_interval_enumerator'
|
7
|
-
|
8
|
-
module Toji
|
9
|
-
module Schedule
|
10
|
-
end
|
11
|
-
end
|
@@ -1,139 +0,0 @@
|
|
1
|
-
module Toji
|
2
|
-
module Schedule
|
3
|
-
class Calendar
|
4
|
-
attr_reader :products
|
5
|
-
|
6
|
-
def initialize
|
7
|
-
@products = []
|
8
|
-
end
|
9
|
-
|
10
|
-
def <<(product)
|
11
|
-
@products << product
|
12
|
-
self
|
13
|
-
end
|
14
|
-
alias_method :add, :<<
|
15
|
-
|
16
|
-
def date_rows
|
17
|
-
events = @products.map{|product| product.events}.flatten
|
18
|
-
|
19
|
-
result = {}
|
20
|
-
events.each {|event|
|
21
|
-
result[event.date] ||= DateRow.new(event.date)
|
22
|
-
result[event.date] << event
|
23
|
-
}
|
24
|
-
|
25
|
-
result
|
26
|
-
end
|
27
|
-
|
28
|
-
def table_data
|
29
|
-
events = @products.map{|product| product.events}.flatten
|
30
|
-
|
31
|
-
koji_len = events.select{|e| e.type==:koji}.map(&:group_index).max + 1
|
32
|
-
rice_len = events.select{|e| e.type==:rice}.map(&:group_index).max + 1
|
33
|
-
min_date = events.map(&:date).min
|
34
|
-
max_date = events.map(&:date).max
|
35
|
-
|
36
|
-
headers = [:date]
|
37
|
-
|
38
|
-
case koji_len
|
39
|
-
when 1
|
40
|
-
headers += [:koji]
|
41
|
-
when 2
|
42
|
-
headers += [:moto_koji, :moromi_koji]
|
43
|
-
else
|
44
|
-
headers += [:moto_koji]
|
45
|
-
(2..koji_len).each {|i|
|
46
|
-
headers << "moromi_koji#{i-1}"
|
47
|
-
}
|
48
|
-
end
|
49
|
-
|
50
|
-
headers += [:moto, :soe, :naka, :tome, :yodan][0...rice_len]
|
51
|
-
(5...rice_len).each {|i|
|
52
|
-
headers << "#{i}dan"
|
53
|
-
}
|
54
|
-
|
55
|
-
_date_rows = date_rows
|
56
|
-
|
57
|
-
rows = []
|
58
|
-
|
59
|
-
date = min_date
|
60
|
-
while date<=max_date
|
61
|
-
columns = [date.strftime("%m/%d")]
|
62
|
-
|
63
|
-
date_row = _date_rows[date]
|
64
|
-
if date_row
|
65
|
-
koji_len.times {|i|
|
66
|
-
columns << (date_row.kojis[i]&.to_h_a || [])
|
67
|
-
}
|
68
|
-
rice_len.times {|i|
|
69
|
-
columns << (date_row.rices[i]&.to_h_a || [])
|
70
|
-
}
|
71
|
-
else
|
72
|
-
(koji_len + rice_len).times {
|
73
|
-
columns << []
|
74
|
-
}
|
75
|
-
end
|
76
|
-
|
77
|
-
rows << columns
|
78
|
-
|
79
|
-
date = date.tomorrow
|
80
|
-
end
|
81
|
-
|
82
|
-
{header: headers, rows: rows}
|
83
|
-
end
|
84
|
-
|
85
|
-
def table_text_data
|
86
|
-
data = table_data
|
87
|
-
data[:rows] = data[:rows].map {|row|
|
88
|
-
row.map {|column|
|
89
|
-
if Array===column
|
90
|
-
column.map{|c|
|
91
|
-
name = c[:product_name]
|
92
|
-
weight = "%.17g" % c[:weight]
|
93
|
-
"#{name}: #{weight}"
|
94
|
-
}.join("<br>")
|
95
|
-
else
|
96
|
-
column
|
97
|
-
end
|
98
|
-
}
|
99
|
-
}
|
100
|
-
data
|
101
|
-
end
|
102
|
-
|
103
|
-
def table
|
104
|
-
data = table_text_data
|
105
|
-
|
106
|
-
Plotly::Plot.new(
|
107
|
-
data: [{
|
108
|
-
type: :table,
|
109
|
-
header: {
|
110
|
-
values: data[:header]
|
111
|
-
},
|
112
|
-
cells: {
|
113
|
-
values: data[:rows].transpose
|
114
|
-
},
|
115
|
-
}],
|
116
|
-
layout: {
|
117
|
-
}
|
118
|
-
)
|
119
|
-
end
|
120
|
-
|
121
|
-
def self.load_hash(hash)
|
122
|
-
hash = hash.deep_symbolize_keys
|
123
|
-
products = hash[:products] || []
|
124
|
-
|
125
|
-
cal = new
|
126
|
-
products.each {|product|
|
127
|
-
cal.add(Product.create(product))
|
128
|
-
}
|
129
|
-
|
130
|
-
cal
|
131
|
-
end
|
132
|
-
|
133
|
-
def self.load_yaml_file(fname)
|
134
|
-
hash = YAML.load_file(fname)
|
135
|
-
load_hash(hash)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|