Skip to content

Instantly share code, notes, and snippets.

@aisipos
Created April 15, 2020 21:30
Show Gist options
  • Save aisipos/efa567ee9fec119dc0a14b248616840f to your computer and use it in GitHub Desktop.
Save aisipos/efa567ee9fec119dc0a14b248616840f to your computer and use it in GitHub Desktop.
Python example solution Gilded Rose code Kata to http://codingdojo.org/kata/GildedRose/
import logging
import inspect
from dataclasses import dataclass, field
from typing import List, ClassVar
import pytest
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger('rose')
class ItemRegistry:
registry = {}
@staticmethod
def register(item_category, cls):
ItemRegistry.registry[item_category] = cls
@staticmethod
def get_class(item_category):
# Default to using Item if name is unknown
return ItemRegistry.registry.get(item_category, Item)
@dataclass
class Item:
category: str
quality: int = 10
sell_in: int = 1
def update_quality(self):
"Daily quality change"
if self.quality > 0:
if self.sell_in >= 0:
self.quality -= 1
else:
self.quality -= 2
def update_sell_in(self):
"Daily sell-in change"
self.sell_in -= 1
def max_quality(self):
if self.quality > 50:
self.quality = 50
RULES = ['update_sell_in', 'update_quality', 'max_quality']
@staticmethod
def make(category, *args, **kwargs):
"""
Instantiate the correct class of Item for the given category
"""
return ItemRegistry.get_class(category)(category, *args, **kwargs)
def update(self):
"""
Apply all rules to this instance
"""
logger.debug("%s %s", id(self), self)
for rule_name in self.RULES:
# Look up rule name on self and call it
getattr(self, rule_name)()
logger.debug("%s %s %s", id(self), rule_name, self)
def named_item(cls):
"Class decorator to register a known item type"
# Register this class so our make factory method knows it
ItemRegistry.register(cls.DEFINED_CATEGORY, cls)
@named_item
class Sulfuras(Item):
DEFINED_CATEGORY = 'Sulfuras'
def update_quality(self):
pass # Sulfuras doesn't go bad
def update_sell_in(self):
pass # Sulfuras doesn't sell
@named_item
class AgedBrie(Item):
DEFINED_CATEGORY = 'Aged Brie'
def update_quality(self):
"Daily quality change"
self.quality += 1 # Brie increases in quality with age
@named_item
class BackstagePass(Item):
DEFINED_CATEGORY = 'Backstage Pass'
def update_quality(self):
"Daily quality change"
if self.sell_in < 0:
self.quality = 0
elif self.sell_in <= 5:
self.quality += 3
elif self.sell_in <= 10:
self.quality += 2
else:
self.quality += 1
@named_item
class Conjured(Item):
DEFINED_CATEGORY = 'Conjured'
def update_quality(self):
"Daily quality change"
if self.quality > 0:
if self.sell_in >= 0:
self.quality -= 2
else:
self.quality -= 4
def test_no_negative_quality():
i = Item.make('test', quality=1); i.update(); assert i.quality == 0
i = Item.make('test', quality=0); i.update(); assert i.quality == 0
def test_quality_suffers_after_sell():
i = Item.make('test', quality=4, sell_in=2); i.update(); assert i.quality == 3
i = Item.make('test', quality=4, sell_in=-1); i.update(); assert i.quality == 2
def test_brie_quality_increases():
i = Item.make('Aged Brie', quality=4, sell_in=2); i.update(); assert i.quality == 5
def test_max_quality():
i = Item.make('Aged Brie', quality=50, sell_in=2); i.update(); assert i.quality == 50
def test_sulfuras():
i = Item.make('Sulfuras', quality=1, sell_in=1); i.update()
assert i.quality == 1
assert i.sell_in == 1
def test_backstage_pass():
i = Item.make('Backstage Pass', quality=10, sell_in=12); i.update(); assert i.quality == 11
i = Item.make('Backstage Pass', quality=10, sell_in=11); i.update(); assert i.quality == 12
i = Item.make('Backstage Pass', quality=10, sell_in=6); i.update(); assert i.quality == 13
i = Item.make('Backstage Pass', quality=10, sell_in=0); i.update(); assert i.quality == 0
def test_conjured():
i = Item.make('Conjured', quality=10, sell_in=12); i.update(); assert i.quality == 8
i = Item.make('Conjured', quality=10, sell_in=0); i.update(); assert i.quality == 6
if __name__=='__main__':
# print(ItemRegistry.registry)
pytest.main(['gilded_rose.py', '-v'])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment