Created
February 23, 2012 09:41
-
-
Save drKreso/1891958 to your computer and use it in GitHub Desktop.
The Gilded Rose Code Kata
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'guerrilla_patch' | |
SPECIAL_ITEMS = { | |
legendary: [ 'Sulfuras, Hand of Ragnaros' ], | |
one_time_event: [ 'Backstage passes to a TAFKAL80ETC concert'], | |
better_with_age: ['Aged Brie'], | |
conjured: ['Conjured Mana Cake'] | |
} | |
QUALITY_AMOUNT_RULES = [ | |
[ "self.standard?", "-1"], | |
[ "self.is? :conjured", "-2"], | |
[ "(self.is?(:one_time_event) && (self.sell_in >= 6 && self.sell_in < 11) )", "2"], | |
[ "(self.is?(:one_time_event) && (self.sell_in < 6 ))", "3"], | |
[ "true", "1"] | |
] | |
EXPIRED_QUALITY_AMOUNT_RULES = [ | |
[ "self.is? :one_time_event", "-self.quality"], | |
[ "self.is? :better_with_age", "1"], | |
[ "self.is? :conjured", "-2"], | |
[ "self.standard?", "-1" ], | |
[ "true", "0"] | |
] | |
def update_quality(items) | |
items.reject do |item| | |
item.extend Gilded | |
item.is? :legendary | |
end.each(&:tick_time) | |
end | |
module Gilded | |
def tick_time | |
adjust_quality | |
adjust_age | |
end | |
def adjust_quality | |
self.quality += find_amount(expired? ? EXPIRED_QUALITY_AMOUNT_RULES : QUALITY_AMOUNT_RULES) | |
limit_quality | |
end | |
def limit_quality | |
self.quality = 0 if self.quality < 0 | |
self.quality = 50 if self.quality > 50 | |
end | |
def adjust_age | |
self.sell_in -= 1 | |
adjust_quality if expired? | |
end | |
let(:expired?) { self.sell_in < 0 } | |
let(:standard?) { (SPECIAL_ITEMS.each_value.reduce([]){|result, array| result += array }).include?(self.name) == false } | |
let(:is?) {|name| SPECIAL_ITEMS[name].include?(self.name) } | |
let(:find_amount) { |rules| eval(rules.select {|item| eval(item[0]) }.flatten[1]) } | |
end | |
# DO NOT CHANGE THINGS BELOW ----------------------------------------- | |
Item = Struct.new(:name, :sell_in, :quality) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I don't think that optimal solution for the problem is sub-classing since classes hardly carry their weight in this example. I liked the JEG2 refactoring with modules.
Still I think the underlying abstraction for this is that you have arbitrary rules for quality with two cases: before and after expiration. You also have one exception of legendary items not being dependent on time.
IMHO code above communicates this nicely and rules are easy to grasp and extend.