musa-dsl 0.22.6 → 0.23.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.
@@ -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