def build_meal(dishes, lower_boundaries, upper_boundaries): #reject if there simply aren't enough meals if len(dishes) < 10: return "NOT ENOUGH DISHES TO MAKE A MEAL" nutrient_reject = {x: 0 for x in TARGET_NUTRIENTS} myMeal = Meal(lower_boundaries) #descending list of foods with most of each respective nutrient sorted_nutrients = { nutrient: sorted(dishes, key=lambda x: x.nutrition[nutrient], reverse=True) for nutrient in TARGET_NUTRIENTS } sorted_indices = {nutrient: 0 for nutrient in TARGET_NUTRIENTS} bestMeal = 0 bestScore = math.inf for i in range(100): highest_unmet = myMeal.nutrient_totals()[0] if sorted_indices[highest_unmet] >= len( sorted_nutrients[highest_unmet]): dish = random.choice(sorted_nutrients[highest_unmet]) else: dish = sorted_nutrients[highest_unmet][ sorted_indices[highest_unmet]] sorted_indices[highest_unmet] += 1 while myMeal.containsDish(dish): if sorted_indices[highest_unmet] >= len( sorted_nutrients[highest_unmet]): dish = random.choice(sorted_nutrients[highest_unmet]) else: dish = sorted_nutrients[highest_unmet][ sorted_indices[highest_unmet]] sorted_indices[highest_unmet] += 1 # print("We need {} so we add {}".format(highest_unmet,dish.name)) # print(myMeal) myMeal.addDish(dish) # print(myMeal) constraint = myMeal.under_upper_bounds(upper_boundaries) if constraint[0]: if myMeal.all_nutrients_met(): return myMeal, True else: # print("Too much of the {} nutrient".format(constraint[1])) myMeal.removeDish(dish.name) # print("Removed {}".format(dish.name)) nutrient_reject[constraint[1]] += 1 if nutrient_reject[constraint[1]] > 3 and not myMeal.isEmpty(): sorted_meal = myMeal.sort_by_nutrient(constraint[1]) myMeal.removeDish(sorted_meal[-1]) # print("Also removed {} because of excess {}".format(sorted_meal[-1], # constraint[1])) nutrient_reject[constraint[1]] = 0 if myMeal.meal_score() < bestScore: bestScore = myMeal.meal_score() bestMeal = Meal(myMeal.boundaries.copy()) bestMeal.items = myMeal.items.copy() bestMeal.totals = myMeal.totals.copy() # print(myMeal.meal_score()) # print() return bestMeal, False
def create_meal(self, mealid): mealigredients = self.get_meal_ingredients(mealid) macros = self.calc_meal(mealid) name = self.get_name(mealid) meal = Meal.Meal(name, mealigredients, macros) return meal
def main(): while True: #user picks meal print_options(OPTIONS) choice = input("Which meal?: ") if is_invalid(choice, len(OPTIONS)): print() print("Please type a number from the menu!") print() continue choice = int(choice) if choice == 4: print() break #user picks dining hall locations = get_locations(MEALS[choice - 1]) print_options(locations + ["Quit"]) choice_2 = input("Which available dining hall?: ") if is_invalid(choice_2, len(locations) + 1): print() print("Please type a number from the menu!") print() continue choice_2 = int(choice_2) if choice_2 == len(locations) + 1: print() break #meal is built testMeal = Meal({}) dishes = crawl_menu(get_menu_url(MEALS[choice - 1], locations[choice_2 - 1]), red_meat=False, fish=False) #user is given results: meals that meet the minimum are printed first #then, meals that are lopsided; there are stored in a list called non_winners non_winners = [] #store a running list of meals to prevent the same meal from printing twice all_meals = [] print() print() print("Meals that meet your minimum requirements:") print() for i in range(5): output = build_meal(dishes, TEST_LB, TEST_UB) if isinstance(output, str): print(output) break meal = output[0] found_winner = output[1] if found_winner: if set(meal.items.keys()) in all_meals: continue print(meal) print(meal.meal_score()) print() all_meals.append(set(meal.items.keys())) else: non_winners.append(meal) # if not isinstance(meal,str): # print(meal.meal_score()) print("Meals that are slightly lopsided:") print() for meal in non_winners: if set(meal.items.keys()) in all_meals: continue print(meal) print(meal.meal_score()) print() all_meals.append(set(meal.items.keys()))