code wiki / _hdl_build / nx_food_menu.nx

nx_food_menu.nx source

↩ module page · 172 lines · 9352 B

1// nx_food_menu.nx -- LIB: per-RESTAURANT availability (the original ask -- "the best stir-fry from the 2// ingredients/options at THEIR local restaurant"). Each restaurant is a record in the store (name, blurb, 3// available-ingredient list); the chooser runs against ONLY that restaurant's menu, so different restaurants 4// yield different recommendations. Also renders a sovereign no-JS directory page. Builds on nx_food_site 5// (fs_render_avail). license_tier: ORIGINAL 6import "nx_food_site.nx" 7import "nx_food_science.nx" 8import "nx_seg_store.nx" 9import "nx_syscalls.nx" 10const K_MAGIC_1024: i64 = 1024 11 12// seed the restaurant records (idempotent). Schema: food:rest:<id> -> name <t> blurb <t> space-separated 13// available ingredient ids; food:restids -> TAB list of restaurant ids. 14func fd_seed_restaurants(prefix: *u8) -> i64 { 15 let keys: *i64 = sys_mmap(8 * 16) as *i64 16 let vals: *i64 = sys_mmap(8 * 16) as *i64 17 var n: i64 = 0 18 keys[n] = "food:restids" as *u8 as i64 19 vals[n] = "goldenwok\tmongoliangrill\tgreenwok\tspicehouse" as *u8 as i64; n = n + 1 20 keys[n] = "food:rest:goldenwok" as *u8 as i64 21 vals[n] = "Golden Wok\tClassic Cantonese-style stir-fry\tbeef chicken tofu broccoli bellpepper onion mushroom garlic ginger scallion soy oyster hoisin" as *u8 as i64; n = n + 1 22 keys[n] = "food:rest:mongoliangrill" as *u8 as i64 23 vals[n] = "Khan's Mongolian Grill\tBuild-your-own Mongolian BBQ bar\tbeef pork chicken tofu broccoli carrot onion snowpea beansprout mushroom garlic ginger chili scallion soy oyster blackbean sweetchili" as *u8 as i64; n = n + 1 24 keys[n] = "food:rest:greenwok" as *u8 as i64 25 vals[n] = "Green Wok\tTofu and vegetable focused, no red meat\ttofu shrimp broccoli bellpepper carrot snowpea mushroom bokchoy beansprout garlic ginger scallion soy hoisin blackbean" as *u8 as i64; n = n + 1 26 keys[n] = "food:rest:spicehouse" as *u8 as i64 27 vals[n] = "Sichuan Spice House\tFiery Sichuan heat\tbeef pork chicken tofu bellpepper onion mushroom garlic ginger chili scallion soy blackbean sweetchili" as *u8 as i64; n = n + 1 28 29 let w: *i64 = ss_begin() 30 var towrite: i64 = 0 31 var i: i64 = 0 32 while i < n { 33 let key: *u8 = keys[i] as *u8 34 let val: *u8 = vals[i] as *u8 35 let vl: i64 = as_len(val) 36 if fd_streq_store(prefix, key, val, vl) == 0 { ss_add(w, 1, key, val, vl); towrite = towrite + 1 } 37 i = i + 1 38 } 39 if towrite > 0 { let seg: i64 = fd_seg_next(prefix); ss_commit(prefix, w, seg) } 40 return towrite 41} 42 43// build an availability mask from a space-separated ingredient-id list; returns the number recognised. 44func fs_avail_from_idlist(world: *i64, listbuf: *u8, listlen: i64, avail: *i64) -> i64 { 45 let n: i64 = world[0] 46 fd_set_all(avail, n, 0) 47 var i: i64 = 0 48 var ls: i64 = 0 49 var recog: i64 = 0 50 while i <= listlen { 51 var sep: i64 = 0 52 if i == listlen { sep = 1 } else { if listbuf[i] == (32 as u8) { sep = 1 } } 53 if sep == 1 { 54 let tl: i64 = i - ls 55 if tl > 0 { 56 let tok: *u8 = sys_mmap(48) 57 var t: i64 = 0 58 while t < tl { tok[t] = listbuf[ls + t]; t = t + 1 } 59 tok[tl] = 0 as u8 60 if fd_set_id(world, avail, tok, 1) == 1 { recog = recog + 1 } 61 } 62 ls = i + 1 63 } 64 i = i + 1 65 } 66 return recog 67} 68 69// fill avail[] for restaurant `rest_id` and copy its display name into name_out; 1 if found, 0 if not. 70func fs_restaurant_avail(store_prefix: *u8, rest_id: *u8, avail: *i64, name_out: *u8) -> i64 { 71 let key: *u8 = sys_mmap(80) 72 var o: i64 = 0 73 o = as_append(key, o, "food:rest:" as *u8) 74 o = as_append(key, o, rest_id) 75 key[o] = 0 as u8 76 let pq: *i64 = sys_mmap(16) as *i64 77 let lq: *i64 = sys_mmap(16) as *i64 78 if ss_get(store_prefix, key, pq, lq) != 1 { return 0 } 79 let rec: *u8 = pq[0] as *u8 80 let rl: i64 = lq[0] 81 fd_field(rec, rl, 0, name_out) 82 let availlist: *u8 = sys_mmap(512) 83 let all_len: i64 = fd_field(rec, rl, 2, availlist) 84 let world: *i64 = fd_world_open(store_prefix) 85 fs_avail_from_idlist(world, availlist, all_len, avail) 86 return 1 87} 88 89// render a per-restaurant recommendation page (only that restaurant's menu available, neutral preference). 90// Returns byte length, or 0 if the restaurant id is unknown. 91func fs_render_restaurant(store_prefix: *u8, catpath: *u8, rest_id: *u8, out: *u8) -> i64 { 92 let avail: *i64 = sys_mmap(8 * 64) as *i64 93 let avoid: *i64 = sys_mmap(8 * 64) as *i64 94 let prefw: *i64 = sys_mmap(8 * 8) as *i64 95 let name: *u8 = sys_mmap(128) 96 if fs_restaurant_avail(store_prefix, rest_id, avail, name) == 0 { return 0 } 97 let world: *i64 = fd_world_open(store_prefix) 98 fd_set_all(avoid, world[0], 0) 99 var z: i64 = 0; while z < FOOD_NAX { prefw[z] = 0; z = z + 1 } 100 return fs_render_avail(store_prefix, catpath, name, avail, avoid, prefw, out) 101} 102 103// emit one restaurant card (link to <id>.html) into out at off; returns new off 104func fs_dir_card(store_prefix: *u8, rest_id: *u8, out: *u8, off: i64) -> i64 { 105 let key: *u8 = sys_mmap(80) 106 var ko: i64 = 0 107 ko = as_append(key, ko, "food:rest:" as *u8) 108 ko = as_append(key, ko, rest_id) 109 key[ko] = 0 as u8 110 let pq: *i64 = sys_mmap(16) as *i64 111 let lq: *i64 = sys_mmap(16) as *i64 112 if ss_get(store_prefix, key, pq, lq) != 1 { return off } 113 let rec: *u8 = pq[0] as *u8 114 let rl: i64 = lq[0] 115 let nm: *u8 = sys_mmap(128); fd_field(rec, rl, 0, nm) 116 let bl: *u8 = sys_mmap(256); fd_field(rec, rl, 1, bl) 117 var o: i64 = off 118 o = as_append(out, o, "<a class='rcard' href='" as *u8) 119 o = as_append(out, o, rest_id) 120 o = as_append(out, o, ".html'><h3>" as *u8) 121 o = as_append_escaped(out, o, nm, as_len(nm)) 122 o = as_append(out, o, "</h3><p>" as *u8) 123 o = as_append_escaped(out, o, bl, as_len(bl)) 124 o = as_append(out, o, "</p></a>" as *u8) 125 return o 126} 127 128// render the sovereign no-JS restaurant directory (lists every restaurant, links to each page) 129func fs_render_directory(store_prefix: *u8, catpath: *u8, out: *u8) -> i64 { 130 var o: i64 = 0 131 o = as_append(out, o, "<!doctype html><html lang='en'><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'><title>Nishi Stir-Fry &mdash; find your restaurant</title><style>:root{--accent:#7a1f1f;--gold:#e3b04b;--bg:#fbf7f0}body{margin:0;font-family:system-ui,sans-serif;color:#1b1410;background:var(--bg);line-height:1.55}.fbar{display:flex;justify-content:space-between;align-items:center;padding:14px 22px;background:var(--accent);color:#fff}.fbar .brand{color:#fff;text-decoration:none;font-weight:800}.fbar .tag{color:var(--gold);font-size:.85rem}.hero{padding:48px 22px 32px;text-align:center;background:linear-gradient(180deg,#7a1f1f,#9a3a2a);color:#fff}.hero h1{margin:0 0 8px;font-size:1.7rem}.hero .sub{margin:0;color:#f5ddc9}main{max-width:660px;margin:0 auto;padding:18px 22px 40px}.grid{display:grid;gap:14px}.rcard{display:block;background:#fff;border-radius:12px;padding:16px 18px;text-decoration:none;color:inherit;box-shadow:0 1px 0 #e8ddc8;border-left:4px solid var(--gold)}.rcard h3{margin:0 0 4px;color:var(--accent)}.rcard p{margin:0;color:#5b4a37}.ftr{padding:24px 22px;text-align:center;color:#8a7a64;font-size:.85rem}</style></head><body>" as *u8) 132 let navb: *u8 = sys_mmap(512) 133 var b: i64 = nw_bind_add(navb, 0, "BRAND" as *u8, "Nishi Stir-Fry" as *u8) 134 b = nw_bind_add(navb, b, "LINKS" as *u8, "Michelin balance at budget prices" as *u8); navb[b] = 0 as u8 135 o = fs_emit_component(catpath, "nav" as *u8, "foodbar" as *u8, navb, out, o) 136 let herob: *u8 = sys_mmap(K_MAGIC_1024) 137 b = nw_bind_add(herob, 0, "TITLE" as *u8, "Find your restaurant" as *u8) 138 b = nw_bind_add(herob, b, "SUB" as *u8, "Pick where you're eating tonight; we'll build the best stir-fry from what they actually serve." as *u8); herob[b] = 0 as u8 139 o = fs_emit_component(catpath, "section" as *u8, "hero" as *u8, herob, out, o) 140 o = as_append(out, o, "<main><div class='grid'>" as *u8) 141 let pq: *i64 = sys_mmap(16) as *i64 142 let lq: *i64 = sys_mmap(16) as *i64 143 if ss_get(store_prefix, "food:restids" as *u8, pq, lq) == 1 { 144 let idsbuf: *u8 = pq[0] as *u8 145 let idslen: i64 = lq[0] 146 var i: i64 = 0 147 var ls: i64 = 0 148 while i <= idslen { 149 var sep: i64 = 0 150 if i == idslen { sep = 1 } else { if idsbuf[i] == (9 as u8) { sep = 1 } } 151 if sep == 1 { 152 let il: i64 = i - ls 153 if il > 0 { 154 let idc: *u8 = sys_mmap(48) 155 var t: i64 = 0 156 while t < il { idc[t] = idsbuf[ls + t]; t = t + 1 } 157 idc[il] = 0 as u8 158 o = fs_dir_card(store_prefix, idc, out, o) 159 } 160 ls = i + 1 161 } 162 i = i + 1 163 } 164 } 165 o = as_append(out, o, "</div></main>" as *u8) 166 let ftrb: *u8 = sys_mmap(512) 167 b = nw_bind_add(ftrb, 0, "COPY" as *u8, "(c) Nishi Family -- sovereign, no tracking, no third-party scripts." as *u8); ftrb[b] = 0 as u8 168 o = fs_emit_component(catpath, "section" as *u8, "footer" as *u8, ftrb, out, o) 169 o = as_append(out, o, "</body></html>" as *u8) 170 out[o] = 0 as u8 171 return o 172}