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
@@ -5,7 +5,6 @@ module Toji
5
5
 
6
6
  def initialize
7
7
  @actuals = []
8
- @expects = []
9
8
  end
10
9
 
11
10
  def actual(moromi, name=:actual)
@@ -17,7 +16,7 @@ module Toji
17
16
  result = []
18
17
 
19
18
  @actuals.each {|moromi, name|
20
- states = moromi.states.select{|s| s.moromi_day && s.bmd}
19
+ states = moromi.wrapped_states.select{|s| s.moromi_day && s.bmd}
21
20
 
22
21
  xs = states.map(&:moromi_day).map{|d| d*DAY}
23
22
  ys = states.map(&:bmd)
@@ -69,127 +69,6 @@ module Toji
69
69
  }
70
70
  )
71
71
  end
72
-
73
- def state_group_order(group_by)
74
- result = {}
75
-
76
- @progresses.map{|progress|
77
- progress.state_group_by(group_by)
78
- }.map{|group|
79
- group.map{|key,states|
80
- [key, states.first.elapsed_time_with_offset]
81
- }.to_h
82
- }.each {|group|
83
- result.merge!(group) {|key,self_val,other_val|
84
- [self_val, other_val].min
85
- }
86
- }
87
-
88
- result.sort_by(&:last).map(&:first)
89
- end
90
-
91
- def state_group_count(group_by)
92
- result = {}
93
-
94
- @progresses.map{|progress|
95
- progress.state_group_count(group_by)
96
- }.each {|group|
97
- result.merge!(group) {|key,self_val,other_val|
98
- [self_val, other_val].max
99
- }
100
- }
101
-
102
- state_group_order(group_by).map {|val|
103
- [val, result[val]]
104
- }.to_h
105
- end
106
-
107
- def table_data(group_by=nil, keys=nil)
108
- case group_by
109
- when :elapsed_time, :elapsed_time_with_offset, nil
110
- table_data_group_by_elapsed_time(keys)
111
- else
112
- table_data_group_by(group_by, keys)
113
- end
114
- end
115
-
116
- def table_data_group_by(group_by, keys=nil)
117
- header = []
118
- cells = []
119
-
120
- group_count = state_group_count(group_by)
121
-
122
- header << ["", group_by]
123
- cells << group_count.inject([]) {|result,(group,num)|
124
- if 0<num
125
- result << group
126
- (num-1).times {
127
- result << ""
128
- }
129
- end
130
- result
131
- }
132
-
133
- @progresses.each {|progress|
134
- data = progress.table_data(keys, group_by, group_count)
135
- header += data[:header].map.with_index{|h,i|
136
- name = i==0 ? progress.name : ""
137
- [name, h]
138
- }
139
- cells += data[:rows].transpose
140
- }
141
-
142
- {header: header, rows: cells.transpose}
143
- end
144
-
145
- def table_data_group_by_elapsed_time(keys=nil, date_format="%m/%d %H:%M")
146
- header = []
147
- cells = []
148
-
149
- elapsed_times = state_group_count(:elapsed_time_with_offset)
150
-
151
- header << ["", :elapsed_time]
152
- utc_offset = Time.at(0).utc_offset
153
-
154
- cells << elapsed_times.inject([]) {|result,(elapsed_time,num)|
155
- if 0<num
156
- result << Time.at(elapsed_time - utc_offset).strftime(date_format)
157
- (num-1).times {
158
- result << ""
159
- }
160
- end
161
- result
162
- }
163
-
164
- @progresses.each {|progress|
165
- data = progress.table_data(keys, :elapsed_time_with_offset, elapsed_times)
166
- header += data[:header].map.with_index{|h,i|
167
- name = i==0 ? progress.name : ""
168
- [name, h]
169
- }
170
- cells += data[:rows].transpose
171
- }
172
-
173
- {header: header, rows: cells.transpose}
174
- end
175
-
176
- def table(group_by=nil, keys=nil)
177
- data = table_data(group_by, keys)
178
-
179
- Plotly::Plot.new(
180
- data: [{
181
- type: :table,
182
- header: {
183
- values: data[:header]
184
- },
185
- cells: {
186
- values: data[:rows].transpose
187
- },
188
- }],
189
- layout: {
190
- }
191
- )
192
- end
193
72
  end
