toji 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,27 @@
1
+ module Toji
2
+ module Brew
3
+ class Builder
4
+
5
+ def initialize(cls)
6
+ @cls = cls
7
+ @records = []
8
+ @date_line = 0
9
+ end
10
+
11
+ def <<(record)
12
+ @records += [record].flatten
13
+ self
14
+ end
15
+ alias_method :add, :<<
16
+
17
+ def date_line(val)
18
+ @date_line = val
19
+ self
20
+ end
21
+
22
+ def build
23
+ @cls.new(@records, @date_line)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,85 @@
1
+ module Toji
2
+ module Brew
3
+ module Graph
4
+ class Ab
5
+ attr_reader :coef
6
+
7
+ def initialize(coef=1.5)
8
+ @coef = coef
9
+ @actuals = []
10
+ @expects = []
11
+ end
12
+
13
+ def actual(moromi, name=:actual)
14
+ @actuals << [moromi, name]
15
+ self
16
+ end
17
+
18
+ def expect(alcohol, nihonshudo)
19
+ @expects << [alcohol.to_f, nihonshudo.to_f]
20
+ self
21
+ end
22
+
23
+ def plot_data
24
+ result = []
25
+
26
+ @actuals.each {|moromi, name|
27
+ states = moromi.select{|s| s.alcohol && s.baume}
28
+
29
+ xs = states.map(&:alcohol)
30
+ ys = states.map(&:baume)
31
+ texts = states.map{|s| "%s<br />alc=%s, be=%s" % [s.display_time, s.alcohol, s.baume]}
32
+
33
+ result << {x: xs, y: ys, text: texts, name: name}
34
+ }
35
+
36
+ @expects.each {|alcohol, nihonshudo|
37
+ ys = [0.0, 8.0]
38
+ xs = ys.map{|b| alcohol - (b - nihonshudo * -0.1) * @coef}
39
+
40
+ name = "%s%s %s" % [nihonshudo<0 ? "" : "+", nihonshudo, alcohol]
41
+
42
+ result << {x: xs, y: ys, name: name}
43
+ }
44
+
45
+ result
46
+ end
47
+
48
+ def min_baume
49
+ @actuals.map {|moromi, name|
50
+ moromi.map(&:baume).compact.min
51
+ }.compact.min || 0
52
+ end
53
+
54
+ def max_baume
55
+ @actuals.map {|moromi, name|
56
+ moromi.map(&:baume).compact.max
57
+ }.compact.max || 0
58
+ end
59
+
60
+ def plot
61
+ #_min_baume = [min_baume-1, 0].min
62
+ _min_baume = 0
63
+
64
+ _max_baume = [max_baume+1, 10].max
65
+
66
+ Plotly::Plot.new(
67
+ data: plot_data,
68
+ layout: {
69
+ xaxis: {
70
+ title: "Alcohol",
71
+ dtick: 2,
72
+ range: [0, 20],
73
+ },
74
+ yaxis: {
75
+ title: "Baume",
76
+ dtick: 1,
77
+ range: [_min_baume, _max_baume],
78
+ }
79
+ }
80
+ )
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,58 @@
1
+ module Toji
2
+ module Brew
3
+ module Graph
4
+ class Bmd
5
+
6
+ def initialize
7
+ @actuals = []
8
+ @expects = []
9
+ end
10
+
11
+ def actual(moromi, name=:actual)
12
+ @actuals << [moromi, name]
13
+ self
14
+ end
15
+
16
+ def plot_data
17
+ result = []
18
+
19
+ @actuals.each {|moromi, name|
20
+ states = moromi.states.select{|s| s.moromi_day && s.bmd}
21
+
22
+ xs = states.map(&:moromi_day).map{|d| d*DAY}
23
+ ys = states.map(&:bmd)
24
+ texts = states.map{|s| "%s<br />moromi day=%d, be=%s, bmd=%s" % [s.display_time, s.moromi_day, s.baume, s.bmd]}
25
+
26
+ result << {x: xs, y: ys, text: texts, name: name}
27
+ }
28
+
29
+ result
30
+ end
31
+
32
+ def max_moromi_day
33
+ @actuals.map(&:first).map(&:moromi_days).max
34
+ end
35
+
36
+ def plot
37
+ _max_moromi_day = [max_moromi_day, 14].max
38
+
39
+ Plotly::Plot.new(
40
+ data: plot_data,
41
+ layout: {
42
+ xaxis: {
43
+ title: "Moromi day",
44
+ dtick: DAY,
45
+ range: [1, _max_moromi_day].map{|d| d*DAY},
46
+ tickvals: _max_moromi_day.times.map{|d| d*DAY},
47
+ ticktext: _max_moromi_day.times.map(&:succ)
48
+ },
49
+ yaxis: {
50
+ title: "BMD",
51
+ }
52
+ }
53
+ )
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,142 @@
1
+ module Toji
2
+ module Brew
3
+ module Graph
4
+ class Progress
5
+
6
+ attr_accessor :enable_annotations
7
+
8
+ def initialize(data, enable_annotations: true)
9
+ @data = data
10
+ @enable_annotations = enable_annotations
11
+ end
12
+
13
+ def has_keys
14
+ @data.map(&:has_keys).flatten.uniq
15
+ end
16
+
17
+ def plot_data(keys=nil)
18
+ if !keys
19
+ keys = has_keys
20
+ end
21
+
22
+ result = []
23
+
24
+ keys &= [:temps, :preset_temp, :room_temp, :room_psychrometry, :baume, :acid, :amino_acid, :alcohol, :bmd]
25
+
26
+ keys.each {|key|
27
+ xs = []
28
+ ys = []
29
+ text = []
30
+ @data.each {|r|
31
+ val = r.send(key)
32
+ if val
33
+ [val].flatten.each_with_index {|v,i|
34
+ xs << r.elapsed_time_with_offset + i
35
+ ys << v
36
+ text << r.display_time
37
+ }
38
+ end
39
+ }
40
+
41
+ line_shape = :linear
42
+ if key==:preset_temp
43
+ line_shape = :hv
44
+ end
45
+
46
+ result << {x: xs, y: ys, text: text, name: key, line: {shape: line_shape}}
47
+ }
48
+
49
+ if 0<@data.states.length && 0<@data.day_offset
50
+ result = result.map{|h|
51
+ h[:x].unshift(0)
52
+ h[:y].unshift(nil)
53
+ h[:text].unshift(nil)
54
+ h
55
+ }
56
+ end
57
+
58
+ result
59
+ end
60
+
61
+ def annotations
62
+ @data.select{|s| s.mark}.map {|s|
63
+ {
64
+ x: s.elapsed_time_with_offset,
65
+ y: s.temps.first || 0,
66
+ xref: 'x',
67
+ yref: 'y',
68
+ text: s.mark,
69
+ showarrow: true,
70
+ arrowhead: 1,
71
+ ax: 0,
72
+ ay: -40
73
+ }
74
+ }
75
+ end
76
+
77
+ def table_data(keys=nil)
78
+ if !keys
79
+ keys = has_keys
80
+ keys.delete(:elapsed_time)
81
+ keys.delete(:time)
82
+ keys.delete(:day)
83
+ keys.delete(:moromi_day)
84
+ keys.delete(:baume)
85
+ keys.delete(:nihonshudo)
86
+ else
87
+ keys &= has_keys
88
+ end
89
+
90
+ cells = @data.map {|s|
91
+ keys.map {|k|
92
+ v = s.send(k)
93
+ if Array===v
94
+ v.map(&:to_s).join(", ")
95
+ elsif Float===v
96
+ v.round(3)
97
+ elsif v
98
+ v
99
+ else
100
+ ""
101
+ end
102
+ }
103
+ }
104
+
105
+ {header: keys, cells: cells.transpose}
106
+ end
107
+
108
+ def plot(keys=nil)
109
+ Plotly::Plot.new(
110
+ data: plot_data(keys),
111
+ layout: {
112
+ xaxis: {
113
+ dtick: DAY,
114
+ tickvals: @data.days.times.map{|d| d*DAY},
115
+ ticktext: @data.day_labels
116
+ },
117
+ annotations: @enable_annotations ? annotations : [],
118
+ }
119
+ )
120
+ end
121
+
122
+ def table(keys=nil)
123
+ data = table_data(keys)
124
+
125
+ Plotly::Plot.new(
126
+ data: [{
127
+ type: :table,
128
+ header: {
129
+ values: data[:header]
130
+ },
131
+ cells: {
132
+ values: data[:cells]
133
+ },
134
+ }],
135
+ layout: {
136
+ }
137
+ )
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,10 @@
1
+ require 'toji/brew/graph/progress'
2
+ require 'toji/brew/graph/bmd'
3
+ require 'toji/brew/graph/ab'
4
+
5
+ module Toji
6
+ module Brew
7
+ module Graph
8
+ end
9
+ end
10
+ end
@@ -1,93 +1,85 @@
1
1
  module Toji
