Skip to content

Instantly share code, notes, and snippets.

@unixcharles
Last active June 23, 2021 14:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save unixcharles/64e88dc2d409a83c994c7343ac152ec3 to your computer and use it in GitHub Desktop.
Save unixcharles/64e88dc2d409a83c994c7343ac152ec3 to your computer and use it in GitHub Desktop.
guilded_rose_kata
class ItemUpdater
class AgedBrie < ItemUpdater
def value_change
-super
end
end
class BackstagePass < ItemUpdater
def value_change
case sell_in
when -Float::INFINITY..0
-quality
when 1..5
3
when 5..10
2
else
1
end
end
end
class Sulfuras < ItemUpdater
def call
# no-op
end
end
class Conjured < ItemUpdater
def value_change
super * 2
end
end
attr_reader :sell_in, :quality
MINIMUM_QUALITY = 0
MAXIMUM_QUALITY = 50
UPDATER_CLASSES = {
'Aged Brie' => AgedBrie,
'Backstage passes to a TAFKAL80ETC concert' => BackstagePass,
'Sulfuras, Hand of Ragnaros' => Sulfuras,
'Conjured Mana Cake' => Conjured,
}
UPDATER_CLASSES.default = self
def self.from_name(name)
UPDATER_CLASSES[name]
end
def initialize(sell_in, quality)
@sell_in = sell_in
@quality = quality
end
def call
@quality = within_boundary(quality + value_change)
@sell_in -= 1
end
def value_change
if sell_in.zero? || sell_in.negative?
-2
else
-1
end
end
private
def within_boundary(value)
value_or_maximum = [MAXIMUM_QUALITY, value].min
[MINIMUM_QUALITY, value_or_maximum].max
end
end
class GildedRose
def initialize(items)
@items = items
end
def update_quality
@items.each do |item|
updater = ItemUpdater.from_name(item.name).new(item.sell_in, item.quality)
updater.call
item.sell_in = updater.sell_in
item.quality = updater.quality
end
end
end
class Item
attr_accessor :name, :sell_in, :quality
def initialize(name, sell_in, quality)
@name = name
@sell_in = sell_in
@quality = quality
end
def to_s
"#{@name}, #{@sell_in}, #{@quality}"
end
end
require File.join(File.dirname(__FILE__), 'gilded_rose')
describe GildedRose do
describe '#update_quality' do
subject { GildedRose.new(items) }
let(:items) { [item] }
let(:item) { Item.new(object_name, 20, 20) }
context 'generic objects' do
let(:object_name) { 'foo' }
it 'does not change the name' do
expect { subject.update_quality }.not_to change { item.name }
end
it 'decrease the sell in date by one' do
expect { subject.update_quality }.to change { item.sell_in }.by(-1)
end
it 'decrease the quality by one' do
expect { subject.update_quality }.to change { item.quality }.by(-1)
end
it 'does not decrease the quality bellow zero' do
item.quality = 0
expect { subject.update_quality }.not_to change { item.quality }
end
it 'decrease the quality by two once the sell in date reach zero' do
item.sell_in = 0
expect { subject.update_quality }.to change { item.quality }.by(-2)
end
end
context 'Aged Brie' do
let(:object_name) { 'Aged Brie' }
it 'does not increase beyond 50' do
item.quality = 50
expect { subject.update_quality }.not_to change { item.quality }
end
it 'increase the quality by one' do
expect { subject.update_quality }.to change { item.quality }.by(+1)
end
it 'increase the quality by two once the sell in date reach zero' do
item.sell_in = 0
expect { subject.update_quality }.to change { item.quality }.by(+2)
end
end
context 'Sulfras' do
let(:object_name) { 'Sulfuras, Hand of Ragnaros' }
it 'does not change the sell in' do
expect { subject.update_quality }.not_to change { item.sell_in }
end
it 'does not change the quality' do
expect { subject.update_quality }.not_to change { item.quality }
end
it 'does not change the quality if the sell in is zero' do
item.sell_in = 0
expect { subject.update_quality }.not_to change { item.quality }
end
end
context 'Backstage passes' do
let(:object_name) { 'Backstage passes to a TAFKAL80ETC concert' }
it 'increase quality by one when the sell in is more than 10 days' do
item.sell_in = 11
expect { subject.update_quality }.to change { item.quality }.by(+1)
end
it 'increase quality by two when the sell in is at 10 days' do
item.sell_in = 10
expect { subject.update_quality }.to change { item.quality }.by(+2)
end
it 'increase quality by three when the sell in is at 5 days' do
item.sell_in = 5
expect { subject.update_quality }.to change { item.quality }.by(+3)
end
it 'drop quality to zero when the sell in is zero' do
item.sell_in = 0
subject.update_quality
expect(item.quality).to be_zero
end
end
context 'Conjured' do
let(:object_name) { 'Conjured Mana Cake' }
it 'decrease the quality by two' do
expect { subject.update_quality }.to change { item.quality }.by(-2)
end
it 'decrease the quality by four once the sell in date reach zero' do
item.sell_in = 0
expect { subject.update_quality }.to change { item.quality }.by(-4)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment