musicality 0.2.0 → 0.3.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.
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