Skip to content

Instantly share code, notes, and snippets.

@mjansen401
Created June 28, 2012 13:17
Show Gist options
  • Save mjansen401/3011318 to your computer and use it in GitHub Desktop.
Save mjansen401/3011318 to your computer and use it in GitHub Desktop.
GildedRose solution
A solution to the Gilded Rose kata in Ruby with specs included.
Tests:
describe GildedRose do
VEST = "+5 Dexterity Vest"
ELIXIR = "Elixir of the Mongoose"
BRIE = "Aged Brie"
SULFURAS = "Sulfuras, Hand of Ragnaros"
BACKSTAGE_PASSES = "Backstage passes to a TAFKAL80ETC concert"
CONJURED_CAKE = "Conjured Mana Cake"
let(:gilded_rose) {GildedRose.new}
let(:vest) {item_by_name(VEST)}
let(:elixir) {item_by_name(ELIXIR)}
let(:brie) {item_by_name(BRIE)}
let(:sulfuras) {item_by_name(SULFURAS)}
let(:passes) {item_by_name(BACKSTAGE_PASSES)}
let(:conjured) {item_by_name(CONJURED_CAKE)}
def item_by_name(name)
gilded_rose.items.find {|item| item.name == name}
end
def update_quality(n = 1)
n.times { gilded_rose.update_quality }
end
context "sell_in values" do
it "decreases by 1 for non-legendary items" do
update_quality
vest.sell_in.should == 9
brie.sell_in.should == 1
elixir.sell_in.should == 4
passes.sell_in.should == 14
conjured.sell_in.should == 2
end
it "stays constant for legendary items" do
update_quality
sulfuras.sell_in.should == 0
update_quality
sulfuras.sell_in.should == 0
end
end
context "quality values" do
context "normal items" do
it "decreases the quality of an item when updating quality" do
update_quality
vest.quality.should == 19
end
it "quality degrades twice as fast once sell in date passes" do
update_quality(10)
vest.quality.should == 10
update_quality
vest.quality.should == 8
end
it "the quality should never be lower than 0" do
update_quality(6)
elixir.quality.should == 0
update_quality
elixir.quality.should == 0
end
end
context "aged brie" do
it "increases in quality when it ages" do
update_quality
brie.quality.should == 1
end
it "does not exceed 50 in quality" do
update_quality(50)
brie.quality.should == 50
update_quality
brie.quality.should == 50
end
end
context "Sulfuras" do
it "should never decrease in quality" do
update_quality
sulfuras.quality.should == 80
end
end
context "backstage passes" do
it "increases in quality by 1 with more than 10 days to sell" do
update_quality(5)
passes.quality.should == 25
end
it "increases in quality by 2 with more than 5 days to sell" do
update_quality(10)
passes.quality.should == 35
end
it "increases by 3 with less than 5 days to sell until expired" do
update_quality(15)
passes.quality.should == 50
end
it "quality drops to 0 when it expires" do
update_quality(16)
passes.quality.should == 0
end
end
context "conjured items" do
it "quality decreases twice as fast as other items" do
update_quality
conjured.quality.should == 4
end
end
end
end
Code:
class GildedRose
attr_accessor :items
VEST = "+5 Dexterity Vest"
ELIXIR = "Elixir of the Mongoose"
BRIE = "Aged Brie"
SULFURAS = "Sulfuras, Hand of Ragnaros"
BACKSTAGE_PASSES = "Backstage passes to a TAFKAL80ETC concert"
CONJURED_CAKE = "Conjured Mana Cake"
def initialize
@items = []
@items << Item.new(VEST, 10, 20)
@items << Item.new(BRIE, 2, 0)
@items << Item.new(ELIXIR, 5, 7)
@items << Item.new(SULFURAS, 0, 80)
@items << Item.new(BACKSTAGE_PASSES, 15, 20)
@items << Item.new(CONJURED_CAKE, 3, 6)
end
def update_quality
@items.each do |item|
rules =
item.sell_in = ItemRules.for_item(item.name).new_sell_in(item)
item.quality = ItemRules.for_item(item.name).new_quality(item)
end
end
end
class BaseItemStrategy
def self.new_sell_in(item)
item.sell_in - 1
end
end
class NormalItemStrategy < BaseItemStrategy
def self.new_quality(item)
return item.quality - 2 if item.sell_in < 0 && item.quality > 0
return item.quality - 1 if item.quality > 0
0
end
end
class BrieStrategy < BaseItemStrategy
def self.new_quality(item)
return item.quality + 1 unless item.quality >= 50
item.quality
end
end
class LegendaryStrategy
def self.new_sell_in(item)
item.sell_in
end
def self.new_quality(item)
item.quality
end
end
class BackstagePassStrategy < BaseItemStrategy
def self.new_quality(item)
return item.quality + 1 if item.sell_in >= 10
return item.quality + 2 if item.sell_in >= 5
return item.quality + 3 if item.sell_in >= 0
0
end
end
class ConjuredItemStrategy < BaseItemStrategy
def self.new_quality(item)
return item.quality - 2 if item.quality > 0
item.quality
end
end
class ItemRules
ITEM_TYPES = {
GildedRose::VEST => NormalItemStrategy,
GildedRose::ELIXIR => NormalItemStrategy,
GildedRose::SULFURAS => LegendaryStrategy,
GildedRose::BRIE => BrieStrategy,
GildedRose::BACKSTAGE_PASSES => BackstagePassStrategy,
GildedRose::CONJURED_CAKE => ConjuredItemStrategy
}
def self.for_item(name)
ITEM_TYPES[name] if ITEM_TYPES[name]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment