// ---- unite -> facteur (mL pour volumes, g pour masses) ; absente => non convertible ----
var UNIT = new Dictionary<string, (double factor, bool isMass)>
{
["cup"] = (236.588, false), ["cups"] = (236.588, false),
["tablespoon"] = (14.7868, false), ["tablespoons"] = (14.7868, false), ["tbsp"] = (14.7868, false), ["tbs"] = (14.7868, false),
["teaspoon"] = (4.92892, false), ["teaspoons"] = (4.92892, false), ["tsp"] = (4.92892, false),
["ounce"] = (28.3495, true), ["ounces"] = (28.3495, true), ["oz"] = (28.3495, true),
["pound"] = (453.592, true), ["pounds"] = (453.592, true), ["lb"] = (453.592, true), ["lbs"] = (453.592, true),
["gram"] = (1, true), ["grams"] = (1, true), ["g"] = (1, true), ["kg"] = (1000, true), ["kilogram"] = (1000, true),
["ml"] = (1, false), ["milliliter"] = (1, false), ["millilitre"] = (1, false),
["l"] = (1000, false), ["liter"] = (1000, false), ["litre"] = (1000, false),
["pint"] = (473.176, false), ["pt"] = (473.176, false), ["quart"] = (946.353, false), ["qt"] = (946.353, false),
["gallon"] = (3785.41, false), ["gal"] = (3785.41, false),
["pinch"] = (0.36, true), ["dash"] = (0.6, false), ["stick"] = (113.0, true), ["sticks"] = (113.0, true),
};
// densite (g/mL) par mot-cle present dans l'item ; defaut 1.0 (eau/aqueux)
var DENS = new (string kw, double d)[]
{
("flour", 0.53), ("sugar", 0.85), ("oil", 0.92), ("butter", 0.911), ("honey", 1.42), ("syrup", 1.33),
("milk", 1.03), ("cream", 1.01), ("water", 1.0), ("salt", 1.22), ("rice", 0.85), ("cocoa", 0.52),
("cornstarch", 0.54), ("oats", 0.41),
};
double Density(string itemLower) { foreach (var (kw, d) in DENS) if (itemLower.Contains(kw)) return d; return 1.0; }
// items COMPTES (unite vide : "2 Eggs", "3 Bananas") -> poids moyen par piece, par mot-cle de tete
var COUNT = new (string kw, double g)[]
{
("egg", 50), ("banana", 120), ("apple", 180), ("onion", 110), ("clove", 5), ("carrot", 60),
("potato", 150), ("tomato", 120), ("lemon", 60), ("lime", 45), ("orange", 130), ("garlic", 5),
("shallot", 30), ("scallion", 15), ("pepper", 120),
};
double CountWeight(string itemLower) { foreach (var (kw, g) in COUNT) if (itemLower.Contains(kw)) return g; return 0; }
// (qty, unite, item) -> grammes ; unite vide => item compte (table COUNT) ; unite inconnue => 0
double ToGrams(double qty, string unit, string itemLower)
{
if (qty <= 0) return 0;
if (unit.Length == 0) { double cw = CountWeight(itemLower); return cw > 0 ? qty * cw : 0; } // "2 Eggs" -> 100 g
if (!UNIT.TryGetValue(unit, out var u)) return 0; // "1 can" -> non convertible
return u.isMass ? qty * u.factor : qty * u.factor * Density(itemLower);
}
// demonstration
foreach (var (q, u, it) in new[] { (2.0, "cups", "white sugar"), (2.0, "cups", "flour"),
(1.0, "teaspoon", "vanilla"), (4.0, "ounces", "butter"), (2.0, "", "eggs"), (1.0, "can", "crushed pineapple") })
Console.WriteLine($" {q} {(u.Length == 0 ? "(compte)" : u),-10} {it,-18} -> {ToGrams(q, u, it):F1} g" +
(ToGrams(q, u, it) == 0 ? " (non convertible)" : ""));