code wiki / _hdl_build / nx_pantry_meal_gate.nx

nx_pantry_meal_gate.nx source

↩ module page · 125 lines · 7615 B

1// nx_pantry_meal_gate.nx -- GATE: the pantry -> food-engine integration (the operator's chain: pantry -> 2// what's expiring -> what can I make -> meal planning). Proves: T1 "what can I make" builds a complete 3// stir-fry from ONLY in-stock ingredients, T2 "cook what's expiring first" forces an expiring protein 4// (Chicken/Tofu) over a fresh one (Beef), T3 a sovereign no-JS "Your Kitchen" page renders from the pantry, 5// T4 a 2-meal plan CONSUMES inventory (stock drops by exactly 2 meals x 5 ingredients). license_tier: ORIGINAL 6import "nx_pantry.nx" 7import "nx_food_site.nx" 8import "nx_inventory.nx" 9import "nx_syscalls.nx" 10 11const PM_FOOD: *u8 = "knowledge/store/food-" 12const PM_INV: *u8 = "knowledge/store/inv-" 13const PM_DOM: *u8 = "kitchen" 14const PM_CAT: *u8 = "knowledge/registry/nishi_builder.tsv" 15 16func g_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 17func g_i(v: i64) -> i64 { 18 let bb: *u8 = sys_mmap(28); var m: i64 = v 19 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 20 let t: *u8 = sys_mmap(28); var k: i64 = 0 21 if m == 0 { t[0] = 48 as u8; k = 1 } 22 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 23 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(1, bb, k); return 0 24} 25func g_show(world: *i64, build: *i64, nb: i64) -> i64 { 26 let names: *i64 = world[4] as *i64 27 var i: i64 = 0 28 while i < nb { if i > 0 { g_p(" | " as *u8) } g_p(names[build[i]] as *u8); i = i + 1 } 29 g_p("\n" as *u8); return 0 30} 31 32func main() -> i64 { 33 g_p("=== nx_pantry_meal_gate (pantry -> what's expiring -> what can I make -> meal plan) ===\n" as *u8) 34 fd_seed(PM_FOOD) 35 fs_teach(PM_CAT) 36 37 // stock the kitchen (today = day 0; chicken/tofu expiring, beef fresh) 38 iv_add(PM_INV, PM_DOM, "beef" as *u8, "Beef" as *u8, "protein" as *u8, 1, "lb" as *u8, "fridge" as *u8, 0, 30, "" as *u8) 39 iv_add(PM_INV, PM_DOM, "chicken" as *u8, "Chicken" as *u8, "protein" as *u8, 2, "lb" as *u8, "fridge" as *u8, 0, 3, "" as *u8) 40 iv_add(PM_INV, PM_DOM, "tofu" as *u8, "Tofu" as *u8, "protein" as *u8, 1, "block" as *u8, "fridge" as *u8, 0, 2, "" as *u8) 41 iv_add(PM_INV, PM_DOM, "broccoli" as *u8, "Broccoli" as *u8, "veg" as *u8, 2, "head" as *u8, "fridge" as *u8, 0, 5, "" as *u8) 42 iv_add(PM_INV, PM_DOM, "onion" as *u8, "Onion" as *u8, "veg" as *u8, 3, "ea" as *u8, "pantry" as *u8, 0, 20, "" as *u8) 43 iv_add(PM_INV, PM_DOM, "snowpea" as *u8, "Snow Peas" as *u8, "veg" as *u8, 2, "bag" as *u8, "fridge" as *u8, 0, 6, "" as *u8) 44 iv_add(PM_INV, PM_DOM, "garlic" as *u8, "Garlic" as *u8, "aromatic" as *u8, 2, "bulb" as *u8, "pantry" as *u8, 0, 60, "" as *u8) 45 iv_add(PM_INV, PM_DOM, "ginger" as *u8, "Ginger" as *u8, "aromatic" as *u8, 2, "knob" as *u8, "fridge" as *u8, 0, 14, "" as *u8) 46 iv_add(PM_INV, PM_DOM, "soy" as *u8, "Soy Sauce" as *u8, "sauce" as *u8, 2, "bottle" as *u8, "pantry" as *u8, 0, 365, "" as *u8) 47 iv_add(PM_INV, PM_DOM, "oyster" as *u8, "Oyster Sauce" as *u8, "sauce" as *u8, 1, "bottle" as *u8, "pantry" as *u8, 0, 200, "" as *u8) 48 iv_add(PM_INV, PM_DOM, "rice" as *u8, "Rice" as *u8, "starch" as *u8, 2, "bag" as *u8, "pantry" as *u8, 0, 0, "" as *u8) 49 50 let world: *i64 = fd_world_open(PM_FOOD) 51 let n: i64 = world[0] 52 let ids: *i64 = world[1] as *i64 53 let names: *i64 = world[4] as *i64 54 55 var pass: i64 = 0 56 var tot: i64 = 0 57 58 // T1 "what can I make" from in-stock ingredients only 59 let avail: *i64 = sys_mmap(8 * 64) as *i64 60 let nav: i64 = fp_pantry_avail(world, PM_INV, PM_DOM, avail) 61 let b1: *i64 = sys_mmap(8 * 16) as *i64; let r1: *i64 = sys_mmap(8 * 16) as *i64 62 let nb1: i64 = fp_choose(PM_FOOD, world, avail, b1, r1) 63 g_p("in-stock ingredients=" as *u8); g_i(nav); g_p(" -> tonight: " as *u8); g_show(world, b1, nb1) 64 tot = tot + 1 65 var ok1: i64 = 1 66 if nb1 != 5 { ok1 = 0 } 67 var t1i: i64 = 0 68 while t1i < nb1 { if iv_qty(PM_INV, PM_DOM, ids[b1[t1i]] as *u8) <= 0 { ok1 = 0 } t1i = t1i + 1 } 69 if ok1 == 1 { pass = pass + 1; g_p("PASS T1 what-can-I-make: a complete stir-fry from only what's in stock\n" as *u8) } else { g_p("FAIL T1\n" as *u8) } 70 71 // T2 cook-what's-expiring-first: forces an expiring protein over fresh Beef 72 let avexp: *i64 = sys_mmap(8 * 64) as *i64 73 fp_expiring_first(world, PM_INV, PM_DOM, PM_FOOD, 0, 3, avail, avexp) 74 let be: *i64 = sys_mmap(8 * 16) as *i64; let re: *i64 = sys_mmap(8 * 16) as *i64 75 let nbe: i64 = fp_choose(PM_FOOD, world, avexp, be, re) 76 g_p("normal protein=" as *u8); g_p(names[b1[0]] as *u8); g_p(" expiring-first protein=" as *u8); g_p(names[be[0]] as *u8); g_p("\n" as *u8) 77 tot = tot + 1 78 var ok2: i64 = 1 79 if nbe != 5 { ok2 = 0 } 80 if fp_is_expiring(PM_INV, PM_DOM, ids[be[0]] as *u8, 0, 3) != 1 { ok2 = 0 } 81 if ok2 == 1 { pass = pass + 1; g_p("PASS T2 expiring-first: the meal uses a soon-to-expire protein (cut waste)\n" as *u8) } else { g_p("FAIL T2\n" as *u8) } 82 83 // T3 sovereign "Your Kitchen" page from the pantry 84 let avoid: *i64 = sys_mmap(8 * 64) as *i64 85 let prefw: *i64 = sys_mmap(8 * 8) as *i64 86 fd_set_all(avoid, n, 0) 87 var z: i64 = 0; while z < FOOD_NAX { prefw[z] = 0; z = z + 1 } 88 let page: *u8 = sys_mmap(65536) 89 let np: i64 = fs_render_avail(PM_FOOD, PM_CAT, "Your Kitchen" as *u8, avail, avoid, prefw, page) 90 tot = tot + 1 91 var ok3: i64 = 1 92 if as_has_thirdparty_js(page, np) != 0 { ok3 = 0 } 93 if as_contains(page, np, names[b1[0]] as *u8) != 1 { ok3 = 0 } 94 if ok3 == 1 { pass = pass + 1; g_p("PASS T3 sovereign 'Your Kitchen' page rendered from the pantry (" as *u8); g_i(np); g_p(" bytes, 0 JS)\n" as *u8) } else { g_p("FAIL T3\n" as *u8) } 95 96 // T4 meal plan: 2 meals, consuming inventory 97 let q0: i64 = fp_total_qty(PM_INV, PM_DOM) 98 // meal 1 99 let m1: *i64 = sys_mmap(8 * 64) as *i64; fp_pantry_avail(world, PM_INV, PM_DOM, m1) 100 let m1e: *i64 = sys_mmap(8 * 64) as *i64; fp_expiring_first(world, PM_INV, PM_DOM, PM_FOOD, 0, 3, m1, m1e) 101 let mb1: *i64 = sys_mmap(8 * 16) as *i64; let mr1: *i64 = sys_mmap(8 * 16) as *i64 102 let nm1: i64 = fp_choose(PM_FOOD, world, m1e, mb1, mr1) 103 g_p(" meal 1: " as *u8); g_show(world, mb1, nm1) 104 fp_consume_build(PM_INV, PM_DOM, world, mb1, nm1) 105 // meal 2 (pantry now depleted) 106 let m2: *i64 = sys_mmap(8 * 64) as *i64; fp_pantry_avail(world, PM_INV, PM_DOM, m2) 107 let m2e: *i64 = sys_mmap(8 * 64) as *i64; fp_expiring_first(world, PM_INV, PM_DOM, PM_FOOD, 0, 3, m2, m2e) 108 let mb2: *i64 = sys_mmap(8 * 16) as *i64; let mr2: *i64 = sys_mmap(8 * 16) as *i64 109 let nm2: i64 = fp_choose(PM_FOOD, world, m2e, mb2, mr2) 110 g_p(" meal 2: " as *u8); g_show(world, mb2, nm2) 111 fp_consume_build(PM_INV, PM_DOM, world, mb2, nm2) 112 let q2: i64 = fp_total_qty(PM_INV, PM_DOM) 113 g_p(" pantry stock: " as *u8); g_i(q0); g_p(" -> " as *u8); g_i(q2); g_p(" units after 2 meals\n" as *u8) 114 tot = tot + 1 115 var ok4: i64 = 1 116 if nm1 != 5 { ok4 = 0 } 117 if nm2 != 5 { ok4 = 0 } 118 if q0 - q2 != 10 { ok4 = 0 } 119 if ok4 == 1 { pass = pass + 1; g_p("PASS T4 meal plan: 2 meals cooked, inventory consumed (10 units depleted)\n" as *u8) } else { g_p("FAIL T4 (q0=" as *u8); g_i(q0); g_p(" q2=" as *u8); g_i(q2); g_p(" nm1=" as *u8); g_i(nm1); g_p(" nm2=" as *u8); g_i(nm2); g_p(")\n" as *u8) } 120 121 g_p("nx_pantry_meal_gate pass=" as *u8); g_i(pass); g_p("/" as *u8); g_i(tot) 122 if pass == tot { g_p(" verdict=GREEN (pantry -> expiry -> what can I make -> meal plan, inventory consumed)\n" as *u8); return 0 } 123 g_p(" verdict=RED\n" as *u8) 124 return 1 125}