code wiki / _hdl_build / nx_pantry_meal_gate.nx

nx_pantry_meal_gate.nx source

↩ module page · 132 lines · 8015 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" 10import "nx_gate_verdict.nx" 11 12const PM_FOOD: *u8 = "knowledge/store/food-" 13const PM_INV: *u8 = "knowledge/store/inv-" 14const PM_DOM: *u8 = "kitchen" 15const PM_CAT: *u8 = "knowledge/registry/nishi_builder.tsv" 16 17func 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 } 18func g_i(v: i64) -> i64 { 19 let bb: *u8 = sys_mmap(28); var m: i64 = v 20 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 21 let t: *u8 = sys_mmap(28); var k: i64 = 0 22 if m == 0 { t[0] = 48 as u8; k = 1 } 23 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 24 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(1, bb, k); return 0 25} 26func g_show(world: *i64, build: *i64, nb: i64) -> i64 { 27 let names: *i64 = world[4] as *i64 28 var i: i64 = 0 29 while i < nb { if i > 0 { g_p(" | " as *u8) } g_p(names[build[i]] as *u8); i = i + 1 } 30 g_p("\n" as *u8); return 0 31} 32 33func main() -> i64 { 34 g_p("=== nx_pantry_meal_gate (pantry -> what's expiring -> what can I make -> meal plan) ===\n" as *u8) 35 fd_seed(PM_FOOD) 36 fs_teach(PM_CAT) 37 38 // stock the kitchen (today = day 0; chicken/tofu expiring, beef fresh) 39 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) 40 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) 41 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) 42 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) 43 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) 44 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) 45 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) 46 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) 47 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) 48 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) 49 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) 50 51 let world: *i64 = fd_world_open(PM_FOOD) 52 let n: i64 = world[0] 53 let ids: *i64 = world[1] as *i64 54 let names: *i64 = world[4] as *i64 55 56 var pass: i64 = 0 57 var tot: i64 = 0 58 59 // T1 "what can I make" from in-stock ingredients only 60 let avail: *i64 = sys_mmap(8 * 64) as *i64 61 let nav: i64 = fp_pantry_avail(world, PM_INV, PM_DOM, avail) 62 let b1: *i64 = sys_mmap(8 * 16) as *i64; let r1: *i64 = sys_mmap(8 * 16) as *i64 63 let nb1: i64 = fp_choose(PM_FOOD, world, avail, b1, r1) 64 g_p("in-stock ingredients=" as *u8); g_i(nav); g_p(" -> tonight: " as *u8); g_show(world, b1, nb1) 65 tot = tot + 1 66 var ok1: i64 = 1 67 if nb1 != 5 { ok1 = 0 } 68 var t1i: i64 = 0 69 while t1i < nb1 { if iv_qty(PM_INV, PM_DOM, ids[b1[t1i]] as *u8) <= 0 { ok1 = 0 } t1i = t1i + 1 } 70 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) } 71 72 // T2 cook-what's-expiring-first: forces an expiring protein over fresh Beef 73 let avexp: *i64 = sys_mmap(8 * 64) as *i64 74 fp_expiring_first(world, PM_INV, PM_DOM, PM_FOOD, 0, 3, avail, avexp) 75 let be: *i64 = sys_mmap(8 * 16) as *i64; let re: *i64 = sys_mmap(8 * 16) as *i64 76 let nbe: i64 = fp_choose(PM_FOOD, world, avexp, be, re) 77 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) 78 tot = tot + 1 79 var ok2: i64 = 1 80 if nbe != 5 { ok2 = 0 } 81 if fp_is_expiring(PM_INV, PM_DOM, ids[be[0]] as *u8, 0, 3) != 1 { ok2 = 0 } 82 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) } 83 84 // T3 sovereign "Your Kitchen" page from the pantry 85 let avoid: *i64 = sys_mmap(8 * 64) as *i64 86 let prefw: *i64 = sys_mmap(8 * 8) as *i64 87 fd_set_all(avoid, n, 0) 88 var z: i64 = 0; while z < FOOD_NAX { prefw[z] = 0; z = z + 1 } 89 let page: *u8 = sys_mmap(65536) 90 let np: i64 = fs_render_avail(PM_FOOD, PM_CAT, "Your Kitchen" as *u8, avail, avoid, prefw, page) 91 tot = tot + 1 92 var ok3: i64 = 1 93 if as_has_thirdparty_js(page, np) != 0 { ok3 = 0 } 94 if as_contains(page, np, names[b1[0]] as *u8) != 1 { ok3 = 0 } 95 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) } 96 97 // T4 meal plan: 2 meals, consuming inventory 98 let q0: i64 = fp_total_qty(PM_INV, PM_DOM) 99 // meal 1 100 let m1: *i64 = sys_mmap(8 * 64) as *i64; fp_pantry_avail(world, PM_INV, PM_DOM, m1) 101 let m1e: *i64 = sys_mmap(8 * 64) as *i64; fp_expiring_first(world, PM_INV, PM_DOM, PM_FOOD, 0, 3, m1, m1e) 102 let mb1: *i64 = sys_mmap(8 * 16) as *i64; let mr1: *i64 = sys_mmap(8 * 16) as *i64 103 let nm1: i64 = fp_choose(PM_FOOD, world, m1e, mb1, mr1) 104 g_p(" meal 1: " as *u8); g_show(world, mb1, nm1) 105 fp_consume_build(PM_INV, PM_DOM, world, mb1, nm1) 106 // meal 2 (pantry now depleted) 107 let m2: *i64 = sys_mmap(8 * 64) as *i64; fp_pantry_avail(world, PM_INV, PM_DOM, m2) 108 let m2e: *i64 = sys_mmap(8 * 64) as *i64; fp_expiring_first(world, PM_INV, PM_DOM, PM_FOOD, 0, 3, m2, m2e) 109 let mb2: *i64 = sys_mmap(8 * 16) as *i64; let mr2: *i64 = sys_mmap(8 * 16) as *i64 110 let nm2: i64 = fp_choose(PM_FOOD, world, m2e, mb2, mr2) 111 g_p(" meal 2: " as *u8); g_show(world, mb2, nm2) 112 fp_consume_build(PM_INV, PM_DOM, world, mb2, nm2) 113 let q2: i64 = fp_total_qty(PM_INV, PM_DOM) 114 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) 115 tot = tot + 1 116 var ok4: i64 = 1 117 if nm1 != 5 { ok4 = 0 } 118 if nm2 != 5 { ok4 = 0 } 119 if q0 - q2 != 10 { ok4 = 0 } 120 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) } 121 122 g_p("nx_pantry_meal_gate pass=" as *u8); g_i(pass); g_p("/" as *u8); g_i(tot) 123 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 124 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 125 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 126 let ctr__dry: *i64 = gv_ctr() 127 ctr__dry[0] = pass 128 ctr__dry[1] = tot 129 let rc__dry: i64 = gv_verdict("PANTRY-MEAL-GATE" as *u8, ctr__dry, "pantry -> expiry -> what can I make -> meal plan, inventory consumed)" as *u8) 130 sys_exit(rc__dry) 131 return rc__dry 132}