toji 1.6.6 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/example/calendar.ipynb +123 -0
  3. data/example/{schedule.yaml → calendar.yaml} +6 -30
  4. data/example/calendar_file.ipynb +338 -0
  5. data/example/example_core.rb +336 -0
  6. data/example/kake_recipe.rb +27 -0
  7. data/example/koji_making.ipynb +16 -15
  8. data/example/koji_making.rb +2 -1
  9. data/example/koji_making.yaml +9 -9
  10. data/example/koji_making_multi.ipynb +26 -25
  11. data/example/koji_recipe.rb +1 -1
  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 +10 -10
  19. data/lib/toji.rb +3 -1
  20. data/lib/toji/brew.rb +1 -2
  21. data/lib/toji/brew/base.rb +7 -71
  22. data/lib/toji/brew/builder.rb +47 -4
  23. data/lib/toji/brew/graph/bmd.rb +0 -1
  24. data/lib/toji/brew/graph/progress.rb +1 -1
  25. data/lib/toji/brew/koji.rb +0 -10
  26. data/lib/toji/brew/moromi.rb +2 -36
  27. data/lib/toji/brew/shubo.rb +0 -5
  28. data/lib/toji/brew/state.rb +87 -104
  29. data/lib/toji/brew/state_wrapper.rb +135 -0
  30. data/lib/toji/calendar.rb +123 -0
  31. data/lib/toji/{schedule → calendar}/date_column.rb +3 -6
  32. data/lib/toji/{schedule → calendar}/date_row.rb +6 -6
  33. data/lib/toji/ingredient.rb +10 -0
  34. data/lib/toji/ingredient/kake.rb +17 -0
  35. data/lib/toji/ingredient/kake/actual.rb +27 -0
  36. data/lib/toji/ingredient/kake/base.rb +18 -0
  37. data/lib/toji/ingredient/kake/expected.rb +41 -0
  38. data/lib/toji/ingredient/koji.rb +19 -0
  39. data/lib/toji/ingredient/koji/actual.rb +30 -0
  40. data/lib/toji/ingredient/koji/actual_fermentable.rb +15 -0
  41. data/lib/toji/ingredient/koji/base.rb +35 -0
  42. data/lib/toji/ingredient/koji/expected.rb +46 -0
  43. data/lib/toji/ingredient/koji/expected_fermentable.rb +15 -0
  44. data/lib/toji/{recipe → ingredient}/koji_rate.rb +1 -1
  45. data/lib/toji/ingredient/rice.rb +10 -0
  46. data/lib/toji/ingredient/rice/actual_steamable.rb +27 -0
  47. data/lib/toji/ingredient/rice/base.rb +41 -0
  48. data/lib/toji/ingredient/rice/expected_steamable.rb +29 -0
  49. data/lib/toji/ingredient/rice_rate.rb +35 -0
  50. data/lib/toji/product.rb +65 -0
  51. data/lib/toji/{schedule/product_event.rb → product/event.rb} +14 -4
  52. data/lib/toji/recipe.rb +120 -5
  53. data/lib/toji/recipe/step.rb +46 -59
  54. data/lib/toji/version.rb +1 -1
  55. metadata +31 -37
  56. data/example/rice_recipe.rb +0 -28
  57. data/example/schedule.ipynb +0 -393
  58. data/example/schedule_file.ipynb +0 -337
  59. data/example/three_step_mashing_recipe.rb +0 -67
  60. data/lib/toji/brew/state_accessor.rb +0 -13
  61. data/lib/toji/brew/state_record.rb +0 -72
  62. data/lib/toji/recipe/ingredient.rb +0 -10
  63. data/lib/toji/recipe/ingredient/koji.rb +0 -21
  64. data/lib/toji/recipe/ingredient/koji/actual.rb +0 -32
  65. data/lib/toji/recipe/ingredient/koji/actual_fermentable.rb +0 -17
  66. data/lib/toji/recipe/ingredient/koji/base.rb +0 -37
  67. data/lib/toji/recipe/ingredient/koji/expected.rb +0 -48
  68. data/lib/toji/recipe/ingredient/koji/expected_fermentable.rb +0 -17
  69. data/lib/toji/recipe/ingredient/rice.rb +0 -21
  70. data/lib/toji/recipe/ingredient/rice/actual.rb +0 -29
  71. data/lib/toji/recipe/ingredient/rice/actual_steamable.rb +0 -29
  72. data/lib/toji/recipe/ingredient/rice/base.rb +0 -51
  73. data/lib/toji/recipe/ingredient/rice/expected.rb +0 -43
  74. data/lib/toji/recipe/ingredient/rice/expected_steamable.rb +0 -31
  75. data/lib/toji/recipe/ingredient/yeast.rb +0 -21
  76. data/lib/toji/recipe/rice_rate.rb +0 -10
  77. data/lib/toji/recipe/rice_rate/base.rb +0 -21
  78. data/lib/toji/recipe/rice_rate/cooked.rb +0 -67
  79. data/lib/toji/recipe/rice_rate/steamed.rb +0 -30
  80. data/lib/toji/recipe/three_step_mashing.rb +0 -274
  81. data/lib/toji/recipe/yeast_rate.rb +0 -41
  82. data/lib/toji/schedule.rb +0 -11
  83. data/lib/toji/schedule/calendar.rb +0 -139
  84. data/lib/toji/schedule/date_interval_enumerator.rb +0 -45
  85. data/lib/toji/schedule/product.rb +0 -93
@@ -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
@@ -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
@@ -1,45 +0,0 @@
1
- module Toji
2
- module Schedule
3
- class DateIntervalEnumerator
4
- include Enumerable
5
-
6
- def initialize(intervals, afterwards)
7
- @intervals = intervals
8
- @afterwards = afterwards
9
- end
10
-
11
- def each(&block)
12
- Enumerator.new do |y|
13
- y << 0
14
- @intervals.each {|interval|
15
- y << interval
16
- }
17
- loop {
18
- y << @afterwards
19
- }
20
- end.each(&block)
21
- end
22
-
23
- def merge(dates, length)
24
- dates = [dates].flatten
25
- enum = each
26
-
27
- length.times {|i|
28
- add = enum.next
29
-
30
- if i==0
31
- dates[i] = dates[i].to_time
32
- elsif Integer===dates[i] && dates[i-1]
33
- dates[i] = dates[i-1].since(dates[i].days)
34
- elsif !dates[i] && dates[i-1]
35
- dates[i] = dates[i-1].since(add.days)
36
- else
37
- dates[i] = dates[i].to_time
38
- end
39
- }
40
-
41
- dates
42
- end
43
- end
44
- end
45
- end
@@ -1,93 +0,0 @@
1
- module Toji
2
- module Schedule
3
- class Product
4
- attr_reader :id
5
- attr_reader :name
6
- attr_reader :description
7
- attr_reader :recipe
8
-
9
- attr_reader :koji_dates
10
- attr_reader :rice_dates
11
-
12
- attr_reader :color
13
-
14
- def initialize(id, name, description, recipe, koji_dates, rice_dates, color=nil)
15
- @id = id
16
- @name = name
17
- @description = description
18
- @recipe = recipe
19
-
20
- @koji_dates = DateIntervalEnumerator.new([], 0).merge(koji_dates, recipe.steps.length)
21
- @rice_dates = DateIntervalEnumerator.new([recipe.moto_days, recipe.odori_days+1, 1], 1).merge(rice_dates, recipe.steps.length)
22
-
23
- @color = color
24
- end
25
-
26
- def events
27
- events = []
28
-
29
- @koji_dates.length.times {|i|
30
- events << ProductEvent.new(self, :koji, i)
31
- }
32
-
33
- @rice_dates.length
34
- .times.map {|i|
35
- ProductEvent.new(self, :rice, i)
36
- }
37
- .delete_if {|e|
38
- 4<=e.index && e.weight==0
39
- }
40
- .each {|e|
41
- events << e
42
- }
43
-
44
- events
45
- end
46
-
47
- def to_h
48
- {
49
- id: @id,
50
- name: @name,
51
- description: @description,
52
- recipe: @recipe.table_data,
53
- color: @color,
54
- }
55
- end
56
-
57
- def self.create(args)
58
- if self===args
59
- args
60
- elsif Hash===args
61
- recipe = args.fetch(:recipe)
62
- if Symbol===recipe
63
- recipe = Recipe::ThreeStepMashing::TEMPLATES.fetch(recipe)
64
- end
65
- if args[:scale]
66
- recipe = recipe.scale(args[:scale])
67
- end
68
- if args[:round]
69
- recipe = recipe.round(args[:round])
70
- end
71
- if args[:moto_days]
72
- recipe.moto_days = args[:moto_days]
73
- end
74
- if args[:odori_days]
75
- recipe.odori_days = args[:odori_days]
76
- end
77
-
78
- new(
79
- args[:id],
80
- args[:name],
81
- args[:description],
82
- recipe,
83
- args[:koji_dates],
84
- args[:rice_dates],
85
- args[:color]
86
- )
87
- else
88
- raise "not supported class: #{args.class}"
89
- end
90
- end
91
- end
92
- end
93
- end