Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Python OOP Retake Exam - 22 August 2022 - Food Orders App
- # https://judge.softuni.org/Contests/Practice/Index/3591#1
- =============================================================================================
- # file name: validator.py
- class Validator:
- @staticmethod
- def raise_if_string_is_empty(string: str, error_msg: str):
- if string.strip() == '':
- raise ValueError(error_msg)
- @staticmethod
- def raise_if_phone_number_is_invalid(phone_number: str, error_msg):
- if len([n for n in phone_number if n.isdigit()]) != 10 or \
- phone_number[0] != '0':
- raise ValueError(error_msg)
- @staticmethod
- def raise_if_price_less_or_eq_zero(price: float, error_msg):
- if price <= 0:
- raise ValueError(error_msg)
- @staticmethod
- def raise_if_menu_is_less_than_5_dishes(menu, error_msg):
- if len(menu) < 5:
- raise Exception(error_msg)
- @staticmethod
- def find_client_by_phone_number(phone_number, client_list):
- client = [c for c in client_list if c.phone_number == phone_number]
- if client:
- return client[0]
- return None
- @staticmethod
- def raise_if_meal_name_not_in_menu(client_orders, menu):
- for meal, count in client_orders.items():
- if meal not in [m.name for m in menu]:
- raise Exception(f'{meal} is not on the menu!')
- @staticmethod
- def raise_if_qnt_is_wrong(client_orders, menu):
- all_qnt = [order.quantity for order in menu]
- all_products = [product.name for product in menu]
- all_types = [type(product).__name__ for product in menu]
- result1 = dict(zip(all_products, all_qnt))
- result2 = dict(zip(all_products, all_types))
- for meal, count in client_orders.items():
- if count > result1[meal]:
- raise Exception(f'Not enough quantity of {result2[meal]}: {meal}!')
- @staticmethod
- def remove_qnt_from_general_menu(general_menu, meal, qnt):
- for obj_meal in general_menu:
- if obj_meal.name == meal:
- obj_meal.quantity -= qnt
- @staticmethod
- def add_qnt_to_general_menu(general_menu, meal, qnt):
- for obj in general_menu:
- if obj.name == meal:
- obj.quantity += qnt
- =============================================================================================
- # file name: dessert.py
- from project.meals.meal import Meal
- class Dessert(Meal):
- def __init__(self, name: str, price: float, quantity=30):
- super().__init__(name, price, quantity)
- def details(self):
- return f'Dessert {self.name}: {self.price:.2f}lv/piece'
- =============================================================================================
- # file name: main_dish.py
- from project.meals.meal import Meal
- class MainDish(Meal):
- def __init__(self, name: str, price: float, quantity=50):
- super().__init__(name, price, quantity)
- def details(self):
- return f'Main Dish {self.name}: {self.price:.2f}lv/piece'
- =============================================================================================
- # file name: meal.py
- from abc import ABC, abstractmethod
- from project.helper.validator import Validator
- class Meal(ABC):
- def __init__(self, name: str, price: float, quantity: int):
- self.name = name
- self.price = price
- self.quantity = quantity
- @property
- def name(self):
- return self.__name
- @name.setter
- def name(self, value):
- Validator.raise_if_string_is_empty(value, 'Name cannot be an empty string!')
- self.__name = value
- @property
- def price(self):
- return self.__price
- @price.setter
- def price(self, value):
- Validator.raise_if_price_less_or_eq_zero(value, 'Invalid price!')
- self.__price = value
- @abstractmethod
- def details(self):
- ...
- =============================================================================================
- # file name: starter.py
- from project.meals.meal import Meal
- class Starter(Meal):
- def __init__(self, name: str, price: float, quantity=60):
- super().__init__(name, price, quantity)
- def details(self):
- return f'Starter {self.name}: {self.price:.2f}lv/piece'
- =============================================================================================
- # file name: client.py
- from project.helper.validator import Validator
- class Client:
- def __init__(self, phone_number: str):
- self.phone_number = phone_number
- self.shopping_cart = [] # List to add OBJs by the client !
- self.bill = float(0.0)
- @property
- def phone_number(self):
- return self.__phone_number
- @phone_number.setter
- def phone_number(self, value):
- Validator.raise_if_phone_number_is_invalid(value, 'Invalid phone number!')
- self.__phone_number = value
- =============================================================================================
- # file name: food_orders_app.py
- from project.client import Client
- from project.helper.validator import Validator
- from project.meals.dessert import Dessert
- from project.meals.main_dish import MainDish
- from project.meals.meal import Meal
- from project.meals.starter import Starter
- class FoodOrdersApp:
- def __init__(self):
- self.menu = [] # all the meals (objects)!
- self.clients_list = [] # all the clients (objects)!
- self.order = 0
- def register_client(self, client_phone_number: str):
- client = Client(client_phone_number)
- if [c for c in self.clients_list if c.phone_number == client_phone_number]:
- raise Exception('The client has already been registered!')
- self.clients_list.append(client)
- return f'Client {client_phone_number} registered successfully.'
- def add_meals_to_menu(self, *meals: Meal):
- for meal in meals:
- if type(meal).__name__ in ['Starter', 'MainDish', 'Dessert']:
- self.menu.append(meal)
- def show_menu(self):
- Validator.raise_if_menu_is_less_than_5_dishes(self.menu, 'The menu is not ready!')
- result = ''
- for meal in self.menu:
- result += meal.details() + '\n'
- return result.strip()
- def add_meals_to_shopping_cart(self, client_phone_number: str, **meal_names_and_quantities):
- client = None
- # Validate menu before adding items to the client!
- Validator.raise_if_menu_is_less_than_5_dishes(self.menu, 'The menu is not ready!')
- # searching for client , if not in the list -> auto-add it !
- client = Validator.find_client_by_phone_number(client_phone_number, self.clients_list)
- if client is None:
- client = Client(client_phone_number)
- self.clients_list.append(client)
- Validator.raise_if_meal_name_not_in_menu(meal_names_and_quantities, self.menu)
- Validator.raise_if_qnt_is_wrong(meal_names_and_quantities, self.menu)
- self.add_client_order_to_client_shopping_card(client, meal_names_and_quantities)
- print_names = [x.name for x in client.shopping_cart]
- return f"Client {client.phone_number} successfully ordered {', '.join(print_names)} for {client.bill:.2f}lv."
- def add_client_order_to_client_shopping_card(self, client: Client, client_order):
- class_mapper = {
- 'Starter': Starter,
- 'MainDish': MainDish,
- 'Dessert': Dessert,
- }
- meal_names = []
- for meal, qnt in client_order.items():
- Validator.remove_qnt_from_general_menu(self.menu, meal, qnt)
- meal_names.append(meal)
- current_type = [type(obj).__name__ for obj in self.menu if obj.name == meal][0]
- current_price = [obj.price for obj in self.menu if obj.name == meal][0]
- current_meal_obj = class_mapper[current_type](meal, current_price, qnt)
- client.bill += current_price * qnt
- client.shopping_cart.append(current_meal_obj)
- def cancel_order(self, client_phone_number: str):
- client = Validator.find_client_by_phone_number(client_phone_number, self.clients_list)
- if len(client.shopping_cart) <= 0:
- raise Exception('There are no ordered meals!')
- else:
- for obj in client.shopping_cart:
- meal_name = obj.name
- meal_qnt = obj.quantity
- Validator.add_qnt_to_general_menu(self.menu, meal_name, meal_qnt)
- client.shopping_cart = []
- client.bill = 0
- return f"Client {client_phone_number} successfully canceled his order."
- def finish_order(self, client_phone_number: str):
- client = Validator.find_client_by_phone_number(client_phone_number, self.clients_list)
- if len(client.shopping_cart) <= 0:
- raise Exception('There are no ordered meals!')
- self.order += 1
- total_paid_money = client.bill
- client.shopping_cart = []
- client.bill = 0
- return f"Receipt #{self.order} with total amount of {total_paid_money:.2f}" \
- f" was successfully paid for {client_phone_number}."
- def __str__(self):
- result = f'Food Orders App has {len(self.menu)} meals on the menu ' \
- f'and {len(self.clients_list)} clients.'
- return result.strip()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement