toji 1.6.8 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/example/calendar.ipynb +383 -0
  3. data/example/{schedule.yaml → calendar.yaml} +6 -30
  4. data/example/calendar_file.ipynb +338 -0
  5. data/example/example_core.rb +354 -0
  6. data/example/kake_ingredient.rb +26 -0
  7. data/example/{koji_recipe.rb → koji_ingredient.rb} +1 -2
  8. data/example/koji_making.ipynb +16 -15
  9. data/example/koji_making.rb +2 -1
  10. data/example/koji_making.yaml +10 -9
  11. data/example/koji_making_multi.ipynb +27 -61
  12. data/example/moromi.ipynb +25 -24
  13. data/example/moromi.rb +1 -0
  14. data/example/moromi.yaml +10 -4
  15. data/example/recipe.rb +75 -0
  16. data/example/shubo.ipynb +15 -14
  17. data/example/shubo.rb +2 -1
  18. data/example/shubo.yaml +12 -11
  19. data/lib/toji.rb +3 -1
  20. data/lib/toji/brew.rb +4 -3
  21. data/lib/toji/brew/base.rb +8 -92
  22. data/lib/toji/brew/builder.rb +77 -6
  23. data/lib/toji/brew/graph/bmd.rb +1 -2
  24. data/lib/toji/brew/graph/multi_progress.rb +0 -121
  25. data/lib/toji/brew/graph/progress.rb +17 -52
  26. data/lib/toji/brew/koji.rb +2 -11
  27. data/lib/toji/brew/moromi.rb +4 -37
  28. data/lib/toji/brew/shubo.rb +2 -6
  29. data/lib/toji/brew/state.rb +90 -103
  30. data/lib/toji/brew/wrapped_state.rb +136 -0
  31. data/lib/toji/calendar.rb +123 -0
  32. data/lib/toji/{schedule → calendar}/date_column.rb +3 -6
  33. data/lib/toji/{schedule → calendar}/date_row.rb +6 -6
  34. data/lib/toji/ingredient.rb +10 -0
  35. data/lib/toji/ingredient/kake.rb +17 -0
  36. data/lib/toji/ingredient/kake/actual.rb +26 -0
  37. data/lib/toji/ingredient/kake/base.rb +18 -0
  38. data/lib/toji/ingredient/kake/expected.rb +40 -0
  39. data/lib/toji/ingredient/koji.rb +19 -0
  40. data/lib/toji/ingredient/koji/actual.rb +29 -0
  41. data/lib/toji/ingredient/koji/actual_fermentable.rb +15 -0
  42. data/lib/toji/ingredient/koji/base.rb +35 -0
  43. data/lib/toji/ingredient/koji/expected.rb +45 -0
  44. data/lib/toji/ingredient/koji/expected_fermentable.rb +15 -0
  45. data/lib/toji/{recipe → ingredient}/koji_rate.rb +1 -1
  46. data/lib/toji/ingredient/rice.rb +10 -0
  47. data/lib/toji/ingredient/rice/actual_steamable.rb +27 -0
  48. data/lib/toji/ingredient/rice/base.rb +40 -0
  49. data/lib/toji/ingredient/rice/expected_steamable.rb +27 -0
  50. data/lib/toji/ingredient/rice_rate.rb +23 -0
  51. data/lib/toji/product.rb +65 -0
  52. data/lib/toji/{schedule/product_event.rb → product/event.rb} +4 -4
  53. data/lib/toji/recipe.rb +111 -5
  54. data/lib/toji/recipe/step.rb +49 -64
  55. data/lib/toji/version.rb +1 -1
  56. metadata +33 -39
  57. data/example/rice_recipe.rb +0 -28
  58. data/example/schedule.ipynb +0 -393
  59. data/example/schedule_file.ipynb +0 -337
  60. data/example/three_step_mashing_recipe.rb +0 -67
  61. data/lib/toji/brew/state_accessor.rb +0 -13
  62. data/lib/toji/brew/state_record.rb +0 -72
  63. data/lib/toji/recipe/ingredient.rb +0 -10
  64. data/lib/toji/recipe/ingredient/koji.rb +0 -21
  65. data/lib/toji/recipe/ingredient/koji/actual.rb +0 -32
  66. data/lib/toji/recipe/ingredient/koji/actual_fermentable.rb +0 -17
  67. data/lib/toji/recipe/ingredient/koji/base.rb +0 -37
  68. data/lib/toji/recipe/ingredient/koji/expected.rb +0 -48
  69. data/lib/toji/recipe/ingredient/koji/expected_fermentable.rb +0 -17
  70. data/lib/toji/recipe/ingredient/rice.rb +0 -21
  71. data/lib/toji/recipe/ingredient/rice/actual.rb +0 -29
  72. data/lib/toji/recipe/ingredient/rice/actual_steamable.rb +0 -29
  73. data/lib/toji/recipe/ingredient/rice/base.rb +0 -51
  74. data/lib/toji/recipe/ingredient/rice/expected.rb +0 -43
  75. data/lib/toji/recipe/ingredient/rice/expected_steamable.rb +0 -31
  76. data/lib/toji/recipe/ingredient/yeast.rb +0 -21
  77. data/lib/toji/recipe/rice_rate.rb +0 -10
  78. data/lib/toji/recipe/rice_rate/base.rb +0 -21
  79. data/lib/toji/recipe/rice_rate/cooked.rb +0 -67
  80. data/lib/toji/recipe/rice_rate/steamed.rb +0 -30
  81. data/lib/toji/recipe/three_step_mashing.rb +0 -274
  82. data/lib/toji/recipe/yeast_rate.rb +0 -41
  83. data/lib/toji/schedule.rb +0 -11
  84. data/lib/toji/schedule/calendar.rb +0 -139
  85. data/lib/toji/schedule/date_interval_enumerator.rb +0 -45
  86. data/lib/toji/schedule/product.rb +0 -117
@@ -0,0 +1,338 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "metadata": {
7
+ "scrolled": false
8
+ },
9
+ "outputs": [
10
+ {
11
+ "name": "stdout",
12
+ "output_type": "stream",
13
+ "text": [
14
+ "仕1 姫野国夫による酒母省略仕込\n"
15
+ ]
16
+ },
17
+ {
18
+ "data": {
19
+ "text/html": [
20
+ "\n",
21
+ " <script>\n",
22
+ " requirejs.config({paths: { 'plotly': ['https://cdn.plot.ly/plotly-latest.min'] }})\n",
23
+ " </script>\n",
24
+ "\n",
25
+ "\n",
26
+ "<div id=\"58eeefc0-da74-4dfe-9d62-922a143d1573\" style=\"height: 100%; width: 100%;\"></div>\n",
27
+ "\n",
28
+ "<script>\n",
29
+ " require(['plotly'], function(Plotly) { \n",
30
+ "Plotly.newPlot(\n",
31
+ " '58eeefc0-da74-4dfe-9d62-922a143d1573',\n",
32
+ " [{\"type\":\"table\",\"header\":{\"values\":[\"\",\"moto\",\"soe\",\"naka\",\"tome\",\"yodan\",\"total\"]},\"cells\":{\"values\":[[\"rice_total\",\"kake\",\"koji\",\"alcohol\",\"water\",\"lactic_acid\"],[35.0,\"\",35,\"\",123,0.8],[65.0,65,\"\",\"\",\"\",\"\"],[200.0,150,50,\"\",200,\"\"],[300.0,245,55,\"\",400,\"\"],[\"\",\"\",\"\",\"\",128,\"\"],[600.0,460,140,\"\",851,0.8]]}}],\n",
33
+ " {\"height\":350},\n",
34
+ " {\"linkText\":\"Export to plot.ly\",\"showLink\":true}\n",
35
+ ")\n",
36
+ "\n",
37
+ "window.addEventListener('resize', function() {\n",
38
+ " Plotly.Plots.resize(document.getElementById('58eeefc0-da74-4dfe-9d62-922a143d1573'))\n",
39
+ "})\n",
40
+ " }) \n",
41
+ "</script>"
42
+ ],
43
+ "text/plain": [
44
+ "#<Plotly::Offline::HTML:0x00007f98df86e690 @id=\"58eeefc0-da74-4dfe-9d62-922a143d1573\", @data=[{:type=>:table, :header=>{:values=>[\"\", :moto, :soe, :naka, :tome, :yodan, :total]}, :cells=>{:values=>[[:rice_total, :kake, :koji, :alcohol, :water, :lactic_acid], [35.0, \"\", 35, \"\", 123, 0.8], [65.0, 65, \"\", \"\", \"\", \"\"], [200.0, 150, 50, \"\", 200, \"\"], [300.0, 245, 55, \"\", 400, \"\"], [\"\", \"\", \"\", \"\", 128, \"\"], [600.0, 460, 140, \"\", 851, 0.8]]}}], @layout={:height=>350}, @config={:linkText=>\"Export to plot.ly\", :showLink=>true}, @embedded=true>"
45
+ ]
46
+ },
47
+ "metadata": {},
48
+ "output_type": "display_data"
49
+ },
50
+ {
51
+ "name": "stdout",
52
+ "output_type": "stream",
53
+ "text": [
54
+ "仕2 姫野国夫による酒母省略仕込\n"
55
+ ]
56
+ },
57
+ {
58
+ "data": {
59
+ "text/html": [
60
+ "\n",
61
+ " <script>\n",
62
+ " requirejs.config({paths: { 'plotly': ['https://cdn.plot.ly/plotly-latest.min'] }})\n",
63
+ " </script>\n",
64
+ "\n",
65
+ "\n",
66
+ "<div id=\"11ed57bf-7469-4286-9005-bb108ca9ccba\" style=\"height: 100%; width: 100%;\"></div>\n",
67
+ "\n",
68
+ "<script>\n",
69
+ " require(['plotly'], function(Plotly) { \n",
70
+ "Plotly.newPlot(\n",
71
+ " '11ed57bf-7469-4286-9005-bb108ca9ccba',\n",
72
+ " [{\"type\":\"table\",\"header\":{\"values\":[\"\",\"moto\",\"soe\",\"naka\",\"tome\",\"yodan\",\"total\"]},\"cells\":{\"values\":[[\"rice_total\",\"kake\",\"koji\",\"alcohol\",\"water\",\"lactic_acid\"],[32.0,\"\",32,\"\",112,0.733],[60.0,60,\"\",\"\",\"\",\"\"],[184.0,138,46,\"\",183,\"\"],[275.0,225,50,\"\",367,\"\"],[\"\",\"\",\"\",\"\",117,\"\"],[551.0,423,128,\"\",779,0.733]]}}],\n",
73
+ " {\"height\":350},\n",
74
+ " {\"linkText\":\"Export to plot.ly\",\"showLink\":true}\n",
75
+ ")\n",
76
+ "\n",
77
+ "window.addEventListener('resize', function() {\n",
78
+ " Plotly.Plots.resize(document.getElementById('11ed57bf-7469-4286-9005-bb108ca9ccba'))\n",
79
+ "})\n",
80
+ " }) \n",
81
+ "</script>"
82
+ ],
83
+ "text/plain": [
84
+ "#<Plotly::Offline::HTML:0x00007f98df8a1298 @id=\"11ed57bf-7469-4286-9005-bb108ca9ccba\", @data=[{:type=>:table, :header=>{:values=>[\"\", :moto, :soe, :naka, :tome, :yodan, :total]}, :cells=>{:values=>[[:rice_total, :kake, :koji, :alcohol, :water, :lactic_acid], [32.0, \"\", 32, \"\", 112, 0.733], [60.0, 60, \"\", \"\", \"\", \"\"], [184.0, 138, 46, \"\", 183, \"\"], [275.0, 225, 50, \"\", 367, \"\"], [\"\", \"\", \"\", \"\", 117, \"\"], [551.0, 423, 128, \"\", 779, 0.733]]}}], @layout={:height=>350}, @config={:linkText=>\"Export to plot.ly\", :showLink=>true}, @embedded=true>"
85
+ ]
86
+ },
87
+ "metadata": {},
88
+ "output_type": "display_data"
89
+ },
90
+ {
91
+ "name": "stdout",
92
+ "output_type": "stream",
93
+ "text": [
94
+ "仕3 灘における仕込配合\n"
95
+ ]
96
+ },
97
+ {
98
+ "data": {
99
+ "text/html": [
100
+ "\n",
101
+ " <script>\n",
102
+ " requirejs.config({paths: { 'plotly': ['https://cdn.plot.ly/plotly-latest.min'] }})\n",
103
+ " </script>\n",
104
+ "\n",
105
+ "\n",
106
+ "<div id=\"6947170f-0778-4b4c-b8ad-347ee1104216\" style=\"height: 100%; width: 100%;\"></div>\n",
107
+ "\n",
108
+ "<script>\n",
109
+ " require(['plotly'], function(Plotly) { \n",
110
+ "Plotly.newPlot(\n",
111
+ " '6947170f-0778-4b4c-b8ad-347ee1104216',\n",
112
+ " [{\"type\":\"table\",\"header\":{\"values\":[\"\",\"moto\",\"soe\",\"naka\",\"tome\",\"alcohol\",\"total\"]},\"cells\":{\"values\":[[\"rice_total\",\"kake\",\"koji\",\"alcohol\",\"water\",\"lactic_acid\"],[63.0,42,21,\"\",77,0.524],[143.0,98,45,\"\",122,\"\"],[254.0,190,64,\"\",302,\"\"],[440.0,366,74,\"\",599,\"\"],[\"\",\"\",\"\",405,\"\",\"\"],[900.0,696,204,405,1100,0.524]]}}],\n",
113
+ " {\"height\":350},\n",
114
+ " {\"linkText\":\"Export to plot.ly\",\"showLink\":true}\n",
115
+ ")\n",
116
+ "\n",
117
+ "window.addEventListener('resize', function() {\n",
118
+ " Plotly.Plots.resize(document.getElementById('6947170f-0778-4b4c-b8ad-347ee1104216'))\n",
119
+ "})\n",
120
+ " }) \n",
121
+ "</script>"
122
+ ],
123
+ "text/plain": [
124
+ "#<Plotly::Offline::HTML:0x00007f98dd2ff440 @id=\"6947170f-0778-4b4c-b8ad-347ee1104216\", @data=[{:type=>:table, :header=>{:values=>[\"\", :moto, :soe, :naka, :tome, :alcohol, :total]}, :cells=>{:values=>[[:rice_total, :kake, :koji, :alcohol, :water, :lactic_acid], [63.0, 42, 21, \"\", 77, 0.524], [143.0, 98, 45, \"\", 122, \"\"], [254.0, 190, 64, \"\", 302, \"\"], [440.0, 366, 74, \"\", 599, \"\"], [\"\", \"\", \"\", 405, \"\", \"\"], [900.0, 696, 204, 405, 1100, 0.524]]}}], @layout={:height=>350}, @config={:linkText=>\"Export to plot.ly\", :showLink=>true}, @embedded=true>"
125
+ ]
126
+ },
127
+ "metadata": {},
128
+ "output_type": "display_data"
129
+ },
130
+ {
131
+ "name": "stdout",
132
+ "output_type": "stream",
133
+ "text": [
134
+ "仕4 酒造教本による標準型仕込配合\n"
135
+ ]
136
+ },
137
+ {
138
+ "data": {
139
+ "text/html": [
140
+ "\n",
141
+ " <script>\n",
142
+ " requirejs.config({paths: { 'plotly': ['https://cdn.plot.ly/plotly-latest.min'] }})\n",
143
+ " </script>\n",
144
+ "\n",
145
+ "\n",
146
+ "<div id=\"b8e03dff-c6c2-4c1c-8de6-37c39f5e742c\" style=\"height: 100%; width: 100%;\"></div>\n",
147
+ "\n",
148
+ "<script>\n",
149
+ " require(['plotly'], function(Plotly) { \n",
150
+ "Plotly.newPlot(\n",
151
+ " 'b8e03dff-c6c2-4c1c-8de6-37c39f5e742c',\n",
152
+ " [{\"type\":\"table\",\"header\":{\"values\":[\"\",\"moto\",\"soe\",\"naka\",\"tome\",\"yodan\",\"total\"]},\"cells\":{\"values\":[[\"rice_total\",\"kake\",\"koji\",\"alcohol\",\"water\",\"lactic_acid\"],[59.0,41,18,\"\",63,0.432],[126.0,90,36,\"\",117,\"\"],[248.0,194,54,\"\",297,\"\"],[396.0,324,72,\"\",567,\"\"],[72.0,72,\"\",\"\",108,\"\"],[901.0,721,180,\"\",1152,0.432]]}}],\n",
153
+ " {\"height\":350},\n",
154
+ " {\"linkText\":\"Export to plot.ly\",\"showLink\":true}\n",
155
+ ")\n",
156
+ "\n",
157
+ "window.addEventListener('resize', function() {\n",
158
+ " Plotly.Plots.resize(document.getElementById('b8e03dff-c6c2-4c1c-8de6-37c39f5e742c'))\n",
159
+ "})\n",
160
+ " }) \n",
161
+ "</script>"
162
+ ],
163
+ "text/plain": [
164
+ "#<Plotly::Offline::HTML:0x00007f98df06fa48 @id=\"b8e03dff-c6c2-4c1c-8de6-37c39f5e742c\", @data=[{:type=>:table, :header=>{:values=>[\"\", :moto, :soe, :naka, :tome, :yodan, :total]}, :cells=>{:values=>[[:rice_total, :kake, :koji, :alcohol, :water, :lactic_acid], [59.0, 41, 18, \"\", 63, 0.432], [126.0, 90, 36, \"\", 117, \"\"], [248.0, 194, 54, \"\", 297, \"\"], [396.0, 324, 72, \"\", 567, \"\"], [72.0, 72, \"\", \"\", 108, \"\"], [901.0, 721, 180, \"\", 1152, 0.432]]}}], @layout={:height=>350}, @config={:linkText=>\"Export to plot.ly\", :showLink=>true}, @embedded=true>"
165
+ ]
166
+ },
167
+ "metadata": {},
168
+ "output_type": "display_data"
169
+ },
170
+ {
171
+ "name": "stdout",
172
+ "output_type": "stream",
173
+ "text": [
174
+ "仕5 灘における仕込配合\n"
175
+ ]
176
+ },
177
+ {
178
+ "data": {
179
+ "text/html": [
180
+ "\n",
181
+ " <script>\n",
182
+ " requirejs.config({paths: { 'plotly': ['https://cdn.plot.ly/plotly-latest.min'] }})\n",
183
+ " </script>\n",
184
+ "\n",
185
+ "\n",
186
+ "<div id=\"2fb546f4-b05c-47a4-99ae-18a6b3f370a0\" style=\"height: 100%; width: 100%;\"></div>\n",
187
+ "\n",
188
+ "<script>\n",
189
+ " require(['plotly'], function(Plotly) { \n",
190
+ "Plotly.newPlot(\n",
191
+ " '2fb546f4-b05c-47a4-99ae-18a6b3f370a0',\n",
192
+ " [{\"type\":\"table\",\"header\":{\"values\":[\"\",\"moto\",\"soe\",\"naka\",\"tome\",\"alcohol\",\"total\"]},\"cells\":{\"values\":[[\"rice_total\",\"kake\",\"koji\",\"alcohol\",\"water\",\"lactic_acid\"],[63.0,42,21,\"\",77,0.524],[143.0,98,45,\"\",122,\"\"],[254.0,190,64,\"\",302,\"\"],[440.0,366,74,\"\",599,\"\"],[\"\",\"\",\"\",405,\"\",\"\"],[900.0,696,204,405,1100,0.524]]}}],\n",
193
+ " {\"height\":350},\n",
194
+ " {\"linkText\":\"Export to plot.ly\",\"showLink\":true}\n",
195
+ ")\n",
196
+ "\n",
197
+ "window.addEventListener('resize', function() {\n",
198
+ " Plotly.Plots.resize(document.getElementById('2fb546f4-b05c-47a4-99ae-18a6b3f370a0'))\n",
199
+ "})\n",
200
+ " }) \n",
201
+ "</script>"
202
+ ],
203
+ "text/plain": [
204
+ "#<Plotly::Offline::HTML:0x00007f98df94db38 @id=\"2fb546f4-b05c-47a4-99ae-18a6b3f370a0\", @data=[{:type=>:table, :header=>{:values=>[\"\", :moto, :soe, :naka, :tome, :alcohol, :total]}, :cells=>{:values=>[[:rice_total, :kake, :koji, :alcohol, :water, :lactic_acid], [63.0, 42, 21, \"\", 77, 0.524], [143.0, 98, 45, \"\", 122, \"\"], [254.0, 190, 64, \"\", 302, \"\"], [440.0, 366, 74, \"\", 599, \"\"], [\"\", \"\", \"\", 405, \"\", \"\"], [900.0, 696, 204, 405, 1100, 0.524]]}}], @layout={:height=>350}, @config={:linkText=>\"Export to plot.ly\", :showLink=>true}, @embedded=true>"
205
+ ]
206
+ },
207
+ "metadata": {},
208
+ "output_type": "display_data"
209
+ },
210
+ {
211
+ "name": "stdout",
212
+ "output_type": "stream",
213
+ "text": [
214
+ "仕6 酒造教本による標準型仕込配合\n"
215
+ ]
216
+ },
217
+ {
218
+ "data": {
219
+ "text/html": [
220
+ "\n",
221
+ " <script>\n",
222
+ " requirejs.config({paths: { 'plotly': ['https://cdn.plot.ly/plotly-latest.min'] }})\n",
223
+ " </script>\n",
224
+ "\n",
225
+ "\n",
226
+ "<div id=\"be20e0d2-c893-4f32-8ab4-d98ef1af24d9\" style=\"height: 100%; width: 100%;\"></div>\n",
227
+ "\n",
228
+ "<script>\n",
229
+ " require(['plotly'], function(Plotly) { \n",
230
+ "Plotly.newPlot(\n",
231
+ " 'be20e0d2-c893-4f32-8ab4-d98ef1af24d9',\n",
232
+ " [{\"type\":\"table\",\"header\":{\"values\":[\"\",\"moto\",\"soe\",\"naka\",\"tome\",\"yodan\",\"total\"]},\"cells\":{\"values\":[[\"rice_total\",\"kake\",\"koji\",\"alcohol\",\"water\",\"lactic_acid\"],[59.0,41,18,\"\",63,0.432],[126.0,90,36,\"\",117,\"\"],[248.0,194,54,\"\",297,\"\"],[396.0,324,72,\"\",567,\"\"],[72.0,72,\"\",\"\",108,\"\"],[901.0,721,180,\"\",1152,0.432]]}}],\n",
233
+ " {\"height\":350},\n",
234
+ " {\"linkText\":\"Export to plot.ly\",\"showLink\":true}\n",
235
+ ")\n",
236
+ "\n",
237
+ "window.addEventListener('resize', function() {\n",
238
+ " Plotly.Plots.resize(document.getElementById('be20e0d2-c893-4f32-8ab4-d98ef1af24d9'))\n",
239
+ "})\n",
240
+ " }) \n",
241
+ "</script>"
242
+ ],
243
+ "text/plain": [
244
+ "#<Plotly::Offline::HTML:0x00007f98dd350e80 @id=\"be20e0d2-c893-4f32-8ab4-d98ef1af24d9\", @data=[{:type=>:table, :header=>{:values=>[\"\", :moto, :soe, :naka, :tome, :yodan, :total]}, :cells=>{:values=>[[:rice_total, :kake, :koji, :alcohol, :water, :lactic_acid], [59.0, 41, 18, \"\", 63, 0.432], [126.0, 90, 36, \"\", 117, \"\"], [248.0, 194, 54, \"\", 297, \"\"], [396.0, 324, 72, \"\", 567, \"\"], [72.0, 72, \"\", \"\", 108, \"\"], [901.0, 721, 180, \"\", 1152, 0.432]]}}], @layout={:height=>350}, @config={:linkText=>\"Export to plot.ly\", :showLink=>true}, @embedded=true>"
245
+ ]
246
+ },
247
+ "metadata": {},
248
+ "output_type": "display_data"
249
+ },
250
+ {
251
+ "data": {
252
+ "text/html": [
253
+ "\n",
254
+ " <script>\n",
255
+ " requirejs.config({paths: { 'plotly': ['https://cdn.plot.ly/plotly-latest.min'] }})\n",
256
+ " </script>\n",
257
+ "\n",
258
+ "\n",
259
+ "<div id=\"5b26d19a-f3d0-455d-a648-333a815c0893\" style=\"height: 100%; width: 100%;\"></div>\n",
260
+ "\n",
261
+ "<script>\n",
262
+ " require(['plotly'], function(Plotly) { \n",
263
+ "Plotly.newPlot(\n",
264
+ " '5b26d19a-f3d0-455d-a648-333a815c0893',\n",
265
+ " [{\"type\":\"table\",\"header\":{\"values\":[\"date\",\"moto_koji\",\"moromi_koji\",\"moto\",\"soe\",\"naka\",\"tome\",\"yodan\"]},\"cells\":{\"values\":[[\"02/20\",\"02/21\",\"02/22\",\"02/23\",\"02/24\",\"02/25\",\"02/26\",\"02/27\",\"02/28\",\"02/29\",\"03/01\",\"03/02\",\"03/03\",\"03/04\",\"03/05\",\"03/06\",\"03/07\",\"03/08\",\"03/09\",\"03/10\",\"03/11\",\"03/12\",\"03/13\",\"03/14\",\"03/15\",\"03/16\",\"03/17\",\"03/18\",\"03/19\",\"03/20\",\"03/21\",\"03/22\",\"03/23\",\"03/24\",\"03/25\",\"03/26\",\"03/27\",\"03/28\",\"03/29\",\"03/30\",\"03/31\",\"04/01\",\"04/02\",\"04/03\",\"04/04\",\"04/05\",\"04/06\",\"04/07\",\"04/08\",\"04/09\",\"04/10\",\"04/11\",\"04/12\",\"04/13\",\"04/14\",\"04/15\"],[\"仕3: 21\\u003cbr\\u003e仕4: 18\",\"\",\"\",\"\",\"\",\"\",\"\",\"仕5: 21\\u003cbr\\u003e仕6: 18\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"],[\"\",\"\",\"\",\"\",\"仕1: 140\",\"\",\"\",\"仕2: 128\",\"\",\"\",\"\",\"\",\"\",\"\",\"仕3: 183\\u003cbr\\u003e仕4: 162\",\"\",\"\",\"\",\"\",\"\",\"\",\"仕5: 183\\u003cbr\\u003e仕6: 162\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"],[\"\",\"\",\"\",\"\",\"\",\"仕3: 42\\u003cbr\\u003e仕4: 41\",\"\",\"\",\"\",\"\",\"仕1: 0\",\"\",\"仕5: 42\\u003cbr\\u003e仕6: 41\",\"仕2: 0\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"],[\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"仕1: 65\",\"\",\"\",\"仕2: 60\",\"\",\"\",\"\",\"\",\"\",\"仕3: 98\\u003cbr\\u003e仕4: 90\",\"\",\"\",\"\",\"\",\"\",\"\",\"仕5: 98\\u003cbr\\u003e仕6: 90\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"],[\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"仕1: 150\",\"\",\"\",\"仕2: 138\",\"\",\"\",\"\",\"\",\"\",\"仕3: 190\\u003cbr\\u003e仕4: 194\",\"\",\"\",\"\",\"\",\"\",\"\",\"仕5: 190\\u003cbr\\u003e仕6: 194\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"],[\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"仕1: 245\",\"\",\"\",\"仕2: 225\",\"\",\"\",\"\",\"\",\"\",\"仕3: 366\\u003cbr\\u003e仕4: 324\",\"\",\"\",\"\",\"\",\"\",\"\",\"仕5: 366\\u003cbr\\u003e仕6: 324\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"],[\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"仕4: 72\",\"\",\"\",\"\",\"\",\"\",\"\",\"仕6: 72\"]]}}],\n",
266
+ " {\"height\":1000},\n",
267
+ " {\"linkText\":\"Export to plot.ly\",\"showLink\":true}\n",
268
+ ")\n",
269
+ "\n",
270
+ "window.addEventListener('resize', function() {\n",
271
+ " Plotly.Plots.resize(document.getElementById('5b26d19a-f3d0-455d-a648-333a815c0893'))\n",
272
+ "})\n",
273
+ " }) \n",
274
+ "</script>"
275
+ ],
276
+ "text/plain": [
277
+ "#<Plotly::Offline::HTML:0x00007f98df09ede8 @id=\"5b26d19a-f3d0-455d-a648-333a815c0893\", @data=[{:type=>:table, :header=>{:values=>[:date, :moto_koji, :moromi_koji, :moto, :soe, :naka, :tome, :yodan]}, :cells=>{:values=>[[\"02/20\", \"02/21\", \"02/22\", \"02/23\", \"02/24\", \"02/25\", \"02/26\", \"02/27\", \"02/28\", \"02/29\", \"03/01\", \"03/02\", \"03/03\", \"03/04\", \"03/05\", \"03/06\", \"03/07\", \"03/08\", \"03/09\", \"03/10\", \"03/11\", \"03/12\", \"03/13\", \"03/14\", \"03/15\", \"03/16\", \"03/17\", \"03/18\", \"03/19\", \"03/20\", \"03/21\", \"03/22\", \"03/23\", \"03/24\", \"03/25\", \"03/26\", \"03/27\", \"03/28\", \"03/29\", \"03/30\", \"03/31\", \"04/01\", \"04/02\", \"04/03\", \"04/04\", \"04/05\", \"04/06\", \"04/07\", \"04/08\", \"04/09\", \"04/10\", \"04/11\", \"04/12\", \"04/13\", \"04/14\", \"04/15\"], [\"仕3: 21<br>仕4: 18\", \"\", \"\", \"\", \"\", \"\", \"\", \"仕5: 21<br>仕6: 18\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"], [\"\", \"\", \"\", \"\", \"仕1: 140\", \"\", \"\", \"仕2: 128\", \"\", \"\", \"\", \"\", \"\", \"\", \"仕3: 183<br>仕4: 162\", \"\", \"\", \"\", \"\", \"\", \"\", \"仕5: 183<br>仕6: 162\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"], [\"\", \"\", \"\", \"\", \"\", \"仕3: 42<br>仕4: 41\", \"\", \"\", \"\", \"\", \"仕1: 0\", \"\", \"仕5: 42<br>仕6: 41\", \"仕2: 0\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"], [\"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"仕1: 65\", \"\", \"\", \"仕2: 60\", \"\", \"\", \"\", \"\", \"\", \"仕3: 98<br>仕4: 90\", \"\", \"\", \"\", \"\", \"\", \"\", \"仕5: 98<br>仕6: 90\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"], [\"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"仕1: 150\", \"\", \"\", \"仕2: 138\", \"\", \"\", \"\", \"\", \"\", \"仕3: 190<br>仕4: 194\", \"\", \"\", \"\", \"\", \"\", \"\", \"仕5: 190<br>仕6: 194\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"], [\"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"仕1: 245\", \"\", \"\", \"仕2: 225\", \"\", \"\", \"\", \"\", \"\", \"仕3: 366<br>仕4: 324\", \"\", \"\", \"\", \"\", \"\", \"\", \"仕5: 366<br>仕6: 324\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"], [\"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"仕4: 72\", \"\", \"\", \"\", \"\", \"\", \"\", \"仕6: 72\"]]}}], @layout={:height=>1000}, @config={:linkText=>\"Export to plot.ly\", :showLink=>true}, @embedded=true>"
278
+ ]
279
+ },
280
+ "metadata": {},
281
+ "output_type": "display_data"
282
+ },
283
+ {
284
+ "data": {
285
+ "text/plain": [
286
+ "#<CZTop::Socket::PUB:0x7f98e10534d0 last_endpoint=\"tcp://127.0.0.1:56639\">"
287
+ ]
288
+ },
289
+ "execution_count": 1,
290
+ "metadata": {},
291
+ "output_type": "execute_result"
292
+ }
293
+ ],
294
+ "source": [
295
+ "$LOAD_PATH << File.dirname(__FILE__) + \"/../lib\"\n",
296
+ "require 'toji'\n",
297
+ "require './example_core'\n",
298
+ "require 'rbplotly'\n",
299
+ "\n",
300
+ "cal = Example::Calendar.load_yaml_file(\"calendar.yaml\")\n",
301
+ "\n",
302
+ "cal.products.each {|product|\n",
303
+ " puts \"%s %s\" % [product.name, product.description]\n",
304
+ " \n",
305
+ " product.recipe.table.tap {|t|\n",
306
+ " t.layout.height = 350\n",
307
+ " }.show\n",
308
+ "}\n",
309
+ "\n",
310
+ "cal.table.tap {|t|\n",
311
+ " t.layout.height = 1000\n",
312
+ "}.show"
313
+ ]
314
+ },
315
+ {
316
+ "cell_type": "code",
317
+ "execution_count": null,
318
+ "metadata": {},
319
+ "outputs": [],
320
+ "source": []
321
+ }
322
+ ],
323
+ "metadata": {
324
+ "kernelspec": {
325
+ "display_name": "Ruby 2.7.1",
326
+ "language": "ruby",
327
+ "name": "ruby"
328
+ },
329
+ "language_info": {
330
+ "file_extension": ".rb",
331
+ "mimetype": "application/x-ruby",
332
+ "name": "ruby",
333
+ "version": "2.6.3"
334
+ }
335
+ },
336
+ "nbformat": 4,
337
+ "nbformat_minor": 2
338
+ }
@@ -0,0 +1,354 @@
1
+ require 'securerandom'
2
+
3
+ module Example
4
+
5
+ module Brew
6
+ class State
7
+ include Toji::Brew::State
8
+ include Toji::Brew::State::BaumeToNihonshudo
9
+
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
19
+ end
20
+
21
+ module BrewGenerator
22
+ def builder
23
+ Toji::Brew::Builder.new(self)
24
+ end
25
+
26
+ def load_hash(hash)
27
+ hash = hash.deep_symbolize_keys
28
+
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
37
+
38
+ def load_yaml_file(fname)
39
+ hash = YAML.load_file(fname)
40
+ load_hash(hash)
41
+ end
42
+ end
43
+
44
+ class Base
45
+ include Toji::Brew::Base
46
+ extend BrewGenerator
47
+
48
+ def initialize
49
+ @states = []
50
+ @day_offset = 0
51
+ @base_time = 0
52
+ end
53
+ end
54
+
55
+ class Koji < Base
56
+ include Toji::Brew::Koji
57
+ end
58
+
59
+ class Shubo < Base
60
+ include Toji::Brew::Shubo
61
+ end
62
+
63
+ class Moromi < Base
64
+ include Toji::Brew::Moromi
65
+ end
66
+ end
67
+
68
+
69
+ class Step
70
+ include Toji::Recipe::Step
71
+
72
+ # 総重量
73
+ def weight_total
74
+ kake + koji + water + lactic_acid + alcohol + yeast
75
+ end
76
+
77
+ def to_h
78
+ {
79
+ name: name,
80
+ kake: kake,
81
+ koji: koji,
82
+ water: water,
83
+ lactic_acid: lactic_acid,
84
+ alcohol: alcohol,
85
+ yeast: yeast,
86
+ koji_interval_days: koji_interval_days,
87
+ kake_interval_days: kake_interval_days,
88
+ }
89
+ end
90
+
91
+ 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)
92
+ new.tap {|o|
93
+ o.name = name
94
+ o.kake = kake.to_f
95
+ o.koji = koji.to_f
96
+ o.water = water.to_f
97
+ o.lactic_acid = lactic_acid.to_f
98
+ o.alcohol = alcohol.to_f
99
+ o.yeast = yeast.to_f
100
+ o.koji_interval_days = koji_interval_days.to_i
101
+ o.kake_interval_days = kake_interval_days.to_i
102
+ }
103
+ end
104
+ end
105
+
106
+
107
+ class Recipe
108
+ include Toji::Recipe
109
+
110
+ def initialize
111
+ @steps = []
112
+ end
113
+
114
+ #def to_h
115
+ # {
116
+ # steps: steps.map(&:to_h),
117
+ # cumulative_rice_totals: cumulative_rice_totals,
118
+ # cumulative_shubo_rates: cumulative_shubo_rates,
119
+ # shubo_rate: shubo_rate,
120
+ # rice_rates: rice_rates,
121
+ # }
122
+ #end
123
+
124
+ def self.create(steps)
125
+ new.tap {|o|
126
+ o.steps = steps
127
+ }
128
+ end
129
+
130
+ # 乳酸は汲水100L当たり比重1.21の乳酸(90%乳酸と称される)を650〜720ml添加する。
131
+ # 添加する酵母の量は、酒母の総米100kg当たり協会酵母アンプル1〜2本である。
132
+ #
133
+ # 出典: 酒造教本 P80
134
+ #
135
+ # ここでは間をとって乳酸は685ml、酵母は1.5本とする。
136
+ TEMPLATES = {
137
+ # 酒造教本による標準型仕込配合
138
+ # 出典: 酒造教本 P97
139
+ sokujo_textbook: create(
140
+ [
141
+ Step.create(
142
+ name: :moto,
143
+ kake: 45,
144
+ koji: 20,
145
+ water: 70,
146
+ lactic_acid: 70/100.0*0.685,
147
+ yeast: (45+20)/100.0*1.5,
148
+ koji_interval_days: 0,
149
+ kake_interval_days: 5,
150
+ ),
151
+ Step.create(
152
+ name: :soe,
153
+ kake: 100,
154
+ koji: 40,
155
+ water: 130,
156
+ koji_interval_days: 14,
157
+ kake_interval_days: 15,
158
+ ),
159
+ Step.create(
160
+ name: :naka,
161
+ kake: 215,
162
+ koji: 60,
163
+ water: 330,
164
+ koji_interval_days: 0,
165
+ kake_interval_days: 2,
166
+ ),
167
+ Step.create(
168
+ name: :tome,
169
+ kake: 360,
170
+ koji: 80,
171
+ water: 630,
172
+ koji_interval_days: 0,
173
+ kake_interval_days: 1,
174
+ ),
175
+ Step.create(
176
+ name: :yodan,
177
+ kake: 80,
178
+ water: 120,
179
+ kake_interval_days: 25,
180
+ ),
181
+ ].map(&:freeze).freeze
182
+ ).freeze,
183
+ # 灘における仕込配合の平均値
184
+ # 出典: http://www.nada-ken.com/main/jp/index_shi/234.html
185
+ sokujo_nada: create(
186
+ [
187
+ Step.create(
188
+ name: :moto,
189
+ kake: 93,
190
+ koji: 47,
191
+ water: 170,
192
+ lactic_acid: 170/100.0*0.685,
193
+ yeast: (93+47)/100.0*1.5,
194
+ koji_interval_days: 0,
195
+ kake_interval_days: 5,
196
+ ),
197
+ Step.create(
198
+ name: :soe,
199
+ kake: 217,
200
+ koji: 99,
201
+ water: 270,
202
+ koji_interval_days: 14,
203
+ kake_interval_days: 15,
204
+ ),
205
+ Step.create(
206
+ name: :naka,
207
+ kake: 423,
208
+ koji: 143,
209
+ water: 670,
210
+ koji_interval_days: 0,
211
+ kake_interval_days: 2,
212
+ ),
213
+ Step.create(
214
+ name: :tome,
215
+ kake: 813,
216
+ koji: 165,
217
+ water: 1330,
218
+ koji_interval_days: 0,
219
+ kake_interval_days: 1,
220
+ ),
221
+ Step.create(
222
+ name: :alcohol,
223
+ alcohol: 900
224
+ ),
225
+ ].map(&:freeze).freeze
226
+ ).freeze,
227
+ # 簡易酒母省略仕込
228
+ # 出典: https://www.jstage.jst.go.jp/article/jbrewsocjapan1915/60/11/60_11_999/_article/-char/ja/
229
+ simple_sokujo_himeno: create(
230
+ [
231
+ Step.create(
232
+ name: :moto,
233
+ kake: 0,
234
+ koji: 70,
235
+ water: 245,
236
+ lactic_acid: 1.6,
237
+ yeast: 5,
238
+ koji_interval_days: 0,
239
+ kake_interval_days: 6,
240
+ ),
241
+ Step.create(
242
+ name: :soe,
243
+ kake: 130,
244
+ koji: 0,
245
+ water: 0,
246
+ koji_interval_days: 0,
247
+ kake_interval_days: 1,
248
+ ),
249
+ Step.create(
250
+ name: :naka,
251
+ kake: 300,
252
+ koji: 100,
253
+ water: 400,
254
+ koji_interval_days: 0,
255
+ kake_interval_days: 2,
256
+ ),
257
+ Step.create(
258
+ name: :tome,
259
+ kake: 490,
260
+ koji: 110,
261
+ water: 800,
262
+ koji_interval_days: 0,
263
+ kake_interval_days: 1,
264
+ ),
265
+ Step.create(
266
+ name: :yodan,
267
+ water: 255
268
+ ),
269
+ ].map(&:freeze).freeze
270
+ ).freeze,
271
+ }.freeze
272
+ end
273
+
274
+
275
+ class Product
276
+ include Toji::Product
277
+
278
+ attr_accessor :description
279
+ attr_accessor :color
280
+
281
+ def initialize(reduce_key, name, description, recipe, start_date, color=nil)
282
+ @reduce_key = reduce_key || SecureRandom.uuid
283
+ @name = name
284
+ @description = description
285
+ @recipe = recipe
286
+ @start_date = start_date
287
+ @color = color
288
+ end
289
+
290
+ def to_h
291
+ {
292
+ id: id,
293
+ name: name,
294
+ description: @description,
295
+ recipe: @recipe.table_data,
296
+ start_date: @start_date,
297
+ koji_dates: koji_dates,
298
+ kake_dates: kake_dates,
299
+ events: events.map(&:to_h),
300
+ events_group: events_group,
301
+ color: @color,
302
+ }
303
+ end
304
+
305
+ def self.create(args)
306
+ if self===args
307
+ args
308
+ elsif Hash===args
309
+ recipe = args.fetch(:recipe)
310
+ if Symbol===recipe
311
+ recipe = Recipe::TEMPLATES.fetch(recipe)
312
+ end
313
+ if args[:scale]
314
+ recipe = recipe.scale(args[:scale])
315
+ end
316
+ if args[:round]
317
+ recipe = recipe.round(args[:round])
318
+ end
319
+
320
+ new(
321
+ args[:id],
322
+ args[:name],
323
+ args[:description],
324
+ recipe,
325
+ args[:start_date],
326
+ args[:color]
327
+ )
328
+ else
329
+ raise "not supported class: #{args.class}"
330
+ end
331
+ end
332
+ end
333
+
334
+
335
+ class Calendar < Toji::Calendar
336
+
337
+ def self.load_hash(hash)
338
+ hash = hash.deep_symbolize_keys
339
+ products = hash[:products] || []
340
+
341
+ cal = new
342
+ products.each {|product|
343
+ cal.add(Product.create(product))
344
+ }
345
+
346
+ cal
347
+ end
348
+
349
+ def self.load_yaml_file(fname)
350
+ hash = YAML.load_file(fname)
351
+ load_hash(hash)
352
+ end
353
+ end
354
+ end