Skip to content
Snippets Groups Projects
Commit 4950b9f3 authored by ulif's avatar ulif
Browse files

Merge branch 'dwcoder-fix-iss19'

parents 3a56fe25 db9165e5
No related branches found
No related tags found
No related merge requests found
...@@ -131,9 +131,8 @@ class RealDiceRandomSource(object): ...@@ -131,9 +131,8 @@ class RealDiceRandomSource(object):
We make sure that `num_rolls`, the number of rolls, is in an We make sure that `num_rolls`, the number of rolls, is in an
acceptable range and issue an hint about the procedure. acceptable range and issue an hint about the procedure.
""" """
if num_rolls < 1: if num_rolls == 0:
raise ValueError( raise(ValueError)
"Must provide at least %s items" % self.dice_sides)
if (self.dice_sides ** num_rolls) < len(sequence): if (self.dice_sides ** num_rolls) < len(sequence):
print( print(
"Warning: entropy is reduced! Using only first %s of %s " "Warning: entropy is reduced! Using only first %s of %s "
...@@ -150,6 +149,22 @@ class RealDiceRandomSource(object): ...@@ -150,6 +149,22 @@ class RealDiceRandomSource(object):
"""Pick one item out of `sequence`. """Pick one item out of `sequence`.
""" """
num_rolls = int(math.log(len(sequence), self.dice_sides)) num_rolls = int(math.log(len(sequence), self.dice_sides))
use_modulo = False
if num_rolls < 1:
# If this happens, there are less values in the sequence to
# choose from than there are dice sides.
# First check whehter the length is 1. Then we don't have
# to do anything else
if len(sequence) == 1:
# Check whether len(sequence) is a factor of dice.sides
return sequence[0]
if self.dice_sides % len(sequence) == 0:
use_modulo = True
num_rolls = 1
else:
# otherwise We will perform one extra roll and apply modulo
use_modulo = True
num_rolls = 2
self.pre_check(num_rolls, sequence) self.pre_check(num_rolls, sequence)
result = 0 result = 0
for i in range(num_rolls, 0, -1): for i in range(num_rolls, 0, -1):
...@@ -159,4 +174,6 @@ class RealDiceRandomSource(object): ...@@ -159,4 +174,6 @@ class RealDiceRandomSource(object):
rolled = input_func( rolled = input_func(
"What number shows dice number %s? " % (num_rolls - i + 1)) "What number shows dice number %s? " % (num_rolls - i + 1))
result += ((self.dice_sides ** (i - 1)) * (int(rolled) - 1)) result += ((self.dice_sides ** (i - 1)) * (int(rolled) - 1))
if use_modulo:
result = result % len(sequence)
return sequence[result] return sequence[result]
...@@ -219,13 +219,6 @@ class TestRealDiceRandomSource(object): ...@@ -219,13 +219,6 @@ class TestRealDiceRandomSource(object):
src = RealDiceRandomSource(None) src = RealDiceRandomSource(None)
assert src.choice([1, 2, 3, 4, 5, 6]) == 1 assert src.choice([1, 2, 3, 4, 5, 6]) == 1
def test_choice_len_too_short(self, monkeypatch):
# We raise an exception if choice gets less than 6 elements.
self.fake_input_values(["1"], monkeypatch)
src = RealDiceRandomSource(None)
with pytest.raises(ValueError):
assert src.choice([1, 2, 3, 4, 5]) # list len < 6
def test_choice_input_lower_value_borders(self, monkeypatch): def test_choice_input_lower_value_borders(self, monkeypatch):
# choice() does not accept "0" but it accepts "1" # choice() does not accept "0" but it accepts "1"
self.fake_input_values(["0", "1"], monkeypatch) self.fake_input_values(["0", "1"], monkeypatch)
...@@ -263,3 +256,29 @@ class TestRealDiceRandomSource(object): ...@@ -263,3 +256,29 @@ class TestRealDiceRandomSource(object):
src.pre_check(5, ['doesntmatter']) src.pre_check(5, ['doesntmatter'])
out, err = capsys.readouterr() out, err = capsys.readouterr()
assert "Please roll 5 dice (or a single dice 5 times)." in out assert "Please roll 5 dice (or a single dice 5 times)." in out
def test_sequence_less_than_dice_sides(self, capsys, monkeypatch):
# Test to see whether we can use a n-sided die to choose from
# a sequence with less than n items
src = RealDiceRandomSource(None)
src.dice_sides = 6
# A length of 1 requires no rolls
self.fake_input_values(["1"], monkeypatch)
picked = src.choice([1])
out, err = capsys.readouterr()
assert "roll" not in out
assert picked == 1
# A length of 2,3 only requires 1 roll
for choice_length in (2, 3):
self.fake_input_values(["1"], monkeypatch)
picked = src.choice(range(1, choice_length + 1))
out, err = capsys.readouterr()
assert "roll 1 dice" in out
assert picked == 1
# A length of 4,5 requires 2 rolls
for choice_length in (4, 5):
self.fake_input_values(["1", "1"], monkeypatch)
picked = src.choice(range(1, choice_length + 1))
out, err = capsys.readouterr()
assert "roll 2 dice" in out
assert picked == 1
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment