code wiki / _hdl_build / nx_food_site.nx

nx_food_site.nx source

↩ module page · 139 lines · 9756 B

1// nx_food_site.nx -- LIB: the CONSUME surface. Renders the restaurant SITE from the LIVE grounded store, 2// composed from the `food` builder domain (catalog templates resolved by nb_lookup + the domain-agnostic 3// nw_render binding substitution). Closes the food loop end to end: seg-store -> engine -> builder domain -> 4// sovereign no-JS page. Boundary defense (rule 12): all data bindings are HTML-escaped by nw_bind_add, so a 5// restaurant name like "<script>" cannot inject markup. license_tier: ORIGINAL 6import "nx_food_science.nx" 7import "nx_web_render.nx" 8import "nx_food_clean_source.nx" 9import "nx_syscalls.nx" 10 11// resolve a FOOD-domain component (kind,id) from the catalog and render it with `bindings` (nw_emit_component 12// is hardcoded to the web domain, so the food branch needs its own thin resolver over the shared nw_render). 13func fs_emit_component(catpath: *u8, kind: *u8, id: *u8, bindings: *u8, out: *u8, off: i64) -> i64 { 14 let tpl: *u8 = sys_mmap(4096) 15 if nb_lookup(catpath, "food" as *u8, kind, id, tpl) == 0 { return off } 16 return nw_render(out, off, tpl, bindings) 17} 18 19// format an integer into a fresh NUL-terminated buffer (for escaped bindings) 20func fs_num(v: i64) -> *u8 { 21 let b: *u8 = sys_mmap(24) 22 let o: i64 = fd_apnum(b, 0, v) 23 b[o] = 0 as u8 24 return b 25} 26 27// join the display names of every build member with role rc into out (", " separated, NUL-terminated) 28func fs_role_names(world: *i64, build: *i64, roles: *i64, nb: i64, rc: i64, out: *u8) -> i64 { 29 let names: *i64 = world[4] as *i64 30 var o: i64 = 0 31 var first: i64 = 1 32 var i: i64 = 0 33 while i < nb { 34 if roles[i] == rc { 35 if first == 0 { o = as_append(out, o, ", " as *u8) } 36 o = as_append(out, o, names[build[i]] as *u8) 37 first = 0 38 } 39 i = i + 1 40 } 41 out[o] = 0 as u8 42 return o 43} 44 45// TEACH the food domain to a builder catalog (durable registry). Idempotent (nb_register skips if present). 46// Returns the food-domain emitter count after teaching. 47func fs_teach(catpath: *u8) -> i64 { 48 nb_register(catpath, "food" as *u8, "nav" as *u8, "foodbar" as *u8, "Food nav bar" as *u8, "<nav class='fbar'><a class='brand' href='/'>{BRAND}</a><span class='tag'>{LINKS}</span></nav>" as *u8) 49 nb_register(catpath, "food" as *u8, "section" as *u8, "hero" as *u8, "Food hero" as *u8, "<header class='hero'><h1>{TITLE}</h1><p class='sub'>{SUB}</p></header>" as *u8) 50 nb_register(catpath, "food" as *u8, "section" as *u8, "recommendation" as *u8, "Stir-fry recommendation" as *u8, "<section class='rec'><h2>{HEAD}</h2><ul class='build'><li><b>Protein:</b> {PROTEIN}</li><li><b>Vegetables:</b> {VEG}</li><li><b>Aromatics:</b> {AROMATIC}</li><li><b>Sauce:</b> {SAUCE}</li></ul><p class='why'>{WHY}</p></section>" as *u8) 51 nb_register(catpath, "food" as *u8, "section" as *u8, "science" as *u8, "Food-science breakdown" as *u8, "<section class='sci'><h2>{HEAD}</h2><dl class='metrics'><dt>Five-taste balance (lower is better)</dt><dd>{BALANCE}</dd><dt>Pairing affinity (recipe-grounded)</dt><dd>{AFFINITY}</dd><dt>Texture contrast</dt><dd>{TEXTURE}</dd><dt>Overall score</dt><dd>{SCORE}</dd></dl><p class='note'>{NOTE}</p></section>" as *u8) 52 nb_register(catpath, "food" as *u8, "section" as *u8, "footer" as *u8, "Food footer" as *u8, "<footer class='ftr'><p>{COPY}</p></footer>" as *u8) 53 return nb_count(catpath, "food" as *u8, "*" as *u8) 54} 55 56// render the full sovereign site (NUL-terminated) into out; returns byte length. Composes nav + hero + 57// recommendation + science + footer from the catalog, bound to the LIVE chooser output over `store_prefix`. 58// all-available, neutral-preference wrapper (the R-SITE flagship page) 59func fs_render(store_prefix: *u8, catpath: *u8, restaurant: *u8, out: *u8) -> i64 { 60 let h0: *i64 = fd_world_open(store_prefix) 61 let n0: i64 = h0[0] 62 let avail0: *i64 = sys_mmap(8 * 64) as *i64 63 let avoid0: *i64 = sys_mmap(8 * 64) as *i64 64 let prefw0: *i64 = sys_mmap(8 * 8) as *i64 65 fd_set_all(avail0, n0, 1); fd_set_all(avoid0, n0, 0) 66 var z0: i64 = 0; while z0 < FOOD_NAX { prefw0[z0] = 0; z0 = z0 + 1 } 67 return fs_render_avail(store_prefix, catpath, restaurant, avail0, avoid0, prefw0, out) 68} 69 70// the core renderer: compose the site for an explicit availability mask + preference profile. Used by the 71// flagship page (all available) AND by per-restaurant pages (only that restaurant's menu available). 72func fs_render_avail(store_prefix: *u8, catpath: *u8, restaurant: *u8, avail: *i64, avoid: *i64, prefw: *i64, out: *u8) -> i64 { 73 let h: *i64 = fd_world_open(store_prefix) 74 let n: i64 = h[0] 75 let frame: *i64 = sys_mmap(8 * 16) as *i64 76 let nframe: i64 = fd_load_frame(store_prefix, frame) 77 let wts: *i64 = sys_mmap(8 * 8) as *i64 78 fd_load_weights(store_prefix, wts) 79 let build: *i64 = sys_mmap(8 * 16) as *i64 80 let roles: *i64 = sys_mmap(8 * 16) as *i64 81 let nb: i64 = fd_choose(h, avail, avoid, prefw, frame, nframe, wts, build, roles) 82 83 let pn: *u8 = sys_mmap(256); fs_role_names(h, build, roles, nb, FROLE_PRO, pn) 84 let vn: *u8 = sys_mmap(256); fs_role_names(h, build, roles, nb, FROLE_VEG, vn) 85 let an: *u8 = sys_mmap(256); fs_role_names(h, build, roles, nb, FROLE_ARO, an) 86 let sn: *u8 = sys_mmap(256); fs_role_names(h, build, roles, nb, FROLE_SAU, sn) 87 let imb: i64 = fd_imbalance(h, build, nb) 88 let aff: i64 = fd_affinity_total(h, build, nb) 89 let tex: i64 = fd_texture_contrast(h, build, nb) 90 let sc: i64 = fd_score(h, build, nb, prefw, wts) 91 92 var o: i64 = 0 93 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</title><style>:root{--ink:#1b1410;--accent:#7a1f1f;--gold:#e3b04b;--bg:#fbf7f0}*{box-sizing:border-box}body{margin:0;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:var(--ink);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;letter-spacing:.3px}.fbar .tag{color:var(--gold);font-size:.85rem}.hero{padding:56px 22px 40px;text-align:center;background:linear-gradient(180deg,#7a1f1f,#9a3a2a);color:#fff}.hero h1{margin:0 0 8px;font-size:1.8rem}.hero .sub{margin:0;color:#f5ddc9;max-width:46ch;margin-inline:auto}main{max-width:660px;margin:0 auto;padding:8px 22px 40px}section{background:#fff;border-radius:12px;padding:18px 20px;margin-top:18px;box-shadow:0 1px 0 #e8ddc8}h2{font-size:1.15rem;margin:0 0 10px;border-bottom:2px solid var(--gold);padding-bottom:6px}ul.build{list-style:none;padding:0;margin:0}ul.build li{padding:6px 0;border-bottom:1px solid #f0e7d6}.why{color:#5b4a37;margin:12px 0 0}dl.metrics{display:grid;grid-template-columns:1fr auto;gap:6px 14px;margin:0}dl.metrics dt{color:#5b4a37}dl.metrics dd{margin:0;font-weight:800;font-variant-numeric:tabular-nums;text-align:right}.note{color:#5b4a37;margin:12px 0 0}.ftr{padding:24px 22px;text-align:center;color:#8a7a64;font-size:.85rem}</style></head><body>" as *u8) 94 95 let nbnav: *u8 = sys_mmap(512) 96 var b: i64 = nw_bind_add(nbnav, 0, "BRAND" as *u8, "Nishi Stir-Fry" as *u8) 97 b = nw_bind_add(nbnav, b, "LINKS" as *u8, "Michelin balance at budget prices" as *u8); nbnav[b] = 0 as u8 98 o = fs_emit_component(catpath, "nav" as *u8, "foodbar" as *u8, nbnav, out, o) 99 100 let title: *u8 = sys_mmap(256) 101 var tt: i64 = as_append(title, 0, "The best stir-fry at " as *u8); tt = as_append(title, tt, restaurant); title[tt] = 0 as u8 102 let nbhero: *u8 = sys_mmap(1024) 103 b = nw_bind_add(nbhero, 0, "TITLE" as *u8, title) 104 b = nw_bind_add(nbhero, b, "SUB" as *u8, "Built from what they actually have on hand tonight, balanced by food science." as *u8); nbhero[b] = 0 as u8 105 o = fs_emit_component(catpath, "section" as *u8, "hero" as *u8, nbhero, out, o) 106 107 o = as_append(out, o, "<main>" as *u8) 108 109 let nbrec: *u8 = sys_mmap(2048) 110 b = nw_bind_add(nbrec, 0, "HEAD" as *u8, "Tonight's build" as *u8) 111 b = nw_bind_add(nbrec, b, "PROTEIN" as *u8, pn) 112 b = nw_bind_add(nbrec, b, "VEG" as *u8, vn) 113 b = nw_bind_add(nbrec, b, "AROMATIC" as *u8, an) 114 b = nw_bind_add(nbrec, b, "SAUCE" as *u8, sn) 115 b = nw_bind_add(nbrec, b, "WHY" as *u8, "Chosen to balance the five tastes with an aromatic backbone, textural contrast, and pairings grounded in real recipes." as *u8); nbrec[b] = 0 as u8 116 o = fs_emit_component(catpath, "section" as *u8, "recommendation" as *u8, nbrec, out, o) 117 118 let nbsci: *u8 = sys_mmap(1024) 119 b = nw_bind_add(nbsci, 0, "HEAD" as *u8, "Why this is the best" as *u8) 120 b = nw_bind_add(nbsci, b, "BALANCE" as *u8, fs_num(imb)) 121 b = nw_bind_add(nbsci, b, "AFFINITY" as *u8, fs_num(aff)) 122 b = nw_bind_add(nbsci, b, "TEXTURE" as *u8, fs_num(tex)) 123 b = nw_bind_add(nbsci, b, "SCORE" as *u8, fs_num(sc)) 124 b = nw_bind_add(nbsci, b, "NOTE" as *u8, "The Michelin balance, at your local spot's prices." as *u8); nbsci[b] = 0 as u8 125 o = fs_emit_component(catpath, "section" as *u8, "science" as *u8, nbsci, out, o) 126 127 // clean-sourcing badge: the impact economics, joined to the recommendation (covered veg only; honest) 128 o = fc_render_badge(store_prefix, h, build, roles, nb, out, o) 129 130 o = as_append(out, o, "</main>" as *u8) 131 132 let nbftr: *u8 = sys_mmap(512) 133 b = nw_bind_add(nbftr, 0, "COPY" as *u8, "(c) Nishi Family -- sovereign, no tracking, no third-party scripts." as *u8); nbftr[b] = 0 as u8 134 o = fs_emit_component(catpath, "section" as *u8, "footer" as *u8, nbftr, out, o) 135 136 o = as_append(out, o, "</body></html>" as *u8) 137 out[o] = 0 as u8 138 return o 139}