musicality 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +30 -0
  3. data/lib/musicality/errors.rb +1 -0
  4. data/lib/musicality/notation/conversion/change_conversion.rb +63 -3
  5. data/lib/musicality/notation/conversion/note_time_converter.rb +23 -5
  6. data/lib/musicality/notation/conversion/score_conversion.rb +60 -0
  7. data/lib/musicality/notation/conversion/score_converter.rb +105 -0
  8. data/lib/musicality/notation/model/change.rb +98 -28
  9. data/lib/musicality/notation/model/part.rb +1 -1
  10. data/lib/musicality/notation/model/score.rb +4 -4
  11. data/lib/musicality/notation/packing/change_packing.rb +35 -25
  12. data/lib/musicality/notation/packing/score_packing.rb +2 -2
  13. data/lib/musicality/notation/util/function.rb +99 -0
  14. data/lib/musicality/notation/util/piecewise_function.rb +79 -99
  15. data/lib/musicality/notation/util/transition.rb +12 -0
  16. data/lib/musicality/notation/util/value_computer.rb +12 -152
  17. data/lib/musicality/performance/conversion/score_collator.rb +35 -20
  18. data/lib/musicality/performance/midi/part_sequencer.rb +2 -5
  19. data/lib/musicality/validatable.rb +6 -1
  20. data/lib/musicality/version.rb +1 -1
  21. data/lib/musicality.rb +4 -4
  22. data/musicality.gemspec +1 -0
  23. data/spec/notation/conversion/change_conversion_spec.rb +216 -9
  24. data/spec/notation/conversion/measure_note_map_spec.rb +2 -2
  25. data/spec/notation/conversion/note_time_converter_spec.rb +91 -9
  26. data/spec/notation/conversion/{measured_score_conversion_spec.rb → score_conversion_spec.rb} +44 -9
  27. data/spec/notation/conversion/score_converter_spec.rb +246 -0
  28. data/spec/notation/model/change_spec.rb +139 -36
  29. data/spec/notation/model/part_spec.rb +3 -3
  30. data/spec/notation/model/score_spec.rb +4 -4
  31. data/spec/notation/packing/change_packing_spec.rb +222 -71
  32. data/spec/notation/packing/part_packing_spec.rb +1 -1
  33. data/spec/notation/packing/score_packing_spec.rb +3 -2
  34. data/spec/notation/util/function_spec.rb +43 -0
  35. data/spec/notation/util/transition_spec.rb +51 -0
  36. data/spec/notation/util/value_computer_spec.rb +43 -87
  37. data/spec/performance/conversion/score_collator_spec.rb +46 -7
  38. data/spec/performance/midi/part_sequencer_spec.rb +2 -1
  39. metadata +29 -14
  40. data/lib/musicality/notation/conversion/measured_score_conversion.rb +0 -70
  41. data/lib/musicality/notation/conversion/measured_score_converter.rb +0 -95
  42. data/lib/musicality/notation/conversion/unmeasured_score_conversion.rb +0 -47
  43. data/lib/musicality/notation/conversion/unmeasured_score_converter.rb +0 -64
  44. data/spec/notation/conversion/measured_score_converter_spec.rb +0 -329
  45. data/spec/notation/conversion/unmeasured_score_conversion_spec.rb +0 -71
  46. data/spec/notation/conversion/unmeasured_score_converter_spec.rb +0 -116
@@ -11,90 +11,154 @@ describe Change::Immediate do
11
11
  @p.should be_a Hash
12
12
  end
13
13
 
14
- it 'should have "type" and "value" keys' do
14
+ it 'should have "type" and "end_value" keys' do
15
15
  @p.should have_key("type")
16
- @p.should have_key("value")
16
+ @p.should have_key("end_value")
17
17
  end
18
18
 
19
19
  it 'should assign "Immediate" to "type" key' do
20
20
  @p["type"].should eq("Immediate")
21
21
  end
22
22
 
23
- it 'should assign value to "value" key' do
24
- @p["value"].should eq(@c.value)
23
+ it 'should assign end_value to "end_value" key' do
24
+ @p["end_value"].should eq(@c.end_value)
25
+ end
26
+
27
+ context 'given :with method' do
28
+ it 'should send the :with method to end_value' do
29
+ p = @c.pack(:with => :to_s)
30
+ p["end_value"].should be_a String
31
+ p["end_value"].to_f.should eq(@c.end_value)
32
+ end
25
33
  end
