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.
This commit is contained in:
uzairarslan committed 2026-09-24 03:21:18 +05:00
1 parent 19011580f5
commit fc9ceaad09
1 file changed
+62 -28
+62 -28
View File
@@ -15,39 +15,73 @@ class GildedRose(object):
def update_quality(self): def update_quality(self):
for item in self.items: for item in self.items:
self._update_item(item) 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 @staticmethod
def _update_item(item): def _sell_by_date_passed(item):
if item.name == SULFURAS: # sell_in is the number of days left to sell, so on the day it reaches
return # legendary: never has to be sold and never changes # 0 the item goes past its sell-by date as this update runs.
return item.sell_in <= 0
if item.name != AGED_BRIE and item.name != BACKSTAGE_PASS: @staticmethod
if item.quality > MIN_QUALITY: def _change_quality(item, delta):
item.quality = item.quality - 1 item.quality = max(MIN_QUALITY, min(MAX_QUALITY, item.quality + delta))
else:
if item.quality < MAX_QUALITY:
item.quality = item.quality + 1
if item.name == BACKSTAGE_PASS:
if item.sell_in < 11:
if item.quality < MAX_QUALITY:
item.quality = item.quality + 1
if item.sell_in < 6:
if item.quality < MAX_QUALITY:
item.quality = item.quality + 1
item.sell_in = item.sell_in - 1
if item.sell_in < 0: class AgedBrieUpdater(ItemUpdater):
if item.name != AGED_BRIE: """Appreciates at the same rate ordinary items degrade."""
if item.name != BACKSTAGE_PASS:
if item.quality > MIN_QUALITY: def _quality_delta(self, item):
item.quality = item.quality - 1 return 2 if self._sell_by_date_passed(item) else 1
else:
item.quality = MIN_QUALITY
else: class BackstagePassUpdater(ItemUpdater):
if item.quality < MAX_QUALITY: """Appreciates faster as the concert approaches, then becomes worthless."""
item.quality = item.quality + 1
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: class Item: