musa-dsl 0.22.6 → 0.23.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,237 @@
1
+ module Musa
2
+ module Series::Operations
3
+ def buffered(sync: false)
4
+ if sync
5
+ SyncBufferSerie.new(self)
6
+ else
7
+ BufferSerie.new(self)
8
+ end
9
+ end
10
+
11
+ class SyncBufferSerie
12
+ include Series::Serie.with(source: true)
13
+
14
+ def initialize(serie)
15
+ self.source = serie
16
+ @history = []
17
+ @buffers = Set[]
18
+
19
+ init
20
+ end
21
+
22
+ private def _restart
23
+ @source.restart
24
+ clear_old_history
25
+ end
26
+
27
+ private def _next_value
28
+ @source.next_value.tap { |value| @history << value unless value.nil? && !@history.empty? && @history.last.nil? }
29
+ end
30
+
31
+ def buffer
32
+ @buffer ||= Buffer.new(@history)
33
+ @buffer.send(@get).tap { |_| @buffers << _ }
34
+ end
35
+
36
+ private def clear_old_history
37
+ min_last_nil_index = @buffers.collect(&:last_nil_index).min
38
+
39
+ if min_last_nil_index && min_last_nil_index >=0
40
+ @history = @history.drop(min_last_nil_index)
41
+
42
+ @buffers.each do |b|
43
+ b._reindex(@history, min_last_nil_index)
44
+ end
45
+ end
46
+ end
47
+
48
+ class Buffer
49
+ include Series::Serie.base
50
+
51
+ def initialize(history)
52
+ @history = history
53
+ @last_nil_index = -1
54
+ init
55
+ end
56
+
57
+ attr_reader :last_nil_index
58
+
59
+ def _reindex(history, offset)
60
+ @history = history
61
+
62
+ @last_nil_index -= offset
63
+ @index -= offset
64
+ end
65
+
66
+ private def _init
67
+ @index = @last_nil_index
68
+ @wait_restart = false
69
+ end
70
+
71
+ private def _next_value
72
+ @index += 1 if @index + 1 < @history.size && !@wait_restart
73
+
74
+ if @history[@index].nil? && @index < @history.size
75
+
76
+ @wait_restart = true
77
+
78
+ if @index + 1 < @history.size
79
+ @last_nil_index = @index
80
+ end
81
+ end
82
+
83
+ @history[@index]
84
+ end
85
+ end
86
+
87
+ private_constant :Buffer
88
+ end
89
+
90
+ private_constant :SyncBufferSerie
91
+
92
+ class BufferSerie
93
+ # modo fill_on_restart: cuando una serie hace restart, las demás no se ven afectadas porque siguen recibiendo
94
+ # todos los elementos de la serie original
95
+
96
+ include Series::Serie.with(source: true)
97
+
98
+ def initialize(serie)
99
+ self.source = serie
100
+
101
+ @history = [nil]
102
+ @nils = [0]
103
+ @buffers = Set[]
104
+
105
+ @singleton = nil
106
+ @buffer = nil
107
+
108
+ init
109
+ end
110
+
111
+ def instance
112
+ @singleton ||= super
113
+ end
114
+
115
+ def buffer
116
+ @buffer ||= Buffer.new(self)
117
+ @buffer
118
+ end
119
+
120
+ private def _restart(main)
121
+ raise ArgumentError, "Can't restart a BufferSerie directly. Should use a buffer instance instead." unless main
122
+ return if @source_just_restarted
123
+
124
+ next_nil = @nils.find { |_| _ > main.index }
125
+
126
+ if next_nil && main.index < next_nil
127
+ main.last_nil_index = main.index = next_nil
128
+
129
+ else
130
+ until _next_value.nil?; end
131
+ main.last_nil_index = main.index = @nils.last
132
+ end
133
+
134
+ clear_old_history
135
+
136
+ @source.restart
137
+ @source_just_restarted = true
138
+ end
139
+
140
+ private def _next_value
141
+ @source_just_restarted = false
142
+ value = @source.next_value
143
+
144
+ if value.nil?
145
+ unless @history.last.nil?
146
+ @history << nil
147
+ @nils << @history.size - 1
148
+ end
149
+ else
150
+ @history << value
151
+ end
152
+
153
+ value
154
+ end
155
+
156
+ def _register(buffer)
157
+ @buffers << buffer
158
+
159
+ buffer.history = @history
160
+ buffer.last_nil_index = 0
161
+ end
162
+
163
+ private def clear_old_history
164
+ min_last_nil_index = @buffers.collect(&:last_nil_index).min
165
+
166
+ if min_last_nil_index && min_last_nil_index >=0
167
+
168
+ pre_nils = @nils.clone
169
+ @history = @history.drop(min_last_nil_index)
170
+
171
+ @nils.collect! { |_| _ - min_last_nil_index }
172
+ @nils.delete_if(&:negative?)
173
+
174
+ @buffers.each do |b|
175
+ b._reindex(@history, min_last_nil_index)
176
+ end
177
+ end
178
+ end
179
+
180
+ class Buffer
181
+ include Series::Serie.with(source: true, private_source: true)
182
+
183
+ def initialize(base)
184
+ self.source = base
185
+
186
+ mark_as_prototype! # necesario para que se creen instancias diferentes cada vez que se ejecute BufferSerie.buffer()
187
+
188
+ init
189
+ end
190
+
191
+ attr_accessor :history
192
+ attr_accessor :last_nil_index
193
+ attr_accessor :index
194
+
195
+ def _reindex(history, offset)
196
+ @history = history
197
+ @last_nil_index -= offset
198
+ @index -= offset
199
+ end
200
+
201
+ private def _init
202
+ @source._register(self) if instance?
203
+ @index = @last_nil_index
204
+ end
205
+
206
+ private def _restart
207
+ @source.restart(self)
208
+ @needs_restart = false
209
+ end
210
+
211
+ private def _next_value
212
+ value = nil
213
+
214
+ unless @needs_restart
215
+ if @index + 1 < @history.size
216
+ @index += 1
217
+ value = @history[@index]
218
+ else
219
+ @source.next_value
220
+ value = _next_value
221
+ end
222
+
223
+ if value.nil?
224
+ @needs_restart = true
225
+ end
226
+ end
227
+
228
+ value
229
+ end
230
+ end
231
+
232
+ private_constant :Buffer
233
+ end
234
+
235
+ private_constant :BufferSerie
236
+ end
237
+ end
@@ -1,175 +1,174 @@
1
1
  module Musa
