import pandas # Functions go here def make_statement(statement, decoration): """Emphasises headings by adding decoration at the start and end""" print(f"{decoration * 3} {statement} {decoration * 3}") def string_check(question, valid_answers=('yes', 'no'), num_letters=1): """Checks that users enter the full word or the 'n' letter/s of a word from a list of valid responses""" while True: response = input(question).lower() for answer in valid_answers: # check if the response is the entire word if response == answer: return answer # check if it's the first letter elif response == answer[:num_letters]: return answer print(f"Please choose an option from {valid_answers}") def instructions(): print() make_statement("Instructions", "✔") print(''' 1. Enter your name. 2. Choose pickup or delivery. An $11.99 fee applies to delivery. 3. If you choose delivery, you’ll also enter your phone number and address. 4. Select your pizza, base type, size and any extra toppings (maximum of 3 extra toppings) using the menus. 5. Choose to add another pizza. A maximum of 5 pizzas can be ordered. 6. When you're done, you’ll see a full summary that shows your details and everything you ordered—including prices. 7. The grand total will be displayed and you can then confirm your order. ''') def not_blank(question): """Checks that a user response is not blank""" while True: response = input(question).strip() if response != "": return response print("Sorry, this can't be blank. Please try again.\n") def phone_number_check(question): """Checks users enter an integer that is at least 7 digits long""" error = "Please enter a phone number at least 7 digits long (no spaces, decimals, letters, or symbols)." while True: response = input(question).strip() # Checks if the input is at least 7 digits long if response.isdigit() and len(response) >= 7: return response else: print(error) def int_check(question, low, high): """Checks users enter an integer between two values""" error = f"Please enter an integer between {low} and {high} (ie: a number which does not have a decimal part)." while True: try: # Change the response to an integer and check if it's between the chosen numbers response = int(input(question)) if low <= response <= high: return response else: print(error) except ValueError: print(error) def currency(x): """Formats numbers as currency ($#.##)""" return "${:.2f}".format(x) # Menu setup: # Pizzas pizza_data = { "Item": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "Pizza": ["Cheese", "Ham & Cheese", "Pepperoni", "Hawaiian", "Meat Lovers", "BBQ Chicken", "Vegetarian", "Seafood", "Supreme", "Butter Chicken"], "Price": [5.99, 6.99, 6.99, 6.99, 8.99, 8.99, 11.99, 12.99, 12.99, 13.99] } # Base type type_of_base_data = { "Item": [1, 2, 3, 4, 5], "Base Type": ["Regular Crust", "Thin Crust", "Stuffed Crust", "Extra Cheese", "Garlic Crust"], "Price": [0.00, 1.99, 1.99, 1.99, 1.99] } # Base size size_of_base_data = { "Item": [1, 2, 3], "Size": ["Small", "Medium", "Large"], "Price": [0.00, 2.99, 5.99] } # Additional toppings extra_toppings = { "Item": [1, 2, 3, 4, 5, 6, 7], "Extra Toppings": ["No Extra Toppings", "Ham", "Pepperoni", "Pineapple", "Olives", "Chicken", "Bacon"], "Price": [0.00, 1.99, 1.99, 1.99, 1.99, 2.99, 3.99] } # Convert each dictionary into a DataFrame pizza_df = pandas.DataFrame(pizza_data) base_df = pandas.DataFrame(type_of_base_data) size_df = pandas.DataFrame(size_of_base_data) extras_df = pandas.DataFrame(extra_toppings) # Main routine starts here # Order confirmation loop while True: # Program main heading make_statement("Welcome to the Pizza Ordering Program", "🍕") # Ask user if they want to see the ordering instructions and display them if requested print() want_instructions = string_check("Do you want to see the ordering instructions? ") # Get customers details if want_instructions == "yes": instructions() print() # Ask user for their name (and check it's not blank) name = not_blank("Enter your name: ") # Ask user for pickup or delivery order_method = string_check("Pickup or delivery? (Note: Delivery is $11.99 extra) ", ['pickup', 'delivery']) # If delivery is chosen ask for phone number and address if order_method == "delivery": phone_number = phone_number_check("Phone number: ") address = not_blank("Delivery address: ") else: phone_number = None address = None # Order variables max_pizzas = 5 pizza_count = 0 total_order_price = 0 total_order = [] grand_total = 0 # Collecting the order from the customer loop while True: # Change pizzas by + 1 pizza_count += 1 # Main statement print() make_statement("Menu", "-") # PIZZA # Printing out pizza menu print() print("Pizzas:") print(pizza_df.to_string(index=False)) # Asking for what number the pizza they want is assigned to print() pizza_choice = int_check("Enter the number assigned to the pizza you want (1,10): ", 1, 10) pizza_item = pizza_choice - 1 pizza_name = pizza_df.at[pizza_item, "Pizza"] pizza_price = pizza_df.at[pizza_item, "Price"] # BASE TYPE # Printing out the base type menu print() print() print("Base Type:") print(base_df.to_string(index=False)) # Asking for what number the type of base they want is assigned to print() base_choice = int_check("Enter the number assigned to the base type you want (1,5): ", 1, 5) base_item = base_choice - 1 base_name = base_df.at[base_item, "Base Type"] base_price = base_df.at[base_item, "Price"] # SIZE # Printing out the size menu print() print() print("Size:") print(size_df.to_string(index=False)) # Asking for what number the type of base they want is assigned to print() size_choice = int_check("Enter the number assigned to the size you want (1–3): ", 1, 3) size_item = size_choice - 1 size_name = size_df.at[size_item, "Size"] size_price = size_df.at[size_item, "Price"] # EXTRA TOPPINGS toppings_selected = [] total_extras_price = 0 topping_limit = 3 topping_count = 0 # Extra toppings loop so the customer can add more than one extra topping on the same pizza while True: # Printing out the extra toppings menu print() print() print("Extra Toppings: A maximum of 3 extra toppings can be added.") print(extras_df.to_string(index=False)) # Asking for what number the extra topping they want is assigned to print() extras_choice = int_check("Enter the number assigned to the extra topping you want (1-7): ", 1, 7) extras_item = extras_choice - 1 extras_name = extras_df.at[extras_item, "Extra Toppings"] extras_price = extras_df.at[extras_item, "Price"] # Add topping lists toppings_selected.append(f"{extras_name} - {currency(extras_price)}") total_extras_price += extras_price topping_count += 1 # Break out of the loop if the customer selected no extra toppings if extras_name == "No Extra Toppings": break # Check topping limit if topping_count >= topping_limit: print("You have reached the maximum of 3 extra toppings.") break # Ask customer if they want more additional toppings extra_topping_answer = string_check("Do you want to add another extra topping? ") if extra_topping_answer == "no": break # Calculate total individual pizza price individual_pizza_price = pizza_price + base_price + size_price + total_extras_price # Add individual pizza price to the total order price total_order_price += individual_pizza_price # Gather individual pizza order and add into the total order list order = { "Pizza #": pizza_count, "Pizza": pizza_name, "Pizza Price": pizza_price, "Base Type": base_name, "Base Price": base_price, "Size": size_name, "Size Price": size_price, "Extra Toppings": toppings_selected, "Total Price": individual_pizza_price } # Store as dictionary in list total_order.append(order) # Check if the customer has ordered the maximum amount of pizzas if pizza_count < max_pizzas: # Ask them if they would like to order another pizza print() another_pizza = string_check("Do you want to order another pizza? ") if another_pizza == "no": break # Inform the user that they have ordered the maximum amount of pizzas else: print() print("You have ordered the maximum amount of 5 pizzas.") break # End of ordering loop # ORDER SUMMARY: # Output customers details print() make_statement("Order Summary", "-") print() print(f"Name: {name.capitalize()}.") print(f"Order Method: {order_method.capitalize()}") if order_method == "delivery": delivery_fee = 11.99 grand_total += delivery_fee print(f"Delivery: {currency(delivery_fee)}") print(f"Phone Number: {phone_number}") print(f"Address: {address}") # Output total order print() for item in total_order: print(f"Pizza #{item['Pizza #']}") print(f"Pizza: {item['Pizza']} - {currency(item['Pizza Price'])}") print(f"Base Type: {item['Base Type']} - {currency(item['Base Price'])}") print(f"Size: {item['Size']} - {currency(item['Size Price'])}") print(f"Extra Toppings: {', '.join(item['Extra Toppings'])}") print(f"Total: {currency(item['Total Price'])}") print() # Output grand total - all pizzas and delivery cost grand_total += total_order_price print(f"Your grand total is {currency(grand_total)}") # Confirm order confirmation = string_check("Do you confirm your order? ") print() if confirmation == "yes": print("Your order has been sent.") # Ask if the user want to place another order print() another_order = string_check("Would you like to place another order? ") # Message to customer if they do not want to order another pizza if another_order == "no": print() print(f"Please have your payment ready on {order_method}. We accept eftpos, credit card and cash. Thank " f"you for ordering from the Pizza Ordering Program.") break # Message to customer if they cancel their order else: print("Order Cancelled. Returning to the start.") print()