From c900787aa7838d2c708c6c0e92f9da9f7c9121d2 Mon Sep 17 00:00:00 2001 From: David Gay Date: Sat, 13 Apr 2024 21:21:01 -0400 Subject: Dice lib --- app/lib/dice.rb | 29 +++++++++++++++++++++++++++++ app/lib/dice/result.rb | 32 ++++++++++++++++++++++++++++++++ app/lib/dice/roll.rb | 14 ++++++++++++++ test/lib/dice_test.rb | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+) create mode 100644 app/lib/dice.rb create mode 100644 app/lib/dice/result.rb create mode 100644 app/lib/dice/roll.rb create mode 100644 test/lib/dice_test.rb 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 -- cgit v1.2.3