diff --git a/cauldron/data/foods_seed.json b/cauldron/data/foods_seed.json new file mode 100644 index 0000000..19890b0 --- /dev/null +++ b/cauldron/data/foods_seed.json @@ -0,0 +1,2063 @@ +[ + { + "canonical_name": "all-purpose flour", + "category": "baking", + "density_g_per_ml": 0.528, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 168894, + "notes": null + }, + { + "canonical_name": "arrowroot flour", + "category": "baking", + "density_g_per_ml": 0.541, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170684, + "notes": null + }, + { + "canonical_name": "bread flour", + "category": "baking", + "density_g_per_ml": 0.579, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 168896, + "notes": null + }, + { + "canonical_name": "brown rice flour", + "category": "baking", + "density_g_per_ml": 0.668, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 168898, + "notes": null + }, + { + "canonical_name": "brown sugar", + "category": "baking", + "density_g_per_ml": 0.747, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 168833, + "notes": null + }, + { + "canonical_name": "cake flour", + "category": "baking", + "density_g_per_ml": 0.579, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 169723, + "notes": null + }, + { + "canonical_name": "carob flour", + "category": "baking", + "density_g_per_ml": 0.421, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 173755, + "notes": null + }, + { + "canonical_name": "chocolate syrup", + "category": "baking", + "density_g_per_ml": 1.353, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 170681, + "notes": null + }, + { + "canonical_name": "corn flour", + "category": "baking", + "density_g_per_ml": 0.495, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170290, + "notes": "whole-grain yellow" + }, + { + "canonical_name": "dark rye flour", + "category": "baking", + "density_g_per_ml": 0.541, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 168885, + "notes": null + }, + { + "canonical_name": "defatted soy flour", + "category": "baking", + "density_g_per_ml": 0.445, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 174275, + "notes": null + }, + { + "canonical_name": "dutch-process cocoa powder", + "category": "baking", + "density_g_per_ml": 0.364, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 169594, + "notes": "processed with alkali; distinct from natural cocoa in leavening chemistry" + }, + { + "canonical_name": "full-fat soy flour", + "category": "baking", + "density_g_per_ml": 0.353, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 174273, + "notes": "raw" + }, + { + "canonical_name": "granulated sugar", + "category": "baking", + "density_g_per_ml": 0.849, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 169655, + "notes": null + }, + { + "canonical_name": "light rye flour", + "category": "baking", + "density_g_per_ml": 0.431, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 168887, + "notes": null + }, + { + "canonical_name": "maple sugar", + "category": "baking", + "density_g_per_ml": 0.609, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 169658, + "notes": null + }, + { + "canonical_name": "masa harina", + "category": "baking", + "density_g_per_ml": 0.482, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 169694, + "notes": "enriched white corn masa flour" + }, + { + "canonical_name": "millet flour", + "category": "baking", + "density_g_per_ml": 0.503, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 172023, + "notes": null + }, + { + "canonical_name": "oat flour", + "category": "baking", + "density_g_per_ml": 0.44, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 169741, + "notes": "partially debranned" + }, + { + "canonical_name": "powdered sugar", + "category": "baking", + "density_g_per_ml": 0.495, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 169656, + "notes": null + }, + { + "canonical_name": "self-rising cornmeal", + "category": "baking", + "density_g_per_ml": 0.719, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 168869, + "notes": "bolted, with wheat flour added" + }, + { + "canonical_name": "self-rising flour", + "category": "baking", + "density_g_per_ml": 0.528, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 168895, + "notes": null + }, + { + "canonical_name": "sorghum flour", + "category": "baking", + "density_g_per_ml": 0.681, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 173262, + "notes": null + }, + { + "canonical_name": "turbinado sugar", + "category": "baking", + "density_g_per_ml": 0.894, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170674, + "notes": null + }, + { + "canonical_name": "unsweetened baking chocolate", + "category": "baking", + "density_g_per_ml": 0.558, + "default_unit_class": "count", + "common_size_g": 28, + "usda_fdc_id": 167568, + "notes": "standard 1 oz square" + }, + { + "canonical_name": "unsweetened cocoa powder", + "category": "baking", + "density_g_per_ml": 0.364, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 169593, + "notes": null + }, + { + "canonical_name": "vanilla extract", + "category": "baking", + "density_g_per_ml": 0.87, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 173471, + "notes": null + }, + { + "canonical_name": "white rice flour", + "category": "baking", + "density_g_per_ml": 0.668, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 169714, + "notes": null + }, + { + "canonical_name": "acerola juice", + "category": "beverage", + "density_g_per_ml": 1.022, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171687, + "notes": null + }, + { + "canonical_name": "apple juice", + "category": "beverage", + "density_g_per_ml": 1.048, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 173933, + "notes": null + }, + { + "canonical_name": "black tea", + "category": "beverage", + "density_g_per_ml": 1.002, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 173227, + "notes": null + }, + { + "canonical_name": "blackberry juice", + "category": "beverage", + "density_g_per_ml": 1.057, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 173947, + "notes": null + }, + { + "canonical_name": "brewed coffee", + "category": "beverage", + "density_g_per_ml": 1.002, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171890, + "notes": null + }, + { + "canonical_name": "club soda", + "category": "beverage", + "density_g_per_ml": 1.001, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 174842, + "notes": null + }, + { + "canonical_name": "coconut water", + "category": "beverage", + "density_g_per_ml": 1.014, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 170174, + "notes": null + }, + { + "canonical_name": "cranberry juice cocktail", + "category": "beverage", + "density_g_per_ml": 1.069, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171903, + "notes": null + }, + { + "canonical_name": "decaf black tea", + "category": "beverage", + "density_g_per_ml": 1.002, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 174871, + "notes": null + }, + { + "canonical_name": "decaf coffee", + "category": "beverage", + "density_g_per_ml": 1.002, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171889, + "notes": null + }, + { + "canonical_name": "decaf green tea", + "category": "beverage", + "density_g_per_ml": 1.0, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171910, + "notes": null + }, + { + "canonical_name": "fruit punch", + "category": "beverage", + "density_g_per_ml": 1.044, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 174153, + "notes": null + }, + { + "canonical_name": "grape juice", + "category": "beverage", + "density_g_per_ml": 1.069, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 173042, + "notes": null + }, + { + "canonical_name": "grapefruit juice", + "category": "beverage", + "density_g_per_ml": 1.063, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 174678, + "notes": null + }, + { + "canonical_name": "green tea", + "category": "beverage", + "density_g_per_ml": 1.018, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171917, + "notes": null + }, + { + "canonical_name": "hibiscus tea", + "category": "beverage", + "density_g_per_ml": 1.002, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171946, + "notes": null + }, + { + "canonical_name": "lemon juice", + "category": "beverage", + "density_g_per_ml": 1.031, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 167747, + "notes": null + }, + { + "canonical_name": "lemonade", + "category": "beverage", + "density_g_per_ml": 1.044, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 173217, + "notes": null + }, + { + "canonical_name": "lime juice", + "category": "beverage", + "density_g_per_ml": 1.032, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 168156, + "notes": null + }, + { + "canonical_name": "limeade", + "category": "beverage", + "density_g_per_ml": 1.044, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 174862, + "notes": null + }, + { + "canonical_name": "non-alcoholic beer", + "category": "beverage", + "density_g_per_ml": 1.001, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 174863, + "notes": null + }, + { + "canonical_name": "non-alcoholic wine", + "category": "beverage", + "density_g_per_ml": 0.981, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 174157, + "notes": null + }, + { + "canonical_name": "passion fruit juice", + "category": "beverage", + "density_g_per_ml": 1.044, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 169109, + "notes": null + }, + { + "canonical_name": "pink grapefruit juice", + "category": "beverage", + "density_g_per_ml": 1.044, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 167774, + "notes": null + }, + { + "canonical_name": "pink lemonade", + "category": "beverage", + "density_g_per_ml": 1.045, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 173667, + "notes": null + }, + { + "canonical_name": "pomegranate juice", + "category": "beverage", + "density_g_per_ml": 1.057, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 167787, + "notes": null + }, + { + "canonical_name": "prune juice", + "category": "beverage", + "density_g_per_ml": 1.082, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 167753, + "notes": null + }, + { + "canonical_name": "root beer", + "category": "beverage", + "density_g_per_ml": 1.041, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171871, + "notes": null + }, + { + "canonical_name": "sparkling water", + "category": "beverage", + "density_g_per_ml": 1.001, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 173233, + "notes": null + }, + { + "canonical_name": "tonic water", + "category": "beverage", + "density_g_per_ml": 1.031, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171869, + "notes": null + }, + { + "canonical_name": "vegetable juice", + "category": "beverage", + "density_g_per_ml": 1.048, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 170063, + "notes": null + }, + { + "canonical_name": "water", + "category": "beverage", + "density_g_per_ml": 1.0, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 173647, + "notes": null + }, + { + "canonical_name": "blue cheese", + "category": "dairy", + "density_g_per_ml": 0.571, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 172175, + "notes": null + }, + { + "canonical_name": "brick cheese", + "category": "dairy", + "density_g_per_ml": 0.518, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 172176, + "notes": null + }, + { + "canonical_name": "brie cheese", + "category": "dairy", + "density_g_per_ml": 0.812, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 172177, + "notes": null + }, + { + "canonical_name": "camembert cheese", + "category": "dairy", + "density_g_per_ml": 1.04, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 172178, + "notes": null + }, + { + "canonical_name": "cheddar cheese", + "category": "dairy", + "density_g_per_ml": 0.689, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 173414, + "notes": null + }, + { + "canonical_name": "cheese slice", + "category": "dairy", + "density_g_per_ml": null, + "default_unit_class": "count", + "common_size_g": 28, + "usda_fdc_id": null, + "notes": "generic pre-sliced cheese; 1 slice ≈ 28 g" + }, + { + "canonical_name": "colby cheese", + "category": "dairy", + "density_g_per_ml": 0.518, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 173416, + "notes": null + }, + { + "canonical_name": "cotija cheese", + "category": "dairy", + "density_g_per_ml": 0.507, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 170898, + "notes": null + }, + { + "canonical_name": "cottage cheese", + "category": "dairy", + "density_g_per_ml": 0.919, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 172179, + "notes": "creamed, full-fat" + }, + { + "canonical_name": "cream cheese", + "category": "dairy", + "density_g_per_ml": 0.879, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 173418, + "notes": null + }, + { + "canonical_name": "dry whole milk", + "category": "dairy", + "density_g_per_ml": 0.541, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170876, + "notes": "powdered whole milk" + }, + { + "canonical_name": "egg", + "category": "dairy", + "density_g_per_ml": 1.027, + "default_unit_class": "count", + "common_size_g": 50, + "usda_fdc_id": 171287, + "notes": "large whole egg" + }, + { + "canonical_name": "eggnog", + "category": "dairy", + "density_g_per_ml": 1.074, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171258, + "notes": null + }, + { + "canonical_name": "evaporated milk", + "category": "dairy", + "density_g_per_ml": 1.065, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 172194, + "notes": null + }, + { + "canonical_name": "feta cheese", + "category": "dairy", + "density_g_per_ml": 0.634, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 173420, + "notes": null + }, + { + "canonical_name": "fontina cheese", + "category": "dairy", + "density_g_per_ml": 0.507, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 170843, + "notes": null + }, + { + "canonical_name": "gruyere cheese", + "category": "dairy", + "density_g_per_ml": 0.507, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 171242, + "notes": null + }, + { + "canonical_name": "half and half", + "category": "dairy", + "density_g_per_ml": 1.019, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171255, + "notes": null + }, + { + "canonical_name": "heavy cream", + "category": "dairy", + "density_g_per_ml": 0.884, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 170859, + "notes": null + }, + { + "canonical_name": "light cream", + "category": "dairy", + "density_g_per_ml": 1.014, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 170857, + "notes": "coffee cream or table cream" + }, + { + "canonical_name": "limburger cheese", + "category": "dairy", + "density_g_per_ml": 0.566, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 171243, + "notes": null + }, + { + "canonical_name": "mexican blend cheese", + "category": "dairy", + "density_g_per_ml": 0.473, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 171288, + "notes": "four-cheese shredded blend" + }, + { + "canonical_name": "mozzarella cheese", + "category": "dairy", + "density_g_per_ml": 0.518, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 171244, + "notes": "low moisture, part-skim" + }, + { + "canonical_name": "parmesan cheese", + "category": "dairy", + "density_g_per_ml": 0.38, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 171247, + "notes": "grated" + }, + { + "canonical_name": "queso anejo", + "category": "dairy", + "density_g_per_ml": 0.558, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 172201, + "notes": null + }, + { + "canonical_name": "queso asadero", + "category": "dairy", + "density_g_per_ml": 0.518, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 173437, + "notes": null + }, + { + "canonical_name": "queso blanco", + "category": "dairy", + "density_g_per_ml": 0.499, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 172224, + "notes": null + }, + { + "canonical_name": "queso chihuahua", + "category": "dairy", + "density_g_per_ml": 0.518, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 173438, + "notes": null + }, + { + "canonical_name": "queso fresco", + "category": "dairy", + "density_g_per_ml": 0.516, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 172223, + "notes": null + }, + { + "canonical_name": "queso seco", + "category": "dairy", + "density_g_per_ml": 0.41, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 172222, + "notes": "dry white cheese" + }, + { + "canonical_name": "rice milk", + "category": "dairy", + "density_g_per_ml": 1.014, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171942, + "notes": "unsweetened" + }, + { + "canonical_name": "ricotta cheese", + "category": "dairy", + "density_g_per_ml": 1.044, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171248, + "notes": "part-skim" + }, + { + "canonical_name": "sour cream", + "category": "dairy", + "density_g_per_ml": 0.892, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171257, + "notes": null + }, + { + "canonical_name": "sweetened condensed milk", + "category": "dairy", + "density_g_per_ml": 1.293, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 171275, + "notes": null + }, + { + "canonical_name": "whole milk", + "category": "dairy", + "density_g_per_ml": 1.027, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 172217, + "notes": null + }, + { + "canonical_name": "bacon grease", + "category": "meat", + "density_g_per_ml": 0.872, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 172345, + "notes": null + }, + { + "canonical_name": "beef broth", + "category": "meat", + "density_g_per_ml": 1.014, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171538, + "notes": null + }, + { + "canonical_name": "beef tallow", + "category": "meat", + "density_g_per_ml": 0.866, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171400, + "notes": null + }, + { + "canonical_name": "canned chicken", + "category": "meat", + "density_g_per_ml": 0.866, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 171110, + "notes": "no broth" + }, + { + "canonical_name": "canned mackerel", + "category": "meat", + "density_g_per_ml": 0.803, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 175121, + "notes": "drained" + }, + { + "canonical_name": "canned sardines", + "category": "meat", + "density_g_per_ml": 0.63, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 175139, + "notes": "in oil, drained, with bone" + }, + { + "canonical_name": "canned shrimp", + "category": "meat", + "density_g_per_ml": 0.541, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 171972, + "notes": null + }, + { + "canonical_name": "canned tuna", + "category": "meat", + "density_g_per_ml": 0.617, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 173708, + "notes": "light, in oil, drained" + }, + { + "canonical_name": "caviar", + "category": "meat", + "density_g_per_ml": 1.082, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 174188, + "notes": null + }, + { + "canonical_name": "chicken breast", + "category": "meat", + "density_g_per_ml": 0.592, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 171477, + "notes": "cooked, meat only, roasted" + }, + { + "canonical_name": "chicken dark meat", + "category": "meat", + "density_g_per_ml": 0.592, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 171069, + "notes": "cooked, meat only, roasted" + }, + { + "canonical_name": "chicken drumstick", + "category": "meat", + "density_g_per_ml": 0.676, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 172377, + "notes": "cooked, meat only" + }, + { + "canonical_name": "chicken fat", + "category": "meat", + "density_g_per_ml": 0.866, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 173564, + "notes": null + }, + { + "canonical_name": "chicken giblets", + "category": "meat", + "density_g_per_ml": 0.613, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 171058, + "notes": null + }, + { + "canonical_name": "chicken gizzard", + "category": "meat", + "density_g_per_ml": 0.613, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 171457, + "notes": null + }, + { + "canonical_name": "chicken heart", + "category": "meat", + "density_g_per_ml": 0.613, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 171059, + "notes": null + }, + { + "canonical_name": "chicken light meat", + "category": "meat", + "density_g_per_ml": 0.592, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 171466, + "notes": "cooked, meat only, roasted" + }, + { + "canonical_name": "chicken liver pate", + "category": "meat", + "density_g_per_ml": 0.879, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 172928, + "notes": null + }, + { + "canonical_name": "chicken thigh", + "category": "meat", + "density_g_per_ml": 0.592, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 172389, + "notes": "cooked, meat only" + }, + { + "canonical_name": "chicken wing", + "category": "meat", + "density_g_per_ml": 0.592, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 172393, + "notes": "cooked, meat only" + }, + { + "canonical_name": "fish broth", + "category": "meat", + "density_g_per_ml": 1.031, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171606, + "notes": null + }, + { + "canonical_name": "fish roe", + "category": "meat", + "density_g_per_ml": 0.947, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 175132, + "notes": null + }, + { + "canonical_name": "ham", + "category": "meat", + "density_g_per_ml": 0.592, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 167872, + "notes": "cured, boneless, roasted" + }, + { + "canonical_name": "pickled herring", + "category": "meat", + "density_g_per_ml": 0.592, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 175118, + "notes": null + }, + { + "canonical_name": "pork heart", + "category": "meat", + "density_g_per_ml": 0.613, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 168268, + "notes": null + }, + { + "canonical_name": "pork kidney", + "category": "meat", + "density_g_per_ml": 0.592, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 167860, + "notes": null + }, + { + "canonical_name": "pork leg", + "category": "meat", + "density_g_per_ml": 0.571, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 168225, + "notes": "fresh ham, lean only, roasted" + }, + { + "canonical_name": "pork shoulder", + "category": "meat", + "density_g_per_ml": 0.571, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 167846, + "notes": "lean only, roasted" + }, + { + "canonical_name": "smoked salmon", + "category": "meat", + "density_g_per_ml": 0.575, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 173687, + "notes": null + }, + { + "canonical_name": "smoked whitefish", + "category": "meat", + "density_g_per_ml": 0.575, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 173712, + "notes": null + }, + { + "canonical_name": "turkey and pork sausage", + "category": "meat", + "density_g_per_ml": 0.549, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 167694, + "notes": "cooked" + }, + { + "canonical_name": "alfalfa sprout", + "category": "nut-seed", + "density_g_per_ml": 0.171, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 168384, + "notes": null + }, + { + "canonical_name": "almond", + "category": "nut-seed", + "density_g_per_ml": 0.463, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170567, + "notes": null + }, + { + "canonical_name": "almond oil", + "category": "nut-seed", + "density_g_per_ml": 0.918, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171031, + "notes": null + }, + { + "canonical_name": "almond paste", + "category": "nut-seed", + "density_g_per_ml": 0.959, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170160, + "notes": null + }, + { + "canonical_name": "anise seed", + "category": "nut-seed", + "density_g_per_ml": 0.44, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 171316, + "notes": null + }, + { + "canonical_name": "black walnut", + "category": "nut-seed", + "density_g_per_ml": 0.528, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170186, + "notes": null + }, + { + "canonical_name": "black-eyed pea", + "category": "nut-seed", + "density_g_per_ml": 0.708, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 173758, + "notes": "dried mature seeds" + }, + { + "canonical_name": "brazil nut", + "category": "nut-seed", + "density_g_per_ml": 0.562, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170569, + "notes": null + }, + { + "canonical_name": "caraway seed", + "category": "nut-seed", + "density_g_per_ml": 0.44, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170918, + "notes": null + }, + { + "canonical_name": "cashew", + "category": "nut-seed", + "density_g_per_ml": 0.58, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170571, + "notes": "dry roasted unsalted; no raw entry available in this batch" + }, + { + "canonical_name": "chestnut", + "category": "nut-seed", + "density_g_per_ml": 0.613, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170574, + "notes": "raw, unpeeled" + }, + { + "canonical_name": "coconut", + "category": "nut-seed", + "density_g_per_ml": 0.338, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170169, + "notes": "raw meat" + }, + { + "canonical_name": "coriander seed", + "category": "nut-seed", + "density_g_per_ml": 0.352, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170922, + "notes": null + }, + { + "canonical_name": "dill seed", + "category": "nut-seed", + "density_g_per_ml": 0.436, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170925, + "notes": null + }, + { + "canonical_name": "dry roasted almond", + "category": "nut-seed", + "density_g_per_ml": 0.583, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170158, + "notes": null + }, + { + "canonical_name": "dry roasted peanut", + "category": "nut-seed", + "density_g_per_ml": 0.617, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 173806, + "notes": null + }, + { + "canonical_name": "fennel seed", + "category": "nut-seed", + "density_g_per_ml": 0.399, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 171323, + "notes": null + }, + { + "canonical_name": "fenugreek seed", + "category": "nut-seed", + "density_g_per_ml": 0.751, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 171324, + "notes": null + }, + { + "canonical_name": "flaxseed", + "category": "nut-seed", + "density_g_per_ml": 0.615, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 169414, + "notes": null + }, + { + "canonical_name": "flaxseed oil", + "category": "nut-seed", + "density_g_per_ml": 0.921, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 167702, + "notes": "cold pressed" + }, + { + "canonical_name": "hazelnut", + "category": "nut-seed", + "density_g_per_ml": 0.458, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170581, + "notes": null + }, + { + "canonical_name": "hazelnut oil", + "category": "nut-seed", + "density_g_per_ml": 0.918, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171427, + "notes": null + }, + { + "canonical_name": "hemp seed", + "category": "nut-seed", + "density_g_per_ml": 0.676, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170148, + "notes": "hulled" + }, + { + "canonical_name": "hickory nut", + "category": "nut-seed", + "density_g_per_ml": 0.507, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170177, + "notes": null + }, + { + "canonical_name": "lotus seed", + "category": "nut-seed", + "density_g_per_ml": 0.135, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170149, + "notes": "dried" + }, + { + "canonical_name": "lupin bean", + "category": "nut-seed", + "density_g_per_ml": 0.761, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 172423, + "notes": "dried mature seeds" + }, + { + "canonical_name": "macadamia nut", + "category": "nut-seed", + "density_g_per_ml": 0.566, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170178, + "notes": null + }, + { + "canonical_name": "mixed nuts", + "category": "nut-seed", + "density_g_per_ml": 0.554, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170585, + "notes": "dry roasted with peanuts, unsalted" + }, + { + "canonical_name": "nutmeg", + "category": "nut-seed", + "density_g_per_ml": 0.46, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 171326, + "notes": "ground" + }, + { + "canonical_name": "peanut", + "category": "nut-seed", + "density_g_per_ml": 0.617, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 172430, + "notes": null + }, + { + "canonical_name": "peanut flour", + "category": "nut-seed", + "density_g_per_ml": 0.254, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 174267, + "notes": "defatted" + }, + { + "canonical_name": "peanut oil", + "category": "nut-seed", + "density_g_per_ml": 0.913, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171410, + "notes": null + }, + { + "canonical_name": "pecan", + "category": "nut-seed", + "density_g_per_ml": 0.44, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170182, + "notes": null + }, + { + "canonical_name": "pigeon pea", + "category": "nut-seed", + "density_g_per_ml": 0.866, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 172436, + "notes": "dried mature seeds" + }, + { + "canonical_name": "pine nut", + "category": "nut-seed", + "density_g_per_ml": 0.571, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170591, + "notes": null + }, + { + "canonical_name": "pistachio", + "category": "nut-seed", + "density_g_per_ml": 0.52, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170184, + "notes": "raw" + }, + { + "canonical_name": "poppy seed", + "category": "nut-seed", + "density_g_per_ml": 0.582, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 171330, + "notes": null + }, + { + "canonical_name": "roasted chestnut", + "category": "nut-seed", + "density_g_per_ml": 0.604, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170190, + "notes": null + }, + { + "canonical_name": "roasted pistachio", + "category": "nut-seed", + "density_g_per_ml": 0.52, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170185, + "notes": "dry roasted, unsalted" + }, + { + "canonical_name": "sesame seed", + "category": "nut-seed", + "density_g_per_ml": 0.609, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170150, + "notes": "whole, dried" + }, + { + "canonical_name": "split pea", + "category": "nut-seed", + "density_g_per_ml": 0.828, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 172428, + "notes": "green, dried" + }, + { + "canonical_name": "sunflower seed", + "category": "nut-seed", + "density_g_per_ml": 0.393, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170562, + "notes": "kernels, dried" + }, + { + "canonical_name": "sweetened shredded coconut", + "category": "nut-seed", + "density_g_per_ml": 0.393, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 168586, + "notes": null + }, + { + "canonical_name": "walnut", + "category": "nut-seed", + "density_g_per_ml": 0.376, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170187, + "notes": "English walnut" + }, + { + "canonical_name": "walnut oil", + "category": "nut-seed", + "density_g_per_ml": 0.918, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171030, + "notes": null + }, + { + "canonical_name": "almond butter", + "category": "oil-fat", + "density_g_per_ml": 1.069, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 168588, + "notes": null + }, + { + "canonical_name": "anhydrous butter oil", + "category": "oil-fat", + "density_g_per_ml": 0.866, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 173412, + "notes": "Nearly pure butterfat; functionally equivalent to ghee" + }, + { + "canonical_name": "apricot kernel oil", + "category": "oil-fat", + "density_g_per_ml": 0.918, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171032, + "notes": null + }, + { + "canonical_name": "canola oil", + "category": "oil-fat", + "density_g_per_ml": 0.927, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 172336, + "notes": null + }, + { + "canonical_name": "cashew butter", + "category": "oil-fat", + "density_g_per_ml": 1.082, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170163, + "notes": null + }, + { + "canonical_name": "cocoa butter", + "category": "oil-fat", + "density_g_per_ml": 0.918, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171421, + "notes": null + }, + { + "canonical_name": "coconut oil", + "category": "oil-fat", + "density_g_per_ml": 0.918, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171412, + "notes": null + }, + { + "canonical_name": "corn oil", + "category": "oil-fat", + "density_g_per_ml": 0.918, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171029, + "notes": null + }, + { + "canonical_name": "lard", + "category": "oil-fat", + "density_g_per_ml": 0.866, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 171401, + "notes": null + }, + { + "canonical_name": "margarine", + "category": "oil-fat", + "density_g_per_ml": 0.947, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 171431, + "notes": null + }, + { + "canonical_name": "oat oil", + "category": "oil-fat", + "density_g_per_ml": 0.918, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 173576, + "notes": null + }, + { + "canonical_name": "olive oil", + "category": "oil-fat", + "density_g_per_ml": 0.913, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171413, + "notes": null + }, + { + "canonical_name": "palm kernel oil", + "category": "oil-fat", + "density_g_per_ml": 0.918, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171422, + "notes": null + }, + { + "canonical_name": "palm oil", + "category": "oil-fat", + "density_g_per_ml": 0.915, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171015, + "notes": null + }, + { + "canonical_name": "peanut butter", + "category": "oil-fat", + "density_g_per_ml": 1.086, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 174266, + "notes": "Smooth style" + }, + { + "canonical_name": "peanut butter, chunky", + "category": "oil-fat", + "density_g_per_ml": 1.086, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 174265, + "notes": null + }, + { + "canonical_name": "safflower oil", + "category": "oil-fat", + "density_g_per_ml": 0.918, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171027, + "notes": "High-oleic variety" + }, + { + "canonical_name": "salted butter", + "category": "oil-fat", + "density_g_per_ml": 0.96, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 173410, + "notes": null + }, + { + "canonical_name": "sesame oil", + "category": "oil-fat", + "density_g_per_ml": 0.918, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171016, + "notes": null + }, + { + "canonical_name": "sesame paste", + "category": "oil-fat", + "density_g_per_ml": 1.082, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170191, + "notes": "Raw (unroasted) sesame butter; used in Chinese cooking — distinct from tahini" + }, + { + "canonical_name": "soybean oil", + "category": "oil-fat", + "density_g_per_ml": 0.918, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171012, + "notes": null + }, + { + "canonical_name": "sunflower oil", + "category": "oil-fat", + "density_g_per_ml": 0.927, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 172338, + "notes": "High-oleic variety; more heat-stable" + }, + { + "canonical_name": "sunflower seed butter", + "category": "oil-fat", + "density_g_per_ml": 1.082, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 168595, + "notes": null + }, + { + "canonical_name": "tahini", + "category": "oil-fat", + "density_g_per_ml": 1.014, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 170189, + "notes": "Roasted sesame seed butter" + }, + { + "canonical_name": "vegetable shortening", + "category": "oil-fat", + "density_g_per_ml": 0.866, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 173584, + "notes": null + }, + { + "canonical_name": "apple", + "category": "produce-fruit", + "density_g_per_ml": 0.495, + "default_unit_class": "count", + "common_size_g": 180, + "usda_fdc_id": 171688, + "notes": null + }, + { + "canonical_name": "avocado", + "category": "produce-fruit", + "density_g_per_ml": 0.741, + "default_unit_class": "count", + "common_size_g": 200, + "usda_fdc_id": 171705, + "notes": null + }, + { + "canonical_name": "banana", + "category": "produce-fruit", + "density_g_per_ml": 0.793, + "default_unit_class": "count", + "common_size_g": 118, + "usda_fdc_id": 173944, + "notes": null + }, + { + "canonical_name": "crabapple", + "category": "produce-fruit", + "density_g_per_ml": 0.465, + "default_unit_class": "count", + "common_size_g": 75, + "usda_fdc_id": 171721, + "notes": null + }, + { + "canonical_name": "grape", + "category": "produce-fruit", + "density_g_per_ml": 0.638, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 174683, + "notes": "European type (red or green seedless); sold by weight, measured by cup in recipes" + }, + { + "canonical_name": "grapefruit", + "category": "produce-fruit", + "density_g_per_ml": 0.972, + "default_unit_class": "count", + "common_size_g": 246, + "usda_fdc_id": 174673, + "notes": "pink and red; most common market variety" + }, + { + "canonical_name": "lemon", + "category": "produce-fruit", + "density_g_per_ml": 0.896, + "default_unit_class": "count", + "common_size_g": 60, + "usda_fdc_id": 167746, + "notes": null + }, + { + "canonical_name": "lemon peel", + "category": "produce-fruit", + "density_g_per_ml": 0.406, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 167749, + "notes": "fresh zest; used by teaspoon or tablespoon" + }, + { + "canonical_name": "lime", + "category": "produce-fruit", + "density_g_per_ml": null, + "default_unit_class": "count", + "common_size_g": 65, + "usda_fdc_id": null, + "notes": "added; absent from source batch" + }, + { + "canonical_name": "mango", + "category": "produce-fruit", + "density_g_per_ml": 0.697, + "default_unit_class": "count", + "common_size_g": 200, + "usda_fdc_id": 169910, + "notes": null + }, + { + "canonical_name": "orange", + "category": "produce-fruit", + "density_g_per_ml": 0.761, + "default_unit_class": "count", + "common_size_g": 130, + "usda_fdc_id": 169097, + "notes": null + }, + { + "canonical_name": "orange juice", + "category": "produce-fruit", + "density_g_per_ml": 1.048, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 169098, + "notes": "freshly squeezed" + }, + { + "canonical_name": "orange peel", + "category": "produce-fruit", + "density_g_per_ml": 0.406, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 169103, + "notes": "fresh zest; used by teaspoon or tablespoon" + }, + { + "canonical_name": "peach", + "category": "produce-fruit", + "density_g_per_ml": null, + "default_unit_class": "count", + "common_size_g": 150, + "usda_fdc_id": null, + "notes": "added; only processed peach variants in source batch" + }, + { + "canonical_name": "pear", + "category": "produce-fruit", + "density_g_per_ml": 0.636, + "default_unit_class": "count", + "common_size_g": 178, + "usda_fdc_id": 169118, + "notes": null + }, + { + "canonical_name": "pineapple", + "category": "produce-fruit", + "density_g_per_ml": 0.697, + "default_unit_class": "mixed", + "common_size_g": 900, + "usda_fdc_id": 169124, + "notes": "whole fruit ~900g; chunks measured by cup" + }, + { + "canonical_name": "prickly pear", + "category": "produce-fruit", + "density_g_per_ml": 0.63, + "default_unit_class": "count", + "common_size_g": 103, + "usda_fdc_id": 167750, + "notes": null + }, + { + "canonical_name": "strawberry", + "category": "produce-fruit", + "density_g_per_ml": null, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": null, + "notes": "added; sold by weight or pint, used by cup or count in recipes" + }, + { + "canonical_name": "strawberry guava", + "category": "produce-fruit", + "density_g_per_ml": 1.031, + "default_unit_class": "count", + "common_size_g": 30, + "usda_fdc_id": 173045, + "notes": null + }, + { + "canonical_name": "watermelon", + "category": "produce-fruit", + "density_g_per_ml": 0.647, + "default_unit_class": "mixed", + "common_size_g": null, + "usda_fdc_id": 167765, + "notes": "whole or cubed; use volume for flesh" + }, + { + "canonical_name": "white grapefruit", + "category": "produce-fruit", + "density_g_per_ml": 0.972, + "default_unit_class": "count", + "common_size_g": 246, + "usda_fdc_id": 174676, + "notes": null + }, + { + "canonical_name": "banana pepper", + "category": "spice", + "density_g_per_ml": 0.524, + "default_unit_class": "count", + "common_size_g": 33, + "usda_fdc_id": 169394, + "notes": "one medium banana pepper ~33 g" + }, + { + "canonical_name": "basil", + "category": "spice", + "density_g_per_ml": 0.14, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 172232, + "notes": "fresh leaves" + }, + { + "canonical_name": "cinnamon", + "category": "spice", + "density_g_per_ml": 0.527, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171320, + "notes": "ground" + }, + { + "canonical_name": "cumin", + "category": "spice", + "density_g_per_ml": 0.416, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 170923, + "notes": "whole seed; ground is similar density" + }, + { + "canonical_name": "dried basil", + "category": "spice", + "density_g_per_ml": 0.218, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171317, + "notes": null + }, + { + "canonical_name": "fresh ginger", + "category": "spice", + "density_g_per_ml": 0.406, + "default_unit_class": "mass", + "common_size_g": null, + "usda_fdc_id": 169231, + "notes": "raw root; sold by weight" + }, + { + "canonical_name": "garlic powder", + "category": "spice", + "density_g_per_ml": 0.642, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171325, + "notes": null + }, + { + "canonical_name": "ground ginger", + "category": "spice", + "density_g_per_ml": 0.358, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 170926, + "notes": null + }, + { + "canonical_name": "jalapeño pepper", + "category": "spice", + "density_g_per_ml": 0.38, + "default_unit_class": "count", + "common_size_g": 14, + "usda_fdc_id": 168576, + "notes": "one medium jalapeño ~14 g" + }, + { + "canonical_name": "onion powder", + "category": "spice", + "density_g_per_ml": 0.477, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171327, + "notes": null + }, + { + "canonical_name": "oregano", + "category": "spice", + "density_g_per_ml": 0.284, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171328, + "notes": "dried" + }, + { + "canonical_name": "paprika", + "category": "spice", + "density_g_per_ml": 0.463, + "default_unit_class": "volume", + "common_size_g": null, + "usda_fdc_id": 171329, + "notes": null + } +] diff --git a/cauldron/foods.py b/cauldron/foods.py index f62322d..be08130 100644 --- a/cauldron/foods.py +++ b/cauldron/foods.py @@ -1,20 +1,22 @@ """Foods catalog — canonical food rows + the seed loader. -Phase A step 1 (v0.3): seed cauldron_foods from USDA SR Legacy via the -JSON file at cauldron/data/foods_seed_usda.json. Idempotent — running -multiple times is fine, INSERT IGNORE on the unique canonical_name key. +Seed = cauldron/data/foods_seed.json (Sonnet-curated, ~229 clean rows +with proper densities and unit classes). The raw USDA dump still lives +at foods_seed_usda.json as a reference; we don't load it directly. -Phase A step 2 (next commit): aggregator engine reads these rows + the -per-household cauldron_food_mapping to group recipe ingredients. - -Phase A step 3 (later): claude-curated cleanup of the USDA seed (better -names, missing common foods, count-based foods like 'egg' / 'onion'). +Lookup is exact + case-insensitive. Mealie's parser already +canonicalizes food names household-side via its own alias system, so +the food.name we get from Mealie is consistent across recipes. When a +Mealie food name has no match in cauldron_foods, server.py's +ensure_food() calls clawdforge to fetch density+unit_class+common_size_g +for that exact name, persists it with source='claude', and the +household's catalog grows organically. """ import json from pathlib import Path -SEED_PATH = Path(__file__).parent / "data" / "foods_seed_usda.json" +SEED_PATH = Path(__file__).parent / "data" / "foods_seed.json" def seed_count(db) -> int: @@ -53,13 +55,15 @@ def _load_seed_file(db, path: Path) -> int: """ INSERT IGNORE INTO cauldron_foods (canonical_name, category, density_g_per_ml, - default_unit_class, usda_fdc_id, usda_description, source) - VALUES (%s, %s, %s, %s, %s, %s, 'usda') + common_size_g, default_unit_class, usda_fdc_id, + usda_description, source) + VALUES (%s, %s, %s, %s, %s, %s, %s, 'usda') """, ( entry["canonical_name"][:255], entry.get("category"), entry.get("density_g_per_ml"), + entry.get("common_size_g"), entry.get("default_unit_class") or "mass", entry.get("usda_fdc_id"), (entry.get("usda_description") or "")[:500], @@ -72,25 +76,65 @@ def _load_seed_file(db, path: Path) -> int: return inserted -def search_food(db, name: str, *, limit: int = 5) -> list[dict]: - """Best-effort canonical food lookup by name (used by aggregator + UI).""" +def search_food(db, name: str, *, limit: int = 1) -> list[dict]: + """Case-insensitive exact match. Returns [] on miss. + + `limit` kept for backwards-compat with callers; only ever returns 0 or 1. + """ + name_clean = (name or "").strip().lower() + if not name_clean: + return [] + with db.conn() as c, c.cursor() as cur: + cur.execute( + """SELECT id, canonical_name, category, density_g_per_ml, + default_unit_class, common_size_g, source + FROM cauldron_foods + WHERE LOWER(canonical_name) = %s + LIMIT 1""", + (name_clean,), + ) + row = cur.fetchone() + return [dict(row)] if row else [] + + +def upsert_claude_food( + db, + *, + canonical_name: str, + density_g_per_ml: float | None, + default_unit_class: str, + common_size_g: float | None, + category: str | None = None, +) -> dict: + """Insert (or update if a row already exists) a canonical food row from + a clawdforge response. Returns the row as a dict. Idempotent.""" + name = canonical_name.strip().lower()[:255] + cls = (default_unit_class or "mass").lower() + if cls not in ("mass", "volume", "count", "mixed"): + cls = "mass" with db.conn() as c, c.cursor() as cur: cur.execute( """ - SELECT id, canonical_name, category, density_g_per_ml, - default_unit_class, common_size_g - FROM cauldron_foods - WHERE canonical_name LIKE %s OR canonical_name LIKE %s - ORDER BY - (CASE WHEN canonical_name = %s THEN 0 - WHEN canonical_name LIKE %s THEN 1 - ELSE 2 END), - CHAR_LENGTH(canonical_name) - LIMIT %s + INSERT INTO cauldron_foods + (canonical_name, category, density_g_per_ml, + common_size_g, default_unit_class, source) + VALUES (%s, %s, %s, %s, %s, 'claude') + ON DUPLICATE KEY UPDATE + category=COALESCE(VALUES(category), category), + density_g_per_ml=COALESCE(VALUES(density_g_per_ml), density_g_per_ml), + common_size_g=COALESCE(VALUES(common_size_g), common_size_g), + default_unit_class=VALUES(default_unit_class), + source='claude' """, - (f"{name}%", f"%{name}%", name, f"{name}%", limit), + (name, category, density_g_per_ml, common_size_g, cls), ) - return [dict(r) for r in cur.fetchall()] + cur.execute( + """SELECT id, canonical_name, category, density_g_per_ml, + default_unit_class, common_size_g, source + FROM cauldron_foods WHERE LOWER(canonical_name)=%s LIMIT 1""", + (name,), + ) + return dict(cur.fetchone()) def get_food(db, food_id: int) -> dict | None: diff --git a/cauldron/forge.py b/cauldron/forge.py index f6fed2e..5087fb3 100644 --- a/cauldron/forge.py +++ b/cauldron/forge.py @@ -215,6 +215,73 @@ class Forge: ) + def fetch_food_info(self, name: str, *, model: str | None = None) -> dict: + """Ask Sonnet for density + unit class + common size of a single + food. Returns a dict shaped like: + + {"density_g_per_ml": 1.04 | null, + "default_unit_class": "mass"|"volume"|"count", + "common_size_g": 150.0 | null, + "category": "produce"|"dairy"|... | null} + + density_g_per_ml is null when the food doesn't sensibly convert + between mass and volume (e.g., whole onions, eggs — these are + count-style). common_size_g lets the aggregator handle "1 onion" + as a count → mass conversion. Cheap call, cached forever once + persisted to cauldron_foods. + """ + prompt = ( + f"Give nutritional/cooking metadata for the food: {name!r}.\n\n" + "Output JSON ONLY, no prose: " + '{"density_g_per_ml": float|null, ' + '"default_unit_class": "mass"|"volume"|"count", ' + '"common_size_g": float|null, ' + '"category": "produce"|"dairy"|"meat"|"grain"|"baking"|"pantry"' + '|"spice"|"oil"|"beverage"|"other"|null}\n\n' + "Rules:\n" + "- density_g_per_ml: typical packed/cooking density. Null if " + "the food is count-based (whole onions, eggs).\n" + "- default_unit_class: how this food is most often measured " + "(salt=mass; milk=volume; egg=count).\n" + "- common_size_g: the typical mass of one whole unit (1 onion " + "≈ 150g; 1 egg ≈ 50g). Null if the food isn't naturally counted.\n" + "- category: best single fit; null if uncertain.\n" + ) + result = self.run(prompt, model=model or "sonnet", timeout_secs=60) + return _extract_food_info(result) + + +def _extract_food_info(forge_result: dict) -> dict: + """Normalize clawdforge wrapper → food info dict. Defensive on shapes.""" + if not isinstance(forge_result, dict): + raise ForgeError("forge result not a dict") + inner = forge_result.get("result", forge_result) + if isinstance(inner, str): + inner = _parse_json_blob(inner) + if not isinstance(inner, dict): + raise ForgeError(f"forge result not a dict: {str(inner)[:200]}") + + cls = (inner.get("default_unit_class") or "mass").strip().lower() + if cls not in ("mass", "volume", "count", "mixed"): + cls = "mass" + + def _f(v): + if v is None: + return None + try: + x = float(v) + return x if x > 0 else None + except (TypeError, ValueError): + return None + + return { + "density_g_per_ml": _f(inner.get("density_g_per_ml")), + "default_unit_class": cls, + "common_size_g": _f(inner.get("common_size_g")), + "category": (inner.get("category") or None) and str(inner["category"])[:64], + } + + def _extract_plan_slots(forge_result: dict): """clawdforge wraps its return; the JSON we asked for can sit in a few different shapes. Normalize aggressively.""" diff --git a/cauldron/server.py b/cauldron/server.py index 39728c7..001675c 100644 --- a/cauldron/server.py +++ b/cauldron/server.py @@ -501,8 +501,6 @@ def create_app() -> Flask: plan = db.get_or_create_plan(hid, this_monday) db.enrich_plan_with_slots(plan) - scoreboard = db.household_scoreboard(hid) - streak = db.household_streak(hid) pick_count = len(db.list_household_pick_slugs(hid)) # Resolve display names for any subs we render — locked_by + every @@ -523,8 +521,6 @@ def create_app() -> Flask: locked_by_display=locked_by_display, generated_by_display=generated_by_display, sub_display=sub_display, - scoreboard=scoreboard, - streak=streak, current_user_sub=u["sub"], pick_count=pick_count, active="plan", @@ -611,15 +607,6 @@ def create_app() -> Flask: "plan": _plan_payload(plan), }), 409 - # Award 1pt per pick that landed (one row per (sub, pick_used) per - # plan, deduped client-side: a pick with two pickers gives both 1pt). - for s in slots: - for sub in s.get("picker_subs") or []: - try: - db.award_pick_points(hid, plan["id"], sub, 1, "pick_used") - except Exception as exc: - app.logger.warning("award_pick_points failed for %s: %s", sub, exc) - plan = db.mark_plan_generated(plan["id"], u["sub"]) db.enrich_plan_with_slots(plan) return jsonify({"ok": True, "plan": _plan_payload(plan)}) @@ -678,12 +665,6 @@ def create_app() -> Flask: return jsonify({"error": "forge_failed", "detail": str(e)}), 502 db.save_plan_slots(plan["id"], slots) - for s in slots: - for sub in s.get("picker_subs") or []: - try: - db.award_pick_points(hid, plan["id"], sub, 1, "pick_used") - except Exception as exc: - app.logger.warning("award_pick_points failed for %s: %s", sub, exc) plan = db.mark_plan_generated(plan["id"], u["sub"]) db.enrich_plan_with_slots(plan) return jsonify({"ok": True, "plan": _plan_payload(plan)}) @@ -739,9 +720,39 @@ def create_app() -> Flask: original_text=ri.get("display") or _ing_render(qty, unit, food_name, note), )) + # foods_lookup: exact match → clawdforge fallback that persists. + # Per-request cache so the same food in multiple recipes isn't + # re-queried within one /list render. + lookup_cache: dict[str, dict | None] = {} + def foods_lookup(name: str): - hits = foods.search_food(db, name, limit=1) - return hits[0] if hits else None + key = (name or "").strip().lower() + if not key: + return None + if key in lookup_cache: + return lookup_cache[key] + hits = foods.search_food(db, key, limit=1) + if hits: + lookup_cache[key] = hits[0] + return hits[0] + # Miss — ask clawdforge, persist, return. On any failure, cache + # None for this request so we don't spam the model. + try: + info = forge.fetch_food_info(key) + row = foods.upsert_claude_food( + db, + canonical_name=key, + density_g_per_ml=info.get("density_g_per_ml"), + default_unit_class=info.get("default_unit_class") or "mass", + common_size_g=info.get("common_size_g"), + category=info.get("category"), + ) + lookup_cache[key] = row + return row + except Exception as exc: + app.logger.warning("forge.fetch_food_info(%r) failed: %s", key, exc) + lookup_cache[key] = None + return None lines = aggregator.aggregate(raw_ings, foods_lookup) return render_template( diff --git a/cauldron/templates/plan.html b/cauldron/templates/plan.html index b1ef3f4..a44aa18 100644 --- a/cauldron/templates/plan.html +++ b/cauldron/templates/plan.html @@ -93,9 +93,9 @@ · {{ plan.locked_at.strftime('%a %-I:%M %p') }} {% elif plan.slots %} generated{% if generated_by_display %} by {{ generated_by_display }}{% endif %}. - lock when ready — first to lock takes the week. + lock it in when the household has agreed. {% else %} - {{ pick_count }} pinned in the pool. summon the planner to build a 7-day plan, then race to lock. + {{ pick_count }} pinned in the pool. summon the planner to build a 7-day plan. {% endif %} @@ -115,15 +115,12 @@ {% if plan.locked_at %}

this week's plan is locked. it'll archive Sunday night and a fresh week opens Monday.

- {% if plan.locked_reason == 'user' and plan.locked_by_sub == current_user_sub %} -

🏆 you locked this one in.

- {% endif %} {% elif not plan.slots %}

no plan yet. summon claude to build one from the {{ pick_count }} pinned pick{{ '' if pick_count == 1 else 's' }} + the rest of the grimoire.

sonnet · ~30s
{% else %} -

plan's set. lock it in to claim the week — first to lock wins.

+

plan's set.

{% if plan.generated_by_sub == current_user_sub %} @@ -159,53 +156,6 @@ {% endif %} -
-
-

scoreboard

- picks landed · weeks won -
- - {% if streak and streak.count >= 2 %} -

- 🔥 {{ streak.display_name }} - on a {{ streak.count }}-week run. -

- {% endif %} - - {% if scoreboard and scoreboard|selectattr("points")|list or scoreboard and scoreboard|selectattr("wins")|list %} - - - - - - - - - - - {% for s in scoreboard %} - - - - - - - {% endfor %} - -
memberptswinslast
- {{ loop.index }}. - - {{ s.display_name or s.email.split('@')[0] }} - - {% if s.sub == current_user_sub %}· you{% endif %} - {{ s.points or 0 }}{{ s.wins or 0 }} - {{ s.last_win.strftime('%b %-d') if s.last_win else '—' }} -
- {% else %} -

nobody's locked or generated yet. be the first.

- {% endif %} -
-