194
73
  end
195
74
  end
@@ -75,7 +75,7 @@ module Toji
75
75
  result << {x: xs, y: ys, text: text, name: "#{name}#{key}", line: {dash: @dash, shape: line_shape}, marker: {color: PLOT_COLORS[key]}}
76
76
  }
77
77
 
78
- if 0<@brew.states.length && 0<@brew.day_offset
78
+ if 0<@brew.wrapped_states.length && 0<@brew.day_offset
79
79
  result = result.map{|h|
80
80
  h[:x].unshift(0)
81
81
  h[:y].unshift(nil)
@@ -84,8 +84,8 @@ module Toji
84
84
  }
85
85
  end
86
86
 
87
- #if 0<@brew.states.length && @brew.states.last.time.strftime("%T")!="00:00:00"
88
- # t = @brew.states.last.elapsed_time_with_offset
87
+ #if 0<@brew.wrapped_states.length && @brew.wrapped_states.last.time.strftime("%T")!="00:00:00"
88
+ # t = @brew.wrapped_states.last.elapsed_time_with_offset
89
89
  # t -= (t % DAY) - DAY
90
90
  #
91
91
  # result = result.map{|h|
@@ -100,7 +100,7 @@ module Toji
100
100
  end
101
101
 
102
102
  def annotations
103
- return [] if @enable_annotations
103
+ return [] if !@enable_annotations
104
104
 
