From 1dd293dfebc661d4cc677cb56c00f3af5e65f373 Mon Sep 17 00:00:00 2001 From: Mohammed Mohideen M Z Date: Mon, 23 Jun 2025 22:37:26 +0530 Subject: [PATCH] refactor: Refactored gildedrose --- python/README.md | 8 ++- python/gilded_rose.py | 135 ++++++++++++++++++++++++++----------- python/test_gilded_rose.py | 36 ++++++---- python/texttest_fixture.py | 49 ++++++++------ 4 files changed, 154 insertions(+), 74 deletions(-) diff --git a/python/README.md b/python/README.md index 7504b97c..16d772fd 100644 --- a/python/README.md +++ b/python/README.md @@ -4,10 +4,16 @@ For exercise instructions see [top level README](../README.md) Suggestion: create a python virtual environment for this project. See the [documentation](https://docs.python.org/3/library/venv.html) +## Run the pip install from the Command-Line for required dependencies + +``` +pip install -r requirements.txt +``` + ## Run the unit tests from the Command-Line ``` -python test_gilded_rose.py +pytest test_gilded_rose.py ``` ## Run the TextTest fixture from the Command-Line diff --git a/python/gilded_rose.py b/python/gilded_rose.py index 4f21ea64..326d65a7 100755 --- a/python/gilded_rose.py +++ b/python/gilded_rose.py @@ -1,46 +1,103 @@ -# -*- coding: utf-8 -*- +""" + gilded_rose.py + Refactoring logic for Gilded Rose Module. + Author: Mohammed Mohideen M Z +""" -class GildedRose(object): +from dataclasses import dataclass +from abc import ABC, abstractmethod +@dataclass +class Item: + """Represents an item with a name, sell_in, and quality.""" + name: str + sell_in: int + quality: int + + def __repr__(self): + return f"{self.name}, {self.sell_in}, {self.quality}" + + +class ItemUpdater(ABC): + """Abstract base class for updating item behavior.""" + def __init__(self, item): + self.item = item + + def update(self): + """Update the item's sell_in and quality.""" + pass + + +class NormalItem(ItemUpdater): + """Standard item that degrades in quality as it gets older.""" + def update(self): + self.item.sell_in -= 1 + if self.item.quality > 0: + self.item.quality -= 1 + if self.item.sell_in < 0 and self.item.quality > 0: + self.item.quality -= 1 + + +class AgedBrie(ItemUpdater): + """Item that increases in quality the older it gets.""" + def update(self): + self.item.sell_in -= 1 + if self.item.quality < 50: + self.item.quality += 1 + if self.item.sell_in < 0 and self.item.quality < 50: + self.item.quality += 1 + + +class BackstagePasses(ItemUpdater): + """Item that increases in quality as its sell_in date approaches, + but drops to 0 after the concert.""" + def update(self): + self.item.sell_in -= 1 + if self.item.sell_in < 0: + self.item.quality = 0 + else: + if self.item.quality < 50: + self.item.quality += 1 + if self.item.sell_in < 10: + self.item.quality += 1 + if self.item.sell_in < 5: + self.item.quality += 1 + self.item.quality = min(self.item.quality, 50) + + +class Sulfuras(ItemUpdater): + """Legendary item that never changes in quality or sell_in.""" + + +class ConjuredItem(ItemUpdater): + """Item that degrades in quality twice as fast as normal items.""" + def update(self): + self.item.sell_in -= 1 + degrade = 2 + if self.item.sell_in < 0: + degrade *= 2 + self.item.quality = max(0, self.item.quality - degrade) + + +class GildedRose: + """Main class that manages and updates a list of items.""" def __init__(self, items): self.items = items + @staticmethod + def create_updater(item): + if item.name == "Aged Brie": + return AgedBrie(item) + elif item.name == "Backstage passes": + return BackstagePasses(item) + elif item.name == "Sulfuras": + return Sulfuras(item) + elif "Conjured" in item.name: + return ConjuredItem(item) + else: + return NormalItem(item) + 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 - - -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) + updater = self.create_updater(item) + updater.update() diff --git a/python/test_gilded_rose.py b/python/test_gilded_rose.py index 1c92f638..c6088696 100644 --- a/python/test_gilded_rose.py +++ b/python/test_gilded_rose.py @@ -1,16 +1,28 @@ # -*- coding: utf-8 -*- -import unittest - +import pytest from gilded_rose import Item, GildedRose -class GildedRoseTest(unittest.TestCase): - def test_foo(self): - items = [Item("foo", 0, 0)] - gilded_rose = GildedRose(items) - gilded_rose.update_quality() - self.assertEqual("fixme", items[0].name) - - -if __name__ == '__main__': - unittest.main() +class TestGildedRose: + @pytest.mark.parametrize( + "name, sell_in, quality, expected_sell_in, expected_quality", + [ + ("Normal Item", 10, 20, 9, 19), + ("Normal Item", 0, 10, -1, 8), + ("Aged Brie", 2, 0, 1, 1), + ("Aged Brie", -1, 49, -2, 50), + ("Backstage passes", 11, 20, 10, 21), + ("Backstage passes", 10, 20, 9, 22), + ("Backstage passes", 5, 20, 4, 23), + ("Backstage passes", 0, 20, -1, 0), + ("Sulfuras", 0, 80, 0, 80), + ("Conjured Mana Cake", 3, 6, 2, 4), + ("Conjured Mana Cake", 0, 10, -1, 6), + ] + ) + def test_item_behavior(self, name, sell_in, quality, expected_sell_in, expected_quality): + items = [Item(name, sell_in, quality)] + gr = GildedRose(items) + gr.update_quality() + assert items[0].sell_in == expected_sell_in + assert items[0].quality == expected_quality diff --git a/python/texttest_fixture.py b/python/texttest_fixture.py index 86af5ef7..c59338a5 100644 --- a/python/texttest_fixture.py +++ b/python/texttest_fixture.py @@ -1,30 +1,35 @@ -# -*- coding: utf-8 -*- -from __future__ import print_function +""" + texttest_fixture.py + Simulates item updates for the Gilded Rose. + Author: Mohammed Mohideen M Z +""" +from gilded_rose import Item, GildedRose +import sys -from gilded_rose import * - -if __name__ == "__main__": - print ("OMGHAI!") +def main(): + print("OMGHAI!") items = [ - Item(name="+5 Dexterity Vest", sell_in=10, quality=20), - Item(name="Aged Brie", sell_in=2, quality=0), - Item(name="Elixir of the Mongoose", sell_in=5, quality=7), - Item(name="Sulfuras, Hand of Ragnaros", sell_in=0, quality=80), - Item(name="Sulfuras, Hand of Ragnaros", sell_in=-1, quality=80), - Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=15, quality=20), - Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=10, quality=49), - Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=5, quality=49), - Item(name="Conjured Mana Cake", sell_in=3, quality=6), # <-- :O - ] + Item(name="+5 Dexterity Vest", sell_in=10, quality=20), + Item(name="Aged Brie", sell_in=2, quality=0), + Item(name="Elixir of the Mongoose", sell_in=5, quality=7), + Item(name="Sulfuras, Hand of Ragnaros", sell_in=0, quality=80), + Item(name="Sulfuras, Hand of Ragnaros", sell_in=-1, quality=80), + Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=15, quality=20), + Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=10, quality=49), + Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=5, quality=49), + Item(name="Conjured Mana Cake", sell_in=3, quality=6), # <-- :O + ] + days = int(sys.argv[1]) + 1 if len(sys.argv) > 1 else 2 + + app = GildedRose(items) - days = 2 - import sys - if len(sys.argv) > 1: - days = int(sys.argv[1]) + 1 for day in range(days): - print("-------- day %s --------" % day) + print("-------- day {} --------".format(day)) print("name, sellIn, quality") for item in items: print(item) print("") - GildedRose(items).update_quality() + app.update_quality() + +if __name__ == "__main__": + main()