26
34
  end
27
35
  end
28
36
 
29
37
  describe Change::Gradual do
30
38
  describe '#pack' do
31
- context 'in general' do
32
- before :all do
33
- @c = Change::Gradual.new(200,2.5,3.3,4.5)
34
- @p = @c.pack
35
- end
36
-
37
- it 'should return a Hash' do
38
- @p.should be_a Hash
39
- end
40
-
41
- it 'should have "type", "value", and "impending" keys' do
42
- @p.should have_key("type")
43
- @p.should have_key("value")
44
- @p.should have_key("impending")
45
- end
46
-
47
- it 'should assign "Gradual" to "type" key' do
48
- @p["type"].should eq("Gradual")
49
- end
50
-
51
- it 'should assign value to "value" key' do
52
- @p["value"].should eq(@c.value)
53
- end
54
-
55
- it 'should assign impending to "impending" key' do
56
- @p["impending"].should eq(@c.impending)
57
- end
39
+ before :all do
40
+ @c = Change::Gradual.linear(200,2.5)
41
+ @p = @c.pack
58
42
  end
59
43
 
60
- context 'elapsed and remaining are 0' do
61
- before :all do
62
- @c = Change::Gradual.new(200,2.5)
63
- @p = @c.pack
64
- end
65
-
66
- it 'should *only* have "type", "value", and "impending" keys' do
67
- @p.keys.sort.should eq(["impending","type","value"])
68
- end
44
+ it 'should return a Hash' do
45
+ @p.should be_a Hash
46
+ end
47
+
48
+ it 'should have "type", "end_value", "duration", "transition", and keys' do
49
+ @p.keys.sort.should eq(["duration","end_value","transition","type"])
50
+ end
51
+
52
+ it 'should assign "Gradual" to "type" key' do
53
+ @p["type"].should eq("Gradual")
54
+ end
55
+
56
+ it 'should assign end_value to "end_value" key' do
57
+ @p["end_value"].should eq(@c.end_value)
58
+ end
59
+
60
+ it 'should assign duration to "duration" key' do
61
+ @p["duration"].should eq(@c.duration)
62
+ end
63
+
64
+ it 'should assign start value to "start_value" key' do
65
+ @p["start_value"].should eq(@c.start_value)
69
66
  end
70
67
 
71
- context 'elapsed is not 0, but remaining is 0' do
72
- before :all do
73
- @c = Change::Gradual.new(200,2.5,1.1)
74
- @p = @c.pack
68
+ it 'should assign transition to "transition" key' do
69
+ @p["transition"].should eq(@c.transition)
70
+ end
71
+
72
+ context 'given :with method' do
73
+ it 'should send the :with method to end_value' do
74
+ p = @c.pack(:with => :to_s)
75
+ p["end_value"].should be_a String
76
+ p["end_value"].to_f.should eq(@c.end_value)
75
77
  end
76
-
77
- it 'should *only* have "type", "value", "impending", and "elapsed" keys' do
78
- @p.keys.sort.should eq(["elapsed","impending","type","value"])
78
+ end
79
+
80
+ context 'given start value' do
81
+ it 'should assign start_value to "start_value" ' do
82
+ c = Change::Gradual.linear(200,2.5,start_value: 20)
83
+ p = c.pack
84
+ p.should have_key("start_value")
85
+ p["start_value"].should eq(c.start_value)
79
86
  end
80
87
 
81
- it 'should assign elapsed to "elapsed" key' do
82
- @p["elapsed"].should eq(@c.elapsed)
88
+ context 'given :with method' do
89
+ it 'should send the :with method to end_value' do
90
+ c = Change::Gradual.linear(200,2.5,start_value: 20)
91
+ p = c.pack(:with => :to_s)
92
+ p["start_value"].should be_a String
93
+ p["start_value"].to_f.should eq(c.start_value)
94
+ end
83
95
  end
84
96
  end
97
+ end
98
+ end
99
+
100
+ describe Change::Gradual::Trimmed do
101
+ describe '#pack' do
102
+ before :all do
103
+ @c = Change::Gradual::Trimmed.linear(200,2.5,preceding:1,remaining:0.5)
104
+ @p = @c.pack
105
+ end
85
106
 
86
- context 'elapsed and remaining are not 0' do
87
- before :all do
88
- @c = Change::Gradual.new(200,2.5,1.1,2.2)
89
- @p = @c.pack
107
+ it 'should return a Hash' do
108
+ @p.should be_a Hash
109
+ end
110
+
111
+ it 'should have "type", "end_value", "duration", "transition", "preceding", "remaining" keys' do
112
+ @p.keys.sort.should eq(["duration","end_value","preceding","remaining","transition","type"])
113
+ end
114
+
115
+ it 'should assign "Gradual::Trimmed" to "type" key' do
116
+ @p["type"].should eq("Gradual::Trimmed")
117
+ end
118
+
119
+ it 'should assign end_value to "end_value" key' do
120
+ @p["end_value"].should eq(@c.end_value)
121
+ end
122
+
123
+ it 'should assign duration to "duration" key' do
124
+ @p["duration"].should eq(@c.duration)
125
+ end
126
+
127
+ it 'should assign transition to "transition" key' do
128
+ @p["transition"].should eq(@c.transition)
129
+ end
130
+
131
+ it 'should assign preceding to "preceding" key' do
132
+ @p["preceding"].should eq(@c.preceding)
133
+ end
134
+
135
+ it 'should assign remaining to "remaining" key' do
136
+ @p["remaining"].should eq(@c.remaining)
137
+ end
138
+
139
+ context 'given :with method' do
140
+ it 'should send the :with method to end_value' do
141
+ p = @c.pack(:with => :to_s)
142
+ p["end_value"].should be_a String
143
+ p["end_value"].to_f.should eq(@c.end_value)
90
144
  end
91
-
92
- it 'should *only* have "type", "value", "impending", "elapsed", and "remaining" keys' do
93
- @p.keys.sort.should eq(["elapsed","impending","remaining","type","value"])
145
+ end
146
+
147
+ context 'given start value' do
148
+ it 'should assign start_value to "start_value" ' do
149
+ c = Change::Gradual.linear(200,2.5,start_value: 20).trim(0.5,0.5)
150
+ p = c.pack
151
+ p.should have_key("start_value")
152
+ p["start_value"].should eq(c.start_value)
94
153
  end
95
154
 
96
- it 'should assign remaining to "remaining" key' do
97
- @p["remaining"].should eq(@c.remaining)
155
+ context 'given :with method' do
156
+ it 'should send the :with method to end_value' do
157
+ c = Change::Gradual.linear(200,2.5,start_value: 20).trim(0.5,0.5)
158
+ p = c.pack(:with => :to_s)
159
+ p["start_value"].should be_a String
160
+ p["start_value"].to_f.should eq(c.start_value)
161
+ end
98
162
  end
99
163
  end
100
164
  end
@@ -113,18 +177,25 @@ describe Change do
113
177
  @c2.should be_a Change::Immediate
114
178
  end
115
179
 
116
- it 'should successfully unpack the change value' do
117
- @c2.value.should eq @c.value
180
+ it 'should successfully unpack the change end_value' do
181
+ @c2.end_value.should eq @c.end_value
118
182
  end
119
183
 
120
- it 'should successfully unpack the change duration' do
121
- @c2.duration.should eq @c.duration
184
+ context 'pack/unpack using :with method' do
185
+ it 'should use given :with method to convert end_value' do
186
+ c = Change::Immediate.new(0.5)
187
+ h = c.pack(:with => :to_s)
188
+ c2 = Change.unpack(h)
189
+ c2.end_value.should be_a String
190
+ c3 = Change.unpack(h, :with => :to_f)
191
+ c3.end_value.should be_a Float
192
+ end
122
193
  end
123
194
  end
124
195
 
125
196
  context 'given a packed gradual change' do
126
197
  before :all do
127
- @c = Change::Gradual.new(0.3,1.5,1.1,0.2)
198
+ @c = Change::Gradual.sigmoid(0.3,1.5)
128
199
  @a = @c.pack
129
200
  @c2 = Change.unpack(@a)
130
201
  end
@@ -133,21 +204,101 @@ describe Change do
133
204
  @c2.should be_a Change::Gradual
134
205
  end
135
206
 
136
- it 'should successfully unpack the change value' do
137
- @c2.value.should eq @c.value
207
+ it 'should unpack the end_value' do
208
+ @c2.end_value.should eq @c.end_value
209
+ end
210
+
211
+ it 'should unpack the change duration' do
212
+ @c2.duration.should eq @c.duration
213
+ end
214
+
215
+ it 'should unpack the change transition' do
216
+ @c2.transition.should eq @c.transition
217
+ end
218
+
219
+ it 'should unpack the change start_value' do
220
+ @c2.start_value.should eq @c.start_value
138
221
  end
139
222
 
140
- it 'should successfully unpack the change impending (duration)' do
141
- @c2.impending.should eq @c.impending
223
+ context 'pack/unpack using :with method' do
224
+ it 'should use given :with method to convert end_value' do
225
+ c = Change::Gradual.linear(0.5,2)
226
+ h = c.pack(:with => :to_s)
227
+ c2 = Change.unpack(h)
228
+ c2.end_value.should be_a String
229
+ c3 = Change.unpack(h, :with => :to_f)
230
+ c3.end_value.should be_a Float
231
+ end
232
+
233
+ context 'when change start_value is not nil' do
234
+ it 'should use given :with method to convert start_value' do
235
+ c = Change::Gradual.linear(0.5,2,start_value: 0.1)
236
+ h = c.pack(:with => :to_s)
237
+ c2 = Change.unpack(h)
238
+ c2.start_value.should be_a String
239
+ c3 = Change.unpack(h, :with => :to_f)
240
+ c3.start_value.should be_a Float
241
+ end
242
+ end
243
+ end
244
+ end
245
+
246
+ context 'given a packed gradual (trimmed) change' do
247
+ before :all do
248
+ @c = Change::Gradual::Trimmed.sigmoid(0.3,1.5,preceding:0.1,remaining:0.1)
249
+ @a = @c.pack
250
+ @c2 = Change.unpack(@a)
142
251
  end
143
252
 
144
- it 'should successfully unpack the change elapsed' do
145
- @c2.elapsed.should eq @c.elapsed
253
+ it 'should return a Change::Gradual' do
254
+ @c2.should be_a Change::Gradual
255
+ end
256
+
257
+ it 'should successfully unpack the end_value' do
258
+ @c2.end_value.should eq @c.end_value
259
+ end
260
+
261
+ it 'should successfully unpack the change duration' do
262
+ @c2.duration.should eq @c.duration
146
263
  end
147
264
 
265
+ it 'should successfully unpack the change transition' do
266
+ @c2.transition.should eq @c.transition
267
+ end
268
+
269
+ it 'should unpack the change start_value' do
270
+ @c2.start_value.should eq @c.start_value
271
+ end
272
+
273
+ it 'should successfully unpack the change preceding' do
274
+ @c2.preceding.should eq @c.preceding
275
+ end
276
+
148
277
  it 'should successfully unpack the change remaining' do
149
278
  @c2.remaining.should eq @c.remaining
150
- end
151
- end
279
+ end
280
+
281
+ context 'pack/unpack using :with method' do
282
+ it 'should use given :with method to convert end_value' do
283
+ c = Change::Gradual.linear(0.5,2).trim(0.4,0.3)
284
+ h = c.pack(:with => :to_s)
285
+ c2 = Change.unpack(h)
286
+ c2.end_value.should be_a String
287
+ c3 = Change.unpack(h, :with => :to_f)
288
+ c3.end_value.should be_a Float
289
+ end
290
+
291
+ context 'when change start_value is not nil' do
292
+ it 'should use given :with method to convert start_value' do
293
+ c = Change::Gradual.linear(0.5,2,start_value: 0.1).trim(0.4,0.3)
294
+ h = c.pack(:with => :to_s)
295
+ c2 = Change.unpack(h)
296
+ c2.start_value.should be_a String
297
+ c3 = Change.unpack(h, :with => :to_f)
298
+ c3.start_value.should be_a Float
299
+ end
300
+ end
301
+ end
302
+ end
152
303
  end
153
304
  end
@@ -7,7 +7,7 @@ describe Part do
7
7
  notes: Note.split_parse("/4Bb2 /8 /8F3= /2F3 /4Bb2 /8 /8F3= /2F3"),
8
8
  dynamic_changes: {
9
9
  1 => Change::Immediate.new(Dynamics::PP),
10
- 2 => Change::Gradual.new(Dynamics::FF, 2.0)
10
+ 2 => Change::Gradual.linear(Dynamics::FF, 2.0)
11
11
  }
12
12
  )
13
13
 
@@ -1,6 +1,7 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
2
 
3
3
  measured_score = Score::Measured.new(FOUR_FOUR,120) do |s|
4
+ s.meter_changes[1] = Change::Immediate.new(THREE_FOUR)
4
5
  s.program = Program.new([0...2, 0...2,2...4,0...2])
5
6
  s.parts["lead"] = Part.new(Dynamics::MF) do |p|
6
7
  riff = "/6Bb3 /4 /12Db4= /6Db4= /36Db4 /36Eb4 /36Db4 /6Ab3 /12Db4 \
@@ -58,9 +59,9 @@ describe Score::Measured do
58
59
  end
59
60
  end
60
61
 
61
- it 'should pack meter change values as strings' do
62
+ it 'should pack meter change end values as strings' do
62
63
  @h['meter_changes'].each do |offset,packed_v|
63
- packed_v[0].should be_a String
64
+ packed_v["end_value"].should be_a String
64
65
  end
65
66
  end
66
67
 
@@ -0,0 +1,43 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe Function::Constant do
4
+ it 'should always return the same value' do
5
+ f = Function::Constant.new(20)
6
+ f.at(0).should eq(20)
7
+ f.at(-1000).should eq(20)
8
+ f.at(1000).should eq(20)
9
+ end
10
+ end
11
+
12
+ describe Function::Linear do
13
+ it 'should evaluate along the line going between the two initial points' do
14
+ f = Function::Linear.new([5,10],[7,11])
15
+ f.at(4).should eq(9.5)
16
+ f.at(5).should eq(10)
17
+ f.at(6).should eq(10.5)
18
+ f.at(7).should eq(11)
19
+ f.at(8).should eq(11.5)
20
+ end
21
+ end
22
+
23
+ describe Function::Sigmoid do
24
+ it 'should evaluate along the line going between the two initial points' do
25
+ f = Function::Sigmoid.new([5,10],[7,11])
26
+ f.at(4).should be < 10
27
+ f.at(5).should eq(10)
28
+ f.at(6).should eq(10.5)
29
+ f.at(7).should eq(11)
30
+ f.at(8).should be > 11
31
+ end
32
+
33
+ describe '.find_y0' do
34
+ it 'should return the starting y-value for the given sigmoid domain' do
35
+ x0, x1 = 3, 6
36
+ y0, y1 = 5, 10
37
+ f = Function::Sigmoid.new([x0,y0],[x1,y1])
38
+ pt = [4,f.at(4)]
39
+ y0_ = Function::Sigmoid.find_y0(x0..x1, pt, y1)
40
+ y0_.should eq(y0)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,51 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe Transition do
4
+ describe '#initialize' do
5
+ context 'zero-length domain' do
6
+ it 'should create one piece' do
7
+ t = Transition.new(Function::Constant.new(3),5..5)
8
+ t.pieces.size.should eq(1)
9
+ end
10
+ end
11
+
12
+ context 'positive-length domain' do
13
+ it 'should create two pieces' do
14
+ t = Transition.new(Function::Linear.new([0,0],[2,1]),3..5)
15
+ t.pieces.size.should eq(2)
16
+ end
17
+ end
18
+ end
19
+
20
+ describe '#at' do
21
+ before :all do
22
+ @f = Function::Linear.new([0,0],[2,1])
23
+ @d = 3..5
24
+ @t = Transition.new(@f,@d)
25
+ end
26
+
27
+ context 'given value before transition domain starts' do
28
+ it 'should raise DomainError' do
29
+ expect { @t.at(@d.first - 1e-5) }.to raise_error(DomainError)
30
+ expect { @t.at(@d.first - 1e5) }.to raise_error(DomainError)
31
+ end
32
+ end
33
+
34
+ context 'given value in transition domain' do
35
+ it 'should not raise DomainError' do
36
+ @d.entries.each {|x| expect { @t.at(x) }.to_not raise_error }
37
+ end
38
+
39
+ it 'should calculate return value using the transition function' do
40
+ @d.entries.each {|x| @t.at(x).should eq(@f.at(x)) }
41
+ end
42
+ end
43
+
44
+ context 'given value after transition domain' do
45
+ it 'should return same value as at the end of transition domain' do
46
+ @t.at(@d.last + 1e-5).should eq(@t.at(@d.last))
47
+ @t.at(@d.last + 1e5).should eq(@t.at(@d.last))
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,10 +1,11 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
2
 
3
3
  describe ValueComputer do
4
- describe '#value_at' do
4
+ describe '#at' do
5
5
  before :all do
6
- @value_change1 = Change::Immediate.new(0.6)
7
- @value_change2 = Change::Gradual.new(0.6, 1.0)
6
+ @immed_change = Change::Immediate.new(0.6)
7
+ @lin_change = Change::Gradual.linear(0.6, 1.0)
8
+ @sigm_change = Change::Gradual.sigmoid(0.6, 1.0)
8
9
  end
9
10
 
10
11
  context "constant value" do
@@ -13,134 +14,89 @@ describe ValueComputer do
13
14
  end
14
15
 
15
16
  it "should always return default value if no changes are given" do
16
- [ValueComputer.domain_min, -1000, 0, 1, 5, 100, 10000, ValueComputer.domain_max].each do |offset|
17
- @comp.value_at(offset).should eq(0.5)
17
+ [ValueComputer::DOMAIN_MIN, -1000, 0, 1, 5, 100, 10000, ValueComputer::DOMAIN_MAX].each do |offset|
18
+ @comp.at(offset).should eq(0.5)
18
19
  end
19
20
  end
20
21
  end
21
22
 
22
23
  context "one change, no transition" do
23
24
  before :each do
24
- @comp = ValueComputer.new 0.5, 1.0 => @value_change1
25
+ @comp = ValueComputer.new 0.5, 1.0 => @immed_change
25
26
  end
26
27
 
27
28
  it "should be the default value just before the first change" do
28
- @comp.value_at(0.999).should eq(0.5)
29
+ @comp.at(0.999).should eq(0.5)
29
30
  end
30
31
 
31
32
  it "should transition to the second value immediately" do
32
- @comp.value_at(1.0).should eq(0.6)
33
+ @comp.at(1.0).should eq(0.6)
33
34
  end
34
35
 
35
36
  it "should be the first value for all time before" do
36
- @comp.value_at(ValueComputer.domain_min).should eq(0.5)
37
+ @comp.at(ValueComputer::DOMAIN_MIN).should eq(0.5)
37
38
  end
38
39
 
39
40
  it "should be at the second value for all time after" do
40
- @comp.value_at(ValueComputer.domain_max).should eq(0.6)
41
+ @comp.at(ValueComputer::DOMAIN_MAX).should eq(0.6)
41
42
  end
42
43
  end
43
44
 
44
45
  context "one change, linear transition" do
45
46
  before :each do
46
- @comp = ValueComputer.new 0.2, 1.0 => @value_change2
47
+ @comp = ValueComputer.new 0.2, 1.0 => @lin_change
47
48
  end
48
49
 
49
50
  it "should be the first (starting) value just before the second value" do
50
- @comp.value_at(0.999).should eq(0.2)
51
+ @comp.at(0.999).should eq(0.2)
51
52
  end
52
53
 
53
54
  it "should be the first (starting) value exactly at the second value" do
54
- @comp.value_at(1.0).should eq(0.2)
55
+ @comp.at(1.0).should eq(0.2)
55
56
  end
56
57
 
57
58
  it "should be 1/4 to the second value after 1/4 transition duration has elapsed" do
58
- @comp.value_at(Rational(5,4).to_f).should eq(0.3)
59
+ @comp.at(Rational(5,4).to_f).should eq(0.3)
59
60
  end
60
61
 
61
62
  it "should be 1/2 to the second value after 1/2 transition duration has elapsed" do
62
- @comp.value_at(Rational(6,4).to_f).should eq(0.4)
63
+ @comp.at(Rational(6,4).to_f).should eq(0.4)
63
64
  end
64
65
 
65
66
  it "should be 3/4 to the second value after 3/4 transition duration has elapsed" do
66
- @comp.value_at(Rational(7,4).to_f).should eq(0.5)
67
+ @comp.at(Rational(7,4).to_f).should eq(0.5)
67
68
  end
68
69
 
69
70
  it "should be at the second value after transition duration has elapsed" do
70
- @comp.value_at(Rational(8,4).to_f).should eq(0.6)
71
+ @comp.at(Rational(8,4).to_f).should eq(0.6)
71
72
  end
72
73
  end
73
74
 
74
- # context "one change, sigmoid transition" do
75
- # before :all do
76
- # @cases = [
77
- # { :start_value => 0, :end_value => 1, :offset => 0, :duration => 1.0, :abruptness => 0.75 },
78
- # { :start_value => 0.25, :end_value => 0.75, :offset => 1.0, :duration => 2.0, :abruptness => 0.75 },
79
- # { :start_value => -1.0, :end_value => 5.5, :offset => 2.4, :duration => 20, :abruptness => 0.75 },
80
- # { :start_value => 10, :end_value => 100, :offset => 20, :duration => 4, :abruptness => 0.75 },
81
- # ]
82
- #
83
- # @computers = {}
84
- # @cases.each do |case_hash|
85
- # start_value = case_hash[:start_value]
86
- # offset = case_hash[:offset]
87
- # end_value = case_hash[:end_value]
88
- # duration = case_hash[:duration]
89
- # #abruptness = case_hash[:abruptness]
90
- #
91
- # change = Change::Gradual.new(end_value, duration)
92
- # @computers[case_hash] = ValueComputer.new start_value, offset => change
93
- # # @computers[case_hash].plot_range(offset..(offset + duration), 0.01)
94
- # end
95
- # end
96
- #
97
- # it "should be the first (starting) value just before the value change offset" do
98
- # @computers.each do |case_hash, comp|
99
- # comp.value_at(case_hash[:offset] - 0.0001).should eq(case_hash[:start_value])
100
- # end
101
- # end
102
- #
103
- # it "should be very nearly the first (starting) value exactly at the value change offset" do
104
- # @computers.each do |case_hash, comp|
105
- # comp.value_at(case_hash[:offset]).should be_within(0.0001).of(case_hash[:start_value])
106
- # end
107
- # end
108
- #
109
- # it "should be within 1% of start/end difference away from the start value after 1/4 transition duration has elapsed" do
110
- # @computers.each do |case_hash, comp|
111
- # test_offset = case_hash[:offset] + (case_hash[:duration] * 0.25)
112
- # start_value = case_hash[:start_value]
113
- # end_value = case_hash[:end_value]
114
- # tolerance = 0.01 * (end_value - start_value)
115
- # comp.value_at(test_offset).should be_within(tolerance).of(start_value)
116
- # end
117
- # end
118
- #
119
- # it "should be half way to the end value after half way through transition" do
120
- # @computers.each do |case_hash, comp|
121
- # test_offset = case_hash[:offset] + (case_hash[:duration] * 0.5)
122
- # start_value = case_hash[:start_value]
123
- # expected_value = start_value + (case_hash[:end_value] - start_value) * 0.5
124
- # comp.value_at(test_offset).should be_within(0.0001).of(expected_value)
125
- # end
126
- # end
127
- #
128
- # it "should be within 1% of start/end difference away from the end value after 3/4 transition duration has elapsed" do
129
- # @computers.each do |case_hash, comp|
130
- # test_offset = case_hash[:offset] + (case_hash[:duration] * 0.75)
131
- # start_value = case_hash[:start_value]
132
- # end_value = case_hash[:end_value]
133
- # tolerance = 0.01 * (end_value - start_value)
134
- # comp.value_at(test_offset).should be_within(tolerance).of(end_value)
135
- # end
136
- # end
137
- #
138
- # it "should be at the second value after transition duration has elapsed" do
139
- # @computers.each do |case_hash, comp|
140
- # comp.value_at(case_hash[:offset] + case_hash[:duration]).should eq(case_hash[:end_value])
141
- # end
142
- # end
143
- # end
75
+ context "one change, sigmoid transition" do
76
+ before :each do
77
+ @comp = ValueComputer.new 0.2, 1.0 => @sigm_change
78
+ end
79
+
80
+ it "should be the first (starting) value just before the second value" do
81
+ @comp.at(0.999).should eq(0.2)
82
+ end
83
+
84
+ it "should be the first (starting) value exactly at the second value" do
85
+ @comp.at(1.0).should eq(0.2)
86
+ end
87
+
88
+ it "should be 1/2 to the second value after 1/2 transition duration has elapsed" do
89
+ @comp.at(1.5).should be_within(1e-5).of(0.4)
90
+ end
91
+
92
+ it "should be at the second value exactly where transition duration has elapsed" do
93
+ @comp.at(2).should eq(0.6)
94
+ end
95
+
96
+ it "should be at the second value just after transition duration has elapsed" do
97
+ @comp.at(2.001).should eq(0.6)
98
+ end
99
+ end
144
100
  end
145
101
  end
146
102