105
105
  @brew.select{|s| s.mark}.map {|s|
106
106
  {
@@ -117,28 +117,7 @@ module Toji
117
117
  }
118
118
  end
119
119
 
120
- def state_group_by(group_by)
121
- group = {}
122
- prev = nil
123
-
124
- @brew.each {|state|
125
- val = state.send(group_by) || prev
126
- prev = val
127
-
128
- group[val] ||= []
129
- group[val] << state
130
- }
131
-
132
- group
133
- end
134
-
135
- def state_group_count(group_by)
136
- state_group_by(group_by).map{|val,states|
137
- [val, states.length]
138
- }.to_h
139
- end
140
-
141
- def table_data(keys=nil, group_by=nil, group_count=nil)
120
+ def table_data(keys=nil)
142
121
  if !keys
143
122
  keys = @brew.has_keys
144
123
  keys.delete(:elapsed_time)
@@ -151,33 +130,19 @@ module Toji
151
130
  keys &= @brew.has_keys
152
131
  end
153
132
 
154
- if group_by && group_count
155
- brew_hash = state_group_by(group_by)
156
- else
157
- group_count = state_group_count(:itself)
158
- brew_hash = state_group_by(:itself)
159
- end
160
-
161
133
  rows = []
162
- group_count.each {|group_value,num|
163
- states = brew_hash[group_value] || []
164
- num ||= states.length
165
-
166
- num.times {|i|
167
- state = states[i]
168
-
169
- rows << keys.map {|k|
170
- v = state&.send(k)
171
- if Array===v
172
- v.map(&:to_s).join(", ")
173
- elsif Float===v
174
- v.round(3)
175
- elsif v
176
- v
177
- else
178
- ""
179
- end
180
- }
134
+ @brew.each {|state|
135
+ rows << keys.map {|k|
136
+ v = state&.send(k)
137
+ if Array===v
138
+ v.map(&:to_s).join(", ")
139
+ elsif Float===v
140
+ v.round(3).to_s
141
+ elsif v
142
+ v.to_s
143
+ else
144
+ ""
145
+ end
181
146
  }
182
147
  }
183
148
 
@@ -1,16 +1,7 @@
1
1
  module Toji
2
2
  module Brew
3
- class Koji < Base
4
-
5
- state_reader :hikikomi
6
- state_reader :tokomomi
7
- state_reader :kirikaeshi
8
- state_reader :mori
9
- state_reader :naka_shigoto
10
- state_reader :shimai_shigoto
11
- state_reader :tsumikae
12
- state_reader :dekoji
13
-
3
+ module Koji
4
+ include Base
14
5
 
15
6
  def progress(name: nil, dash: :solid, enable_annotations: true)
16
7
  Graph::Progress.new(self, name: name, dash: dash, enable_annotations: enable_annotations)
@@ -1,42 +1,9 @@
1
1
  module Toji
2
2
  module Brew
3
- class Moromi < Base
3
+ module Moromi
4
+ include Base
4
5
 
5
- state_reader :moto
6
- state_reader :soe
7
- state_reader :naka
8
- state_reader :tome
9
- state_reader :yodan
10
-
11
- attr_writer :prefix_day_labels
12
-
13
- def prefix_day_labels
14
- if @prefix_day_labels
15
- @prefix_day_labels
16
- elsif !self[:soe] && !self[:tome]
17
- nil
18
- else
19
- labels = []
20
- [:soe, :naka, :tome].each {|mark|
21
- s = self[mark]
22
- if s
23
- i = s.day - 1
24
- labels[i] = mark
25
- end
26
- }
27
-
28
- soe_i = labels.index(:soe)
29
- labels.map.with_index {|label,i|
30
- if label
31
- label
32
- elsif !soe_i || i<soe_i
33
- :moto
34
- else
35
- :odori
36
- end
37
- }
38
- end
39
- end
6
+ attr_accessor :prefix_day_labels
40
7
 
41
8
  def moromi_tome_day
42
9
  prefix_day_labels&.length
@@ -57,7 +24,7 @@ module Toji
57
24
  if _prefix
58
25
  _prefix + moromi_days.times.map{|i| i+2}.map(&:to_s)
59
26
  else
60
- self.days.times.map{|i| i+1}.map(&:to_s)
27
+ super
61
28
  end
62
29
  end
63
30
 
@@ -1,11 +1,7 @@
1
1
  module Toji
2
2
  module Brew
3
- class Shubo < Base
4
-
5
- state_reader :mizukoji
6
- state_reader :shikomi
7
- state_reader :utase
8
- state_reader :wake
3
+ module Shubo
4
+ include Base
9
5
 
10
6
  def progress(name: nil, dash: :solid, enable_annotations: true)
11
7
  Graph::Progress.new(self, name: name, dash: dash, enable_annotations: enable_annotations)
@@ -1,134 +1,121 @@
1
- require 'forwardable'
2
-
3
1
  module Toji
4
2
  module Brew
5
- class State
6
- extend Forwardable
3
+ module State
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
+ :warmings,
18
+ :note,
19
+ ].freeze
7
20
 
8
- attr_accessor :elapsed_time
9
21
  attr_accessor :time
10
- attr_reader :record
11
- attr_reader :brew
12
-
13
- def_delegators :@record, :mark
14
- def_delegators :@record, :temps
15
- def_delegators :@record, :preset_temp
16
- def_delegators :@record, :room_temp
17
- def_delegators :@record, :room_psychrometry
18
- def_delegators :@record, :acid
19
- def_delegators :@record, :amino_acid
20
- def_delegators :@record, :alcohol
21
- def_delegators :@record, :warmings
22
- def_delegators :@record, :note
23
-
24
- def initialize(elapsed_time, record, brew)
25
- @elapsed_time = elapsed_time
26
- @record = record
27
- @brew = brew
28
- end
22
+ attr_accessor :elapsed_time
23
+ attr_accessor :mark
24
+ attr_accessor :temps
29
25
 
30
- def day
31
- ((elapsed_time_with_offset.to_f + 1) / DAY).ceil
32
- end
26
+ attr_accessor :preset_temp
27
+ attr_accessor :room_temp
28
+ attr_accessor :room_psychrometry
33
29
 
34
- def day_label
35
- @brew.day_labels[day - 1]
36
- end
30
+ attr_accessor :baume
31
+ attr_accessor :nihonshudo
32
+ attr_accessor :acid
33
+ attr_accessor :amino_acid
34
+ attr_accessor :alcohol
37
35
 
38
- def elapsed_time_with_offset
39
- @elapsed_time + @brew.day_offset
40
- end
36
+ attr_accessor :warmings
37
+ attr_accessor :note
41
38
 
42
- def baume
43
- if @record.baume
44
- @record.baume
45
- elsif @record.nihonshudo
46
- @record.nihonshudo * -0.1
47
- end
39
+
40
+ def self.included(cls)
41
+ cls.prepend PrependMethods
48
42
  end
49
43
 
50
- def nihonshudo
51
- if @record.nihonshudo
52
- @record.nihonshudo
53
- elsif @record.baume
54
- @record.baume * -10
44
+ module PrependMethods
45
+ def temps
46
+ (super || []).map(&:to_f)
55
47
  end
56
- end
57
48
 
58
- def display_baume
59
- if @record.baume || @record.nihonshudo
60
- b = baume
61
- if b<3.0
62
- nihonshudo
63
- else
64
- b
65
- end
49
+ def temps=(val)
50
+ super([val].flatten.compact.map(&:to_f))
66
51
  end
67
- end
68
52
 
69
- def display_time(format="%m/%d %H:%M")
70
- if @time
71
- @time.strftime(format)
72
- elsif @brew.min_time
73
- time = @brew.min_time + @elapsed_time
74
- time.strftime(format)
75
- else
76
- utc_offset = Time.at(0).utc_offset
77
- Time.at(@elapsed_time - utc_offset).strftime(format)
53
+ def time=(val)
54
+ super(val&.to_time)
78
55
  end
79
- end
80
56
 
81
- def moromi_day
82
- _tome_day = @brew.moromi_tome_day
83
- _now_day = day
57
+ def warmings
58
+ super || []
59
+ end
84
60
 
85
- if _tome_day && _tome_day < _now_day
86
- _now_day - _tome_day + 1
61
+ def warmings=(val)
62
+ super([val].flatten.compact)
87
63
  end
88
64
  end
89
65
 
90
- def bmd
91
- _moromi_day = moromi_day
92
- _baume = baume
66
+ module BaumeToNihonshudo
67
+ def nihonshudo
68
+ if self.baume
69
+ self.baume * -10
70
+ end
71
+ end
93
72
 
94
- if _moromi_day && _baume
95
- _moromi_day * _baume
73
+ def nihonshudo=(val)
74
+ if val
75
+ self.baume = val.to_f / -10.0
76
+ else
77
+ self.baume = nil
78
+ end
96
79
  end
97
80
  end
98
81
 
99
- def expected_alcohol(target_alc, target_nihonshudo, coef)
100
- _baume = baume
82
+ module NihonshudoToBaume
83
+ def baume
84
+ if self.nihonshudo
85
+ self.nihonshudo / -10.0
86
+ end
87
+ end
101
88
 
102
- if _baume
103
- target_alc - (_baume - target_nihonshudo * -0.1) * coef
89
+ def baume=(val)
90
+ if val
91
+ self.nihonshudo = val.to_f * -10
92
+ else
93
+ self.nihonshudo = nil
94
+ end
104
95
  end
105
96
  end
106
97
 
107
- def to_h
108
- {
109
- elapsed_time: elapsed_time,
110
- time: time,
111
- mark: mark,
112
- temps: temps,
113
- preset_temp: preset_temp,
114
- room_temp: room_temp,
115
- room_psychrometry: room_psychrometry,
116
- acid: acid,
117
- amino_acid: amino_acid,
118
- alcohol: alcohol,
119
- warmings: warmings,
120
- note: note,
121
-
122
- day: day,
123
- day_label: day_label,
124
- elapsed_time_with_offset: elapsed_time_with_offset,
125
- baume: baume,
126
- nihonshudo: nihonshudo,
127
- display_baume: display_baume,
128
- display_time: display_time,
129
- moromi_day: moromi_day,
130
- bmd: bmd,
131
- }
98
+ def self.create(val)
99
+ if State===val
100
+ val
101
+ elsif WrappedState==val
102
+ val.state
103
+ #elsif Hash===val
104
+ # #s = Class.new {
105
+ # # include State
106
+ # #}.new
107
+ # s = Object.new.tap {|o|
108
+ # o.extend State
109
+ # o.extend State::PrependMethods
110
+ # }
111
+
112
+ # KEYS.each {|k|
113
+ # s.send("#{k}=", val[k])
114
+ # }
115
+ # s
116
+ else
117
+ raise Error, "ArgumentError: cant cast to Toji::Brew::State"
118
+ end
132
119
  end
133
120
  end
134
121
  end