2
- module Series
3
- module SerieOperations
4
- def split
5
- Splitter.new(Splitter::BufferedProxy.new(self))
6
- end
2
+ module Series::Operations
3
+ def split
4
+ Splitter.new(Splitter::BufferedProxy.new(self))
5
+ end
7
6
 
8
- class Splitter
9
- include Enumerable
7
+ class Splitter
8
+ include Enumerable
10
9
 
11
- def initialize(proxy)
12
- @proxy = proxy
13
- @series = {}
14
- end
10
+ def initialize(proxy)
11
+ @proxy = proxy
12
+ @series = {}
13
+ end
15
14
 
16
- def [](key_or_index)
17
- if @series.has_key?(key_or_index)
18
- @series[key_or_index]
19
- else
20
- @series[key_or_index] = Split.new(@proxy, key_or_index)
21
- end
15
+ def [](key_or_index)
16
+ if @series.has_key?(key_or_index)
17
+ @series[key_or_index]
18
+ else
19
+ @series[key_or_index] = Split.new(@proxy, key_or_index)
22
20
  end
21
+ end
23
22
 
24
- def each
25
- if block_given?
26
- if @proxy.hash_mode?
27
- @proxy.components.each do |key|
28
- yield [key, self[key]]
29
- end
30
- elsif @proxy.array_mode?
31
- @proxy.components.each do |index|
32
- yield self[index]
33
- end
34
- else
35
- # do nothing
23
+ def each
24
+ if block_given?
25
+ if @proxy.hash_mode?
26
+ @proxy.components.each do |key|
27
+ yield [key, self[key]]
36
28
  end
