code wiki / _hdl_build / nx_household.nx
nx_household.nx source
↩ module page · 91 lines · 5371 B
1// nx_household.nx -- LIB: the HOUSEHOLD COMMAND CENTER. One sovereign no-JS dashboard tying the whole
2// ecosystem together: tonight's dinner (what you can cook from the pantry), what's expiring, the shopping list
3// (low stock), grow-your-own savings, and the estate net worth -- each pulled LIVE from the food + inventory
4// engines. The single "it all works together" surface. Boundary-escaped. (Named nx_household to avoid the
5// existing IoT nx_home.nx.) license_tier: ORIGINAL
6import "nx_pantry.nx"
7import "nx_garden.nx"
8import "nx_inventory.nx"
9import "nx_food_science.nx"
10import "nx_syscalls.nx"
11
12func hh_money(dst: *u8, off: i64, cents: i64) -> i64 {
13 var o: i64 = off
14 dst[o] = 36 as u8; o = o + 1
15 o = fd_apnum(dst, o, cents / 100)
16 dst[o] = 46 as u8; o = o + 1
17 let r: i64 = cents % 100
18 dst[o] = (48 + (r / 10)) as u8; o = o + 1
19 dst[o] = (48 + (r % 10)) as u8; o = o + 1
20 return o
21}
22
23// append display names of inventory ids[0..n) (", " joined, escaped); "(none)" if empty
24func hh_inv_names(inv_prefix: *u8, domain: *u8, ids: *i64, n: i64, out: *u8, off: i64) -> i64 {
25 var o: i64 = off
26 if n == 0 { return as_append(out, o, "(none)" as *u8) }
27 var i: i64 = 0
28 while i < n {
29 if i > 0 { o = as_append(out, o, ", " as *u8) }
30 let nm: *u8 = sys_mmap(64)
31 iv_field_of(inv_prefix, domain, ids[i] as *u8, 0, nm)
32 o = as_append_escaped(out, o, nm, as_len(nm))
33 i = i + 1
34 }
35 return o
36}
37
38func hh_render_dashboard(food_prefix: *u8, inv_prefix: *u8, pantry_dom: *u8, estate_dom: *u8, household: *u8, out: *u8) -> i64 {
39 let world: *i64 = fd_world_open(food_prefix)
40 let names: *i64 = world[4] as *i64
41
42 // tonight's dinner: choose from what's in stock
43 let avail: *i64 = sys_mmap(8 * 64) as *i64
44 fp_pantry_avail(world, inv_prefix, pantry_dom, avail)
45 let build: *i64 = sys_mmap(8 * 16) as *i64
46 let roles: *i64 = sys_mmap(8 * 16) as *i64
47 let nb: i64 = fp_choose(food_prefix, world, avail, build, roles)
48
49 var o: i64 = 0
50 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>Your Nishi Home</title><style>body{margin:0;font-family:system-ui,sans-serif;color:#1b232c;background:#eef2f5;line-height:1.5}header{background:#0b2545;color:#fff;padding:26px 22px}header h1{margin:0;font-size:1.5rem}header p{margin:4px 0 0;color:#bcd2ea}main{max-width:680px;margin:0 auto;padding:18px 16px 40px;display:grid;gap:14px}.tile{background:#fff;border-radius:12px;padding:16px 18px;box-shadow:0 1px 0 #dde5ec}.tile h2{margin:0 0 6px;font-size:1rem;color:#0b2545;display:flex;justify-content:space-between;align-items:baseline}.tile .big{font-size:1.15rem;font-weight:700}.muted{color:#5b6b7a}.save{color:#1f7a44}.expire{color:#a85b00;font-weight:600}</style></head><body><header><h1>Your Nishi Home</h1><p>" as *u8)
51 o = as_append_escaped(out, o, household, as_len(household))
52 o = as_append(out, o, "</p></header><main>" as *u8)
53
54 o = as_append(out, o, "<div class='tile'><h2>Tonight you can make</h2><div class='big'>" as *u8)
55 if nb == 5 {
56 var i: i64 = 0
57 while i < nb { if i > 0 { o = as_append(out, o, " · " as *u8) } o = as_append_escaped(out, o, names[build[i]] as *u8, as_len(names[build[i]] as *u8)); i = i + 1 }
58 } else { o = as_append(out, o, "Not enough on hand for a full stir-fry — see the shopping list." as *u8) }
59 o = as_append(out, o, "</div><p class='muted'>balanced by food science, from what's in your kitchen.</p></div>" as *u8)
60
61 let exp: *i64 = sys_mmap(8 * 256) as *i64
62 let nexp: i64 = iv_expiring(inv_prefix, pantry_dom, 0, 3, exp)
63 o = as_append(out, o, "<div class='tile'><h2>Use these soon <span class='expire'>" as *u8)
64 o = fd_apnum(out, o, nexp); o = as_append(out, o, " expiring</span></h2><div class='expire'>" as *u8)
65 o = hh_inv_names(inv_prefix, pantry_dom, exp, nexp, out, o)
66 o = as_append(out, o, "</div></div>" as *u8)
67
68 let lid: *i64 = sys_mmap(8 * 256) as *i64
69 let lneed: *i64 = sys_mmap(8 * 256) as *i64
70 let nlo: i64 = iv_low_stock(inv_prefix, pantry_dom, lid, lneed)
71 o = as_append(out, o, "<div class='tile'><h2>Shopping list <span class='muted'>" as *u8)
72 o = fd_apnum(out, o, nlo); o = as_append(out, o, " to buy</span></h2><div>" as *u8)
73 o = hh_inv_names(inv_prefix, pantry_dom, lid, nlo, out, o)
74 o = as_append(out, o, "</div></div>" as *u8)
75
76 let og: *i64 = sys_mmap(16) as *i64
77 let mealsav: i64 = gd_meal_savings(food_prefix, world, build, nb, og)
78 o = as_append(out, o, "<div class='tile'><h2>Grow & save</h2><div class='big save'>" as *u8)
79 o = hh_money(out, o, mealsav * 3 * 52)
80 o = as_append(out, o, " / year</div><p class='muted'>grow " as *u8)
81 o = fd_apnum(out, o, og[0]); o = as_append(out, o, " of tonight's ingredients yourself (cooked 3×/week).</p></div>" as *u8)
82
83 let netw: i64 = iv_value_total(inv_prefix, estate_dom)
84 o = as_append(out, o, "<div class='tile'><h2>Estate <span class='muted'>cataloged for your will</span></h2><div class='big'>" as *u8)
85 o = hh_money(out, o, netw)
86 o = as_append(out, o, "</div><p class='muted'>total catalogued net worth.</p></div>" as *u8)
87
88 o = as_append(out, o, "</main></body></html>" as *u8)
89 out[o] = 0 as u8
90 return o
91}