Collaborama About Help Contact Anonymous [login] Source: site.view [edit] Function name: guessFoodClassification Arguments: dish,ingredients,cuisineStyle Description: Page type: webl Render function: Module: global Page source: // ************************************************************ // WineCom.webl // Encapsulates Wine.com's APIs // // Implemented Functions: // guessFoodClassification(Ingredients, Dish) // findWineRecommendation(FoodClassification) // // Author: Adam Cheyer // ************************************************************ // Structure representing foodType, Ingredients, and Styles, with some keywords to help guessing var winePairingData = `foodType, 3008, Meat, meat ingredient, 3015, Beef, steak style, 3019, Herbs, herb style, 3020, Hot Spices, spice|chili powder|chili style, 3021, Mushroom, mushrooms style, 3022, Stew, stew style, 3023, BBQ, barbecue style, 3024, Burgers, hamburger|burger ingredient, 3016, Lamb, lamb style, 3025, Herbs, herb style, 3026, Hot Spices, spice|chili powder|chili ingredient, 3017, Pork, pig style, 3027, Herbs, herb style, 3028, Hot Spices, spice|chili powder|chili style, 3029, Mushroom, mushrooms style, 3030, Sausage, sausage style, 3031, Tenderloin, loin style, 3032, BBQ, barbecue style, 3033, Breaded, breadcrumbs style, 3034, Fruit, fruit|apple ingredient, 3018, Veal, veal style, 3035, Herbs, herb style, 3036, Lemon/Citrus, lemon|orange style, 3037, Mushroom, mushrooms style, 3038, Breaded, breadcrumbs style, 3039, Chops, chop foodType, 3009, Cheese, frommage ingredient, 3040, Blue, blue ingredient, 3041, Cheddar, cheddar ingredient, 3042, Creamy, creamcheese ingredient, 3043, Goat, goat ingredient, 3044, Hard, firm ingredient, 3045, Semi-Firm, semifirm ingredient, 3046, Stinky, smelly foodType, 3010, Dessert, dessert ingredient, 3047, Berries, strawberries|raspberries ingredient, 3048, Chocolate, chocolate ingredient, 3049, Cream or Custard, cream|custard ingredient, 3050, Lemon, lemon|lime foodType, 3012, Pasta & Grains, pasta|noodles|spaghetti|penne|lasagna|lasagne ingredient, 3055, Lasagne, lasagna|lasagne|italian style, 3060, Meat, meat sauce|bolognese|hamburger|sausage style, 3061, Vegetable, vegetables ingredient, 3056, Paella, paella ingredient, 3057, Pasta,pasta|noodles|spaghetti|penne|italian style, 3067, Meat, meat sauce|bolognese style, 3068, Mushroom, mushrooms style, 3069, Pesto, pesto style, 3070, Tomato-base, tomato|bolognese style, 3071, Vegetable, vegetables style, 3072, White Sauce/Seafood, flour|seafood|fish style, 3073, Cream-Based, cream ingredient, 3058, Pizza, pizza style, 3062, Meat, sausage|hamburger|american style, 3063, Vegetable, vegetables|onions|pepper ingredient, 3059, Risotto, risotta style, 3064, Mushroom, mushrooms style, 3065, Plain, plain style, 3066, Primavera, primavera foodType, 3013, Poultry, poultry ingredient, 3074, Cassoulet, cassoulet ingredient, 3075, Chicken, chicken style, 3078, Herbs, herb style, 3079, Lemon/Citrus, lemon|citrus style, 3080, Mushroom, mushrooms style, 3081, Mustard, mustard style, 3082, Spicy, spice style, 3083, BBQ, barbecue style, 3084, Cream-Based, cream style, 3085, Fried, fried ingredient, 3076, Duck, canard|french style, 3086, Seared, sear style, 3087, Confit, confit style, 3088, Fois Gras, fois gras style, 3089, Fruit, fruit ingredient, 3077, Turkey, turkey style, 3090, Lemon/Citrus, lemon|citrus style, 3091, Roasted, roast style, 3092, Breaded, breadcrumbs foodType, 3014, Seafood, seafood|fish ingredient, 3093, Crab, crab style, 3102, Soft Shelled, shell|shelled style, 3103, Spicy, spice style, 3104, Butter, butter style, 3105, Crab Cakes, crab cakes ingredient, 3094, Lobster, lobster style, 3106, Butter, butter ingredient, 3095, Oysters, oyster ingredient, 3096, Salmon, salmon style, 3107, Herbs, herb style, 3108, Mustard, mustard style, 3109, Grilled, grill ingredient, 3097, Scallops, scallop style, 3110, Herbs, herb style, 3111, Lemon/Citrus, lemon|citrus style, 3112, Butter, butter ingredient, 3098, Shrimp, shrimp style, 3113, Lemon/Citrus, lemon|citrus style, 3114, Herbs, herb ingredient, 3099, Sushi, sushi ingredient, 3100, Tuna, tuna|ahi style, 3115, Seared, seared style, 3116, Spicy, spice ingredient, 3101, White Fish, white fish style, 3117, Herbs, herb style, 3118, Hot Spices, spice style, 3119, Lemon/Citrus, lemon|citrus style, 3120, Stew, stew style, 3121, Fish Tacos, tacos|mexican style, 3122, Fried, fried `; var lines = Str_Split(winePairingData, "\n"); var count = 0; // ------------------------------------------------------------ // Parse the ingredient data and build a representative structure // ------------------------------------------------------------ var buildStructure = fun(itemType, exitList) var res = []; var last = nil; var obj = nil; while (count < Size(lines)) do var cols = Str_Split(lines[count], ","); last = obj; obj = [. type=Str_Trim(cols[0]), id=Str_Trim(cols[1]), name=Str_Trim(cols[2]), synonyms=(Str_Split(Str_Trim(cols[3]), "|")?nil) .]; count = count + 1; if (obj.type == itemType) then res = res + [obj] else if (obj.type member exitList) then count = count - 1; return res end; count = count - 1; last.children := buildStructure(obj.type, [itemType] + exitList); end; end; return res end; // ------------------------------------------------------------ // Checks whether current foodClassification is a match for ingredients list // ------------------------------------------------------------ var matchesIngredients = fun(obj, ingredients) var ok = Str_ToLowerCase(obj.name) member ingredients; if !ok and (obj.synonyms != nil) then every syn in obj.synonyms do ok = ok or (Str_ToLowerCase(Str_Trim(syn)) member ingredients) end; end; return ok end; // ------------------------------------------------------------ // Returns a list of matching Classifications for a list of ingredients // returns count=N, path=... // ------------------------------------------------------------ var bestMatch = fun(ingredients, struc) var res = []; every obj in struc do var cnt = 0; if matchesIngredients(obj, ingredients) then if obj.type == "ingredient" then cnt = 5 elsif obj.type == "foodType" then cnt = 7 else cnt = 1 end; res = res + [ [. count=cnt, path=obj.name .] ]; end; var c = obj.children ? nil; if c != nil then every match in bestMatch(ingredients, c) do res = res + [ [. count = cnt + match.count, path = obj.name + "," + match.path .] ]; end end end; return res end; // ------------------------------------------------------------ // Given a dish name and it's list of ingredients, try to guess // which would be the best food classification. // ------------------------------------------------------------ var callGuessFoodClassification = fun(dish, ingredients, cuisine) if (Size(ingredients) == 1) and (dish == nil) then dish = ingredients[0] end; if (cuisine != nil) and (dish == nil) then dish = cuisine end; var res = []; var structure = buildStructure("foodType", []); if (dish != nil) then every word in Str_Split(dish, " ") do ingredients = ingredients + [ Str_ToLowerCase(Str_Trim(word)) ] end end; if (cuisine != nil) then ingredients = ingredients + [ Str_ToLowerCase(Str_Trim(cuisine)) ] end; if (dish != nil) then res = [ [. dish = dish .] ]; end; var match = Sort(bestMatch(ingredients, structure), fun(a, b) var diff = a.count - b.count; if diff > 0 then -1 elsif diff == 0 then 0 else 1 end end); PrintLn("Matches: " + ToString(match)); if Size(match) > 0 then var cols = Str_Split(match[0].path, ","); var type = cols[0] ? nil; var ingredient = cols[1] ? nil; var style = cols[2] ? nil; res = [[. dish = ToString(dish), foodType = cols[0] .]]; if (ingredient != nil) then res[0].ingredient := ingredient end; if (style != nil) then res[0].style := style end; end; res; end; // ------------------------------------------------------------ // Implements guessFoodClassification function // Inputs: dish, ingredients // Outputs: foodClassfication // ------------------------------------------------------------ var guessFoodClassification = fun(dish, ingredients, cuisineStyle) var res = []; if Stringp(ingredients) then ingredients = [ ingredients ] end; if (ingredients == nil) and (dish != nil) then ingredients = [] end; if (ingredients != nil) then res = callGuessFoodClassification(dish, ingredients, cuisineStyle); end; return res end; var CleanArg = fun(a) if Str_StartsWith(a, `\[`) then a = WubEval(a); elsif a == "nil" or a == "" then a = nil else if Str_StartsWith(a, `"`) and Str_EndsWith(a, `"`) then a = Select(a, 1, Size(a) - 2) end; end; return a end; var res = guessFoodClassification(CleanArg(dish), CleanArg(ingredients), CleanArg(cuisineStyle)); NewPage(WubCall("toJSON", [res]), "text/plain");