Files
GildedRose-Refactoring-Kata/python/gilded_rose.py
T
uzairarslan fc9ceaad09 Split update logic into one updater class per item type
ItemUpdater has the normal rules. Brie, backstage passes and Sulfuras
subclass it and override only what differs. GildedRose picks the right
one through updater_for. Tests and approved output unchanged.
2026-09-24 03:21:18 +05:00

95 lines
2.5 KiB
Python
Executable File

# -*- coding: utf-8 -*-
AGED_BRIE = "Aged Brie"
BACKSTAGE_PASS = "Backstage passes to a TAFKAL80ETC concert"
SULFURAS = "Sulfuras, Hand of Ragnaros"
MIN_QUALITY = 0
MAX_QUALITY = 50
class GildedRose(object):
def __init__(self, items):
self.items = items
def update_quality(self):
for item in self.items:
updater_for(item).update(item)
class ItemUpdater:
"""End-of-day rules for an ordinary item.
Subclasses override only the part that differs for their category. Quality
is assumed to start within [MIN_QUALITY, MAX_QUALITY] as the requirements
state; it is clamped to that range after every change.
"""
def update(self, item):
self._change_quality(item, self._quality_delta(item))
item.sell_in -= 1
def _quality_delta(self, item):
return -2 if self._sell_by_date_passed(item) else -1
@staticmethod
def _sell_by_date_passed(item):
# sell_in is the number of days left to sell, so on the day it reaches
# 0 the item goes past its sell-by date as this update runs.
return item.sell_in <= 0
@staticmethod
def _change_quality(item, delta):
item.quality = max(MIN_QUALITY, min(MAX_QUALITY, item.quality + delta))
class AgedBrieUpdater(ItemUpdater):
"""Appreciates at the same rate ordinary items degrade."""
def _quality_delta(self, item):
return 2 if self._sell_by_date_passed(item) else 1
class BackstagePassUpdater(ItemUpdater):
"""Appreciates faster as the concert approaches, then becomes worthless."""
def _quality_delta(self, item):
if self._sell_by_date_passed(item):
return -item.quality
if item.sell_in <= 5:
return 3
if item.sell_in <= 10:
return 2
return 1
class SulfurasUpdater(ItemUpdater):
"""Legendary: never has to be sold and never changes."""
def update(self, item):
pass
_UPDATERS_BY_NAME = {
AGED_BRIE: AgedBrieUpdater(),
BACKSTAGE_PASS: BackstagePassUpdater(),
SULFURAS: SulfurasUpdater(),
}
_DEFAULT_UPDATER = ItemUpdater()
def updater_for(item):
"""Pick the rule set that applies to an item. Updaters are stateless."""
return _UPDATERS_BY_NAME.get(item.name, _DEFAULT_UPDATER)
class Item:
def __init__(self, name, sell_in, quality):
self.name = name
self.sell_in = sell_in
self.quality = quality
def __repr__(self):
return "%s, %s, %s" % (self.name, self.sell_in, self.quality)