brainstorm 0.0.0 → 0.0.5
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/VERSION +1 -1
- data/lib/brainstorm.rb +193 -1
- metadata +3 -3
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.0.
|
|
1
|
+
0.0.5
|
data/lib/brainstorm.rb
CHANGED
|
@@ -1,17 +1,209 @@
|
|
|
1
1
|
require 'unobservable'
|
|
2
2
|
|
|
3
3
|
module Brainstorm
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Start
|
|
7
|
+
def to_s
|
|
8
|
+
"[START]"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def start
|
|
13
|
+
Start.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class Finish
|
|
17
|
+
def to_s
|
|
18
|
+
"[FINISH]"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def finish
|
|
23
|
+
Finish.new
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Value
|
|
28
|
+
attr_reader :value
|
|
29
|
+
def initialize(value)
|
|
30
|
+
@value = value
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def to_s
|
|
34
|
+
"[#{@value}]"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
4
38
|
|
|
39
|
+
def value(value)
|
|
40
|
+
Value.new(value)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def self.function_for(*args, &block)
|
|
46
|
+
if block
|
|
47
|
+
return block
|
|
48
|
+
elsif args.size == 1
|
|
49
|
+
return args[0]
|
|
50
|
+
elsif args.size == 2
|
|
51
|
+
return args[0].method(args[1])
|
|
52
|
+
else
|
|
53
|
+
raise ArgumentError, "Unable to convert arguments to a callable"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
5
59
|
class Neuron
|
|
6
60
|
include Unobservable::Support
|
|
7
61
|
|
|
8
62
|
attr_event :fired
|
|
9
63
|
|
|
10
|
-
def
|
|
64
|
+
def call(item)
|
|
65
|
+
raise NotImplementedError, "Neuron is an abstact base class."
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def >>(callable)
|
|
69
|
+
self.fired.register {|i| callable.call(i) }
|
|
70
|
+
return callable
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
def fire(item)
|
|
11
75
|
raise_event :fired, item
|
|
12
76
|
end
|
|
13
77
|
end
|
|
78
|
+
|
|
79
|
+
class Forwarder < Neuron
|
|
80
|
+
def call(item)
|
|
81
|
+
fire item
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class Selector < Neuron
|
|
88
|
+
attr_accessor :function
|
|
14
89
|
|
|
90
|
+
def initialize(*args, &block)
|
|
91
|
+
@function = Brainstorm.function_for(*args, &block)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def call(item)
|
|
95
|
+
if @function.call(item)
|
|
96
|
+
fire start
|
|
97
|
+
fire value(item)
|
|
98
|
+
fire finish
|
|
99
|
+
else
|
|
100
|
+
fire value(item)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def select(*args, &block)
|
|
106
|
+
Selector.new(*args, &block)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class Debouncer < Neuron
|
|
112
|
+
attr_accessor :quiet_period
|
|
113
|
+
attr_reader :timer, :state
|
|
114
|
+
|
|
115
|
+
def initialize(quiet_period)
|
|
116
|
+
@quiet_period = quiet_period
|
|
117
|
+
|
|
118
|
+
@timer = 0
|
|
119
|
+
@state = :asleep
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def is_asleep?
|
|
123
|
+
@state == :asleep
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def is_buffering?
|
|
127
|
+
@state == :buffering
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def call(item)
|
|
132
|
+
if item.is_a? Start
|
|
133
|
+
if is_asleep?
|
|
134
|
+
fire start
|
|
135
|
+
elsif is_buffering?
|
|
136
|
+
@buffer.each {|i| fire i}
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
@state = :in_block
|
|
140
|
+
elsif item.is_a? Finish
|
|
141
|
+
@buffer = []
|
|
142
|
+
@timer = 0
|
|
143
|
+
|
|
144
|
+
@state = :buffering
|
|
145
|
+
else
|
|
146
|
+
if is_buffering?
|
|
147
|
+
@buffer.push item
|
|
148
|
+
|
|
149
|
+
@timer += 1
|
|
150
|
+
if @timer > @quiet_period
|
|
151
|
+
fire finish
|
|
152
|
+
@buffer.each {|i| fire i}
|
|
153
|
+
|
|
154
|
+
@state = :asleep
|
|
155
|
+
end
|
|
156
|
+
else
|
|
157
|
+
fire item
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class Aggregator < Neuron
|
|
168
|
+
def initialize
|
|
169
|
+
@buffer = []
|
|
170
|
+
|
|
171
|
+
@is_capturing = false
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def call(item)
|
|
175
|
+
if @is_capturing
|
|
176
|
+
if item.is_a? Start
|
|
177
|
+
# TODO: Improve error-handling here
|
|
178
|
+
$stderr.puts "Unexpected 'Start' token encountered"
|
|
179
|
+
elsif item.is_a? Finish
|
|
180
|
+
fire @buffer.dup
|
|
181
|
+
@is_capturing = false
|
|
182
|
+
elsif item.is_a? Value
|
|
183
|
+
@buffer.push item.value
|
|
184
|
+
else
|
|
185
|
+
# TODO: Improve error-handling here
|
|
186
|
+
$stderr.puts "Non-aggregate token encountered"
|
|
187
|
+
end
|
|
188
|
+
else
|
|
189
|
+
if item.is_a? Start
|
|
190
|
+
@buffer = []
|
|
191
|
+
@is_capturing = true
|
|
192
|
+
elsif item.is_a? Finish
|
|
193
|
+
# TODO: Improve error-handling here
|
|
194
|
+
$stderr.puts "Unexpected 'Finish' token encountered"
|
|
195
|
+
elsif item.is_a? Value
|
|
196
|
+
# Just ignore the value
|
|
197
|
+
else
|
|
198
|
+
# TODO: Improve error-handling here
|
|
199
|
+
$stderr.puts "Non-aggregate token encountered"
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
15
207
|
end
|
|
16
208
|
|
|
17
209
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: brainstorm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.5
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2012-11-
|
|
12
|
+
date: 2012-11-12 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: unobservable
|
|
@@ -123,7 +123,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
123
123
|
version: '0'
|
|
124
124
|
segments:
|
|
125
125
|
- 0
|
|
126
|
-
hash:
|
|
126
|
+
hash: 3645590703583659599
|
|
127
127
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
128
128
|
none: false
|
|
129
129
|
requirements:
|