toji 2.12.0 → 2.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/example/calendar.ipynb +42 -51
  3. data/example/calendar.yaml +6 -6
  4. data/example/calendar_file.ipynb +35 -35
  5. data/example/example_core.rb +1039 -234
  6. data/example/kake_ingredient.rb +21 -15
  7. data/example/koji_ingredient.rb +31 -21
  8. data/example/{koji_making.ipynb → koji_progress.ipynb} +14 -14
  9. data/example/{koji_making.rb → koji_progress.rb} +3 -2
  10. data/example/{koji_making.yaml → koji_progress.yaml} +8 -9
  11. data/example/{koji_making_multi.ipynb → koji_progress_multi.ipynb} +21 -22
  12. data/example/{moromi.ipynb → moromi_progress.ipynb} +22 -22
  13. data/example/{moromi.rb → moromi_progress.rb} +3 -2
  14. data/example/{moromi.yaml → moromi_progress.yaml} +0 -0
  15. data/example/moto_progress.ipynb +121 -0
  16. data/example/{moto.rb → moto_progress.rb} +3 -2
  17. data/example/{moto.yaml → moto_progress.yaml} +14 -15
  18. data/example/recipe.rb +44 -32
  19. data/lib/toji.rb +4 -2
  20. data/lib/toji/calendar.rb +12 -12
  21. data/lib/toji/calendar/date_column.rb +8 -8
  22. data/lib/toji/calendar/date_row.rb +6 -6
  23. data/lib/toji/ingredient.rb +6 -2
  24. data/lib/toji/ingredient/alcohol.rb +14 -0
  25. data/lib/toji/ingredient/base.rb +12 -0
  26. data/lib/toji/ingredient/kake.rb +3 -9
  27. data/lib/toji/ingredient/koji.rb +19 -10
  28. data/lib/toji/ingredient/lactic_acid.rb +14 -0
  29. data/lib/toji/ingredient/rice.rb +51 -4
  30. data/lib/toji/ingredient/tanekoji.rb +29 -0
  31. data/lib/toji/ingredient/water.rb +18 -0
  32. data/lib/toji/ingredient/yeast.rb +21 -0
  33. data/lib/toji/processing.rb +18 -0
  34. data/lib/toji/{event → processing}/base.rb +1 -3
  35. data/lib/toji/processing/cooled_rice.rb +22 -0
  36. data/lib/toji/processing/cooled_rice_element.rb +8 -0
  37. data/lib/toji/processing/dekoji.rb +22 -0
  38. data/lib/toji/processing/dekoji_element.rb +8 -0
  39. data/lib/toji/processing/kake_processing.rb +7 -0
  40. data/lib/toji/processing/koji_processing.rb +10 -0
  41. data/lib/toji/processing/rice_processing.rb +19 -0
  42. data/lib/toji/processing/soaked_rice.rb +49 -0
  43. data/lib/toji/processing/soaked_rice_element.rb +18 -0
  44. data/lib/toji/processing/steamed_rice.rb +22 -0
  45. data/lib/toji/processing/steamed_rice_element.rb +8 -0
  46. data/lib/toji/product.rb +11 -32
  47. data/lib/toji/product/schedule_factory.rb +80 -0
  48. data/lib/toji/progress.rb +23 -0
  49. data/lib/toji/progress/base_progress.rb +37 -0
  50. data/lib/toji/progress/base_state.rb +36 -0
  51. data/lib/toji/progress/builder.rb +53 -0
  52. data/lib/toji/progress/graph.rb +11 -0
  53. data/lib/toji/{brew → progress}/graph/ab.rb +6 -6
  54. data/lib/toji/{brew → progress}/graph/bmd.rb +2 -2
  55. data/lib/toji/{brew/graph/multi_progress.rb → progress/graph/multi_progress_note.rb} +11 -11
  56. data/lib/toji/{brew/graph/progress.rb → progress/graph/progress_note.rb} +20 -18
  57. data/lib/toji/progress/koji_progress.rb +15 -0
  58. data/lib/toji/progress/koji_state.rb +23 -0
  59. data/lib/toji/{brew/moromi.rb → progress/moromi_progress.rb} +10 -6
  60. data/lib/toji/progress/moromi_state.rb +77 -0
  61. data/lib/toji/progress/moto_progress.rb +15 -0
  62. data/lib/toji/progress/moto_state.rb +31 -0
  63. data/lib/toji/progress/progress.rb +16 -0
  64. data/lib/toji/progress/state.rb +22 -0
  65. data/lib/toji/progress/state/baume_to_nihonshudo.rb +21 -0
  66. data/lib/toji/progress/state/nihonshudo_to_baume.rb +21 -0
  67. data/lib/toji/recipe.rb +51 -39
  68. data/lib/toji/recipe/ab_expect.rb +2 -2
  69. data/lib/toji/recipe/action.rb +2 -2
  70. data/lib/toji/recipe/step.rb +106 -71
  71. data/lib/toji/schedule.rb +5 -0
  72. data/lib/toji/schedule/action_schedule.rb +9 -0
  73. data/lib/toji/schedule/base.rb +9 -0
  74. data/lib/toji/schedule/kake_schedule.rb +11 -0
  75. data/lib/toji/schedule/koji_schedule.rb +11 -0
  76. data/lib/toji/schedule/rice_schedule.rb +16 -0
  77. data/lib/toji/utils.rb +43 -0
  78. data/lib/toji/version.rb +1 -1
  79. metadata +61 -47
  80. data/lib/toji/brew.rb +0 -18
  81. data/lib/toji/brew/base.rb +0 -55
  82. data/lib/toji/brew/builder.rb +0 -98
  83. data/lib/toji/brew/graph.rb +0 -11
  84. data/lib/toji/brew/koji.rb +0 -11
  85. data/lib/toji/brew/moto.rb +0 -11
  86. data/lib/toji/brew/state.rb +0 -122
  87. data/lib/toji/brew/wrapped_state.rb +0 -109
  88. data/lib/toji/event.rb +0 -5
  89. data/lib/toji/event/action_event.rb +0 -12
  90. data/lib/toji/event/kake_event.rb +0 -13
  91. data/lib/toji/event/koji_event.rb +0 -19
  92. data/lib/toji/event/rice_event.rb +0 -34
  93. data/lib/toji/ingredient/kake/actual.rb +0 -26
  94. data/lib/toji/ingredient/kake/base.rb +0 -18
  95. data/lib/toji/ingredient/kake/expected.rb +0 -40
  96. data/lib/toji/ingredient/koji/actual.rb +0 -29
  97. data/lib/toji/ingredient/koji/actual_fermentable.rb +0 -15
  98. data/lib/toji/ingredient/koji/base.rb +0 -35
  99. data/lib/toji/ingredient/koji/expected.rb +0 -45
  100. data/lib/toji/ingredient/koji/expected_fermentable.rb +0 -15
  101. data/lib/toji/ingredient/koji_rate.rb +0 -16
  102. data/lib/toji/ingredient/rice/actual_steamable.rb +0 -27
  103. data/lib/toji/ingredient/rice/base.rb +0 -40
  104. data/lib/toji/ingredient/rice/expected_steamable.rb +0 -27
  105. data/lib/toji/ingredient/rice_rate.rb +0 -23
  106. data/lib/toji/product/event_factory.rb +0 -70
@@ -0,0 +1,18 @@
1
+ module Toji
2
+ module Processing
3
+ module SoakedRiceElement
4
+ # 白米重量
5
+ attr_reader :weight
6
+
7
+ # 浸漬時間
8
+ attr_reader :soaking_time
9
+
10
+ # 浸漬米重量
11
+ attr_reader :soaked
12
+
13
+ def soaking_ratio
14
+ (soaked.to_f - weight.to_f) / weight.to_f
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ module Toji
2
+ module Processing
3
+ module SteamedRice
4
+ # 親 (belongs_to: Toji::Processing::RiceProcessing)
5
+ attr_reader :processing
6
+
7
+ # 要素 (has_many: Toji::Processing::SteamedRiceElement)
8
+ attr_reader :elements
9
+
10
+ # 蒸米総重量
11
+ def weight
12
+ (elements || []).map(&:weight).sum
13
+ end
14
+
15
+ # 蒸米歩合
16
+ def steaming_ratio
17
+ raw_weight = processing.soaked_rice.weight.to_f
18
+ (weight.to_f - raw_weight) / raw_weight
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,8 @@
1
+ module Toji
2
+ module Processing
3
+ module SteamedRiceElement
4
+ # 蒸米重量
5
+ attr_reader :weight
6
+ end
7
+ end
8
+ end
@@ -1,42 +1,21 @@
1
- require 'toji/product/event_factory'
1
+ require 'toji/product/schedule_factory'
2
2
 
3
3
  module Toji
4
4
  module Product
5
- attr_accessor :name
6
- attr_accessor :recipe
7
- attr_accessor :base_date
5
+ # @dynamic name
6
+ # @dynamic recipe
7
+ # @dynamic base_date
8
8
 
9
- attr_accessor :koji_events
10
- attr_accessor :kake_events
11
- attr_accessor :action_events
9
+ # @dynamic koji_schedules
10
+ # @dynamic kake_schedules
11
+ # @dynamic action_schedules
12
12
 
13
- def koji_dates
14
- date = base_date
15
- recipe.steps.map {|step|
16
- date = date.next_day(step.koji_interval_days)
17
- }
13
+ def rice_schedules
14
+ koji_schedules + kake_schedules
18
15
  end
19
16
 
20
- def kake_dates
21
- date = base_date
22
- recipe.steps.map {|step|
23
- date = date.next_day(step.kake_interval_days)
24
- }
25
- end
26
-
27
- def action_dates
28
- date = base_date
29
- recipe.actions.map {|action|
30
- date = date.next_day(action.interval_days)
31
- }
32
- end
33
-
34
- def rice_events
35
- koji_events + kake_events
36
- end
37
-
38
- def events
39
- rice_events + action_events
17
+ def schedules
18
+ rice_schedules + action_schedules
40
19
  end
41
20
  end
42
21
  end
@@ -0,0 +1,80 @@
1
+ module Toji
2
+ module Product
3
+ module ScheduleFactory
4
+
5
+ def create_koji_schedule(date:, step_indexes:, kojis:)
6
+ raise Error, "implement required: create_koji_schedule"
7
+ end
8
+
9
+ def create_kake_schedule(date:, step_indexes:, kakes:)
10
+ raise Error, "implement required: create_kake_schedule"
11
+ end
12
+
13
+ def create_action_schedule(date:, action_index:, action:)
14
+ raise Error, "implement required: create_action_schedule"
15
+ end
16
+
17
+ def koji_schedules
18
+ recipe.steps.inject([]) {|result, step|
19
+ step.kojis&.each {|koji|
20
+ result << {
21
+ step_index: {
22
+ index: step.index,
23
+ subindex: step.subindex,
24
+ },
25
+ date: base_date.next_day(koji.interval_days),
26
+ koji: koji,
27
+ }
28
+ }
29
+ result
30
+ }.select {|schedule|
31
+ 0<schedule[:koji]&.weight.to_f
32
+ }.group_by {|schedule|
33
+ [schedule[:date], schedule[:koji].group_key]
34
+ }.map {|(date, _group_key), schedules|
35
+ create_koji_schedule(
36
+ date: date,
37
+ step_indexes: schedules.map {|schedule| schedule[:step_index]}.sort_by {|x| [x[:index], x[:subindex]]},
38
+ kojis: schedules.map{|schedule| schedule[:koji]},
39
+ )
40
+ }
41
+ end
42
+
43
+ def kake_schedules
44
+ recipe.steps.inject([]) {|result, step|
45
+ step.kakes&.each {|kake|
46
+ result << {
47
+ step_index: {
48
+ index: step.index,
49
+ subindex: step.subindex,
50
+ },
51
+ date: base_date.next_day(kake.interval_days),
52
+ kake: kake,
53
+ }
54
+ }
55
+ result
56
+ }.select {|schedule|
57
+ 0<schedule[:kake]&.weight.to_f
58
+ }.group_by {|schedule|
59
+ [schedule[:date], schedule[:kake].group_key, schedule[:step_index]]
60
+ }.map {|(date, _group_key, _step_index), schedules|
61
+ create_kake_schedule(
62
+ date: date,
63
+ step_indexes: schedules.map {|schedule| schedule[:step_index]}.sort_by {|x| [x[:index], x[:subindex]]},
64
+ kakes: schedules.map{|schedule| schedule[:kake]},
65
+ )
66
+ }
67
+ end
68
+
69
+ def action_schedules
70
+ recipe.actions.map.with_index {|action, i|
71
+ create_action_schedule(
72
+ date: base_date.next_day(action.interval_days),
73
+ action_index: i,
74
+ action: action,
75
+ )
76
+ }
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,23 @@
1
+ module Toji
2
+ module Progress
3
+ SECOND = 1
4
+ MINUTE = 60 * SECOND
5
+ HOUR = 60 * MINUTE
6
+ DAY = 24 * HOUR
7
+ end
8
+ end
9
+
10
+ require 'toji/progress/state'
11
+ require 'toji/progress/base_state'
12
+ require 'toji/progress/koji_state'
13
+ require 'toji/progress/moto_state'
14
+ require 'toji/progress/moromi_state'
15
+
16
+ require 'toji/progress/progress'
17
+ require 'toji/progress/base_progress'
18
+ require 'toji/progress/koji_progress'
19
+ require 'toji/progress/moto_progress'
20
+ require 'toji/progress/moromi_progress'
21
+
22
+ require 'toji/progress/builder'
23
+ require 'toji/progress/graph'
@@ -0,0 +1,37 @@
1
+ module Toji
2
+ module Progress
3
+ module BaseProgress
4
+ include Progress
5
+
6
+ def base_time
7
+ states&.first&.time&.to_time
8
+ end
9
+
10
+ def day_offset
11
+ t = base_time
12
+ if t
13
+ offset = (t - Time.mktime(t.year, t.month, t.day)).to_i
14
+ (DAY - date_line + offset) % DAY
15
+ end
16
+ end
17
+
18
+ def days
19
+ ((states&.last&.elapsed_time_with_offset&.to_f + 1) / DAY).ceil
20
+ end
21
+
22
+ def day_labels
23
+ days.times.map(&:succ).map(&:to_s)
24
+ end
25
+
26
+ def all_keys
27
+ BaseState::REQUIRED_KEYS
28
+ end
29
+
30
+ def has_keys
31
+ all_keys.select {|k|
32
+ states.find {|s| s.send(k).present?}
33
+ }
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,36 @@
1
+ module Toji
2
+ module Progress
3
+ module BaseState
4
+ include State
5
+
6
+ REQUIRED_KEYS = [
7
+ :time,
8
+ :elapsed_time,
9
+ :day,
10
+ :day_label,
11
+ :display_time,
12
+ :mark,
13
+ ].freeze
14
+
15
+ def elapsed_time
16
+ time - progress.base_time
17
+ end
18
+
19
+ def elapsed_time_with_offset
20
+ elapsed_time + progress.day_offset
21
+ end
22
+
23
+ def day
24
+ ((elapsed_time_with_offset.to_f + 1) / DAY).ceil
25
+ end
26
+
27
+ def day_label
28
+ progress.day_labels[day - 1]
29
+ end
30
+
31
+ def display_time(format="%m/%d %H:%M")
32
+ time.strftime(format)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,53 @@
1
+ module Toji
2
+ module Progress
3
+ class Builder
4
+
5
+ def initialize(progress_cls, state_cls)
6
+ @progress_cls = progress_cls
7
+ @state_cls = state_cls
8
+ @states = []
9
+ @date_line = 0
10
+ @prefix_day_labels = nil
11
+ end
12
+
13
+ def <<(state)
14
+ @states += [state].flatten.map {|state|
15
+ if State===state
16
+ state
17
+ else
18
+ @state_cls.create(state)
19
+ end
20
+ }
21
+ self
22
+ end
23
+ alias_method :add, :<<
24
+
25
+ def date_line(val, unit=SECOND)
26
+ @date_line = (val * unit).to_i
27
+ self
28
+ end
29
+
30
+ def prefix_day_labels(val)
31
+ @prefix_day_labels = val
32
+ self
33
+ end
34
+
35
+ def build
36
+ progress = @progress_cls.new
37
+
38
+ states = @states.map{|s|
39
+ s.progress = progress
40
+ s
41
+ }.sort_by(&:time)
42
+
43
+ progress.states = states
44
+ progress.date_line = @date_line
45
+ if progress.respond_to?(:prefix_day_labels=)
46
+ progress.prefix_day_labels = @prefix_day_labels
47
+ end
48
+
49
+ progress
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,11 @@
1
+ require 'toji/progress/graph/progress_note'
2
+ require 'toji/progress/graph/multi_progress_note'
3
+ require 'toji/progress/graph/bmd'
4
+ require 'toji/progress/graph/ab'
5
+
6
+ module Toji
7
+ module Progress
8
+ module Graph
9
+ end
10
+ end
11
+ end
@@ -1,5 +1,5 @@
1
1
  module Toji
2
- module Brew
2
+ module Progress
3
3
  module Graph
4
4
  class Ab
5
5
  def initialize
@@ -34,7 +34,7 @@ module Toji
34
34
  result = []
35
35
 
36
36
  @actuals.each {|moromi, name|
37
- states = moromi.wrapped_states.select{|s| s.alcohol && s.baume}
37
+ states = moromi.states.select{|s| s.alcohol && s.baume}
38
38
 
39
39
  xs = states.map(&:alcohol)
40
40
  ys = states.map(&:baume)
@@ -57,14 +57,14 @@ module Toji
57
57
 
58
58
  def min_baume
59
59
  @actuals.map {|moromi, name|
60
- moromi.wrapped_states.map(&:baume).compact.min
61
- }.compact.min || 0
60
+ moromi.states.map(&:baume).compact.min
61
+ }.compact.min || 0.0
62
62
  end
63
63
 
64
64
  def max_baume
65
65
  @actuals.map {|moromi, name|
66
- moromi.wrapped_states.map(&:baume).compact.max
67
- }.compact.max || 0
66
+ moromi.states.map(&:baume).compact.max
67
+ }.compact.max || 0.0
68
68
  end
69
69
 
70
70
  def plot
@@ -1,5 +1,5 @@
1
1
  module Toji
2
- module Brew
2
+ module Progress
3
3
  module Graph
4
4
  class Bmd
5
5
 
@@ -16,7 +16,7 @@ module Toji
16
16
  result = []
17
17
 
18
18
  @actuals.each {|moromi, name|
19
- states = moromi.wrapped_states.select{|s| s.moromi_day && s.bmd}
19
+ states = moromi.states.select{|s| s.moromi_day && s.bmd}
20
20
 
21
21
  xs = states.map(&:moromi_day).map{|d| d*DAY}
22
22
  ys = states.map(&:bmd)
@@ -1,7 +1,7 @@
1
1
  module Toji
2
- module Brew
2
+ module Progress
3
3
  module Graph
4
- class MultiProgress
4
+ class MultiProgressNote
5
5
 
6
6
  LINE_DASHES = [
7
7
  :solid,
@@ -23,15 +23,15 @@ module Toji
23
23
  end
24
24
 
25
25
  case source
26
- when Progress
26
+ when ProgressNote
27
27
  progress = source.dup
28
28
  progress.name = name
29
29
  progress.dash = dash
30
30
  progress.enable_annotations = enable_annotations
31
- when Base
32
- progress = source.progress(name: name, dash: dash, enable_annotations: enable_annotations)
31
+ when Progress
32
+ progress = source.progress_note(name: name, dash: dash, enable_annotations: enable_annotations)
33
33
  else
34
- raise Error, "ArgumentError: Progress or Base required"
34
+ raise Error, "ArgumentError: Toji::Progress::Graph::ProgressNote or Toji::Progress::Progress required"
35
35
  end
36
36
 
37
37
  @progresses << progress
@@ -52,17 +52,17 @@ module Toji
52
52
  end
53
53
 
54
54
  def plot(keys=nil)
55
- brews = @progresses.map(&:brew)
56
- max_brew_days = brews.map(&:days).max
57
- index = brews.index{|brew| brew.days==max_brew_days}
58
- day_labels = brews[index].day_labels
55
+ progresses = @progresses.map(&:progress)
56
+ max_days = progresses.map(&:days).max
57
+ index = progresses.index{|progress| progress.days==max_days}
58
+ day_labels = progresses[index].day_labels
59
59
 
60
60
  Plotly::Plot.new(
61
61
  data: plot_data(keys),
62
62
  layout: {
63
63
  xaxis: {
64
64
  dtick: DAY,
65
- tickvals: max_brew_days.times.map{|d| d*DAY},
65
+ tickvals: max_days.times.map{|d| d*DAY},
66
66
  ticktext: day_labels
67
67
  },
68
68
  annotations: annotations,