code wiki / _hdl_build / nx_food_clean_source.nx
nx_food_clean_source.nx source
↩ module page · 132 lines · 8756 B
1// nx_food_clean_source.nx -- LIB: the CLEAN-SOURCING badge that joins the stir-fry SITE to the impact ECONOMICS
2// (operator: "we gain more profit and they spend less via them buying from us"). For the vegetables in a chosen
3// build that Nishi grows regeneratively (present in the impact catalog), it aggregates the per-item customer
4// savings vs conventional and renders a sovereign no-JS "Clean sourcing" section for the recommendation page --
5// so the diner SEES, on the same page that picks their dish, that the produce we source is cleaner AND cheaper.
6//
7// HONEST BY CONSTRUCTION: only ingredients ACTUALLY in the catalog count (im_field_int < 0 == absent), the
8// section states how many, and a non-catalog ingredient is reported as not-yet-covered -- never a faked number.
9// The seeded estimates VARY truthfully (onion/garlic are low-residue even conventionally -> small clean gap;
10// bok choy / snow peas higher -> larger gap), so the badge cannot greenwash. Reuses nx_impact accessors;
11// integer cents only (no float); each record CITEs the regenerative-agriculture corpus. license_tier: ORIGINAL
12import "nx_impact.nx"
13import "nx_food_science.nx"
14import "nx_seg_store.nx"
15import "nx_syscalls.nx"
16
17// 1 if `slug` is a Nishi-sourced item in the impact catalog (the nishi record is present), else 0.
18// im_field_int returns -1 when the record is absent; field 1 (pesticide) is always >=0 when present.
19func fc_covered(prefix: *u8, slug: *u8) -> i64 {
20 if im_field_int(prefix, slug, "nishi" as *u8, 1) < 0 { return 0 }
21 return 1
22}
23
24// seed impact records for the common stir-fry VEGETABLES (idempotent / additive; no index touched, so the
25// Dirty-Dozen produce storefront's food:impactids is left alone). Each veg: conv + nishi, triple-win by
26// construction, cited. Returns the number of records freshly written. Slugs MATCH the food world ids.
27func fc_seed_veg(prefix: *u8) -> i64 {
28 let keys: *i64 = sys_mmap(8 * 24) as *i64
29 let vals: *i64 = sys_mmap(8 * 24) as *i64
30 var n: i64 = 0
31 keys[n] = "food:impact:broccoli:conv" as *u8 as i64; vals[n] = "Conventional broccoli\t28\t500\t280\t3\t250\t190\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
32 keys[n] = "food:impact:broccoli:nishi" as *u8 as i64; vals[n] = "Nishi broccoli\t5\t180\t150\t9\t220\t80\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
33 keys[n] = "food:impact:onion:conv" as *u8 as i64; vals[n] = "Conventional onion\t16\t300\t90\t3\t130\t100\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
34 keys[n] = "food:impact:onion:nishi" as *u8 as i64; vals[n] = "Nishi onion\t3\t140\t60\t9\t115\t45\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
35 keys[n] = "food:impact:carrot:conv" as *u8 as i64; vals[n] = "Conventional carrot\t30\t350\t130\t3\t140\t105\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
36 keys[n] = "food:impact:carrot:nishi" as *u8 as i64; vals[n] = "Nishi carrot\t5\t150\t80\t9\t125\t50\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
37 keys[n] = "food:impact:snowpea:conv" as *u8 as i64; vals[n] = "Conventional snow peas\t42\t600\t320\t3\t380\t290\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
38 keys[n] = "food:impact:snowpea:nishi" as *u8 as i64; vals[n] = "Nishi snow peas\t6\t250\t170\t9\t340\t130\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
39 keys[n] = "food:impact:mushroom:conv" as *u8 as i64; vals[n] = "Conventional mushroom\t20\t700\t180\t3\t300\t230\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
40 keys[n] = "food:impact:mushroom:nishi" as *u8 as i64; vals[n] = "Nishi mushroom\t4\t320\t110\t9\t270\t100\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
41 keys[n] = "food:impact:bokchoy:conv" as *u8 as i64; vals[n] = "Conventional bok choy\t55\t450\t220\t3\t260\t200\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
42 keys[n] = "food:impact:bokchoy:nishi" as *u8 as i64; vals[n] = "Nishi bok choy\t6\t190\t130\t9\t230\t85\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
43 keys[n] = "food:impact:beansprout:conv" as *u8 as i64; vals[n] = "Conventional bean sprouts\t15\t250\t90\t3\t180\t140\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
44 keys[n] = "food:impact:beansprout:nishi" as *u8 as i64; vals[n] = "Nishi bean sprouts\t3\t110\t55\t9\t160\t60\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
45 keys[n] = "food:impact:garlic:conv" as *u8 as i64; vals[n] = "Conventional garlic\t8\t400\t160\t3\t150\t115\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
46 keys[n] = "food:impact:garlic:nishi" as *u8 as i64; vals[n] = "Nishi garlic\t2\t180\t100\t9\t135\t55\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
47 keys[n] = "food:impact:ginger:conv" as *u8 as i64; vals[n] = "Conventional ginger\t25\t450\t200\t3\t220\t170\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
48 keys[n] = "food:impact:ginger:nishi" as *u8 as i64; vals[n] = "Nishi ginger\t4\t200\t120\t9\t200\t80\tperma_a8_regenerative_ag" as *u8 as i64; n = n + 1
49
50 let w: *i64 = ss_begin()
51 var tw: i64 = 0
52 var i: i64 = 0
53 while i < n {
54 let k: *u8 = keys[i] as *u8
55 let v: *u8 = vals[i] as *u8
56 let vl: i64 = as_len(v)
57 if fd_streq_store(prefix, k, v, vl) == 0 { ss_add(w, 1, k, v, vl); tw = tw + 1 }
58 i = i + 1
59 }
60 if tw > 0 { let seg: i64 = fd_seg_next(prefix); ss_commit(prefix, w, seg) }
61 return tw
62}
63
64// total customer savings (cents) over the VEG members of `build` that are catalog-covered (Nishi vs conv).
65func fc_build_savings(prefix: *u8, h: *i64, build: *i64, roles: *i64, nb: i64) -> i64 {
66 let ids: *i64 = h[1] as *i64
67 var s: i64 = 0
68 var i: i64 = 0
69 while i < nb {
70 if roles[i] == FROLE_VEG {
71 let slug: *u8 = ids[build[i]] as *u8
72 if fc_covered(prefix, slug) == 1 { s = s + im_savings(prefix, slug, "nishi" as *u8, "conv" as *u8) }
73 }
74 i = i + 1
75 }
76 return s
77}
78
79// how many VEG members of `build` are catalog-covered (the honest coverage count).
80func fc_build_covered(prefix: *u8, h: *i64, build: *i64, roles: *i64, nb: i64) -> i64 {
81 let ids: *i64 = h[1] as *i64
82 var c: i64 = 0
83 var i: i64 = 0
84 while i < nb {
85 if roles[i] == FROLE_VEG {
86 let slug: *u8 = ids[build[i]] as *u8
87 if fc_covered(prefix, slug) == 1 { c = c + 1 }
88 }
89 i = i + 1
90 }
91 return c
92}
93
94// render the sovereign no-JS "Clean sourcing" <section> into out at off; returns new off. Lists each covered
95// veg with its MEASURED clean score + per-item savings, plus the whole-build total; honest fallback if none.
96// Reuses the site's existing CSS classes (section / h2 / dl.metrics / .note) -- no new styles required.
97func fc_render_badge(prefix: *u8, h: *i64, build: *i64, roles: *i64, nb: i64, out: *u8, off: i64) -> i64 {
98 let ids: *i64 = h[1] as *i64
99 let names: *i64 = h[4] as *i64
100 let covered: i64 = fc_build_covered(prefix, h, build, roles, nb)
101 let total: i64 = fc_build_savings(prefix, h, build, roles, nb)
102 var o: i64 = off
103 o = as_append(out, o, "<section class='clean'><h2>Clean sourcing — what you save with Nishi</h2>" as *u8)
104 if covered == 0 {
105 o = as_append(out, o, "<p class='note'>The vegetables in tonight's build aren't in our regenerative catalog yet — sourced conventionally for now. We add clean-grown produce as the farm scales.</p></section>" as *u8)
106 return o
107 }
108 o = as_append(out, o, "<dl class='metrics'>" as *u8)
109 var i: i64 = 0
110 while i < nb {
111 if roles[i] == FROLE_VEG {
112 let slug: *u8 = ids[build[i]] as *u8
113 if fc_covered(prefix, slug) == 1 {
114 let nm: *u8 = names[build[i]] as *u8
115 o = as_append(out, o, "<dt>" as *u8)
116 o = as_append_escaped(out, o, nm, as_len(nm))
117 o = as_append(out, o, " — clean " as *u8)
118 o = fd_apnum(out, o, im_clean(prefix, slug, "nishi" as *u8))
119 o = as_append(out, o, "/100</dt><dd>save " as *u8)
120 o = im_money(out, o, im_savings(prefix, slug, "nishi" as *u8, "conv" as *u8))
121 o = as_append(out, o, "</dd>" as *u8)
122 }
123 }
124 i = i + 1
125 }
126 o = as_append(out, o, "<dt><b>Whole build</b></dt><dd><b>save " as *u8)
127 o = im_money(out, o, total)
128 o = as_append(out, o, "</b></dd></dl><p class='note'>For the " as *u8)
129 o = fd_apnum(out, o, covered)
130 o = as_append(out, o, " vegetable(s) Nishi grows regeneratively, you pay less AND get cleaner, soil-building produce — less pesticide residue, more soil health. Impact figures are Nishi planning estimates grounded in the regenerative-agriculture corpus.</p></section>" as *u8)
131 return o
132}