Created
April 15, 2020 21:30
-
-
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/
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
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