nudge 0.2.8 → 0.2.9
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/instructions/conversion/float_from_proportion.rb +25 -0
- data/lib/instructions/conversion/proportion_from_float.rb +26 -0
- data/lib/instructions/float/float_divide.rb +1 -1
- data/lib/instructions/proportion/proportion_bounded_add.rb +23 -0
- data/lib/instructions/proportion/proportion_bounded_divide.rb +32 -0
- data/lib/instructions/proportion/proportion_bounded_subtract.rb +25 -0
- data/lib/instructions/proportion/proportion_max.rb +23 -0
- data/lib/instructions/proportion/proportion_min.rb +23 -0
- data/lib/instructions/proportion/proportion_multiply.rb +23 -0
- data/lib/interpreter/types/proportion_type.rb +39 -0
- data/lib/nudge.rb +3 -0
- data/spec/instructions/float/float_from_proportion_spec.rb +37 -0
- data/spec/instructions/proportion/proportion_bounded_add_spec.rb +52 -0
- data/spec/instructions/proportion/proportion_bounded_divide_spec.rb +59 -0
- data/spec/instructions/proportion/proportion_bounded_subtract_spec.rb +52 -0
- data/spec/instructions/proportion/proportion_from_float_spec.rb +48 -0
- data/spec/instructions/proportion/proportion_max_spec.rb +51 -0
- data/spec/instructions/proportion/proportion_min_spec.rb +51 -0
- data/spec/instructions/proportion/proportion_multiply_spec.rb +51 -0
- data/spec/interpreter/proportion_type_spec.rb +99 -0
- data/spec/interpreter/types_spec.rb +0 -1
- data/spec/spec_helper.rb +1 -1
- metadata +30 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.9
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# pops the top +:proportion+ item;
|
2
|
+
# pushes a new +:float+ item with the same value
|
3
|
+
#
|
4
|
+
# *needs:* 1 +:proportion+
|
5
|
+
#
|
6
|
+
# *pushes:* 1 +:float+
|
7
|
+
#
|
8
|
+
|
9
|
+
class FloatFromProportionInstruction < Instruction
|
10
|
+
def preconditions?
|
11
|
+
needs :proportion, 1
|
12
|
+
end
|
13
|
+
|
14
|
+
def setup
|
15
|
+
@arg = @context.pop_value(:proportion)
|
16
|
+
end
|
17
|
+
|
18
|
+
def derive
|
19
|
+
@result = ValuePoint.new("float", @arg)
|
20
|
+
end
|
21
|
+
|
22
|
+
def cleanup
|
23
|
+
pushes :float, @result
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# pops the top +:float+ item;
|
2
|
+
# pushes a new +:proportion+ item,
|
3
|
+
# with value obtained by taking the float modulo 1.0
|
4
|
+
#
|
5
|
+
# *needs:* 1 +:float+
|
6
|
+
#
|
7
|
+
# *pushes:* 1 +:proportion+
|
8
|
+
#
|
9
|
+
|
10
|
+
class ProportionFromFloatInstruction < Instruction
|
11
|
+
def preconditions?
|
12
|
+
needs :float, 1
|
13
|
+
end
|
14
|
+
|
15
|
+
def setup
|
16
|
+
@arg = @context.pop_value(:float)
|
17
|
+
end
|
18
|
+
|
19
|
+
def derive
|
20
|
+
@result = ValuePoint.new("proportion", @arg % 1.0)
|
21
|
+
end
|
22
|
+
|
23
|
+
def cleanup
|
24
|
+
pushes :proportion, @result
|
25
|
+
end
|
26
|
+
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# note: the top item is the denominator, the second item is the numerator
|
5
5
|
#
|
6
|
-
# note: will push an +:error+ ValuePoint instead of
|
6
|
+
# note: will push an +:error+ ValuePoint instead of a +:float+ if the numerator is 0.0
|
7
7
|
#
|
8
8
|
# *needs:* 2 +:float+
|
9
9
|
#
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# pops the top 2 items of the +:proportion+ stack;
|
2
|
+
# pushes a ValuePoint with their sum (or 1.0, whichever is smaller) onto the +:proportion+ stack
|
3
|
+
#
|
4
|
+
# *needs:* 2 +:proportion+
|
5
|
+
#
|
6
|
+
# *pushes:* 1 +:proportion+
|
7
|
+
#
|
8
|
+
|
9
|
+
class ProportionBoundedAddInstruction < Instruction
|
10
|
+
def preconditions?
|
11
|
+
needs :proportion, 2
|
12
|
+
end
|
13
|
+
def setup
|
14
|
+
@arg1 = @context.pop_value(:proportion)
|
15
|
+
@arg2 = @context.pop_value(:proportion)
|
16
|
+
end
|
17
|
+
def derive
|
18
|
+
@result = ValuePoint.new("proportion", [@arg1 + @arg2, 1.0].min)
|
19
|
+
end
|
20
|
+
def cleanup
|
21
|
+
pushes :proportion, @result
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# pops the top 2 items of the +:proportion+ stack;
|
2
|
+
# pushes a ValuePoint with their quotient onto the +:proportion+ stack, bounded by [0.0,1.0]
|
3
|
+
#
|
4
|
+
# note: the top item is the denominator, the second item is the numerator
|
5
|
+
#
|
6
|
+
# note: will push an +:error+ ValuePoint instead of the expected result if the numerator is 0.0
|
7
|
+
#
|
8
|
+
# *needs:* 2 +:proportion+
|
9
|
+
#
|
10
|
+
# *pushes:* 1 +:proportion+
|
11
|
+
#
|
12
|
+
|
13
|
+
class ProportionBoundedDivideInstruction < Instruction
|
14
|
+
def preconditions?
|
15
|
+
needs :proportion, 2
|
16
|
+
end
|
17
|
+
def setup
|
18
|
+
@arg2 = @context.pop_value(:proportion)
|
19
|
+
@arg1 = @context.pop_value(:proportion)
|
20
|
+
end
|
21
|
+
def derive
|
22
|
+
if @arg2 != 0.0
|
23
|
+
quotient = [@arg1/@arg2, 1.0].min
|
24
|
+
@result = ValuePoint.new("proportion", quotient)
|
25
|
+
else
|
26
|
+
raise NaNResultError, "#{self.class} cannot divide by 0.0"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
def cleanup
|
30
|
+
pushes :proportion, @result
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# pops the top 2 items of the +:proportion+ stack;
|
2
|
+
# pushes a ValuePoint with their difference (or 0.0, whichever is bigger) onto the +:proportion+ stack
|
3
|
+
#
|
4
|
+
# *note:* the first item popped is the number to be subtracted from the other
|
5
|
+
#
|
6
|
+
# *needs:* 2 +:proportion+
|
7
|
+
#
|
8
|
+
# *pushes:* 1 +:proportion+
|
9
|
+
#
|
10
|
+
|
11
|
+
class ProportionBoundedSubtractInstruction < Instruction
|
12
|
+
def preconditions?
|
13
|
+
needs :proportion, 2
|
14
|
+
end
|
15
|
+
def setup
|
16
|
+
@arg2 = @context.pop_value(:proportion)
|
17
|
+
@arg1 = @context.pop_value(:proportion)
|
18
|
+
end
|
19
|
+
def derive
|
20
|
+
@result = ValuePoint.new("proportion", [@arg1 - @arg2, 0.0].max)
|
21
|
+
end
|
22
|
+
def cleanup
|
23
|
+
pushes :proportion, @result
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# pops the top 2 items of the +:proportion+ stack;
|
2
|
+
# pushes a new ValuePoint onto the +:proportion+ stack with the largest of the two values
|
3
|
+
#
|
4
|
+
# *needs:* 2 +:proportion+
|
5
|
+
#
|
6
|
+
# *pushes:* 1 +:proportion+
|
7
|
+
#
|
8
|
+
|
9
|
+
class ProportionMaxInstruction < Instruction
|
10
|
+
def preconditions?
|
11
|
+
needs :proportion, 2
|
12
|
+
end
|
13
|
+
def setup
|
14
|
+
@arg2 = @context.pop_value(:proportion)
|
15
|
+
@arg1 = @context.pop_value(:proportion)
|
16
|
+
end
|
17
|
+
def derive
|
18
|
+
@result = ValuePoint.new("proportion", [@arg1, @arg2].max)
|
19
|
+
end
|
20
|
+
def cleanup
|
21
|
+
pushes :proportion, @result
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# pops the top 2 items of the +:proportion+ stack;
|
2
|
+
# pushes a new ValuePoint onto the +:proportion+ stack with the smallest of the two values
|
3
|
+
#
|
4
|
+
# *needs:* 2 +:proportion+
|
5
|
+
#
|
6
|
+
# *pushes:* 1 +:proportion+
|
7
|
+
#
|
8
|
+
|
9
|
+
class ProportionMinInstruction < Instruction
|
10
|
+
def preconditions?
|
11
|
+
needs :proportion, 2
|
12
|
+
end
|
13
|
+
def setup
|
14
|
+
@arg2 = @context.pop_value(:proportion)
|
15
|
+
@arg1 = @context.pop_value(:proportion)
|
16
|
+
end
|
17
|
+
def derive
|
18
|
+
@result = ValuePoint.new("proportion", [@arg1, @arg2].min)
|
19
|
+
end
|
20
|
+
def cleanup
|
21
|
+
pushes :proportion, @result
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# pops the top 2 items of the +:proportion+ stack;
|
2
|
+
# pushes a ValuePoint with their product onto the +:proportion+ stack
|
3
|
+
#
|
4
|
+
# *needs:* 2 +:proportion+
|
5
|
+
#
|
6
|
+
# *pushes:* 1 +:proportion+
|
7
|
+
#
|
8
|
+
|
9
|
+
class ProportionMultiplyInstruction < Instruction
|
10
|
+
def preconditions?
|
11
|
+
needs :proportion, 2
|
12
|
+
end
|
13
|
+
def setup
|
14
|
+
@arg2 = @context.pop_value(:proportion)
|
15
|
+
@arg1 = @context.pop_value(:proportion)
|
16
|
+
end
|
17
|
+
def derive
|
18
|
+
@result = ValuePoint.new("proportion", @arg1 * @arg2)
|
19
|
+
end
|
20
|
+
def cleanup
|
21
|
+
pushes :proportion, @result
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module NudgeType
|
2
|
+
|
3
|
+
class ProportionType
|
4
|
+
extend TypeBehaviors
|
5
|
+
@default_lowest = 0.0
|
6
|
+
@default_highest = 1.0
|
7
|
+
|
8
|
+
def self.default_lowest
|
9
|
+
@default_lowest
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.default_highest
|
13
|
+
@default_highest
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.random_value(params = {})
|
17
|
+
bottom = params[:proportion_lower_bound] || @default_lowest
|
18
|
+
top = params[:proportion_upper_bound] || @default_highest
|
19
|
+
raise ArgumentError, "ProportionType#{random_value} bounds must be in range [0.0,1.0]" unless
|
20
|
+
(0.0..1.0).include?(bottom) && (0.0..1.0).include?(top)
|
21
|
+
raise ArgumentError, "ProportionType#{random_value} bounds are inverted" unless
|
22
|
+
bottom <= top
|
23
|
+
range = top - bottom
|
24
|
+
(rand*range) + bottom
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.from_s(string_value)
|
28
|
+
(string_value.to_f != 1.0) ? (string_value.to_f % 1.0) : 1.0
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.recognizes?(a_thing)
|
32
|
+
!a_thing.kind_of?(String) && !a_thing.nil? && a_thing.respond_to?(:to_f)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.any_value(options ={})
|
36
|
+
self.random_value(options)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/nudge.rb
CHANGED
@@ -11,6 +11,7 @@ require 'cli/runner'
|
|
11
11
|
|
12
12
|
require 'interpreter/interpreter'
|
13
13
|
require 'interpreter/types/pushTypes'
|
14
|
+
require 'interpreter/types/proportion_type'
|
14
15
|
require 'interpreter/types/codeType'
|
15
16
|
require 'interpreter/stack'
|
16
17
|
require 'interpreter/programPoints'
|
@@ -23,6 +24,8 @@ Dir.glob(File.dirname(__FILE__) + '/instructions/exec/*') {|file| require file}
|
|
23
24
|
Dir.glob(File.dirname(__FILE__) + '/instructions/int/*') {|file| require file}
|
24
25
|
Dir.glob(File.dirname(__FILE__) + '/instructions/float/*') {|file| require file}
|
25
26
|
Dir.glob(File.dirname(__FILE__) + '/instructions/name/*') {|file| require file}
|
27
|
+
Dir.glob(File.dirname(__FILE__) + '/instructions/proportion/*') {|file| require file}
|
28
|
+
|
26
29
|
|
27
30
|
Dir.glob(File.dirname(__FILE__) + '/instructions/conversion/*') {|file| require file}
|
28
31
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), "../../spec_helper")
|
3
|
+
include Nudge
|
4
|
+
|
5
|
+
describe FloatFromProportionInstruction do
|
6
|
+
|
7
|
+
it_should_behave_like "every Nudge Instruction"
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
@context = Interpreter.new
|
11
|
+
@i1 = FloatFromProportionInstruction.new(@context)
|
12
|
+
@context.clear_stacks
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should check that there are enough parameters" do
|
16
|
+
@context.push(:proportion, 0.4)
|
17
|
+
@i1.preconditions?.should == true
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should raise an error if the preconditions aren't met" do
|
21
|
+
@context.clear_stacks # there are no params at all
|
22
|
+
lambda{@i1.preconditions?}.should raise_error(Instruction::NotEnoughStackItems)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should successfully run #go only if all preconditions are met" do
|
26
|
+
@context.push(:proportion, 0.2)
|
27
|
+
@i1.should_receive(:cleanup)
|
28
|
+
@i1.go
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should create and push the new (expected) value to the right place" do
|
32
|
+
@context.push(:proportion, "0.123")
|
33
|
+
@i1.go
|
34
|
+
@context.depth(:float).should == 1
|
35
|
+
@context.peek_value(:float).should be_close(0.123,0.000001)
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "../../spec_helper")
|
2
|
+
include Nudge
|
3
|
+
|
4
|
+
describe ProportionBoundedAddInstruction do
|
5
|
+
|
6
|
+
it_should_behave_like "every Nudge Instruction"
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@context = Interpreter.new
|
10
|
+
@i1 = ProportionBoundedAddInstruction.new(@context)
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
describe "\#go" do
|
15
|
+
before(:each) do
|
16
|
+
@context = Interpreter.new
|
17
|
+
@i1 = ProportionBoundedAddInstruction.new(@context)
|
18
|
+
@context.clear_stacks
|
19
|
+
@p1 = ValuePoint.new("proportion", 0.2)
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "\#preconditions?" do
|
23
|
+
it "should check that there are enough parameters" do
|
24
|
+
lambda{@i1.preconditions?}.should raise_error
|
25
|
+
10.times {@context.stacks[:proportion].push(@p1)}
|
26
|
+
@i1.preconditions?.should == true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "\#derive" do
|
31
|
+
it "should pop all the arguments" do
|
32
|
+
2.times {@context.stacks[:proportion].push(@p1)}
|
33
|
+
@i1.stub!(:cleanup) # and do nothing
|
34
|
+
@i1.go
|
35
|
+
@context.stacks[:proportion].depth.should == 0
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "\#cleanup" do
|
40
|
+
describe "should push the result" do
|
41
|
+
{[0.1, 0.2] => 0.3, [0.5, 0.5] => 1.0, [0.8, 0.9] => 1.0}.each do |inputs, expected|
|
42
|
+
params = inputs.inspect
|
43
|
+
it "should produce #{expected} given #{params}" do
|
44
|
+
inputs.each {|i| @context.stacks[:proportion].push(ValuePoint.new("proportion", i))}
|
45
|
+
@i1.go
|
46
|
+
@context.stacks[:proportion].peek.value.should be_close(expected,0.000001)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "../../spec_helper")
|
2
|
+
include Nudge
|
3
|
+
|
4
|
+
|
5
|
+
describe ProportionBoundedDivideInstruction do
|
6
|
+
|
7
|
+
it_should_behave_like "every Nudge Instruction"
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
@context = Interpreter.new
|
11
|
+
@i1 = ProportionBoundedDivideInstruction.new(@context)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "\#go" do
|
15
|
+
before(:each) do
|
16
|
+
@i1 = ProportionBoundedDivideInstruction.new(@context)
|
17
|
+
@context.clear_stacks
|
18
|
+
@p1 = ValuePoint.new("proportion", 0.3)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "\#preconditions?" do
|
22
|
+
it "should check that there are enough parameters" do
|
23
|
+
lambda{@i1.preconditions?}.should raise_error
|
24
|
+
10.times {@context.stacks[:proportion].push(@p1)}
|
25
|
+
@i1.preconditions?.should == true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "\#derive" do
|
30
|
+
it "should pop all the arguments" do
|
31
|
+
2.times {@context.stacks[:proportion].push(@p1)}
|
32
|
+
@i1.stub!(:cleanup) # and do nothing
|
33
|
+
@i1.go
|
34
|
+
@context.stacks[:proportion].depth.should == 0
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should push an error if it tries to divide by zero" do
|
38
|
+
@context.clear_stacks
|
39
|
+
@context.stacks[:proportion].push(ValuePoint.new("proportion", 0.9))
|
40
|
+
@context.stacks[:proportion].push(ValuePoint.new("proportion", 0.0))
|
41
|
+
@i1.go
|
42
|
+
@context.stacks[:error].depth.should == 1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "\#cleanup" do
|
47
|
+
describe "should push the result" do
|
48
|
+
{[0.3, 0.11] => 1.0, [0.3,0.8] => 0.375}.each do |inputs, expected|
|
49
|
+
params = inputs.inspect
|
50
|
+
it "should produce #{expected} given #{params}" do
|
51
|
+
inputs.each {|i| @context.stacks[:proportion].push(ValuePoint.new("proportion", i))}
|
52
|
+
@i1.go
|
53
|
+
@context.stacks[:proportion].peek.value.should be_close(expected,0.000001)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "../../spec_helper")
|
2
|
+
include Nudge
|
3
|
+
|
4
|
+
describe ProportionBoundedSubtractInstruction do
|
5
|
+
|
6
|
+
it_should_behave_like "every Nudge Instruction"
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@context = Interpreter.new
|
10
|
+
@i1 = ProportionBoundedSubtractInstruction.new(@context)
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
describe "\#go" do
|
15
|
+
before(:each) do
|
16
|
+
@context = Interpreter.new
|
17
|
+
@i1 = ProportionBoundedSubtractInstruction.new(@context)
|
18
|
+
@context.clear_stacks
|
19
|
+
@p1 = ValuePoint.new("proportion", 0.2)
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "\#preconditions?" do
|
23
|
+
it "should check that there are enough parameters" do
|
24
|
+
lambda{@i1.preconditions?}.should raise_error
|
25
|
+
10.times {@context.stacks[:proportion].push(@p1)}
|
26
|
+
@i1.preconditions?.should == true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "\#derive" do
|
31
|
+
it "should pop all the arguments" do
|
32
|
+
2.times {@context.stacks[:proportion].push(@p1)}
|
33
|
+
@i1.stub!(:cleanup) # and do nothing
|
34
|
+
@i1.go
|
35
|
+
@context.stacks[:proportion].depth.should == 0
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "\#cleanup" do
|
40
|
+
describe "should push the result" do
|
41
|
+
{[0.1, 0.2] => 0.0, [0.5, 0.5] => 0.0, [0.3, 0.05] => 0.25}.each do |inputs, expected|
|
42
|
+
params = inputs.inspect
|
43
|
+
it "should produce #{expected} given #{params}" do
|
44
|
+
inputs.each {|i| @context.stacks[:proportion].push(ValuePoint.new("proportion", i))}
|
45
|
+
@i1.go
|
46
|
+
@context.stacks[:proportion].peek.value.should be_close(expected,0.000001)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), "../../spec_helper")
|
3
|
+
include Nudge
|
4
|
+
|
5
|
+
describe ProportionFromFloatInstruction do
|
6
|
+
|
7
|
+
it_should_behave_like "every Nudge Instruction"
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
@context = Interpreter.new
|
11
|
+
@i1 = ProportionFromFloatInstruction.new(@context)
|
12
|
+
@context.clear_stacks
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should check that there are enough parameters" do
|
16
|
+
@context.push(:float, "0.234")
|
17
|
+
@i1.preconditions?.should == true
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should raise an error if the preconditions aren't met" do
|
21
|
+
@context.clear_stacks # there are no params at all
|
22
|
+
lambda{@i1.preconditions?}.should raise_error(Instruction::NotEnoughStackItems)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should successfully run #go only if all preconditions are met" do
|
26
|
+
@context.push(:float, "0.22")
|
27
|
+
@i1.should_receive(:cleanup)
|
28
|
+
@i1.go
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should create and push the new (expected) value to the right place" do
|
32
|
+
@context.push(:float, "0.1")
|
33
|
+
@i1.go
|
34
|
+
@context.depth(:proportion).should == 1
|
35
|
+
@context.peek_value(:proportion).should == 0.1
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should return a number in [0.0, 1.0]" do
|
39
|
+
@context.push(:float, "11.11")
|
40
|
+
@i1.go
|
41
|
+
@context.depth(:proportion).should == 1
|
42
|
+
@context.peek_value(:proportion).should be_close(0.11, 0.000001)
|
43
|
+
|
44
|
+
@context.push(:float, "-2.7")
|
45
|
+
@i1.go
|
46
|
+
@context.peek_value(:proportion).should be_close(0.3, 0.000001)
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "../../spec_helper")
|
2
|
+
include Nudge
|
3
|
+
|
4
|
+
describe ProportionMaxInstruction do
|
5
|
+
|
6
|
+
it_should_behave_like "every Nudge Instruction"
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@context = Interpreter.new
|
10
|
+
@i1 = ProportionMaxInstruction.new(@context)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "\#go" do
|
14
|
+
before(:each) do
|
15
|
+
@context = Interpreter.new
|
16
|
+
@i1 = ProportionMaxInstruction.new(@context)
|
17
|
+
@context.clear_stacks
|
18
|
+
@p1 = ValuePoint.new("proportion", 0.2)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "\#preconditions?" do
|
22
|
+
it "should check that there are enough parameters" do
|
23
|
+
lambda{@i1.preconditions?}.should raise_error
|
24
|
+
10.times {@context.stacks[:proportion].push(@p1)}
|
25
|
+
@i1.preconditions?.should == true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "\#derive" do
|
30
|
+
it "should pop all the arguments" do
|
31
|
+
2.times {@context.stacks[:proportion].push(@p1)}
|
32
|
+
@i1.stub!(:cleanup) # and do nothing
|
33
|
+
@i1.go
|
34
|
+
@context.stacks[:proportion].depth.should == 0
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "\#cleanup" do
|
39
|
+
describe "should push the result" do
|
40
|
+
{[0.1, 0.2] => 0.2, [0.9, 0.5] => 0.9, [1.0, 1.0] => 1.0}.each do |inputs, expected|
|
41
|
+
params = inputs.inspect
|
42
|
+
it "should produce #{expected} given #{params}" do
|
43
|
+
inputs.each {|i| @context.stacks[:proportion].push(ValuePoint.new("proportion", i))}
|
44
|
+
@i1.go
|
45
|
+
@context.stacks[:proportion].peek.value.should be_close(expected,0.000001)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "../../spec_helper")
|
2
|
+
include Nudge
|
3
|
+
|
4
|
+
describe ProportionMinInstruction do
|
5
|
+
|
6
|
+
it_should_behave_like "every Nudge Instruction"
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@context = Interpreter.new
|
10
|
+
@i1 = ProportionMinInstruction.new(@context)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "\#go" do
|
14
|
+
before(:each) do
|
15
|
+
@context = Interpreter.new
|
16
|
+
@i1 = ProportionMinInstruction.new(@context)
|
17
|
+
@context.clear_stacks
|
18
|
+
@p1 = ValuePoint.new("proportion", 0.2)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "\#preconditions?" do
|
22
|
+
it "should check that there are enough parameters" do
|
23
|
+
lambda{@i1.preconditions?}.should raise_error
|
24
|
+
10.times {@context.stacks[:proportion].push(@p1)}
|
25
|
+
@i1.preconditions?.should == true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "\#derive" do
|
30
|
+
it "should pop all the arguments" do
|
31
|
+
2.times {@context.stacks[:proportion].push(@p1)}
|
32
|
+
@i1.stub!(:cleanup) # and do nothing
|
33
|
+
@i1.go
|
34
|
+
@context.stacks[:proportion].depth.should == 0
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "\#cleanup" do
|
39
|
+
describe "should push the result" do
|
40
|
+
{[0.1, 0.2] => 0.1, [0.9, 0.5] => 0.5, [1.0, 1.0] => 1.0}.each do |inputs, expected|
|
41
|
+
params = inputs.inspect
|
42
|
+
it "should produce #{expected} given #{params}" do
|
43
|
+
inputs.each {|i| @context.stacks[:proportion].push(ValuePoint.new("proportion", i))}
|
44
|
+
@i1.go
|
45
|
+
@context.stacks[:proportion].peek.value.should be_close(expected,0.000001)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "../../spec_helper")
|
2
|
+
include Nudge
|
3
|
+
|
4
|
+
describe ProportionMultiplyInstruction do
|
5
|
+
|
6
|
+
it_should_behave_like "every Nudge Instruction"
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@context = Interpreter.new
|
10
|
+
@i1 = ProportionMultiplyInstruction.new(@context)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "\#go" do
|
14
|
+
before(:each) do
|
15
|
+
@context = Interpreter.new
|
16
|
+
@i1 = ProportionMultiplyInstruction.new(@context)
|
17
|
+
@context.clear_stacks
|
18
|
+
@p1 = ValuePoint.new("proportion", 0.2)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "\#preconditions?" do
|
22
|
+
it "should check that there are enough parameters" do
|
23
|
+
lambda{@i1.preconditions?}.should raise_error
|
24
|
+
10.times {@context.stacks[:proportion].push(@p1)}
|
25
|
+
@i1.preconditions?.should == true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "\#derive" do
|
30
|
+
it "should pop all the arguments" do
|
31
|
+
2.times {@context.stacks[:proportion].push(@p1)}
|
32
|
+
@i1.stub!(:cleanup) # and do nothing
|
33
|
+
@i1.go
|
34
|
+
@context.stacks[:proportion].depth.should == 0
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "\#cleanup" do
|
39
|
+
describe "should push the result" do
|
40
|
+
{[0.1, 0.2] => 0.02, [0.5, 0.5] => 0.25, [1.0, 0.0] => 0.0}.each do |inputs, expected|
|
41
|
+
params = inputs.inspect
|
42
|
+
it "should produce #{expected} given #{params}" do
|
43
|
+
inputs.each {|i| @context.stacks[:proportion].push(ValuePoint.new("proportion", i))}
|
44
|
+
@i1.go
|
45
|
+
@context.stacks[:proportion].peek.value.should be_close(expected,0.000001)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), "/../spec_helper")
|
3
|
+
|
4
|
+
describe "ProportionType" do
|
5
|
+
|
6
|
+
describe "class attributes" do
|
7
|
+
it "should have :default_lowest set to 0.0" do
|
8
|
+
ProportionType.default_lowest.should == 0.0
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should have :default_highest set to 1.0" do
|
12
|
+
ProportionType.default_highest.should == 1.0
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "self.random_value" do
|
17
|
+
it "should respond to random_value" do
|
18
|
+
ProportionType.should respond_to(:random_value)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should call the random number generator" do
|
22
|
+
ProportionType.should_receive(:rand).and_return(0.6)
|
23
|
+
ProportionType.random_value
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should use the :proportion_lower_bound option to set the lower end of the range" do
|
27
|
+
ProportionType.should_receive(:rand).and_return(0.0)
|
28
|
+
ProportionType.random_value(proportion_lower_bound:0.7).should == 0.7
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should use the :proportion_upper_bound option to set the upper end of the range" do
|
32
|
+
ProportionType.should_receive(:rand).and_return(1.0)
|
33
|
+
ProportionType.random_value(proportion_upper_bound:0.6).should == 0.6
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should raise an error if either bound is outside [0.0,1.0]" do
|
37
|
+
lambda{ProportionType.random_value(proportion_upper_bound:71.2)}.should raise_error(ArgumentError)
|
38
|
+
lambda{ProportionType.random_value(proportion_upper_bound:-12.0)}.should raise_error(ArgumentError)
|
39
|
+
lambda{ProportionType.random_value(proportion_lower_bound:71.2)}.should raise_error(ArgumentError)
|
40
|
+
lambda{ProportionType.random_value(proportion_lower_bound:-12.0)}.should raise_error(ArgumentError)
|
41
|
+
|
42
|
+
lambda{ProportionType.random_value(proportion_lower_bound:0.0)}.should_not raise_error(ArgumentError)
|
43
|
+
lambda{ProportionType.random_value(proportion_lower_bound:1.0)}.should_not raise_error(ArgumentError)
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should raise an error if the bounds are inverted" do
|
48
|
+
lambda{ProportionType.random_value(proportion_lower_bound:1.0,
|
49
|
+
proportion_upper_bound:0.0)}.should raise_error(ArgumentError)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "self.from_s" do
|
54
|
+
it "should use to_f" do
|
55
|
+
a = "0.9"
|
56
|
+
a.should_receive(:to_f).at_least(1).times.and_return(0.9)
|
57
|
+
ProportionType.from_s(a)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should return a value modulo 1.0" do
|
61
|
+
ProportionType.from_s("11.0").should == 0.0
|
62
|
+
ProportionType.from_s("-1.1").should be_close(0.9, 0.00000001)
|
63
|
+
ProportionType.from_s("1.1").should be_close(0.1, 0.00000001)
|
64
|
+
ProportionType.from_s("-0.0").should be_close(0.0, 0.00000001)
|
65
|
+
|
66
|
+
ProportionType.from_s("1.0").should == 1.0
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "self.recognizes?" do
|
71
|
+
it "should be true for floatlike things" do
|
72
|
+
ProportionType.recognizes?(0.1).should == true
|
73
|
+
ProportionType.recognizes?(1.0).should == true
|
74
|
+
ProportionType.recognizes?(-111.99).should == true
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should be true for Numerics that respond to to_f" do
|
78
|
+
ProportionType.recognizes?(12).should == true
|
79
|
+
ProportionType.recognizes?(-12).should == true
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should be false for strings" do
|
83
|
+
ProportionType.recognizes?("0.1").should == false
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should be false for nil" do
|
87
|
+
ProportionType.recognizes?(nil).should == false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "self.any_value" do
|
92
|
+
it "should pass everything along to random_value" do
|
93
|
+
args = {foo:12, bar:13, baz:17}
|
94
|
+
ProportionType.should_receive(:random_value).with(args)
|
95
|
+
ProportionType.any_value(args)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 9
|
9
|
+
version: 0.2.9
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Bill Tozier
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2010-05-
|
19
|
+
date: 2010-05-12 00:00:00 -04:00
|
20
20
|
default_executable: nudge
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -114,8 +114,10 @@ files:
|
|
114
114
|
- lib/instructions/conversion/code_from_name.rb
|
115
115
|
- lib/instructions/conversion/float_from_bool.rb
|
116
116
|
- lib/instructions/conversion/float_from_int.rb
|
117
|
+
- lib/instructions/conversion/float_from_proportion.rb
|
117
118
|
- lib/instructions/conversion/int_from_bool.rb
|
118
119
|
- lib/instructions/conversion/int_from_float.rb
|
120
|
+
- lib/instructions/conversion/proportion_from_float.rb
|
119
121
|
- lib/instructions/exec/exec_define.rb
|
120
122
|
- lib/instructions/exec/exec_depth.rb
|
121
123
|
- lib/instructions/exec/exec_do_count.rb
|
@@ -203,12 +205,19 @@ files:
|
|
203
205
|
- lib/instructions/name/name_unbind.rb
|
204
206
|
- lib/instructions/name/name_yank.rb
|
205
207
|
- lib/instructions/name/name_yankdup.rb
|
208
|
+
- lib/instructions/proportion/proportion_bounded_add.rb
|
209
|
+
- lib/instructions/proportion/proportion_bounded_divide.rb
|
210
|
+
- lib/instructions/proportion/proportion_bounded_subtract.rb
|
211
|
+
- lib/instructions/proportion/proportion_max.rb
|
212
|
+
- lib/instructions/proportion/proportion_min.rb
|
213
|
+
- lib/instructions/proportion/proportion_multiply.rb
|
206
214
|
- lib/interpreter/interpreter.rb
|
207
215
|
- lib/interpreter/nudge_program.rb
|
208
216
|
- lib/interpreter/parse.tab.rb
|
209
217
|
- lib/interpreter/programPoints.rb
|
210
218
|
- lib/interpreter/stack.rb
|
211
219
|
- lib/interpreter/types/codeType.rb
|
220
|
+
- lib/interpreter/types/proportion_type.rb
|
212
221
|
- lib/interpreter/types/pushTypes.rb
|
213
222
|
- lib/nudge.rb
|
214
223
|
- readme.md
|
@@ -309,6 +318,7 @@ files:
|
|
309
318
|
- spec/instructions/float/float_flush_spec.rb
|
310
319
|
- spec/instructions/float/float_from_bool_spec.rb
|
311
320
|
- spec/instructions/float/float_from_int_spec.rb
|
321
|
+
- spec/instructions/float/float_from_proportion_spec.rb
|
312
322
|
- spec/instructions/float/float_greater_than_q_spec.rb
|
313
323
|
- spec/instructions/float/float_if_spec.rb
|
314
324
|
- spec/instructions/float/float_less_than_q_spec.rb
|
@@ -371,6 +381,13 @@ files:
|
|
371
381
|
- spec/instructions/name/name_unbind_spec.rb
|
372
382
|
- spec/instructions/name/name_yank_spec.rb
|
373
383
|
- spec/instructions/name/name_yankdup_spec.rb
|
384
|
+
- spec/instructions/proportion/proportion_bounded_add_spec.rb
|
385
|
+
- spec/instructions/proportion/proportion_bounded_divide_spec.rb
|
386
|
+
- spec/instructions/proportion/proportion_bounded_subtract_spec.rb
|
387
|
+
- spec/instructions/proportion/proportion_from_float_spec.rb
|
388
|
+
- spec/instructions/proportion/proportion_max_spec.rb
|
389
|
+
- spec/instructions/proportion/proportion_min_spec.rb
|
390
|
+
- spec/instructions/proportion/proportion_multiply_spec.rb
|
374
391
|
- spec/interpreter/codeblock_point_spec.rb
|
375
392
|
- spec/interpreter/codetype_spec.rb
|
376
393
|
- spec/interpreter/instruction_spec.rb
|
@@ -378,6 +395,7 @@ files:
|
|
378
395
|
- spec/interpreter/nil_point_spec.rb
|
379
396
|
- spec/interpreter/nudge_program_class_methods_spec.rb
|
380
397
|
- spec/interpreter/nudge_program_spec.rb
|
398
|
+
- spec/interpreter/proportion_type_spec.rb
|
381
399
|
- spec/interpreter/reference_point_spec.rb
|
382
400
|
- spec/interpreter/stack_spec.rb
|
383
401
|
- spec/interpreter/types_spec.rb
|
@@ -523,6 +541,7 @@ test_files:
|
|
523
541
|
- spec/instructions/float/float_flush_spec.rb
|
524
542
|
- spec/instructions/float/float_from_bool_spec.rb
|
525
543
|
- spec/instructions/float/float_from_int_spec.rb
|
544
|
+
- spec/instructions/float/float_from_proportion_spec.rb
|
526
545
|
- spec/instructions/float/float_greater_than_q_spec.rb
|
527
546
|
- spec/instructions/float/float_if_spec.rb
|
528
547
|
- spec/instructions/float/float_less_than_q_spec.rb
|
@@ -585,6 +604,13 @@ test_files:
|
|
585
604
|
- spec/instructions/name/name_unbind_spec.rb
|
586
605
|
- spec/instructions/name/name_yank_spec.rb
|
587
606
|
- spec/instructions/name/name_yankdup_spec.rb
|
607
|
+
- spec/instructions/proportion/proportion_bounded_add_spec.rb
|
608
|
+
- spec/instructions/proportion/proportion_bounded_divide_spec.rb
|
609
|
+
- spec/instructions/proportion/proportion_bounded_subtract_spec.rb
|
610
|
+
- spec/instructions/proportion/proportion_from_float_spec.rb
|
611
|
+
- spec/instructions/proportion/proportion_max_spec.rb
|
612
|
+
- spec/instructions/proportion/proportion_min_spec.rb
|
613
|
+
- spec/instructions/proportion/proportion_multiply_spec.rb
|
588
614
|
- spec/interpreter/codeblock_point_spec.rb
|
589
615
|
- spec/interpreter/codetype_spec.rb
|
590
616
|
- spec/interpreter/instruction_spec.rb
|
@@ -592,6 +618,7 @@ test_files:
|
|
592
618
|
- spec/interpreter/nil_point_spec.rb
|
593
619
|
- spec/interpreter/nudge_program_class_methods_spec.rb
|
594
620
|
- spec/interpreter/nudge_program_spec.rb
|
621
|
+
- spec/interpreter/proportion_type_spec.rb
|
595
622
|
- spec/interpreter/reference_point_spec.rb
|
596
623
|
- spec/interpreter/stack_spec.rb
|
597
624
|
- spec/interpreter/types_spec.rb
|