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.
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,136 @@
1
+ require 'forwardable'
2
+
3
+ module Toji
4
+ module Brew
5
+ class WrappedState
6
+ extend Forwardable
7
+
8
+ attr_accessor :elapsed_time
9
+ attr_accessor :time
10
+ attr_reader :state
11
+ attr_reader :brew
12
+
13
+ def_delegators :@state, :mark
14
+ def_delegators :@state, :temps
15
+ def_delegators :@state, :preset_temp
16
+ def_delegators :@state, :room_temp
17
+ def_delegators :@state, :room_psychrometry
18
+ def_delegators :@state, :acid
19
+ def_delegators :@state, :amino_acid
20
+ def_delegators :@state, :alcohol
21
+ def_delegators :@state, :warmings
22
+ def_delegators :@state, :note
23
+
24
+ def initialize(state, brew)
25
+ @elapsed_time = state.elapsed_time
26
+ @time = state.time
27
+ @state = state
28
+ @brew = brew
29
+ end
30
+
31
+ def day
32
+ ((elapsed_time_with_offset.to_f + 1) / DAY).ceil
33
+ end
34
+
35
+ def day_label
36
+ @brew.day_labels[day - 1]
37
+ end
38
+
39
+ def elapsed_time_with_offset
40
+ @elapsed_time + @brew.day_offset
41
+ end
42
+
43
+ def baume
44
+ if @state.baume
45
+ @state.baume
46
+ elsif @state.nihonshudo
47
+ @state.nihonshudo * -0.1
48
+ end
49
+ end
50
+
51
+ def nihonshudo
52
+ if @state.nihonshudo
53
+ @state.nihonshudo
54
+ elsif @state.baume
55
+ @state.baume * -10
56
+ end
57
+ end
58
+
59
+ def display_baume
60
+ if @state.baume || @state.nihonshudo
61
+ b = baume
62
+ if b<3.0
63
+ nihonshudo
64
+ else
65
+ b
66
+ end
67
+ end
68
+ end
69
+
70
+ def display_time(format="%m/%d %H:%M")
71
+ if @time
72
+ @time.strftime(format)
73
+ elsif @brew.base_time
74
+ time = @brew.base_time + @elapsed_time
75
+ time.strftime(format)
76
+ else
77
+ utc_offset = Time.at(0).utc_offset
78
+ Time.at(@elapsed_time - utc_offset).strftime(format)
79
+ end
80
+ end
81
+
82
+ def moromi_day
83
+ _tome_day = @brew.moromi_tome_day
84
+ _now_day = day
85
+
86
+ if _tome_day && _tome_day < _now_day
87
+ _now_day - _tome_day + 1
88
+ end
89
+ end
90
+
91
+ def bmd
92
+ _moromi_day = moromi_day
93
+ _baume = baume
94
+
95
+ if _moromi_day && _baume
96
+ _moromi_day * _baume
97
+ end
98
+ end
99
+
100
+ def expected_alcohol(target_alc, target_nihonshudo, coef)
101
+ _baume = baume
102
+
103
+ if _baume
104
+ target_alc - (_baume - target_nihonshudo * -0.1) * coef
105
+ end
106
+ end
107
+
108
+ def to_h
109
+ {
110
+ elapsed_time: elapsed_time,
111
+ time: time,
112
+ mark: mark,
113
+ temps: temps,
114
+ preset_temp: preset_temp,
115
+ room_temp: room_temp,
116
+ room_psychrometry: room_psychrometry,
117
+ acid: acid,
118
+ amino_acid: amino_acid,
119
+ alcohol: alcohol,
120
+ warmings: warmings,
121
+ note: note,
122
+
123
+ day: day,
124
+ day_label: day_label,
125
+ elapsed_time_with_offset: elapsed_time_with_offset,
126
+ baume: baume,
127
+ nihonshudo: nihonshudo,
128
+ display_baume: display_baume,
129
+ display_time: display_time,
130
+ moromi_day: moromi_day,
131
+ bmd: bmd,
132
+ }
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,123 @@
1
+ require 'toji/calendar/date_row'
2
+ require 'toji/calendar/date_column'
3
+
4
+ module Toji
5
+ class Calendar
6
+ attr_reader :products
7
+
8
+ def initialize
9
+ @products = []
10
+ end
11
+
12
+ def <<(product)
13
+ @products << product
14
+ self
15
+ end
16
+ alias_method :add, :<<
17
+
18
+ def date_rows
19
+ events = @products.map{|product| product.events}.flatten
20
+
21
+ result = {}
22
+ events.each {|event|
23
+ result[event.date] ||= DateRow.new(event.date)
24
+ result[event.date] << event
25
+ }
26
+
27
+ result
28
+ end
29
+
30
+ def table_data
31
+ events = @products.map{|product| product.events}.flatten
32
+
33
+ koji_len = events.select{|e| e.type==:koji}.map(&:group_index).max + 1
34
+ kake_len = events.select{|e| e.type==:kake}.map(&:group_index).max + 1
35
+ min_date = events.map(&:date).min
36
+ max_date = events.map(&:date).max
37
+
38
+ headers = [:date]
39
+
40
+ case koji_len
41
+ when 1
42
+ headers += [:koji]
43
+ when 2
44
+ headers += [:moto_koji, :moromi_koji]
45
+ else
46
+ headers += [:moto_koji]
47
+ (2..koji_len).each {|i|
48
+ headers << "moromi_koji#{i-1}"
49
+ }
50
+ end
51
+
52
+ headers += [:moto, :soe, :naka, :tome, :yodan][0...kake_len]
53
+ (5...kake_len).each {|i|
54
+ headers << "#{i}dan"
55
+ }
56
+
57
+ _date_rows = date_rows
58
+
59
+ rows = []
60
+
61
+ date = min_date
62
+ while date<=max_date
63
+ columns = [date.strftime("%m/%d")]
64
+
65
+ date_row = _date_rows[date]
66
+ if date_row
67
+ koji_len.times {|i|
68
+ columns << (date_row.kojis[i]&.column_events || [])
69
+ }
70
+ kake_len.times {|i|
71
+ columns << (date_row.kakes[i]&.column_events || [])
72
+ }
73
+ else
74
+ (koji_len + kake_len).times {
75
+ columns << []
76
+ }
77
+ end
78
+
79
+ rows << columns
80
+
81
+ date = date.tomorrow
82
+ end
83
+
84
+ {header: headers, rows: rows}
85
+ end
86
+
87
+ def table_text_data
88
+ data = table_data
89
+ data[:rows] = data[:rows].map {|row|
90
+ row.map {|column|
91
+ if Array===column
92
+ column.map{|c|
93
+ name = c[:product].name
94
+ weight = "%.17g" % c[:weight]
95
+ "#{name}: #{weight}"
96
+ }.join("<br>")
97
+ else
98
+ column
99
+ end
100
+ }
101
+ }
102
+ data
103
+ end
104
+
105
+ def table
106
+ data = table_text_data
107
+
108
+ Plotly::Plot.new(
109
+ data: [{
110
+ type: :table,
111
+ header: {
112
+ values: data[:header]
113
+ },
114
+ cells: {
115
+ values: data[:rows].transpose
116
+ },
117
+ }],
118
+ layout: {
119
+ }
120
+ )
121
+ end
122
+ end
123
+ end
@@ -1,5 +1,5 @@
1
1
  module Toji
2
- module Schedule
2
+ class Calendar
3
3
  class DateColumn
4
4
  attr_reader :events
5
5
 
@@ -26,13 +26,10 @@ module Toji
26
26
  }.join("<br>")
27
27
  end
28
28
 
29
- def to_h_a
29
+ def column_events
30
30
  event_groups.map {|es|
31
- product = es.first.product
32
31
  {
33
- product_id: product.id,
34
- product_name: product.name,
35
- product_color: product.color,
32
+ product: es.first.product,
36
33
  weight: es.map(&:weight).sum,
37
34
  }
38
35
  }
@@ -1,14 +1,14 @@
1
1
  module Toji
2
- module Schedule
2
+ class Calendar
3
3
  class DateRow
4
4
  attr_reader :date
5
5
  attr_reader :kojis
6
- attr_reader :rices
6
+ attr_reader :kakes
7
7
 
8
8
  def initialize(date)
9
9
  @date = date
10
10
  @kojis = []
11
- @rices = []
11
+ @kakes = []
12
12
  end
13
13
 
14
14
  def <<(event)
@@ -17,10 +17,10 @@ module Toji
17
17
  index = event.group_index
18
18
  @kojis[index] ||= DateColumn.new
19
19
  @kojis[index] << event
20
- when :rice
20
+ when :kake
21
21
  index = event.group_index
22
- @rices[index] ||= DateColumn.new
23
- @rices[index] << event
22
+ @kakes[index] ||= DateColumn.new
23
+ @kakes[index] << event
24
24
  end
25
25
  end
26
26
  alias_method :add, :<<
@@ -0,0 +1,10 @@
1
+ require 'toji/ingredient/rice'
2
+ require 'toji/ingredient/kake'
3
+ require 'toji/ingredient/koji'
4
+ require 'toji/ingredient/rice_rate'
5
+ require 'toji/ingredient/koji_rate'
6
+
7
+ module Toji
8
+ module Ingredient
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ require 'toji/ingredient/kake/base'
2
+ require 'toji/ingredient/kake/expected'
3
+ require 'toji/ingredient/kake/actual'
4
+
5
+ module Toji
6
+ module Ingredient
7
+ module Kake
8
+ def self.expected(raw, rice_rate: Recipe::RiceRate::DEFAULT)
9
+ Expected.new(raw, rice_rate: rice_rate)
10
+ end
11
+
12
+ def self.actual(raw, soaked, steamed, cooled)
13
+ Actual.new(raw, soaked, steamed, cooled)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ module Toji
2
+ module Ingredient
3
+ module Kake
4
+ class Actual
5
+ include Base
6
+ include Rice::ActualSteamable
7
+
8
+ def initialize(raw, soaked, steamed, cooled)
9
+ @raw = raw.to_f
10
+ @soaked = soaked.to_f
11
+ @steamed = steamed.to_f
12
+ @cooled = cooled.to_f
13
+ end
14
+
15
+ def *(other)
16
+ if Integer===other || Float===other
17
+ Actual.new(raw * other, soaked * other, steamed * other, cooled * other)
18
+ else
19
+ x, y = other.coerce(self)
20
+ x * y
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ module Toji
2
+ module Ingredient
3
+ module Kake
4
+ module Base
5
+ include Rice::Base
6
+
7
+ def +(other)
8
+ if Base===other
9
+ Actual.new(raw + other.raw, soaked + other.soaked, steamed + other.steamed, cooled + other.cooled)
10
+ else
11
+ x, y = other.coerce(self)
12
+ x + y
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,40 @@
1
+ module Toji
2
+ module Ingredient
3
+ module Kake
4
+ class Expected
5
+ include Base
6
+ include Rice::ExpectedSteamable
7
+
8
+ def initialize(raw, rice_rate: RiceRate::DEFAULT)
9
+ @raw = raw.to_f
10
+
11
+ @rice_rate = rice_rate
12
+ @soaked_rate = rice_rate.soaked_rate
13
+ @steamed_rate = rice_rate.steamed_rate
14
+ @cooled_rate = rice_rate.cooled_rate
15
+ end
16
+
17
+ def round(ndigit=0, half: :up)
18
+ self.class.new(@raw.round(ndigit, half: half), rice_rate: @rice_rate)
19
+ end
20
+
21
+ def *(other)
22
+ if Integer===other || Float===other
23
+ self.class.new(@raw * other, rice_rate: @rice_rate)
24
+ else
25
+ x, y = other.coerce(self)
26
+ x * y
27
+ end
28
+ end
29
+
30
+ def self.create(x)
31
+ if self===x
32
+ x
33
+ else
34
+ new(x)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,19 @@
1
+ require 'toji/ingredient/koji/base'
2
+ require 'toji/ingredient/koji/expected_fermentable'
3
+ require 'toji/ingredient/koji/expected'
4
+ require 'toji/ingredient/koji/actual_fermentable'
5
+ require 'toji/ingredient/koji/actual'
6
+
7
+ module Toji
8
+ module Ingredient
9
+ module Koji
10
+ def self.expected(raw, rice_rate: Recipe::RiceRate::DEFAULT, koji_rate: Recipe::KojiRate::DEFAULT)
11
+ Expected.new(raw, rice_rate: rice_rate, koji_rate: koji_rate)
12
+ end
13
+
14
+ def self.actual(raw, soaked, steamed, cooled, tanekoji, dekoji)
15
+ Actual.new(raw, soaked, steamed, cooled, tanekoji, dekoji)
16
+ end
17
+ end
18
+ end
19
+ end