diff --git a/swap_meet/clothing.py b/swap_meet/clothing.py new file mode 100644 index 000000000..807bd24fe --- /dev/null +++ b/swap_meet/clothing.py @@ -0,0 +1,18 @@ +from .item import Item + +class Clothing(Item): + """Class `Item`'s Child class. + + Starts with default values for `condition` and `age`. + Initializes with a named attribute for its type, `"Clothing"`. + """ + + def __init__(self, condition=0, age=0): + super() + self.category = "Clothing" + self.condition = condition + self.age = age + + def __str__(self): + return "The finest clothing you could wear." + diff --git a/swap_meet/decor.py b/swap_meet/decor.py new file mode 100644 index 000000000..6a8a62625 --- /dev/null +++ b/swap_meet/decor.py @@ -0,0 +1,17 @@ +from .item import Item + +class Decor(Item): + """Class `Item`'s Child class. + + Starts with default values for `condition` and `age`. + Initializes with a named attribute for its type, `"Decor"`. + """ + + def __init__(self, condition=0, age=0): + super() + self.category = "Decor" + self.condition = condition + self.age = age + + def __str__(self): + return "Something to decorate your space." \ No newline at end of file diff --git a/swap_meet/electronics.py b/swap_meet/electronics.py new file mode 100644 index 000000000..606cfa6d2 --- /dev/null +++ b/swap_meet/electronics.py @@ -0,0 +1,17 @@ +from .item import Item + +class Electronics(Item): + """Class `Item`'s Child class. + + Starts with default values for `condition` and `age`. + Initializes with a named attribute for its type, `"Electronics"`. + """ + + def __init__(self, condition=0, age=0): + super() + self.category = "Electronics" + self.condition = condition + self.age = age + + def __str__(self): + return "A gadget full of buttons and secrets." \ No newline at end of file diff --git a/swap_meet/item.py b/swap_meet/item.py new file mode 100644 index 000000000..7ab1a3203 --- /dev/null +++ b/swap_meet/item.py @@ -0,0 +1,47 @@ +class Item: + """Represents an item. Parent class for `Clothing`, `Decor`, and `Electronics` child classes. `Vendor` instances can have `Item` instances in their `inventory`. + + Attributes: + condition (int): An optional attribute that defaults to 0 when not + passed into an `Item` object instance. Used to reference an item's + description based in values that range from 0 to 5, where 0 + describes an item in "Poor" condition, and 5 describes an item + that is "Like New". + + category (str): An empty string by default. Represents the category + of an item. Instances can optionally pass in a string with the + keyword argument `category`. + """ + + def __init__(self, category=""): + self.condition = 0 + self.category = category + self.age = 0 + + # Wave 5 + + def condition_description(self): + """Instance method that describes the condition of an item in words based on its `condition`, in a range from 0 to 5. + + Child classes inherit this method as-is, but are able to override it if necessary. The one requirement is that the `condition_description` for all three classes above have the same behavior. + + Returns: + [type]: [description] + """ + + descriptions = { + 5: "Like New", + 4: "Mint", + 3: "Very Good", + 2: "Good", + 1: "Fair", + 0: "Poor" + } + + if self.condition not in descriptions: + return None + return descriptions[self.condition] + + def __str__(self): + """Printable string representation of an Item instance.""" + return "Hello World!" diff --git a/swap_meet/vendor.py b/swap_meet/vendor.py new file mode 100644 index 000000000..97d80eb3f --- /dev/null +++ b/swap_meet/vendor.py @@ -0,0 +1,201 @@ +from .item import Item + +class Vendor: + """Creates instances of a vendor and their list of items. + + If a Vendor object is instantiated without arguments, it's attributes will have default values. + + Attributes: + inventory: An empty list by default. Instances can optionally pass in + a list with the keyword argument `inventory`. + """ + + def __init__(self, inventory=None): + if inventory is None: + self.inventory = [] + else: + self.inventory = inventory + + def add(self, item): + """Adds the `item` to the `inventory`. + + Args: + item (str): The item to be added. + + Returns: + item (str): The item that was added. + """ + + self.inventory.append(item) + return item + + def remove(self, item): + """Removes the matching `item` from the `inventory`. + + Args: + item (str): The item that will be removed. + + Returns: + item (str): The item that was removed. If there is no matching item + in the `inventory`, returns `False`. + """ + + if item in self.inventory: + self.inventory.remove(item) + return item + return False + + def get_by_category(self, category): + """Iterates over the `inventory` to find the categories of the items in that list. + + Args: + category (str): Represents the `category` of the items. + + Returns: + same_category_items: A list of `Item`s in the `inventory` with that + `category`. + """ + + same_category_items = [] + for item in self.inventory: + if item.category == category: + same_category_items.append(item) + return same_category_items + + def swap_items(self, friend, my_item, their_item): + """Removes `my_item` from this `Vendor`'s `inventory` and adds it to the `friend`'s `inventory`. + + Args: + friend (object): An instance of another `Vendor`, representing the + friend that this `Vendor` instance is swapping with. + + my_item (str): Represents the item this `Vendor` instance plans to + give. + + their_item (str): Represents the item the `friend` plans to give. + + Returns: + bool: If this `Vendor`'s `inventory` doesn't contain `my_item` or + the `friend`'s `inventory` doesn't contain `their_item`, + returns `False`; otherwise, returns `True`. + """ + + if my_item in self.inventory and their_item in friend.inventory: + self.remove(my_item) + friend.add(my_item) + friend.remove(their_item) + self.add(their_item) + return True + return False + + def swap_first_item(self, friend): + """Swaps the first item in this `Vendor`'s `inventory` with the first item in the `friend`'s `inventory`. + + Args: + friend (object): An instance of another `Vendor`, representing the + friend that this `Vendor` instance is swapping with. + + Returns: + bool: If either itself or the `friend` have an empty `inventory`, + returns `False`. Otherwise, returns True. + """ + + if not self.inventory or not friend.inventory: + return False + else: + my_item = self.inventory.pop(0) + self.add(friend.inventory.pop(0)) + friend.add(my_item) + return True + + def get_best_by_category(self, item_category): + """Gets the item with the best `condition` in a certain `category`. + + Args: + item_category (str): Represents the `category` of the items. + + Returns: + best_item: A single item, even if there are duplicates (two or more + of the same item with the same `condition`). If there are no + items in the `inventory` that match the `category`, returns `None`. + """ + + best_cond = 0 + best_item = None + + for item in self.get_by_category(item_category): + if item.condition > best_cond: + best_item = item + best_cond = item.condition + return best_item + + def swap_best_by_category(self, other, my_priority, their_priority): + """Swaps the best item of certain categories with another `Vendor`. + + Args: + other (object): Represents another `Vendor` instance to trade with. + + my_priority (str): Represents a `category` that this `Vendor` + instance wants to receive. + + their_priority (str): Represents a `category` that `other` wants + to receive. + + Returns: + bool: If any of both `Vendor` instances doesn't have an item that + matches a desired `category`, returns `False`; otherwise, + returns True. + """ + + mine = self.get_best_by_category(their_priority) + theirs = other.get_best_by_category(my_priority) + if not mine or not theirs: + return False + else: + return self.swap_items(other, mine, theirs) + + def get_by_newest(self): + """`swap_by_newest`s helper method. + This is an instance method, so any instance can access to get the first newest `item` in their `inventory`. + + TODO: + - Implement this method in a way that it also checks the categories + or conditions of the items. + - Have a special class for Vintage Items. + + Returns: + newest_item: A single `item`, even if there are duplicates (two or + more of the same item with the same `condition`). + If there are no items in the `inventory` that match the `category`, returns `None`. + """ + + if self.inventory: + newest_item = self.inventory[0] + min_age = newest_item.age + + for item in self.inventory: + if item.age < min_age: + newest_item = item + min_age = item.age + return newest_item + return None + + def swap_by_newest(self, friend): + """Swaps the newest item in the inventory with another `Vendor`. + + Args: + friend (object): An instance of another `Vendor`, representing the + friend that this `Vendor` instance is swapping with. + + Returns: + bool: If any of both `Vendor` instances doesn't have an item in + their inventory, the swap does not occur; otherwise, returns True. + """ + + my_newest_item = self.get_by_newest() + their_newest_item = friend.get_by_newest() + + if not my_newest_item or not their_newest_item: + return False + else: + self.swap_items(friend, my_newest_item, their_newest_item) diff --git a/tests/test_wave_07_NEW.py b/tests/test_wave_07_NEW.py new file mode 100644 index 000000000..76c2374bc --- /dev/null +++ b/tests/test_wave_07_NEW.py @@ -0,0 +1,77 @@ +import pytest +from swap_meet.vendor import Vendor +from swap_meet.item import Item +from swap_meet.clothing import Clothing +from swap_meet.decor import Decor +from swap_meet.electronics import Electronics + + +def test_get_by_newest(): + item_a = Clothing(age=2) + item_b = Decor(age=2) + item_c = Clothing(age=4) + item_d = Decor(age=5) + item_e = Clothing(age=1) + tai = Vendor( + inventory=[item_a, item_b, item_c, item_d, item_e] + ) + + newest_item = tai.get_by_newest() + + # get_by_newest(self, friend) + assert newest_item == item_e + + +def test_swap_by_newest_no_matches_is_none(): + item_a = Decor(age=2.0) + item_b = Decor(age=1.0) + item_c = Decor(age=4.0) + item_d = Decor(age=8.0) + + tai = Vendor( + inventory=[item_a, item_b, item_c] + ) + ta = Vendor( + inventory=[item_d] + ) + is_swap = tai.swap_by_newest(ta) + + assert is_swap is not False + assert item_d in tai.inventory + assert item_b in ta.inventory + assert item_a not in ta.inventory + + + + +def test_swap_by_newest_with_duplicates(): + item_a = Clothing(age=2) + item_d = Clothing(age=2) + tai = Vendor( + inventory=[item_a] + ) + ta = Vendor( + inventory=[item_d] + ) + is_swap = tai.swap_by_newest(ta) + + assert item_a in ta.inventory + assert is_swap is not False + +def test_swap_by_newest_returns_false(): + tai = Vendor( + inventory=[] + ) + + item_d = Clothing(age=2) + item_e = Decor() + item_f = Clothing(age=5) + jesse = Vendor( + inventory=[item_d, item_e, item_f] + ) + + result = tai.swap_by_newest( + jesse + ) + + assert result is False