code wiki / _hdl_build / nx_pantry.nx

nx_pantry.nx source

↩ module page · 105 lines · 4714 B

1// nx_pantry.nx -- LIB: bridges the universal INVENTORY (a person's pantry stock) to the FOOD-SCIENCE engine. 2// "What can I make" = run the chooser over ONLY the ingredients you actually have (qty>0); "cook what's 3// expiring first" = bias the build toward soon-to-expire items to cut waste; "meal planning" = choose a meal 4// then CONSUME its ingredients from inventory so the next meal sees the depleted pantry. One engine, two 5// stores: the food store (knowledge/store/food-) holds the science; the inventory store holds the stock. 6// license_tier: ORIGINAL 7import "nx_inventory.nx" 8import "nx_food_science.nx" 9import "nx_syscalls.nx" 10 11// 1 if a pantry item is expiring within `within` days of `as_of` (0 expiry = non-perishable -> 0) 12func fp_is_expiring(inv_prefix: *u8, domain: *u8, id: *u8, as_of: i64, within: i64) -> i64 { 13 let e: i64 = iv_expiry(inv_prefix, domain, id) 14 if e > 0 { if e <= as_of + within { return 1 } } 15 return 0 16} 17 18// availability over the food world from the pantry: avail[i]=1 iff that ingredient is in stock (qty>0). 19// Returns the number of in-stock ingredients. 20func fp_pantry_avail(food_world: *i64, inv_prefix: *u8, domain: *u8, avail: *i64) -> i64 { 21 let n: i64 = food_world[0] 22 let ids: *i64 = food_world[1] as *i64 23 var c: i64 = 0 24 var i: i64 = 0 25 while i < n { 26 if iv_qty(inv_prefix, domain, ids[i] as *u8) > 0 { avail[i] = 1; c = c + 1 } else { avail[i] = 0 } 27 i = i + 1 28 } 29 return c 30} 31 32func fp_quota(frame: *i64, nframe: i64, rc: i64) -> i64 { 33 var c: i64 = 0 34 var i: i64 = 0 35 while i < nframe { if frame[i] == rc { c = c + 1 } i = i + 1 } 36 return c 37} 38 39// "cook what's expiring first": for each role with at least `quota` in-stock EXPIRING members, restrict that 40// role to its expiring members (so the build uses them up); other roles unchanged. Never makes a role 41// unfillable (only restricts when enough expiring members exist to meet the quota). Writes into avail_out. 42func fp_expiring_first(food_world: *i64, inv_prefix: *u8, domain: *u8, food_prefix: *u8, as_of: i64, within: i64, avail_in: *i64, avail_out: *i64) -> i64 { 43 let n: i64 = food_world[0] 44 let ids: *i64 = food_world[1] as *i64 45 let role: *i64 = food_world[2] as *i64 46 let frame: *i64 = sys_mmap(8 * 16) as *i64 47 let nframe: i64 = fd_load_frame(food_prefix, frame) 48 var i: i64 = 0 49 while i < n { avail_out[i] = avail_in[i]; i = i + 1 } 50 var rc: i64 = 1 51 while rc <= 4 { 52 let quota: i64 = fp_quota(frame, nframe, rc) 53 if quota > 0 { 54 var expcount: i64 = 0 55 i = 0 56 while i < n { 57 if role[i] == rc { if avail_in[i] == 1 { if fp_is_expiring(inv_prefix, domain, ids[i] as *u8, as_of, within) == 1 { expcount = expcount + 1 } } } 58 i = i + 1 59 } 60 if expcount >= quota { 61 i = 0 62 while i < n { 63 if role[i] == rc { if avail_in[i] == 1 { 64 if fp_is_expiring(inv_prefix, domain, ids[i] as *u8, as_of, within) == 1 { avail_out[i] = 1 } else { avail_out[i] = 0 } 65 } } 66 i = i + 1 67 } 68 } 69 } 70 rc = rc + 1 71 } 72 return 0 73} 74 75// consume one unit of every ingredient in a finished build from the pantry (meal cooked) 76func fp_consume_build(inv_prefix: *u8, domain: *u8, food_world: *i64, build: *i64, nb: i64) -> i64 { 77 let ids: *i64 = food_world[1] as *i64 78 var i: i64 = 0 79 while i < nb { iv_consume(inv_prefix, domain, ids[build[i]] as *u8, 1); i = i + 1 } 80 return 0 81} 82 83// total units of stock across the pantry domain (to show depletion across a meal plan) 84func fp_total_qty(inv_prefix: *u8, domain: *u8) -> i64 { 85 let items: *i64 = sys_mmap(8 * 256) as *i64 86 let n: i64 = iv_list(inv_prefix, domain, items) 87 var t: i64 = 0 88 var i: i64 = 0 89 while i < n { let q: i64 = iv_qty(inv_prefix, domain, items[i] as *u8); if q > 0 { t = t + q } i = i + 1 } 90 return t 91} 92 93// choose a meal over an availability mask (neutral preference); fills build/roles, returns slots filled 94func fp_choose(food_prefix: *u8, food_world: *i64, avail: *i64, build: *i64, roles: *i64) -> i64 { 95 let n: i64 = food_world[0] 96 let avoid: *i64 = sys_mmap(8 * 64) as *i64 97 let prefw: *i64 = sys_mmap(8 * 8) as *i64 98 fd_set_all(avoid, n, 0) 99 var z: i64 = 0; while z < FOOD_NAX { prefw[z] = 0; z = z + 1 } 100 let frame: *i64 = sys_mmap(8 * 16) as *i64 101 let nframe: i64 = fd_load_frame(food_prefix, frame) 102 let wts: *i64 = sys_mmap(8 * 8) as *i64 103 fd_load_weights(food_prefix, wts) 104 return fd_choose(food_world, avail, avoid, prefw, frame, nframe, wts, build, roles) 105}