2
- module Product
3
- class KojiMaking < Base
2
+ module Brew
3
+ class Koji < Base
4
4
 
5
5
  TEMPLATES = {
6
6
  default: [
7
- Job.new(
8
- elapsed_time: 0 * Job::HOUR,
7
+ {
8
+ elapsed_time: 0 * Brew::HOUR,
9
9
  id: :hikikomi,
10
10
  temps: 35.0,
11
11
  room_temp: 28.0,
12
12
  room_psychrometry: nil,
13
- ),
14
- Job.new(
15
- elapsed_time: 1 * Job::HOUR,
13
+ },
14
+ {
15
+ elapsed_time: 1 * Brew::HOUR,
16
16
  id: :tokomomi,
17
17
  temps: 32.0,
18
18
  room_temp: 28.0,
19
19
  room_psychrometry: nil,
20
- ),
21
- Job.new(
22
- elapsed_time: 9 * Job::HOUR,
20
+ },
21
+ {
22
+ elapsed_time: 9 * Brew::HOUR,
23
23
  id: :kirikaeshi,
24
24
  temps: [32.0, 31.0],
25
25
  room_temp: 28.0,
26
26
  room_psychrometry: nil,
27
- ),
28
- Job.new(
29
- elapsed_time: 21 * Job::HOUR,
27
+ },
28
+ {
29
+ elapsed_time: 21 * Brew::HOUR,
30
30
  id: :mori,
31
31
  temps: [35.0, 33.0],
32
32
  room_temp: 28.0,
33
33
  room_psychrometry: 4,
34
- ),
35
- Job.new(
36
- elapsed_time: 29 * Job::HOUR,
34
+ },
35
+ {
36
+ elapsed_time: 29 * Brew::HOUR,
37
37
  id: :naka_shigoto,
38
38
  temps: [37.0, 35.0],
39
39
  room_temp: 28.0,
40
40
  room_psychrometry: 4,
41
- ),
42
- Job.new(
43
- elapsed_time: 35 * Job::HOUR,
41
+ },
42
+ {
43
+ elapsed_time: 35 * Brew::HOUR,
44
44
  id: :shimai_shigoto,
45
45
  temps: [38.0, 37.0],
46
46
  room_temp: 28.0,
47
47
  room_psychrometry: 5,
48
- ),
49
- Job.new(
50
- elapsed_time: 39 * Job::HOUR,
48
+ },
49
+ {
50
+ elapsed_time: 39 * Brew::HOUR,
51
51
  id: :tsumikae,
52
52
  temps: 40.0,
53
53
  room_temp: 28.0,
54
54
  room_psychrometry: 5,
55
- ),
56
- Job.new(
57
- elapsed_time: 44 * Job::HOUR,
55
+ },
56
+ {
57
+ elapsed_time: 44 * Brew::HOUR,
58
58
  id: :dekoji,
59
59
  temps: 40.0,
60
60
  room_temp: 28.0,
61
61
  room_psychrometry: 5,
62
- ),
62
+ },
63
63
  ],
64
64
  }
65
65
 
66
66
 
67
- job_reader :hikikomi
68
- job_reader :tokomomi
69
- job_reader :kirikaeshi
70
- job_reader :mori
71
- job_reader :naka_shigoto
72
- job_reader :shimai_shigoto
73
- job_reader :tsumikae
74
- job_reader :dekoji
67
+ state_reader :hikikomi
68
+ state_reader :tokomomi
69
+ state_reader :kirikaeshi
70
+ state_reader :mori
71
+ state_reader :naka_shigoto
72
+ state_reader :shimai_shigoto
73
+ state_reader :tsumikae
74
+ state_reader :dekoji
75
75
 
76
76
 
77
- def initialize(jobs=[], date_line: 0)
78
- super(jobs, date_line: date_line)
79
- end
80
-
81
- def day_labels
82
- days.times.map(&:succ)
83
- end
84
-
85
77
  def progress(enable_annotations: true)
86
78
  Graph::Progress.new(self, enable_annotations: enable_annotations)
87
79
  end
88
80
 
89
81
  def self.template(key=:default)
90
- new(TEMPLATES[key])
82
+ create(TEMPLATES[key])
91
83
  end
92
84
  end
93
85
  end