//! The weekly menu planner //! extern crate cookbook; extern crate planner; use self::cookbook::*; use self::cookbook::models::Recipe; use self::planner::solver::{Variables, Domain, Problem, Constraint}; /// We want a mapping of the week meals (matin, midi, soir) /// Breakfast => RecipeCategory::Breakfast /// Lunch => RecipeCategory::MainCourse /// Dinner => RecipeCategory::MainCourse type Day = String; enum Meals { Breakfast(Day), Lunch(Day), Dinner(Day) } impl Into for Meals { fn into(self) -> String { match self { Meals::Breakfast(d) => format!("{}_Breakfast", d), Meals::Lunch(d) => format!("{}_Lunch", d), Meals::Dinner(d) => format!("{}_Dinner", d), } } } /// associated with filters for Domain, depending on recipes RecipeCategory enum RecipeCategory { Breakfast, MainCourse } /// It may also contains an initial value for each variable fn generate_variables(domain: &Domain) -> Vec<(String, &Domain, Option<&V>)> { let mut vars = Vec::new(); for day in &["Lundi", "Mardi", "Mercredi"] { vars.push((Meals::Lunch(day.to_string()).into(), domain, None)); vars.push((Meals::Dinner(day.to_string()).into(), domain, None)); } vars } fn ingredients_contains<'a>(assign: &Variables<'a,Recipe>) -> bool { assign.get("Lundi_Lunch").unwrap().unwrap().ingredients.contains("Patates") && !assign.get("Mardi_Lunch").unwrap().unwrap().ingredients.contains("Patates") } fn get_planning_all_results() -> String { let conn = establish_connection(); let possible_values = recipes::load_all(&conn); let domain = Domain::new(possible_values); let mut problem = Problem::build(); for (var, dom, ini) in generate_variables(&domain) { problem = problem.add_variable(var, dom, ini); } let mut problem = problem.add_constraint(ingredients_contains) .finish(); let results = problem.solve_all(); format!("{:#?}\nTotal = {}", &results.first(), results.len()) } fn main() { println!("{}", get_planning_all_results()); }