37
- else
38
- if @proxy.hash_mode?
39
- @proxy.components.collect { |key| [key, self[key]] }.each
40
- elsif @proxy.array_mode?
41
- @proxy.components.collect { |index| self[index] }.each
42
- else
43
- [].each
29
+ elsif @proxy.array_mode?
30
+ @proxy.components.each do |index|
31
+ yield self[index]
44
32
  end
33
+ else
34
+ # do nothing
45
35
  end
46
- end
47
-
48
- def to_hash
36
+ else
49
37
  if @proxy.hash_mode?
50
- @proxy.components.collect { |key| [key, self[key]] }.to_h
38
+ @proxy.components.collect { |key| [key, self[key]] }.each
39
+ elsif @proxy.array_mode?
40
+ @proxy.components.collect { |index| self[index] }.each
51
41
  else
52
- raise RuntimeError, 'Splitter is not based on Hash: can\'t convert to Hash'
42
+ [].each
53
43
  end
54
44
  end
45
+ end
55
46
 
56
- def to_ary
57
- if @proxy.array_mode?
58
- [].tap { |_| @proxy.components.each { |i| _[i] = self[i] } }
59
- else
60
- raise RuntimeError, 'Splitter is not based on Array: can\'t convert to Array'
61
- end
47
+ def to_hash
48
+ if @proxy.hash_mode?
49
+ @proxy.components.collect { |key| [key, self[key]] }.to_h
50
+ else
51
+ raise RuntimeError, 'Splitter is not based on Hash: can\'t convert to Hash'
62
52
  end
53
+ end
63
54
 
64
- class BufferedProxy
65
- include SeriePrototyping
55
+ def to_ary
56
+ if @proxy.array_mode?
57
+ [].tap { |_| @proxy.components.each { |i| _[i] = self[i] } }
58
+ else
59
+ raise RuntimeError, 'Splitter is not based on Array: can\'t convert to Array'
60
+ end
61
+ end
66
62
 
67
- def initialize(hash_or_array_serie)
68
- @source = hash_or_array_serie
63
+ class BufferedProxy
64
+ include Series::Serie::Prototyping
69
65
 
70
- infer_components
66
+ def initialize(hash_or_array_serie)
67
+ @source = hash_or_array_serie
68
+ mark_regarding! @source
71
69
 
72
- restart restart_source: false
73
-
74
- mark_regarding! @source
75
- end
70
+ init
71
+ end
76
72
 
77
- attr_reader :components
73
+ attr_reader :components
78
74
 
79
- def hash_mode?; @hash_mode; end
80
- def array_mode?; @array_mode; end
75
+ def hash_mode?; @hash_mode; end
76
+ def array_mode?; @array_mode; end
81
77
 
82
- def restart(key_or_index = nil, restart_source: true)
83
- if key_or_index
84
- @asked_to_restart[key_or_index] = true
85
- else
86
- @components.each { |c| @asked_to_restart[c] = true }
87
- end
78
+ def init
79
+ infer_components
80
+ end
88
81
 
89
- if @asked_to_restart.values.all?
90
- @source.restart if restart_source
91
- infer_components
92
- end
82
+ def restart(key_or_index = nil)
83
+ if key_or_index
84
+ @asked_to_restart[key_or_index] = true
85
+ else
86
+ @components.each { |c| @asked_to_restart[c] = true }
93
87
  end
94
88
 
95
- private def infer_components
96
- source = @source.instance
97
- sample = source.current_value || source.peek_next_value
89
+ if @asked_to_restart.values.all?
90
+ @source.restart
91
+ infer_components
92
+ end
93
+ end
98
94
 
99
- case sample
100
- when Array
101
- @components = (0..sample.size-1).to_a
102
- @values = []
103
- @array_mode = true
104
- @hash_mode = false
105
- when Hash
106
- @components = sample.keys.clone
107
- @values = {}
108
- @array_mode = false
109
- @hash_mode = true
110
- else
111
- @components = []
112
- @values = nil
113
- @array_mode = @hash_mode = false
114
- end
95
+ private def infer_components
96
+ source = @source.instance
97
+ sample = source.current_value || source.peek_next_value
98
+
99
+ case sample
100
+ when Array
101
+ @components = (0..sample.size-1).to_a
102
+ @values = []
103
+ @array_mode = true
104
+ @hash_mode = false
105
+ when Hash
106
+ @components = sample.keys.clone
107
+ @values = {}
108
+ @array_mode = false
109
+ @hash_mode = true
110
+ else
111
+ @components = []
112
+ @values = nil
113
+ @array_mode = @hash_mode = false
114
+ end
115
115
 
116
- @asked_to_restart = {}
116
+ @asked_to_restart = {}
117
117
 
118
- @components.each do |component|
119
- @asked_to_restart[component] = false
120
- end
118
+ @components.each do |component|
119
+ @asked_to_restart[component] = false
121
120
  end
121
+ end
122
122
 
123
- def next_value(key_or_index)
124
- if @values[key_or_index].nil? || @values[key_or_index].empty?
125
-
126
- hash_or_array_value = @source.next_value
127
-
128
- case hash_or_array_value
129
- when Hash
130
- hash_or_array_value.each do |k, v|
131
- @values[k] ||= []
132
- @values[k] << v
133
- end
134
- when Array
135
- hash_or_array_value.each_index do |i|
136
- @values[i] ||= []
137
- @values[i] << hash_or_array_value[i]
138
- end
123
+ def next_value(key_or_index)
124
+ if @values[key_or_index].nil? || @values[key_or_index].empty?
125
+
126
+ hash_or_array_value = @source.next_value
127
+
128
+ case hash_or_array_value
129
+ when Hash
130
+ hash_or_array_value.each do |k, v|
131
+ @values[k] ||= []
132
+ @values[k] << v
133
+ end
134
+ when Array
135
+ hash_or_array_value.each_index do |i|
136
+ @values[i] ||= []
137
+ @values[i] << hash_or_array_value[i]
139
138
  end
140
139
  end
140
+ end
141
141
 
142
- if @values && !@values[key_or_index].nil?
143
- @values[key_or_index].shift
144
- else
145
- nil
146
- end
142
+ if @values && !@values[key_or_index].nil?
143
+ @values[key_or_index].shift
144
+ else
145
+ nil
147
146
  end
148
147
  end
148
+ end
149
149
 
150
- class Split
151
- include Serie
150
+ class Split
151
+ include Series::Serie.base
152
152
 
153
- def initialize(proxy, key_or_index)
154
- @source = proxy
155
- @key_or_index = key_or_index
153
+ def initialize(proxy, key_or_index)
154
+ @source = proxy
155
+ @key_or_index = key_or_index
156
156
 
157
- mark_regarding! @source
158
- end
159
-
160
- def _restart
161
- @source.restart @key_or_index
162
- end
157
+ mark_regarding! @source
158
+ end
163
159
 
164
- def _next_value
165
- @source.next_value(@key_or_index)
166
- end
160
+ private def _restart
161
+ @source.restart @key_or_index
167
162
  end
168
163
 
169
- private_constant :Split
164
+ private def _next_value
165
+ @source.next_value(@key_or_index)
166
+ end
170
167
  end
171
168
 
172
- private_constant :Splitter
169
+ private_constant :Split
173
170
  end
171
+
172
+ private_constant :Splitter
174
173
  end
175
174
  end