spec/probability_spec.rb in games_dice-0.3.6 vs spec/probability_spec.rb in games_dice-0.3.7
- old
+ new
@@ -7,10 +7,24 @@
it "should create a new distribution from an array and offset" do
pr = GamesDice::Probabilities.new( [1.0], 1 )
pr.should be_a GamesDice::Probabilities
pr.to_h.should be_valid_distribution
end
+
+ it "should raise an error if passed incorrect parameter types" do
+ lambda { GamesDice::Probabilities.new( [ nil ], 20 ) }.should raise_error TypeError
+ lambda { GamesDice::Probabilities.new( [0.3,nil,0.5], 7 ) }.should raise_error TypeError
+ lambda { GamesDice::Probabilities.new( [0.3,0.2,0.5], {} ) }.should raise_error TypeError
+ lambda { GamesDice::Probabilities.new( {:x=>:y}, 17 ) }.should raise_error TypeError
+ end
+
+ it "should raise an error if distribution is incomplete or inaccurate" do
+ lambda { GamesDice::Probabilities.new( [0.3,0.2,0.6], 3 ) }.should raise_error ArgumentError
+ lambda { GamesDice::Probabilities.new( [], 1 ) }.should raise_error ArgumentError
+ lambda { GamesDice::Probabilities.new( [0.9], 1 ) }.should raise_error ArgumentError
+ lambda { GamesDice::Probabilities.new( [-0.9,0.2,0.9], 1 ) }.should raise_error ArgumentError
+ end
end
describe "#for_fair_die" do
it "should create a new distribution based on number of sides" do
pr2 = GamesDice::Probabilities.for_fair_die( 2 )
@@ -23,10 +37,19 @@
h.should be_valid_distribution
h.keys.count.should == sides
h.values.each { |v| v.should be_within(1e-10).of 1.0/sides }
end
end
+
+ it "should raise an error if number of sides is not an integer" do
+ lambda { GamesDice::Probabilities.for_fair_die( {} ) }.should raise_error TypeError
+ end
+
+ it "should raise an error if number of sides is too low or too high" do
+ lambda { GamesDice::Probabilities.for_fair_die( 0 ) }.should raise_error ArgumentError
+ lambda { GamesDice::Probabilities.for_fair_die( 1000001 ) }.should raise_error ArgumentError
+ end
end
describe "#add_distributions" do
it "should combine two distributions to create a third one" do
d4a = GamesDice::Probabilities.new( [ 1.0/4, 1.0/4, 1.0/4, 1.0/4 ], 1 )
@@ -50,10 +73,17 @@
h[9].should be_within(1e-9).of 4.0/36
h[10].should be_within(1e-9).of 3.0/36
h[11].should be_within(1e-9).of 2.0/36
h[12].should be_within(1e-9).of 1.0/36
end
+
+ it "should raise an error if either parameter is not a GamesDice::Probabilities object" do
+ d10 = GamesDice::Probabilities.for_fair_die( 10 )
+ lambda { GamesDice::Probabilities.add_distributions( '', 6 ) }.should raise_error TypeError
+ lambda { GamesDice::Probabilities.add_distributions( d10, 6 ) }.should raise_error TypeError
+ lambda { GamesDice::Probabilities.add_distributions( '', d10 ) }.should raise_error TypeError
+ end
end
describe "#add_distributions_mult" do
it "should combine two multiplied distributions to create a third one" do
d4a = GamesDice::Probabilities.new( [ 1.0/4, 1.0/4, 1.0/4, 1.0/4 ], 1 )
@@ -88,22 +118,48 @@
h[6].should be_within(1e-9).of 0.7 * 0.5
h[8].should be_within(1e-9).of 0.7 * 0.3 + 0.3 * 0.5
h[10].should be_within(1e-9).of 0.7 * 0.2 + 0.3 * 0.3
h[12].should be_within(1e-9).of 0.3 * 0.2
end
+
+ it "should raise an error if passed incorrect objects for distributions" do
+ d10 = GamesDice::Probabilities.for_fair_die( 10 )
+ lambda { GamesDice::Probabilities.add_distributions_mult( 1, '', -1, 6 ) }.should raise_error TypeError
+ lambda { GamesDice::Probabilities.add_distributions_mult( 2, d10, 3, 6 ) }.should raise_error TypeError
+ lambda { GamesDice::Probabilities.add_distributions_mult( 1, '', -1, d10 ) }.should raise_error TypeError
+ end
+
+ it "should raise an error if passed incorrect objects for multipliers" do
+ d10 = GamesDice::Probabilities.for_fair_die( 10 )
+ lambda { GamesDice::Probabilities.add_distributions_mult( {}, d10, [], d10 ) }.should raise_error TypeError
+ lambda { GamesDice::Probabilities.add_distributions_mult( [7], d10, 3, d10 ) }.should raise_error TypeError
+ lambda { GamesDice::Probabilities.add_distributions_mult( 1, d10, {}, d10 ) }.should raise_error TypeError
+ end
end
describe "#from_h" do
it "should create a Probabilities object from a valid hash" do
pr = GamesDice::Probabilities.from_h( { 7 => 0.5, 9 => 0.5 } )
pr.should be_a GamesDice::Probabilities
end
it "should raise an ArgumentError when called with a non-valid hash" do
- # lambda { GamesDice::Probabilities.from_h( :foo ) }.should raise_error ArgumentError
lambda { GamesDice::Probabilities.from_h( { 7 => 0.5, 9 => 0.6 } ) }.should raise_error ArgumentError
end
+
+ it "should raise an TypeError when called with data that is not a hash" do
+ lambda { GamesDice::Probabilities.from_h( :foo ) }.should raise_error TypeError
+ end
+
+ it "should raise a TypeError when called when keys and values are not all integers and floats" do
+ lambda { GamesDice::Probabilities.from_h( { 'x' => 0.5, 9 => 0.5 } ) }.should raise_error
+ lambda { GamesDice::Probabilities.from_h( { 7 => [], 9 => 0.5 } ) }.should raise_error TypeError
+ end
+
+ it "should raise an ArgumentError when results are spread very far apart" do
+ lambda { GamesDice::Probabilities.from_h( { 0 => 0.5, 2000000 => 0.5 } ) }.should raise_error ArgumentError
+ end
end
describe "#implemented_in" do
it "should be either :c or :ruby" do
lang = GamesDice::Probabilities.implemented_in
@@ -118,12 +174,25 @@
let(:pr4) { GamesDice::Probabilities.for_fair_die( 4 ) }
let(:pr6) { GamesDice::Probabilities.for_fair_die( 6 ) }
let(:pr10) { GamesDice::Probabilities.for_fair_die( 10 ) }
let(:pra) { GamesDice::Probabilities.new( [ 0.4, 0.2, 0.4 ], -1 ) }
- # TODO: each
+ describe "#each" do
+ it "should iterate through all result/probability pairs" do
+ yielded = []
+ pr4.each { |r,p| yielded << [r,p] }
+ yielded.should == [ [1,0.25], [2,0.25], [3,0.25], [4,0.25] ]
+ end
+ it "should skip zero probabilities" do
+ pr_plus_minus = GamesDice::Probabilities.new( [ 0.5, 0.0, 0.5 ], -1 )
+ yielded = []
+ pr_plus_minus .each { |r,p| yielded << [r,p] }
+ yielded.should == [ [-1,0.5], [1,0.5] ]
+ end
+ end
+
describe "#p_eql" do
it "should return probability of getting a number inside the range" do
pr2.p_eql(2).should be_within(1.0e-9).of 0.5
pr4.p_eql(1).should be_within(1.0e-9).of 0.25
pr6.p_eql(6).should be_within(1.0e-9).of 1.0/6
@@ -136,10 +205,14 @@
pr4.p_eql(-1).should == 0.0
pr6.p_eql(8).should == 0.0
pr10.p_eql(11).should == 0.0
pra.p_eql(2).should == 0.0
end
+
+ it "should raise a TypeError if asked for probability of non-Integer" do
+ lambda { pr2.p_eql( [] ) }.should raise_error TypeError
+ end
end # describe "#p_eql"
describe "#p_gt" do
it "should return probability of getting a number greater than target" do
pr2.p_gt(1).should be_within(1.0e-9).of 0.5
@@ -167,10 +240,14 @@
pr4.p_gt(-5).should == 1.0
pr6.p_gt(0).should == 1.0
pr10.p_gt(-200).should == 1.0
pra.p_gt(-2).should == 1.0
end
+
+ it "should raise a TypeError if asked for probability of non-Integer" do
+ lambda { pr2.p_gt( {} ) }.should raise_error TypeError
+ end
end # describe "#p_gt"
describe "#p_ge" do
it "should return probability of getting a number greater than or equal to target" do
pr2.p_ge(2).should be_within(1.0e-9).of 0.5
@@ -190,10 +267,14 @@
pr2.p_ge(1).should == 1.0
pr4.p_ge(-5).should == 1.0
pr6.p_ge(1).should == 1.0
pr10.p_ge(-200).should == 1.0
end
+
+ it "should raise a TypeError if asked for probability of non-Integer" do
+ lambda { pr4.p_ge( {} ) }.should raise_error TypeError
+ end
end # describe "#p_ge"
describe "#p_le" do
it "should return probability of getting a number less than or equal to target" do
pr2.p_le(1).should be_within(1.0e-9).of 0.5
@@ -213,10 +294,14 @@
pr2.p_le(0).should == 0.0
pr4.p_le(-5).should == 0.0
pr6.p_le(0).should == 0.0
pr10.p_le(-200).should == 0.0
end
+
+ it "should raise a TypeError if asked for probability of non-Integer" do
+ lambda { pr4.p_le( [] ) }.should raise_error TypeError
+ end
end # describe "#p_le"
describe "#p_lt" do
it "should return probability of getting a number less than target" do
pr2.p_lt(2).should be_within(1.0e-9).of 0.5
@@ -236,10 +321,14 @@
pr2.p_lt(1).should == 0.0
pr4.p_lt(-5).should == 0.0
pr6.p_lt(1).should == 0.0
pr10.p_lt(-200).should == 0.0
end
+
+ it "should raise a TypeError if asked for probability of non-Integer" do
+ lambda { pr6.p_lt( {} ) }.should raise_error TypeError
+ end
end # describe "#p_lt"
describe "#to_h" do
# This is used loads in other tests
it "should represent a valid distribution with each integer result associated with its probability" do
@@ -279,29 +368,37 @@
GamesDice::Probabilities.add_distributions( pr6, pr10 ).expected.should be_within(1.0e-9).of 9.0
end
end
describe "#given_ge" do
- it "should return a new distribution with probabilities calculated assuming value is >= target" do
+ it "should return a new distribution with probabilities calculated assuming value is >= target" do
pd = pr2.given_ge(2)
pd.to_h.should == { 2 => 1.0 }
pd = pr10.given_ge(4)
pd.to_h.should be_valid_distribution
pd.p_eql( 3 ).should == 0.0
pd.p_eql( 10 ).should be_within(1.0e-9).of 0.1/0.7
end
+
+ it "should raise a TypeError if asked for probability of non-Integer" do
+ lambda { pr10.given_ge( [] ) }.should raise_error TypeError
+ end
end
describe "#given_le" do
- it "should return a new distribution with probabilities calculated assuming value is <= target" do
+ it "should return a new distribution with probabilities calculated assuming value is <= target" do
pd = pr2.given_le(2)
pd.to_h.should == { 1 => 0.5, 2 => 0.5 }
pd = pr10.given_le(4)
pd.to_h.should be_valid_distribution
pd.p_eql( 3 ).should be_within(1.0e-9).of 0.1/0.4
pd.p_eql( 10 ).should == 0.0
end
+
+ it "should raise a TypeError if asked for probability of non-Integer" do
+ lambda { pr10.given_le( {} ) }.should raise_error TypeError
+ end
end
describe "#repeat_sum" do
it "should output a valid distribution if params are valid" do
d4a = GamesDice::Probabilities.new( [ 1.0/4, 1.0/4, 1.0/4, 1.0/4 ], 1 )
@@ -310,10 +407,20 @@
pr.to_h.should be_valid_distribution
pr = d4b.repeat_sum( 12 )
pr.to_h.should be_valid_distribution
end
+ it "should raise an error if any param is unexpected type" do
+ d6 = GamesDice::Probabilities.for_fair_die( 6 )
+ lambda{ d6.repeat_sum( {} ) }.should raise_error TypeError
+ end
+
+ it "should raise an error if distribution would have more than a million results" do
+ d1000 = GamesDice::Probabilities.for_fair_die( 1000 )
+ lambda{ d1000.repeat_sum( 11000 ) }.should raise_error
+ end
+
it "should calculate a '3d6' distribution accurately" do
d6 = GamesDice::Probabilities.for_fair_die( 6 )
pr = d6.repeat_sum( 3 )
h = pr.to_h
h.should be_valid_distribution
@@ -342,9 +449,20 @@
d4b = GamesDice::Probabilities.new( [ 1.0/10, 2.0/10, 3.0/10, 4.0/10], 1 )
pr = d4a.repeat_n_sum_k( 3, 2 )
pr.to_h.should be_valid_distribution
pr = d4b.repeat_n_sum_k( 12, 4 )
pr.to_h.should be_valid_distribution
+ end
+
+ it "should raise an error if any param is unexpected type" do
+ d6 = GamesDice::Probabilities.for_fair_die( 6 )
+ lambda{ d6.repeat_n_sum_k( {}, 10 ) }.should raise_error TypeError
+ lambda{ d6.repeat_n_sum_k( 10, {} ) }.should raise_error TypeError
+ end
+
+ it "should raise an error if n is greater than 170" do
+ d6 = GamesDice::Probabilities.for_fair_die( 6 )
+ lambda{ d6.repeat_n_sum_k( 171, 10 ) }.should raise_error
end
it "should calculate a '4d6 keep best 3' distribution accurately" do
d6 = GamesDice::Probabilities.for_fair_die( 6 )
pr = d6.repeat_n_sum_k( 4, 3 )