code wiki / _hdl_build / nx_reorder_gate.nx

nx_reorder_gate.nx source

↩ module page · 139 lines · 8661 B

1// nx_reorder_gate.nx -- GATE: R-REORDER. The supply-chain management layer that closes the loop: par levels -> 2// low-stock detection -> a shopping list generated from what a meal plan consumed. Proves: T1 par set/get, 3// T2 low-stock detection (qty<par, with correct buy quantity), T3 meal-plan integration (consuming ingredients 4// drops them below par -> onto the list), T4 sovereign shopping-list render, T5 SHIPPED via publisher. 5// license_tier: ORIGINAL 6import "nx_shopping.nx" 7import "nx_pantry.nx" 8import "nx_inventory.nx" 9import "nx_food_science.nx" 10import "nx_publisher.nx" 11import "nx_syscalls.nx" 12 13const RO_FOOD: *u8 = "knowledge/store/food-" 14const RO_INV: *u8 = "knowledge/store/inv-" 15const RO_DOM: *u8 = "home" 16const RO_Q: *u8 = "knowledge/publish/shop-queue.tsv" 17const RO_LED: *u8 = "knowledge/publish/shop-ledger.tsv" 18const RO_STG: *u8 = "knowledge/publish/shop-stage" 19const RO_LIVE: *u8 = "knowledge/publish/shop-live" 20const RO_STAGE_FILE: *u8 = "knowledge/staging/shop/list.html" 21const RO_LIVE_FILE: *u8 = "knowledge/publish/shop-live/shopping-list.html" 22 23func 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 } 24func g_i(v: i64) -> i64 { 25 let bb: *u8 = sys_mmap(28); var m: i64 = v 26 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 27 let t: *u8 = sys_mmap(28); var k: i64 = 0 28 if m == 0 { t[0] = 48 as u8; k = 1 } 29 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 30 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(1, bb, k); return 0 31} 32func g_streq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 } 33func g_exists(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 } sys_close(fd); return 1 } 34// need for a given id in (ids,need)[0..n); -1 if absent 35func g_need(ids: *i64, need: *i64, n: i64, target: *u8) -> i64 { var i: i64 = 0; while i < n { if g_streq(ids[i] as *u8, target) == 1 { return need[i] } i = i + 1 } return 0 - 1 } 36 37// stock a stir-fry ingredient with par == qty (so cooking one drops it below par) 38func ro_stock(id: *u8, name: *u8, cat: *u8, qty: i64, unit: *u8) -> i64 { 39 iv_add(RO_INV, RO_DOM, id, name, cat, qty, unit, "kitchen" as *u8, 0, 0, "-" as *u8) 40 iv_set_par(RO_INV, RO_DOM, id, qty) 41 return 0 42} 43 44func main() -> i64 { 45 g_p("=== nx_reorder_gate (R-REORDER: par -> low-stock -> shopping list from a meal plan) ===\n" as *u8) 46 fd_seed(RO_FOOD) 47 48 // stir-fry ingredients (par = qty) 49 ro_stock("chicken" as *u8, "Chicken" as *u8, "protein" as *u8, 2, "lb" as *u8) 50 ro_stock("tofu" as *u8, "Tofu" as *u8, "protein" as *u8, 2, "block" as *u8) 51 ro_stock("broccoli" as *u8, "Broccoli" as *u8, "produce" as *u8, 2, "head" as *u8) 52 ro_stock("onion" as *u8, "Onion" as *u8, "produce" as *u8, 3, "ea" as *u8) 53 ro_stock("snowpea" as *u8, "Snow Peas" as *u8, "produce" as *u8, 2, "bag" as *u8) 54 ro_stock("garlic" as *u8, "Garlic" as *u8, "produce" as *u8, 2, "bulb" as *u8) 55 ro_stock("ginger" as *u8, "Ginger" as *u8, "produce" as *u8, 2, "knob" as *u8) 56 ro_stock("soy" as *u8, "Soy Sauce" as *u8, "condiment" as *u8, 2, "bottle" as *u8) 57 ro_stock("oyster" as *u8, "Oyster Sauce" as *u8, "condiment" as *u8, 2, "bottle" as *u8) 58 ro_stock("rice" as *u8, "Rice" as *u8, "grain" as *u8, 2, "bag" as *u8) 59 // household staples already low (test detection independent of cooking) 60 iv_add(RO_INV, RO_DOM, "eggs" as *u8, "Eggs" as *u8, "dairy" as *u8, 1, "dozen" as *u8, "fridge" as *u8, 0, 0, "-" as *u8); iv_set_par(RO_INV, RO_DOM, "eggs" as *u8, 3) 61 iv_add(RO_INV, RO_DOM, "milk" as *u8, "Milk" as *u8, "dairy" as *u8, 0, "carton" as *u8, "fridge" as *u8, 0, 0, "-" as *u8); iv_set_par(RO_INV, RO_DOM, "milk" as *u8, 2) 62 iv_add(RO_INV, RO_DOM, "flour" as *u8, "Flour" as *u8, "baking" as *u8, 5, "bag" as *u8, "pantry" as *u8, 0, 0, "-" as *u8); iv_set_par(RO_INV, RO_DOM, "flour" as *u8, 2) 63 64 let world: *i64 = fd_world_open(RO_FOOD) 65 let names: *i64 = world[4] as *i64 66 67 var pass: i64 = 0 68 var tot: i64 = 0 69 70 // T1 par set/get 71 tot = tot + 1 72 var ok1: i64 = 1 73 if iv_get_par(RO_INV, RO_DOM, "eggs" as *u8) != 3 { ok1 = 0 } 74 if iv_get_par(RO_INV, RO_DOM, "chicken" as *u8) != 2 { ok1 = 0 } 75 if iv_get_par(RO_INV, RO_DOM, "nope" as *u8) != 0 { ok1 = 0 } // untracked -> 0 76 if ok1 == 1 { pass = pass + 1; g_p("PASS T1 par levels set/get\n" as *u8) } else { g_p("FAIL T1\n" as *u8) } 77 78 // T2 low-stock BEFORE cooking (only the already-low staples) 79 let lid: *i64 = sys_mmap(8 * 256) as *i64 80 let lneed: *i64 = sys_mmap(8 * 256) as *i64 81 let nlo0: i64 = iv_low_stock(RO_INV, RO_DOM, lid, lneed) 82 g_p("low before cooking=" as *u8); g_i(nlo0); g_p(" (eggs need " as *u8); g_i(g_need(lid, lneed, nlo0, "eggs" as *u8)); g_p(", milk need " as *u8); g_i(g_need(lid, lneed, nlo0, "milk" as *u8)); g_p(")\n" as *u8) 83 tot = tot + 1 84 var ok2: i64 = 1 85 if nlo0 != 2 { ok2 = 0 } 86 if g_need(lid, lneed, nlo0, "eggs" as *u8) != 2 { ok2 = 0 } // par3 - qty1 87 if g_need(lid, lneed, nlo0, "milk" as *u8) != 2 { ok2 = 0 } // par2 - qty0 88 if g_need(lid, lneed, nlo0, "flour" as *u8) != (0 - 1) { ok2 = 0 } // well-stocked -> not listed 89 if ok2 == 1 { pass = pass + 1; g_p("PASS T2 low-stock detection (eggs+milk to buy, flour not)\n" as *u8) } else { g_p("FAIL T2\n" as *u8) } 90 91 // T3 cook a meal from the pantry -> consumed ingredients drop below par -> onto the reorder list 92 let avail: *i64 = sys_mmap(8 * 64) as *i64 93 fp_pantry_avail(world, RO_INV, RO_DOM, avail) 94 let b1: *i64 = sys_mmap(8 * 16) as *i64; let r1: *i64 = sys_mmap(8 * 16) as *i64 95 let nb1: i64 = fp_choose(RO_FOOD, world, avail, b1, r1) 96 g_p("cooked: " as *u8) 97 var si: i64 = 0; while si < nb1 { if si > 0 { g_p(" | " as *u8) } g_p(names[b1[si]] as *u8); si = si + 1 } g_p("\n" as *u8) 98 fp_consume_build(RO_INV, RO_DOM, world, b1, nb1) 99 let nlo1: i64 = iv_low_stock(RO_INV, RO_DOM, lid, lneed) 100 g_p("low after cooking=" as *u8); g_i(nlo1); g_p("\n" as *u8) 101 let widx: *i64 = world[1] as *i64 102 let protein_id: *u8 = widx[b1[0]] as *u8 103 g_p(" cooked protein id=" as *u8); g_p(protein_id); g_p(" need=" as *u8); g_i(g_need(lid, lneed, nlo1, protein_id)); g_p("\n" as *u8) 104 tot = tot + 1 105 var ok3: i64 = 1 106 if nb1 != 5 { ok3 = 0 } 107 if nlo1 != 7 { ok3 = 0 } // 2 staples + 5 cooked ingredients 108 if g_need(lid, lneed, nlo1, protein_id) != 1 { ok3 = 0 } // cooked protein now short by 1 109 if ok3 == 1 { pass = pass + 1; g_p("PASS T3 meal -> reorder: cooking dropped 5 ingredients below par (low 2 -> 7)\n" as *u8) } else { g_p("FAIL T3 nlo1=" as *u8); g_i(nlo1); g_p("\n" as *u8) } 110 111 // T4 render the shopping list (sovereign, lists low items + buy quantities) 112 let page: *u8 = sys_mmap(65536) 113 let np: i64 = sh_render_list(RO_INV, RO_DOM, "Your shopping list" as *u8, page) 114 tot = tot + 1 115 var ok4: i64 = 1 116 if as_has_thirdparty_js(page, np) != 0 { ok4 = 0 } 117 if as_contains(page, np, "Milk" as *u8) != 1 { ok4 = 0 } 118 if as_contains(page, np, names[b1[0]] as *u8) != 1 { ok4 = 0 } // cooked protein on the list 119 if as_contains(page, np, "Buy 7 item" as *u8) != 1 { ok4 = 0 } 120 if ok4 == 1 { pass = pass + 1; g_p("PASS T4 sovereign shopping list (" as *u8); g_i(np); g_p(" bytes, 7 items, 0 JS)\n" as *u8) } else { g_p("FAIL T4\n" as *u8) } 121 122 // T5 ship via the publisher 123 sys_mkdir("knowledge/staging" as *u8, 0x1ed) 124 sys_mkdir("knowledge/staging/shop" as *u8, 0x1ed) 125 let sfd: i64 = sys_openat_wr(RO_STAGE_FILE, 420); if sfd >= 0 { sys_write(sfd, page, np); sys_close(sfd) } 126 pub_init() 127 sys_mkdir(RO_STG, 0x1ed) 128 sys_mkdir(RO_LIVE, 0x1ed) 129 pub_submit_to(RO_Q, RO_STAGE_FILE, "shopping-list.html" as *u8, "nishifamily" as *u8, "nishi-home" as *u8, "internal" as *u8) 130 let pubd: i64 = pub_run_full(RO_Q, RO_LED, RO_STG, RO_LIVE, "publish:shop" as *u8) 131 g_p(" pub_run_full -> published_this_pass=" as *u8); g_i(pubd); g_p("\n" as *u8) 132 tot = tot + 1 133 if g_exists(RO_LIVE_FILE) == 1 { pass = pass + 1; g_p("PASS T5 SHIPPED the shopping list to liveroot\n" as *u8) } else { g_p("FAIL T5\n" as *u8) } 134 135 g_p("nx_reorder_gate pass=" as *u8); g_i(pass); g_p("/" as *u8); g_i(tot) 136 if pass == tot { g_p(" verdict=GREEN (supply-chain loop CLOSED: consume -> low-stock -> shopping list -> shipped)\n" as *u8); return 0 } 137 g_p(" verdict=RED\n" as *u8) 138 return 1 139}