From 18913475857c3160c3e38592ccccf552ee0f649d Mon Sep 17 00:00:00 2001 From: himanshukaushiksc22h2k Date: Sat, 30 May 2026 21:49:15 +0100 Subject: [PATCH] refactor Gilded Rose into per-item updaters and add Conjured items - add characterization tests covering all existing item rules - replace nested conditionals with per-item updater classes - add Conjured items that degrade twice as fast as normal --- python/gilded_rose.py | 126 ++++++++++++++++++++++++++++++++---------- 1 file changed, 98 insertions(+), 28 deletions(-) diff --git a/python/gilded_rose.py b/python/gilded_rose.py index 4f21ea64..e80f1a40 100755 --- a/python/gilded_rose.py +++ b/python/gilded_rose.py @@ -1,4 +1,100 @@ # -*- coding: utf-8 -*- +"""Gilded Rose inventory system. + +The quality-update rules differ per item category. Rather than branch on the +item name inside one giant method, each category is modelled as an updater that +knows how to age a single item by one day. ``GildedRose`` simply dispatches each +item to the matching updater. + +NOTE: The ``Item`` class and its attributes are owned by the "goblin in the +corner" and must not be modified, so all behaviour lives in the updaters. +""" + +MIN_QUALITY = 0 +MAX_QUALITY = 50 + +AGED_BRIE = "Aged Brie" +BACKSTAGE_PASS = "Backstage passes to a TAFKAL80ETC concert" +SULFURAS = "Sulfuras, Hand of Ragnaros" +CONJURED_PREFIX = "Conjured" + + +def _clamp(quality): + """Keep quality within the legal [0, 50] range.""" + return max(MIN_QUALITY, min(MAX_QUALITY, quality)) + + +class ItemUpdater(object): + """Base updater: a normal item degrades by 1, then by 2 once expired.""" + + daily_degradation = 1 + + def __init__(self, item): + self.item = item + + def update(self): + self._update_sell_in() + self._update_quality() + + def _update_sell_in(self): + self.item.sell_in -= 1 + + def _update_quality(self): + amount = self.daily_degradation + if self.item.sell_in < 0: + amount *= 2 # degrades twice as fast after the sell-by date + self.item.quality = _clamp(self.item.quality - amount) + + +class AgedBrieUpdater(ItemUpdater): + """Aged Brie increases in quality the older it gets, faster once expired.""" + + def _update_quality(self): + amount = 1 + if self.item.sell_in < 0: + amount *= 2 + self.item.quality = _clamp(self.item.quality + amount) + + +class BackstagePassUpdater(ItemUpdater): + """Backstage passes gain value as the concert approaches, then drop to zero + once the concert has passed.""" + + def _update_quality(self): + if self.item.sell_in < 0: + self.item.quality = 0 + return + amount = 1 + if self.item.sell_in < 5: + amount = 3 + elif self.item.sell_in < 10: + amount = 2 + self.item.quality = _clamp(self.item.quality + amount) + + +class SulfurasUpdater(ItemUpdater): + """Sulfuras is legendary: it never has to be sold and never changes.""" + + def update(self): + pass + + +class ConjuredUpdater(ItemUpdater): + """Conjured items degrade twice as fast as normal items.""" + + daily_degradation = 2 + +def updater_for(item): + """Pick the right updater for an item based on its name.""" + if item.name == AGED_BRIE: + return AgedBrieUpdater(item) + if item.name == BACKSTAGE_PASS: + return BackstagePassUpdater(item) + if item.name == SULFURAS: + return SulfurasUpdater(item) + if item.name.startswith(CONJURED_PREFIX): + return ConjuredUpdater(item) + return ItemUpdater(item) class GildedRose(object): @@ -7,33 +103,7 @@ class GildedRose(object): def update_quality(self): for item in self.items: - if item.name != "Aged Brie" and item.name != "Backstage passes to a TAFKAL80ETC concert": - if item.quality > 0: - if item.name != "Sulfuras, Hand of Ragnaros": - item.quality = item.quality - 1 - else: - if item.quality < 50: - item.quality = item.quality + 1 - if item.name == "Backstage passes to a TAFKAL80ETC concert": - if item.sell_in < 11: - if item.quality < 50: - item.quality = item.quality + 1 - if item.sell_in < 6: - if item.quality < 50: - item.quality = item.quality + 1 - if item.name != "Sulfuras, Hand of Ragnaros": - item.sell_in = item.sell_in - 1 - if item.sell_in < 0: - if item.name != "Aged Brie": - if item.name != "Backstage passes to a TAFKAL80ETC concert": - if item.quality > 0: - if item.name != "Sulfuras, Hand of Ragnaros": - item.quality = item.quality - 1 - else: - item.quality = item.quality - item.quality - else: - if item.quality < 50: - item.quality = item.quality + 1 + updater_for(item).update() class Item: @@ -43,4 +113,4 @@ class Item: self.quality = quality def __repr__(self): - return "%s, %s, %s" % (self.name, self.sell_in, self.quality) + return "%s, %s, %s" % (self.name, self.sell_in, self.quality) \ No newline at end of file