toji 0.1.0 → 1.0.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.
data/lib/toji/graph/ab.rb CHANGED
@@ -9,27 +9,27 @@ module Toji
9
9
  @expects = []
10
10
  end
11
11
 
12
- def actual(jobs, name=:actual)
13
- data = jobs.map{|j| [j.time || j.elapsed_time + jobs.day_offset, j.alcohol, j.baume]}.select{|a| a[1] && a[2]}
14
- xs = data.map{|a| a[1]}
15
- ys = data.map{|a| a[2]}
16
- texts = data.map{|a| "%s<br />alc=%s, be=%s" % a}
17
- @actuals << {x: xs, y: ys, text: texts, name: name}
18
-
12
+ def actual(moromi, name=:actual)
13
+ @actuals << [moromi, name]
19
14
  self
20
15
  end
21
16
 
22
17
  def expect(alcohol, nihonshudo)
23
18
  @expects << [alcohol.to_f, nihonshudo.to_f]
24
-
25
19
  self
26
20
  end
27
21
 
28
22
  def data
29
23
  result = []
30
24
 
31
- @actuals.each {|a|
32
- result << a
25
+ @actuals.each {|moromi, name|
26
+ data = moromi.map{|j| [j.time || j.elapsed_time + moromi.day_offset, j.alcohol, j.baume]}.select{|a| a[1] && a[2]}
27
+
28
+ xs = data.map{|a| a[1]}
29
+ ys = data.map{|a| a[2]}
30
+ texts = data.map{|a| "%s<br />alc=%s, be=%s" % a}
31
+
32
+ result << {x: xs, y: ys, text: texts, name: name}
33
33
  }
34
34
 
35
35
  @expects.each {|alcohol, nihonshudo|
@@ -44,18 +44,22 @@ module Toji
44
44
  result
45
45
  end
46
46
 
47
- def plot
48
- d = data
47
+ def min_baume
48
+ data.map{|h| h[:y].min}.min || 0
49
+ end
50
+
51
+ def max_baume
52
+ data.map{|h| h[:y].max}.max || 0
53
+ end
49
54
 
50
- #min_baume = d.map{|h| h[:y].min}.min || 0
51
- #min_baume = [min_baume-1, 0].min
52
- min_baume = 0
55
+ def plot
56
+ #_min_baume = [min_baume-1, 0].min
57
+ _min_baume = 0
53
58
 
54
- max_baume = d.map{|h| h[:y].max}.max || 0
55
- max_baume = [max_baume+1, 10].max
59
+ _max_baume = [max_baume+1, 10].max
56
60
 
57
61
  Plotly::Plot.new(
58
- data: d,
62
+ data: data,
59
63
  layout: {
60
64
  xaxis: {
61
65
  title: "Alcohol",
@@ -65,7 +69,7 @@ module Toji
65
69
  yaxis: {
66
70
  title: "Baume",
67
71
  dtick: 1,
68
- range: [min_baume, max_baume],
72
+ range: [_min_baume, _max_baume],
69
73
  }
70
74
  }
71
75
  )
@@ -0,0 +1,56 @@
1
+ module Toji
2
+ module Graph
3
+ class Bmd
4
+
5
+ def initialize
6
+ @actuals = []
7
+ @expects = []
8
+ end
9
+
10
+ def actual(moromi, name=:actual)
11
+ @actuals << [moromi, name]
12
+ self
13
+ end
14
+
15
+ def data
16
+ result = []
17
+
18
+ @actuals.each {|moromi, name|
19
+ jobs = moromi.select{|j| j.moromi_time && j.bmd}
20
+
21
+ xs = jobs.map(&:moromi_time)
22
+ ys = jobs.map(&:bmd)
23
+ texts = jobs.map{|j| "%s<br />moromi day=%d, be=%s, bmd=%s" % [j.time || j.elapsed_time + moromi.day_offset, j.moromi_day, j.baume, j.bmd]}
24
+
25
+ result << {x: xs, y: ys, text: texts, name: name}
26
+ }
27
+
28
+ result
29
+ end
30
+
31
+ def max_moromi_day
32
+ @actuals.map(&:first).map(&:moromi_days).max
33
+ end
34
+
35
+ def plot
36
+ _max_moromi_day = [max_moromi_day, 14].max
37
+
38
+ Plotly::Plot.new(
39
+ data: data,
40
+ layout: {
41
+ xaxis: {
42
+ title: "Moromi day",
43
+ dtick: Product::Job::DAY,
44
+ range: [1, _max_moromi_day].map{|d| d*Product::Job::DAY},
45
+ tickvals: _max_moromi_day.times.map{|d| d*Product::Job::DAY},
46
+ ticktext: _max_moromi_day.times.map(&:succ)
47
+ },
48
+ yaxis: {
49
+ title: "BMD",
50
+ }
51
+ }
52
+ )
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,84 @@
1
+ module Toji
2
+ module Graph
3
+ class Progress
4
+
5
+ def initialize(product)
6
+ @product = product
7
+ end
8
+
9
+ def data(keys=nil)
10
+ data = @product.map(&:to_h).map(&:compact)
11
+ if !keys
12
+ keys = data.map(&:keys).flatten.uniq
13
+ end
14
+
15
+ result = []
16
+
17
+ keys &= [:temps, :preset_temp, :room_temp, :room_psychrometry, :baume, :acid, :amino_acid, :alcohol]
18
+
19
+ keys.each {|key|
20
+ xs = []
21
+ ys = []
22
+ text = []
23
+ data.each {|h|
24
+ if h[key]
25
+ [h[key]].flatten.each_with_index {|v,i|
26
+ xs << h[:elapsed_time] + i + @product.day_offset
27
+ ys << v
28
+ text << h[:display_time]
29
+ }
30
+ end
31
+ }
32
+
33
+ line_shape = :linear
34
+ if key==:preset_temp
35
+ line_shape = :hv
36
+ end
37
+
38
+ result << {x: xs, y: ys, text: text, name: key, line: {shape: line_shape}}
39
+ }
40
+
41
+ if 0<@product.day_offset
42
+ result = result.map{|h|
43
+ h[:x].unshift(0)
44
+ h[:y].unshift(nil)
45
+ h[:text].unshift(nil)
46
+ h
47
+ }
48
+ end
49
+
50
+ result
51
+ end
52
+
53
+ def annotations
54
+ @product.select{|j| j.id}.map {|j|
55
+ {
56
+ x: j.elapsed_time + @product.day_offset,
57
+ y: j.temps.first || 0,
58
+ xref: 'x',
59
+ yref: 'y',
60
+ text: j.id,
61
+ showarrow: true,
62
+ arrowhead: 1,
63
+ ax: 0,
64
+ ay: -40
65
+ }
66
+ }
67
+ end
68
+
69
+ def plot
70
+ Plotly::Plot.new(
71
+ data: data,
72
+ layout: {
73
+ xaxis: {
74
+ dtick: Product::Job::DAY,
75
+ tickvals: @product.days.times.map{|d| d*Product::Job::DAY},
76
+ ticktext: @product.day_labels
77
+ },
78
+ annotations: annotations,
79
+ }
80
+ )
81
+ end
82
+ end
83
+ end
84
+ end
data/lib/toji/graph.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'toji/graph/progress'
2
+ require 'toji/graph/bmd'
1
3
  require 'toji/graph/ab'
2
4
 
3
5
  module Toji
@@ -0,0 +1,74 @@
1
+ module Toji
2
+ module Product
3
+ class Base
4
+ include Enumerable
5
+ extend JobAccessor
6
+
7
+ attr_accessor :date_line
8
+ attr_reader :day_offset
9
+
10
+ def initialize(arr=[], date_line: 0)
11
+ @_arr = []
12
+ @_hash = {}
13
+ @date_line = date_line
14
+ @day_offset = 0
15
+
16
+ arr.each {|j|
17
+ self << j
18
+ }
19
+ end
20
+
21
+ def [](id)
22
+ @_hash[id]
23
+ end
24
+
25
+ def <<(job)
26
+ job = Job.create(job)
27
+ if job.id
28
+ if @_hash[job.id]
29
+ @_arr.delete(@_hash[job.id])
30
+ end
31
+ @_hash[job.id] = job
32
+ end
33
+ @_arr << job
34
+ job.jobs = self
35
+ _normalization
36
+ self
37
+ end
38
+ alias_method :add, :<<
39
+
40
+ def _normalization
41
+ min_time = @_arr.select{|j| j.time}.map(&:time).sort.first
42
+
43
+ if min_time
44
+ @_arr.each {|j|
45
+ if j.time
46
+ j.elapsed_time = (j.time - min_time).to_i
47
+ else
48
+ j.time = min_time + j.elapsed_time
49
+ end
50
+ }
51
+ end
52
+
53
+ @_arr = @_arr.sort{|a,b| a.elapsed_time<=>b.elapsed_time}
54
+
55
+ t = @_arr.first&.time
56
+ if t
57
+ @day_offset = t - Time.mktime(t.year, t.month, t.day)
58
+ else
59
+ @day_offset = 0
60
+ end
61
+ @day_offset += ((24 - @date_line) % 24) * Job::HOUR
62
+ end
63
+
64
+ def each(&block)
65
+ _normalization
66
+ @_arr.each(&block)
67
+ end
68
+
69
+ def days
70
+ ((to_a.last.elapsed_time.to_f + @date_line * Job::HOUR) / Job::DAY).ceil + 1
71
+ end
72
+ end
73
+ end
74
+ end
@@ -1,5 +1,5 @@
1
1
  module Toji
2
- module Progress
2
+ module Product
3
3
  class Job
4
4
  HOUR = 60 * 60
5
5
  DAY = 24 * HOUR
@@ -13,8 +13,7 @@ module Toji
13
13
  attr_accessor :time
14
14
  attr_accessor :elapsed_time
15
15
  attr_accessor :id
16
- attr_accessor :before_temp
17
- attr_accessor :after_temp
16
+ attr_accessor :temps
18
17
 
19
18
  attr_accessor :preset_temp
20
19
  attr_accessor :room_temp
@@ -30,15 +29,14 @@ module Toji
30
29
  attr_accessor :note
31
30
 
32
31
  def initialize(
33
- time: nil, elapsed_time: nil, id: nil, before_temp: nil, after_temp: nil,
32
+ time: nil, elapsed_time: nil, id: nil, temps: nil,
34
33
  preset_temp: nil, room_temp: nil, room_psychrometry: nil,
35
34
  baume: nil, nihonshudo: nil, acid: nil, amino_acid: nil, alcohol: nil,
36
35
  warming: nil, note: nil)
37
36
  @time = time
38
37
  @elapsed_time = elapsed_time
39
38
  @id = id
40
- @before_temp = before_temp
41
- @after_temp = after_temp
39
+ self.temps = temps
42
40
 
43
41
  @preset_temp = preset_temp
44
42
  @room_temp = room_temp
@@ -54,18 +52,8 @@ module Toji
54
52
  @note = note
55
53
  end
56
54
 
57
- def temps
58
- result = []
59
-
60
- if @before_temp
61
- result << @before_temp
62
- end
63
-
64
- if @after_temp
65
- result << @after_temp
66
- end
67
-
68
- result
55
+ def temps=(val)
56
+ @temps = [val].flatten.select{|t| t}
69
57
  end
70
58
 
71
59
  def baume
@@ -86,7 +74,7 @@ module Toji
86
74
  end
87
75
  end
88
76
 
89
- def baume_display
77
+ def display_baume
90
78
  if @baume || @nihonshudo
91
79
  b = baume
92
80
  if b<3.0
@@ -97,6 +85,14 @@ module Toji
97
85
  end
98
86
  end
99
87
 
88
+ def display_time(format="%m/%d %H:%M")
89
+ if @time
90
+ time.strftime(format)
91
+ else
92
+ Time.at(elapsed_time).strftime(format)
93
+ end
94
+ end
95
+
100
96
  def moromi_time
101
97
  tome = jobs[:tome]
102
98
  if tome
@@ -124,6 +120,14 @@ module Toji
124
120
  end
125
121
  end
126
122
 
123
+ def expected_alcohol(target_alc, target_nihonshudo, coef)
124
+ _baume = baume
125
+
126
+ if _baume
127
+ target_alc - (_baume - target_nihonshudo * -0.1) * coef
128
+ end
129
+ end
130
+
127
131
  def warmings
128
132
  result = []
129
133
  if @warming & WARM_DAKI
@@ -142,10 +146,9 @@ module Toji
142
146
  {
143
147
  time: time,
144
148
  elapsed_time: elapsed_time,
149
+ display_time: display_time,
145
150
  id: id,
146
151
  preset_temp: preset_temp,
147
- before_temp: before_temp,
148
- after_temp: after_temp,
149
152
  temps: temps,
150
153
  room_temp: room_temp,
151
154
  room_psychrometry: room_psychrometry,
@@ -160,6 +163,14 @@ module Toji
160
163
  note: note,
161
164
  }
162
165
  end
166
+
167
+ def self.create(j)
168
+ if Job===j
169
+ j
170
+ else
171
+ new(**j.to_h)
172
+ end
173
+ end
163
174
  end
164
175
  end
165
176
  end
@@ -1,5 +1,5 @@
1
1
  module Toji
2
- module Progress
2
+ module Product
3
3
  module JobAccessor
4
4
  def job_reader(*args)
5
5
  args.each {|arg|
@@ -1,67 +1,62 @@
1
1
  module Toji
2
- module Progress
3
- class MakeKoji
4
- extend JobAccessor
2
+ module Product
3
+ class KojiMaking < Base
5
4
 
6
5
  TEMPLATES = {
7
6
  default: [
8
7
  Job.new(
9
8
  elapsed_time: 0 * Job::HOUR,
10
9
  id: :hikikomi,
11
- after_temp: 35.0,
10
+ temps: 35.0,
12
11
  room_temp: 28.0,
13
12
  room_psychrometry: nil,
14
13
  ),
15
14
  Job.new(
16
15
  elapsed_time: 1 * Job::HOUR,
17
16
  id: :tokomomi,
18
- after_temp: 32.0,
17
+ temps: 32.0,
19
18
  room_temp: 28.0,
20
19
  room_psychrometry: nil,
21
20
  ),
22
21
  Job.new(
23
22
  elapsed_time: 9 * Job::HOUR,
24
23
  id: :kirikaeshi,
25
- before_temp: 32.0,
26
- after_temp: 31.0,
24
+ temps: [32.0, 31.0],
27
25
  room_temp: 28.0,
28
26
  room_psychrometry: nil,
29
27
  ),
30
28
  Job.new(
31
29
  elapsed_time: 21 * Job::HOUR,
32
30
  id: :mori,
33
- before_temp: 35.0,
34
- after_temp: 33.0,
31
+ temps: [35.0, 33.0],
35
32
  room_temp: 28.0,
36
33
  room_psychrometry: 4,
37
34
  ),
38
35
  Job.new(
39
36
  elapsed_time: 29 * Job::HOUR,
40
37
  id: :naka_shigoto,
41
- before_temp: 37.0,
42
- after_temp: 35.0,
38
+ temps: [37.0, 35.0],
43
39
  room_temp: 28.0,
44
40
  room_psychrometry: 4,
45
41
  ),
46
42
  Job.new(
47
43
  elapsed_time: 35 * Job::HOUR,
48
44
  id: :shimai_shigoto,
49
- before_temp: 38.0,
50
- after_temp: 37.0,
45
+ temps: [38.0, 37.0],
51
46
  room_temp: 28.0,
52
47
  room_psychrometry: 5,
53
48
  ),
54
49
  Job.new(
55
50
  elapsed_time: 39 * Job::HOUR,
56
51
  id: :tsumikae,
57
- after_temp: 40.0,
52
+ temps: 40.0,
58
53
  room_temp: 28.0,
59
54
  room_psychrometry: 5,
60
55
  ),
61
56
  Job.new(
62
57
  elapsed_time: 44 * Job::HOUR,
63
58
  id: :dekoji,
64
- after_temp: 40.0,
59
+ temps: 40.0,
65
60
  room_temp: 28.0,
66
61
  room_psychrometry: 5,
67
62
  ),
@@ -79,17 +74,16 @@ module Toji
79
74
  job_reader :dekoji
80
75
 
81
76
 
82
- def initialize(jobs=[])
83
- @jobs = Jobs.new(jobs)
77
+ def initialize(jobs=[], date_line: 0)
78
+ super(jobs, date_line: date_line)
84
79
  end
85
80
 
86
- def add(job)
87
- @jobs << job
88
- self
81
+ def day_labels
82
+ days.times.map(&:succ)
89
83
  end
90
84
 
91
- def jobs
92
- @jobs.to_a
85
+ def progress
86
+ Graph::Progress.new(self)
93
87
  end
94
88
 
95
89
  def self.template(key=:default)