5. Design a restaurant food ordering system like Zomato, Swiggy, DoorDash
Write code for low level design of a restaurant food ordering and rating system, similar to food delivery apps like Zomato, Swiggy, Door Dash, Uber Eats etc.
There will be food items like 'Veg Burger', 'Veg Spring Roll', 'Ice Cream' etc.
And there will be restaurants from where you can order these food items.
Same food item can be ordered from multiple restaurants. e.g. you can order 'food-1' 'veg burger' from burger king as well as from McDonald's.
Users can order food, rate orders, fetch restaurants with most rating and fetch restaurants with most rating for a particular food item e.g. restaurants which have the most rating for 'veg burger'.
You can practice this question in both Java and Python
Your solution should implement below methods:
Method : init(Helper05 helper)
- Use this method to initialize your instance variables
- use helper's methods for printing logs else logs will not be visible.
Method : orderFood(String orderId, String restaurantId, String foodItemId)
- Orders food item from a restaurant.
- for now lets assume for that only a single food item is purchased in one order.
- orderId, restaurantId, foodItemId will all be valid and available.
- PARAMETER : restaurantId is restaurant from where food is being ordered.
- PARAMETER : foodItemId is food item which is being ordered
Method : rateOrder(String orderId, int rating)
- Customers can rate their order.
- when you are giving rating an order e.g giving 4 stars to an order, then it means you are assigning 4 stars to both the food item in that restaurant as well as 4 stars to the overall restaurant ranting.
- PARAMETER : orderId is order which will be rated by customer, orderId will always be valid i.e. order will always be created for an orderId before rateOrder() is called.
- PARAMETER : rating ranges from 1 to 5 stars in increasing order, 1 being the worst and 5 being the best rating.
Method : List[String] getTopRestaurantsByFood(String foodItemId)
- Fetches a list of top 20 restaurants based on strategy
- unrated restaurants will be at the bottom of list.
- restaurants will be sorted on the basis of strategy
- restaurants are sorted in descending order on average ratings of the food item and then based on restaurant id lexicographically.
- e.g. veg burger is rated 4.3 in restaurant-4 and 4.6 in restaurant-6 then
we will return ['restaurant-6', 'restaurant-4']
- PARAMETER : foodItemId is food item for which restaurants need to be fetched.
Method : List[String] getTopRatedRestaurants()
- returns top 20 most rated restaurants ids sorted in descending order of their ratings.
- if two restaurants have the same rating then they will be ordered lexicographically by their restaurantId.
- Here we are talking about restaurant's overall rating and NOT food item's rating.
- e.g. restaurant-2 is rated 4.6 while restaurant-3 is rated 4.2 and restaurant-5 is rated 4.4 and restaurant-6 is rated 4.6,
we will return ['restaurant-2','restaurant-6', 'restaurant-5', 'restaurant-3']
- even though restaurant-2 and restaurant-6 have same rating , restaurant-6 came later because it is lexicographically greater than restaurant-2
Note :
- There will be at max 50 food items, at max 10,000 restaurants,
and each restaurant can sell at max 25 food items
- Average ratings are rounded down to 1 decimal point,
i.e. 4.05, 4.08, 4.11, 4.12, 4.14 all become 4.1
and 4.15, 4.19, 4.22, 4.24 all become 4.2
- For Python, use round(rating, 1) function to round rating to 1 decimal point.
- For Java, use the formula (double)((int)((rating+0.05)*10))/10.0 to round rating
Example : Read the below method calls to get a better understanding of how this works.
init(helper)
orderFood(orderId = 'order-0', foodItemId = 'food-1', restaurantId = 'restaurant-0')
rateOrder(orderId = 'order-0', rating = 3)
orderFood(orderId = 'order-1', foodItemId = 'food-0', restaurantId = 'restaurant-2')
rateOrder(orderId = 'order-1', rating = 1)
orderFood(orderId = 'order-2', foodItemId = 'food-0', restaurantId = 'restaurant-1')
rateOrder(orderId = 'order-2', rating = 3)
orderFood(orderId = 'order-3', foodItemId = 'food-0', restaurantId = 'restaurant-2')
rateOrder(orderId = 'order-3', rating = 5)
orderFood(orderId = 'order-4', foodItemId = 'food-0', restaurantId = 'restaurant-0')
rateOrder(orderId = 'order-4', rating = 3)
orderFood(orderId = 'order-5', foodItemId = 'food-0', restaurantId = 'restaurant-1')
rateOrder(orderId = 'order-5', rating = 4)
orderFood(orderId = 'order-6', foodItemId = 'food-1', restaurantId = 'restaurant-0')
rateOrder(orderId = 'order-6', rating = 2)
orderFood(orderId = 'order-7', foodItemId = 'food-1', restaurantId = 'restaurant-0')
rateOrder(orderId = 'order-7', rating = 2)
orderFood(orderId = 'order-8', foodItemId = 'food-0', restaurantId = 'restaurant-1')
rateOrder(orderId = 'order-8', rating = 2)
orderFood(orderId = 'order-9', foodItemId = 'food-0', restaurantId = 'restaurant-1')
rateOrder(orderId = 'order-9', rating = 4)
getTopRestaurantsByFood('food-0')
returns [restaurant-1, restaurant-0, restaurant-2]
(For reference only) list of restaurants with rating for food food-0 : [('restaurant-1' : 3.3), ('restaurant-0' : 3.0), ('restaurant-2' : 3.0)]
getTopRestaurantsByFood('food-1')
returns [restaurant-0, restaurant-2]
(For reference only) list of restaurants with rating for food food-1 : [('restaurant-0' : 2.3), ('restaurant-2' : 0.0)]
getTopRatedRestaurants() returns
[restaurant-1, restaurant-2, restaurant-0]
(For reference only) list of top restaurants with rating : [('restaurant-1' : 3.3), ('restaurant-2' : 3.0), ('restaurant-0' : 2.5)]