diff --git a/lib/bottles.rb b/lib/bottles.rb index 27aee4d..3d769a4 100644 --- a/lib/bottles.rb +++ b/lib/bottles.rb @@ -15,7 +15,7 @@ def verses(upper, lower) end def verse(number) - verse_template.lyrics(number, max: max) + verse_template.lyrics(number, max: max, min: min) end end @@ -30,8 +30,8 @@ def min 0 end - def lyrics(number, max: self.max) - new(BottleNumber.for(number, max: max)).lyrics + def lyrics(number, max: self.max, min: self.min) + new(BottleNumber.for(number, max: max, min: min)).lyrics end end @@ -51,8 +51,8 @@ def lyrics class BottleNumber - def self.for(number, max:) - case number + def self.for(number, max:, min:) + bottle_number = case number when 0 BottleNumber0 when 1 @@ -61,13 +61,25 @@ def self.for(number, max:) BottleNumber6 else BottleNumber - end.new(number, max: max) + end.new(number, max: max, min: min) + + if (number == min) + BottleNumberMin.new( + number, + max: max, + min: min, + bottle_number: bottle_number + ) + else + bottle_number + end end - attr_reader :number, :max - def initialize(number, max:) + attr_reader :number, :max, :min + def initialize(number, max:, min:) @number = number @max = max + @min = min end def to_s @@ -91,7 +103,7 @@ def pronoun end def successor - BottleNumber.for(number - 1, max: max) + BottleNumber.for(number - 1, max: max, min: min) end end @@ -99,14 +111,6 @@ class BottleNumber0 < BottleNumber def quantity "no more" end - - def action - "Go to the store and buy some more" - end - - def successor - BottleNumber.for(max, max: max) - end end class BottleNumber1 < BottleNumber @@ -128,3 +132,26 @@ def container "six-pack" end end + +class BottleNumberMin < BottleNumber + def initialize(number, max:, min:, bottle_number:) + super(number, max: max, min: min) + @bottle_number = bottle_number + end + + def quantity + @bottle_number.quantity + end + + def container + @bottle_number.container + end + + def action + "Go to the store and buy some more" + end + + def successor + BottleNumber.for(max, max: max, min: min) + end +end diff --git a/test/bottles_test.rb b/test/bottles_test.rb index 55db7ee..2a6053d 100644 --- a/test/bottles_test.rb +++ b/test/bottles_test.rb @@ -21,7 +21,7 @@ def min 5 end - def lyrics(number, max: nil) + def lyrics(number, max: nil, min: nil) "This is verse #{number}.\n" end end @@ -97,6 +97,15 @@ def test_verse_1 assert_equal expected, BottleVerse.lyrics(1) end + def test_verse_1_with_explicit_min_value + expected = + "1 bottle of beer on the wall, " + + "1 bottle of beer.\n" + + "Go to the store and buy some more, " + + "99 bottles of beer on the wall.\n" + assert_equal expected, BottleVerse.lyrics(1, min: 1) + end + def test_verse_0 expected = "No more bottles of beer on the wall, " + @@ -116,6 +125,39 @@ def test_verse_0_with_explicit_max_value end end +class BottleNumberMinTest < Minitest::Test + def test_verse_1 + expected = + "1 bottle of beer on the wall, " + + "1 bottle of beer.\n" + + "Go to the store and buy some more, " + + "99 bottles of beer on the wall.\n" + assert_equal expected, BottleVerse.new( + BottleNumberMin.new( + 1, + max: 99, + min: 1, + bottle_number: BottleNumber.for(1, max: 99, min: 1) + ) + ).lyrics + end + + def test_verse_0 + expected = + "No more bottles of beer on the wall, " + + "no more bottles of beer.\n" + + "Go to the store and buy some more, " + + "1 six-pack of beer on the wall.\n" + assert_equal expected, BottleVerse.new( + BottleNumberMin.new( + 0, + max: 6, + min: 0, + bottle_number: BottleNumber.for(0, max: 6, min: 0) + ) + ).lyrics + end +end class CountdownSongTest < Minitest::Test def test_verse @@ -181,7 +223,7 @@ def test_song end class Bottles99IntegrationTest < Minitest::Test - def test_partial_7_bottles_song + def test_custom_max_bottles_song expected = <<-SONG 7 bottles of beer on the wall, 7 bottles of beer. Take one down and pass it around, 1 six-pack of beer on the wall. @@ -212,8 +254,38 @@ def test_partial_7_bottles_song expected, CountdownSong.new( verse_template: BottleVerse, - max: 7, - min: 0 + max: 7 + ).song + ) + end + + def test_custom_max_min_bottles_song + expected = <<-SONG +1 six-pack of beer on the wall, 1 six-pack of beer. +Take one down and pass it around, 5 bottles of beer on the wall. + +5 bottles of beer on the wall, 5 bottles of beer. +Take one down and pass it around, 4 bottles of beer on the wall. + +4 bottles of beer on the wall, 4 bottles of beer. +Take one down and pass it around, 3 bottles of beer on the wall. + +3 bottles of beer on the wall, 3 bottles of beer. +Take one down and pass it around, 2 bottles of beer on the wall. + +2 bottles of beer on the wall, 2 bottles of beer. +Take one down and pass it around, 1 bottle of beer on the wall. + +1 bottle of beer on the wall, 1 bottle of beer. +Go to the store and buy some more, 1 six-pack of beer on the wall. + SONG + + assert_equal( + expected, + CountdownSong.new( + verse_template: BottleVerse, + max: 6, + min: 1 ).song ) end