musa-dsl 0.22.6 → 0.23.4

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.
@@ -0,0 +1,236 @@
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(buffer)
121
+ raise ArgumentError, "Can't restart a BufferSerie directly. Should use a buffer instance instead." unless buffer
122
+ return if @source_just_restarted
123
+
124
+ next_nil = @nils.find { |_| _ > buffer.index }
125
+
126
+ if next_nil && buffer.index < next_nil
127
+ buffer.last_nil_index = buffer.index = next_nil
128
+
129
+ else
130
+ until _next_value.nil?; end
131
+ buffer.last_nil_index = buffer.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
+ value = _next_value unless @source.next_value.nil?
220
+ end
221
+
222
+ if value.nil?
223
+ @needs_restart = true
224
+ end
225
+ end
226
+
227
+ value
228
+ end
229
+ end
230
+
231
+ private_constant :Buffer
232
+ end
233
+
234
+ private_constant :BufferSerie
235
+ end
236
+ end
@@ -1,175 +1,189 @@
1
1
  module Musa
2
- module Series
3
- module SerieOperations
4
- def split
5
- Splitter.new(Splitter::BufferedProxy.new(self))
2
+ module Series::Operations
3
+ def split
4
+ Splitter.new(self)
5
+ end
6
+
7
+ class Splitter
8
+ include Enumerable
9
+ include Series::Serie::Prototyping
10
+
11
+ def initialize(source)
12
+ @source = source
13
+ @series = {}
6
14
  end
7
15
 
8
- class Splitter
9
- include Enumerable
16
+ def source=(serie)
17
+ @source = serie
18
+ @proxy.source = @source if @proxy
19
+ end
10
20
 
11
- def initialize(proxy)
12
- @proxy = proxy
13
- @series = {}
14
- end
21
+ protected def _instance!
22
+ super
23
+ @proxy = SplitterProxy.new(@source)
24
+ end
15
25
 
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
26
+ def [](key_or_index)
27
+ raise "Can't get a component because Splitter is a prototype. To get a component you need a Splitter instance." unless @is_instance
28
+
29
+ if @series.key?(key_or_index)
30
+ @series[key_or_index]
31
+ else
32
+ @series[key_or_index] = Split.new(@proxy, key_or_index)
22
33
  end
34
+ end
23
35
 
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
36
+ def each
37
+ raise "Can't iterate because Splitter is a prototype. To iterate you need a Splitter instance." unless @is_instance
38
+
39
+ if block_given?
40
+ if @proxy.hash_mode?
41
+ @proxy.components.each do |key|
42
+ yield [key, self[key]]
36
43
  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
44
+ elsif @proxy.array_mode?
45
+ @proxy.components.each do |index|
46
+ yield self[index]
44
47
  end
48
+ else
49
+ # do nothing
45
50
  end
46
- end
47
-
48
- def to_hash
51
+ else
49
52
  if @proxy.hash_mode?
50
- @proxy.components.collect { |key| [key, self[key]] }.to_h
53
+ @proxy.components.collect { |key| [key, self[key]] }.each
54
+ elsif @proxy.array_mode?
55
+ @proxy.components.collect { |index| self[index] }.each
51
56
  else
52
- raise RuntimeError, 'Splitter is not based on Hash: can\'t convert to Hash'
57
+ [].each
53
58
  end
54
59
  end
60
+ end
55
61
 
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
62
+ def to_hash
63
+ if @proxy.hash_mode?
64
+ @proxy.components.collect { |key| [key, self[key]] }.to_h
65
+ else
66
+ raise RuntimeError, 'Splitter is not based on Hash: can\'t convert to Hash'
62
67
  end
68
+ end
63
69
 
64
- class BufferedProxy
65
- include SeriePrototyping
66
-
67
- def initialize(hash_or_array_serie)
68
- @source = hash_or_array_serie
70
+ def to_ary
71
+ if @proxy.array_mode?
72
+ [].tap { |_| @proxy.components.each { |i| _[i] = self[i] } }
73
+ else
74
+ raise RuntimeError, 'Splitter is not based on Array: can\'t convert to Array'
75
+ end
76
+ end
69
77
 
70
- infer_components
78
+ class SplitterProxy
79
+ def initialize(hash_or_array_serie)
80
+ @source = hash_or_array_serie
81
+ infer_components
82
+ end
71
83
 
72
- restart restart_source: false
84
+ attr_reader :source
73
85
 
74
- mark_regarding! @source
75
- end
86
+ def source=(hash_or_array_serie)
87
+ @source = hash_or_array_serie
88
+ infer_components
89
+ end
76
90
 
77
- attr_reader :components
91
+ def hash_mode?; @hash_mode; end
78
92
 
79
- def hash_mode?; @hash_mode; end
80
- def array_mode?; @array_mode; end
93
+ def array_mode?; @array_mode; end
81
94
 
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
95
+ attr_reader :components
88
96
 
89
- if @asked_to_restart.values.all?
90
- @source.restart if restart_source
91
- infer_components
92
- end
97
+ def restart(key_or_index = nil)
98
+ if key_or_index
99
+ @asked_to_restart[key_or_index] = true
100
+ else
101
+ @components.each { |c| @asked_to_restart[c] = true }
93
102
  end
94
103
 
95
- private def infer_components
96
- source = @source.instance
97
- sample = source.current_value || source.peek_next_value
104
+ if @asked_to_restart.values.all?
105
+ @source.restart
106
+ infer_components
107
+ end
108
+ end
98
109
 
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
110
+ private def infer_components
111
+ source = @source.instance
112
+ sample = source.current_value || source.peek_next_value
113
+
114
+ case sample
115
+ when Array
116
+ @components = (0..sample.size-1).to_a
117
+ @values = []
118
+ @array_mode = true
119
+ @hash_mode = false
120
+ when Hash
121
+ @components = sample.keys.clone
122
+ @values = {}
123
+ @array_mode = false
124
+ @hash_mode = true
125
+ else
126
+ @components = []
127
+ @values = nil
128
+ @array_mode = @hash_mode = false
129
+ end
115
130
 
116
- @asked_to_restart = {}
131
+ @asked_to_restart = {}
117
132
 
118
- @components.each do |component|
119
- @asked_to_restart[component] = false
120
- end
133
+ @components.each do |component|
134
+ @asked_to_restart[component] = false
121
135
  end
136
+ end
137
+
138
+ def next_value(key_or_index)
139
+ if @values[key_or_index].nil? || @values[key_or_index].empty?
140
+
141
+ hash_or_array_value = @source.next_value
122
142
 
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
143
+ case hash_or_array_value
144
+ when Hash
145
+ hash_or_array_value.each do |k, v|
146
+ @values[k] ||= []
147
+ @values[k] << v
148
+ end
149
+ when Array
150
+ hash_or_array_value.each_index do |i|
151
+ @values[i] ||= []
152
+ @values[i] << hash_or_array_value[i]
139
153
  end
140
154
  end
155
+ end
141
156
 
142
- if @values && !@values[key_or_index].nil?
143
- @values[key_or_index].shift
144
- else
145
- nil
146
- end
157
+ if @values && !@values[key_or_index].nil?
158
+ @values[key_or_index].shift
159
+ else
160
+ nil
147
161
  end
148
162
  end
163
+ end
149
164
 
150
- class Split
151
- include Serie
152
-
153
- def initialize(proxy, key_or_index)
154
- @source = proxy
155
- @key_or_index = key_or_index
165
+ class Split
166
+ include Series::Serie.base
156
167
 
157
- mark_regarding! @source
158
- end
168
+ def initialize(proxy, key_or_index)
169
+ @proxy = proxy
170
+ @key_or_index = key_or_index
159
171
 
160
- def _restart
161
- @source.restart @key_or_index
162
- end
172
+ mark_as_instance!
173
+ end
163
174
 
164
- def _next_value
165
- @source.next_value(@key_or_index)
166
- end
175
+ private def _restart
176
+ @proxy.restart(@key_or_index)
167
177
  end
168
178
 
169
- private_constant :Split
179
+ private def _next_value
180
+ @proxy.next_value(@key_or_index)
181
+ end
170
182
  end
171
183
 
172
- private_constant :Splitter
184
+ private_constant :Split
173
185
  end
186
+
187
+ private_constant :Splitter
174
188
  end
175
189
  end