My solution to Basta fazoolin

This was how I handled Basta Fazoolin. Not terribly elegant, but I think I grasped the basic concepts reasonably well. Open to any opinions other’s may have…

class Menu:
  def __init__(self,name,items,start_time,end_time):
    self.name = name
    self.items = items
    self.start_time = start_time
    self.end_time = end_time
  
  def __repr__(self):
    return "{name} menu available from {start_time} to {end_time}".format(name = self.name,start_time = self.start_time,end_time = self.end_time)

  def calculate_bill(self,purchased_items):
    self.purchased_items = purchased_items
    bill = []
    for item in purchased_items:
      for key,value in self.items.items():
        if item == key:
          bill.append(value)
    return sum(bill)
           
brunch = Menu("Brunch",{'pancakes': 7.50, 'waffles': 9.00, 'burger': 11.00, 'home fries': 4.50, 'coffee': 1.50, 'espresso': 3.00, 'tea': 1.00, 'mimosa': 10.50, 'orange juice': 3.50
},11,16)

early_bird = Menu("Early_Bird",{'salumeria plate': 8.00, 'salad and breadsticks (serves 2, no refills)': 14.00, 'pizza with quattro formaggi': 9.00, 'duck ragu': 17.50, 'mushroom ravioli (vegan)': 13.50, 'coffee': 1.50, 'espresso': 3.00,
},15,18)

dinner = Menu("Dinner",{'crostini with eggplant caponata': 13.00, 'ceaser salad': 16.00, 'pizza with quattro formaggi': 11.00, 'duck ragu': 19.50, 'mushroom ravioli (vegan)': 13.50, 'coffee': 2.00, 'espresso': 3.00,
},17,23)

kids = Menu("kids",{'chicken nuggets': 6.50, 'fusilli with wild mushrooms': 12.00, 'apple juice': 3.00
},11,21)

arepas_menu = Menu("Take a/' Arepa",
  {'arepa pabellon': 7.00, 'pernil arepa': 8.50, 'guayanes arepa': 8.00, 'jamon arepa': 7.50
},10,20)


class Franchise:
  def __init__(self,address,menus):
    self.address = address
    self.menus = menus
  def __repr__(self):
    return "Our store is located at {location}.".format(location = self.address)

  def available_menus(self,time):
    self.time = time
    menulist = []
    for menu in self.menus:
        if time >= menu.start_time and time <= menu.end_time:
          for keys in menu.items:
            menulist.append(keys)
    print (menulist)

flagship_store = Franchise("1232 West End Road",[brunch,early_bird,dinner,kids])
new_installment = Franchise("12 East Mulberry Street",[brunch,early_bird,dinner,kids])
arepas_place = Franchise("189 Fitzgerald Avenue",[arepas_menu])


class Business:
  def __init__(self,name,franchises):
    self.name = name
    self.franchises  = franchises
    

biz1 = Business("Basta Fazoolin' with my Heart", [flagship_store, new_installment])
biz2 = Business("Take a' Arepa", arepas_place)


print (brunch)
print (brunch.items)
print (early_bird)
print (kids)
print (dinner)
print(brunch.calculate_bill(['pancakes','home fries']))
print(early_bird.calculate_bill(['salumeria plate','mushroom ravioli (vegan)']))
print(flagship_store)
flagship_store.available_menus(12)
flagship_store.available_menus(17)

  

Hello @codeitcodeitgood,

You may be able to make some of the code more efficient. For instance, consider whether it is really necessary to use a nested loop in the calculate_bill method of Menu.

Edited on July 1, 2020 to add the following:

You can loop through the keys in purchased_items. Within the loop, use each key to get the price of the item, and append that price to bill.

1 Like

Thank you for your response. Maybe something like this?:

 def calculate_bill(self, purchased_items):
    self.purchased_items = purchased_items
    bill= 0
    for y in purchased_items:
      bill += self.items[y]
    return bill

That looks good, but what does this line do?

I removed the line and found the method works effectively without it. I was under the impression that variables used in Class constructors and methods require using the “self” parameter… Perhaps this is true only for the init constructor itself?

Basically, yes. The __init__ method/constructor is used to initialize new instances of the class. This is where the class instances’ attributes are defined. Your calculate_bill method accepts a parameter called purchased_items which can be accessed inside the method, as you’ve seen, just like any function has access to its parameters.

2 Likes

Thank you for your assistance. This is all very new to me. I was recently released from prison in Florida and am adjusting. I didn’t hurt anyone, I just destroyed a bunch of property. I only did a nickel, but it’s amazing how much the world changes in 5 years.

1 Like

You’re welcome.

1 Like

Hello @codeitcodeitgood,

Best of luck to you for a good future.

To aid a discussion about instructional material, it is generally a good idea to provide a link to that material, so here it is:

With the nested loop and the unnecessary assignment statement removed, you now have a good calculate_bill method for the Menu class.

Edited on July 1, 2020 to clarify the following suggestion:

Regarding the nested loops, you can make a similar improvement to the available_menus method in the Franchise class. If you revise that method and post it, we can take a look at it.

1 Like

Thank you - I need all the good luck I can get. Had more than my share of the other kind. Regarding the nested loops, I’m not seeing it. The menus in available_menus are all dictionaries. So I can’t determine how to parse the dictionary without referencing the keys and values separately.

Let’s first note that to create an instance of Franchise, we do something like this:

flagship_store = Franchise("1232 West End Road", [brunch, early_bird, dinner, kids])

The final argument in that line of code is this list of Menu instances:

[brunch, early_bird, dinner, kids]

Also note that the final line in the __init__ method of Franchise is:

    self.menus = menus

That line assigns the list of Menu instances that we provide when we create a Franchise instance to an instance variable named menus. So, to access that list within a method of the Franchise class, we would refer to it as self.menus, assuming that we are following the convention of using self to refer to the current instance. That is what you are doing in this line of code in the available_menus method of Franchise:

    for menu in self.menus:

With each iteration of the loop, menu will reference one of the Menu instances from the list. You test it with this line of code to find out if it is available at the specified time:

        if time >= menu.start_time and time <= menu.end_time:

If the condition is True, all you need to do is append the object referred to as menu to menulist. No intervening action is necessary. You do not need this inner loop header:

          for keys in menu.items:

You only need to do this:

          menulist.append(menu)
1 Like

I get it now - this instruction confused me:

" Let’s tell our customers what they can order! Give Franchise an .available_menus() method that takes in a time parameter and returns a list of the Menu objects that are available at that time."

By ‘Menu’ objects I thought they were referring to Menu items (from the Menu class). I didn’t realize the method’s purpose was just to list the available menus at a given time. Rather, I figured they wanted a list of dishes available. I have a tendency to overcomplicate things. Thank you for the explanation.

1 Like