summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gay <eapoems@riseup.net>2024-04-13 21:21:01 -0400
committerDavid Gay <eapoems@riseup.net>2024-04-13 21:21:01 -0400
commitc900787aa7838d2c708c6c0e92f9da9f7c9121d2 (patch)
treea6dc8e4fc772feda4f8f06fb63e26ad4c5f6b8a6
parent0d233ca818c3873b1d0da3aa132ccdf36c0d3d16 (diff)
Dice lib
-rw-r--r--app/lib/dice.rb29
-rw-r--r--app/lib/dice/result.rb32
-rw-r--r--app/lib/dice/roll.rb14
-rw-r--r--test/lib/dice_test.rb34
4 files changed, 109 insertions, 0 deletions
diff --git a/app/lib/dice.rb b/app/lib/dice.rb
new file mode 100644
index 0000000..3b6df48
--- /dev/null
+++ b/app/lib/dice.rb
@@ -0,0 +1,29 @@
+module Dice
+ # @param sides [Integer]
+ # @return [Dice::Result]
+ def self.roll(sides)
+ result = Dice::Result.new
+ result.add_roll Dice::Roll.new(sides)
+ result
+ end
+
+ # @param formula [String]
+ def self.roll_formula(formula)
+ # Will add other delimiters later.
+ parts = formula.split("d")
+
+ if parts.length < 2
+ raise "Invalid formula: #{formula}"
+ end
+
+ num_dice = parts[0].empty? ? 1 : parts[0].to_i
+ sides = parts[1].to_i
+
+ result = Dice::Result.new
+ num_dice.times do
+ result.add_roll Dice::Roll.new(sides)
+ end
+
+ result
+ end
+end
diff --git a/app/lib/dice/result.rb b/app/lib/dice/result.rb
new file mode 100644
index 0000000..103a282
--- /dev/null
+++ b/app/lib/dice/result.rb
@@ -0,0 +1,32 @@
+class Dice::Result
+ attr_reader :rolls
+
+ def initialize
+ @rolls = []
+ end
+
+ # @param other [Dice::Result]
+ def ==(other)
+ sides == other.sides && face == other.face
+ end
+
+ # @param roll [Dice::Roll]
+ def add_roll(roll)
+ @rolls << roll
+ end
+
+ # @return [Integer]
+ def total
+ @rolls.sum(&:face)
+ end
+
+ def increase_sides_below_max(max_value, increase_by)
+ @rolls.each do |roll|
+ roll.increase_side_below_max(max_value, increase_by)
+ end
+ end
+
+ def to_s
+ "#{total} (#{@rolls.map(&:face).join(', ')})"
+ end
+end
diff --git a/app/lib/dice/roll.rb b/app/lib/dice/roll.rb
new file mode 100644
index 0000000..dd4788b
--- /dev/null
+++ b/app/lib/dice/roll.rb
@@ -0,0 +1,14 @@
+class Dice::Roll
+ attr_reader :sides, :face
+
+ # @param sides [Integer]
+ # @param face [Integer] (Optional) Rolled if not provided.
+ def initialize(sides, face = nil)
+ @sides = sides
+ @face = face || rand(1..sides)
+ end
+
+ def increase_side_below_max(max_value, increase_by)
+ @face += increase_by if @face < max_value
+ end
+end
diff --git a/test/lib/dice_test.rb b/test/lib/dice_test.rb
new file mode 100644
index 0000000..1f36f30
--- /dev/null
+++ b/test/lib/dice_test.rb
@@ -0,0 +1,34 @@
+require "test_helper"
+
+class DiceTest < ActiveSupport::TestCase
+ test "rolls fomula" do
+ result = Dice.roll_formula("4d6+2")
+
+ assert_equal 4, result.rolls.count
+ assert_equal 6, result.rolls.first&.sides
+ end
+
+ test "rolls single die" do
+ result = Dice.roll(10)
+
+ assert_equal 1, result.rolls.count
+ assert_equal 10, result.rolls.first&.sides
+ end
+
+ test "increases sides below max" do
+ original_result = Dice::Result.new
+ original_result.add_roll Dice::Roll.new(6, 5)
+ original_result.add_roll Dice::Roll.new(6, 6)
+ original_result.add_roll Dice::Roll.new(6, 2)
+
+ new_result = original_result.dup
+
+ assert_equal 13, new_result.total
+ new_result.increase_sides_below_max(6, 1)
+ assert_equal 15, new_result.total
+
+ new_result.rolls.each_with_index do |roll, index|
+ assert_equal roll, original_result.rolls[index]
+ end
+ end
+end