code wiki / _hdl_build / nx_ecodesign.nx
nx_ecodesign.nx source
↩ module page · 206 lines · 12202 B
1// nx_ecodesign.nx -- LIB: the REGENERATIVE LANDSCAPE calculator (operator: "more than edibles -- medicinal +
2// wildlife in ALL our calculations; rainwater harvesting w/ 3D-printed concrete structures; climbing useful
3// plants (jasmine/grapes) on the concrete; share with wildlife while discouraging damage; optimal use of the
4// environment while improving it"). Every plant is valued on MULTIPLE axes (edible/medicinal/wildlife/climbing/
5// water/deer-resistance), so the design optimizes total ecosystem value, not just food. Rainwater capture is
6// integer math (no float). Climbing multi-value plants go on the 3D-printed concrete cistern wall. "Share with
7// wildlife while discouraging damage" = high wildlife value AND high deer-resistance. Each plant CITEs a real
8// fetched research source. Plants live in the food store keyed eco:plant:<id>.
9// Schema: eco:plant:<id> -> name <t> edible(0/1) <t> medicinal(0-10) <t> wildlife(0-10) <t> climbing(0/1) <t>
10// water(1-5) <t> deer_resist(0-10) <t> nfix(0/1) <t> cite
11// license_tier: ORIGINAL
12import "nx_food_science.nx"
13import "nx_food_provenance.nx"
14import "nx_seg_store.nx"
15import "nx_syscalls.nx"
16
17func ec_money(dst: *u8, off: i64, cents: i64) -> i64 {
18 var o: i64 = off
19 dst[o] = 36 as u8; o = o + 1
20 o = fd_apnum(dst, o, cents / 100)
21 dst[o] = 46 as u8; o = o + 1
22 let r: i64 = cents % 100
23 dst[o] = (48 + (r / 10)) as u8; o = o + 1
24 dst[o] = (48 + (r % 10)) as u8; o = o + 1
25 return o
26}
27func ec_plant_key(id: *u8, out: *u8) -> i64 {
28 var o: i64 = 0
29 o = as_append(out, o, "eco:plant:" as *u8)
30 o = as_append(out, o, id)
31 out[o] = 0 as u8
32 return o
33}
34func ec_get(prefix: *u8, id: *u8, ptr: *i64, len: *i64) -> i64 {
35 let key: *u8 = sys_mmap(80)
36 ec_plant_key(id, key)
37 return ss_get(prefix, key, ptr, len)
38}
39func ec_field_int(prefix: *u8, id: *u8, f: i64) -> i64 {
40 let pq: *i64 = sys_mmap(16) as *i64
41 let lq: *i64 = sys_mmap(16) as *i64
42 if ec_get(prefix, id, pq, lq) != 1 { return 0 - 1 }
43 let buf: *u8 = sys_mmap(32)
44 let l: i64 = fd_field(pq[0] as *u8, lq[0], f, buf)
45 return fd_atoi(buf, l)
46}
47func ec_field_str(prefix: *u8, id: *u8, f: i64, out: *u8) -> i64 {
48 let pq: *i64 = sys_mmap(16) as *i64
49 let lq: *i64 = sys_mmap(16) as *i64
50 if ec_get(prefix, id, pq, lq) != 1 { out[0] = 0 as u8; return 0 }
51 return fd_field(pq[0] as *u8, lq[0], f, out)
52}
53func ec_edible(prefix: *u8, id: *u8) -> i64 { return ec_field_int(prefix, id, 1) }
54func ec_med(prefix: *u8, id: *u8) -> i64 { return ec_field_int(prefix, id, 2) }
55func ec_wild(prefix: *u8, id: *u8) -> i64 { return ec_field_int(prefix, id, 3) }
56func ec_climbing(prefix: *u8, id: *u8) -> i64 { return ec_field_int(prefix, id, 4) }
57func ec_deer(prefix: *u8, id: *u8) -> i64 { return ec_field_int(prefix, id, 6) }
58
59// TOTAL ECOSYSTEM VALUE -- the operator's "in all our calculations": food + medicine + wildlife together.
60func ec_value(prefix: *u8, id: *u8, wfood: i64, wmed: i64, wwild: i64) -> i64 {
61 let e: i64 = ec_edible(prefix, id)
62 let m: i64 = ec_med(prefix, id)
63 let wd: i64 = ec_wild(prefix, id)
64 var v: i64 = 0
65 if e > 0 { v = v + wfood }
66 v = v + wmed * m + wwild * wd
67 return v
68}
69// "share with wildlife while discouraging damage" = feeds wildlife (>=6) AND deer-resistant (>=6)
70func ec_share_safe(prefix: *u8, id: *u8) -> i64 {
71 if ec_wild(prefix, id) >= 6 { if ec_deer(prefix, id) >= 6 { return 1 } }
72 return 0
73}
74// rainwater capture (litres/year) = roof_area_m2 x rainfall_mm x runoff_pct/100 (1mm on 1m2 = 1 litre). Integer.
75func ec_capture(roof_m2: i64, rainfall_mm: i64, runoff_pct: i64) -> i64 {
76 return roof_m2 * rainfall_mm * runoff_pct / 100
77}
78
79// author the multi-value plant palette + ecosystem-value weights (idempotent). Cites landed perma_*.raw sources.
80func ec_seed(prefix: *u8) -> i64 {
81 let keys: *i64 = sys_mmap(8 * 24) as *i64
82 let vals: *i64 = sys_mmap(8 * 24) as *i64
83 var n: i64 = 0
84 keys[n] = "eco:weights" as *u8 as i64; vals[n] = "8\t2\t2" as *u8 as i64; n = n + 1 // wfood, wmed, wwild
85 keys[n] = "eco:plantids" as *u8 as i64
86 vals[n] = "grape\tjasmine\tlavender\techinacea\tyarrow\tmilkweed\tcomfrey\tclover\tgarlic\tbeebalm\thosta\telderberry" as *u8 as i64; n = n + 1
87 keys[n] = "eco:plant:grape" as *u8 as i64; vals[n] = "Grape\t1\t3\t7\t1\t3\t4\t0\tperma_a2_forest_gardening" as *u8 as i64; n = n + 1
88 keys[n] = "eco:plant:jasmine" as *u8 as i64; vals[n] = "Jasmine\t0\t6\t7\t1\t2\t6\t0\tperma_a2_forest_gardening" as *u8 as i64; n = n + 1
89 keys[n] = "eco:plant:lavender" as *u8 as i64; vals[n] = "Lavender\t0\t7\t9\t0\t1\t9\t0\tperma_a5_polyculture" as *u8 as i64; n = n + 1
90 keys[n] = "eco:plant:echinacea" as *u8 as i64; vals[n] = "Echinacea\t0\t9\t8\t0\t2\t7\t0\tperma_a5_polyculture" as *u8 as i64; n = n + 1
91 keys[n] = "eco:plant:yarrow" as *u8 as i64; vals[n] = "Yarrow\t0\t8\t8\t0\t1\t8\t0\tperma_a6_companion_planting" as *u8 as i64; n = n + 1
92 keys[n] = "eco:plant:milkweed" as *u8 as i64; vals[n] = "Milkweed\t0\t4\t10\t0\t2\t7\t0\tperma_a5_polyculture" as *u8 as i64; n = n + 1
93 keys[n] = "eco:plant:comfrey" as *u8 as i64; vals[n] = "Comfrey\t0\t8\t6\t0\t3\t6\t0\tperma_b6_humus" as *u8 as i64; n = n + 1
94 keys[n] = "eco:plant:clover" as *u8 as i64; vals[n] = "Clover\t0\t3\t7\t0\t3\t3\t1\tperma_b12_nitrogen_fixation" as *u8 as i64; n = n + 1
95 keys[n] = "eco:plant:garlic" as *u8 as i64; vals[n] = "Garlic\t1\t8\t3\t0\t2\t10\t0\tperma_a6_companion_planting" as *u8 as i64; n = n + 1
96 keys[n] = "eco:plant:beebalm" as *u8 as i64; vals[n] = "Bee Balm\t0\t6\t9\t0\t3\t7\t0\tperma_a5_polyculture" as *u8 as i64; n = n + 1
97 keys[n] = "eco:plant:hosta" as *u8 as i64; vals[n] = "Hosta\t0\t1\t5\t0\t4\t1\t0\tperma_a5_polyculture" as *u8 as i64; n = n + 1
98 keys[n] = "eco:plant:elderberry" as *u8 as i64; vals[n] = "Elderberry\t1\t9\t9\t0\t3\t6\t0\tperma_a2_forest_gardening" as *u8 as i64; n = n + 1
99
100 let w: *i64 = ss_begin()
101 var tw: i64 = 0
102 var i: i64 = 0
103 while i < n {
104 let k: *u8 = keys[i] as *u8
105 let v: *u8 = vals[i] as *u8
106 let vl: i64 = as_len(v)
107 if fd_streq_store(prefix, k, v, vl) == 0 { ss_add(w, 1, k, v, vl); tw = tw + 1 }
108 i = i + 1
109 }
110 if tw > 0 { let seg: i64 = fd_seg_next(prefix); ss_commit(prefix, w, seg) }
111 return tw
112}
113
114// walk eco:plantids; outids = ptrs to fresh id copies; returns count
115func ec_list(prefix: *u8, outids: *i64) -> i64 {
116 let pq: *i64 = sys_mmap(16) as *i64
117 let lq: *i64 = sys_mmap(16) as *i64
118 if ss_get(prefix, "eco:plantids" as *u8, pq, lq) != 1 { return 0 }
119 let buf: *u8 = pq[0] as *u8
120 let len: i64 = lq[0]
121 var c: i64 = 0
122 var i: i64 = 0
123 var ls: i64 = 0
124 while i <= len {
125 var sep: i64 = 0
126 if i == len { sep = 1 } else { if buf[i] == (9 as u8) { sep = 1 } }
127 if sep == 1 {
128 let tl: i64 = i - ls
129 if tl > 0 {
130 let tok: *u8 = sys_mmap(48)
131 var t: i64 = 0
132 while t < tl { tok[t] = buf[ls + t]; t = t + 1 } tok[tl] = 0 as u8
133 outids[c] = tok as i64; c = c + 1
134 }
135 ls = i + 1
136 }
137 i = i + 1
138 }
139 return c
140}
141
142// render the regenerative landscape design (NUL-terminated); returns length.
143func ec_render_design(prefix: *u8, roof_m2: i64, rainfall_mm: i64, out: *u8) -> i64 {
144 let pqw: *i64 = sys_mmap(16) as *i64; let lqw: *i64 = sys_mmap(16) as *i64
145 var wfood: i64 = 8; var wmed: i64 = 2; var wwild: i64 = 2
146 if ss_get(prefix, "eco:weights" as *u8, pqw, lqw) == 1 {
147 let f: *u8 = sys_mmap(16)
148 let l0: i64 = fd_field(pqw[0] as *u8, lqw[0], 0, f); wfood = fd_atoi(f, l0)
149 let l1: i64 = fd_field(pqw[0] as *u8, lqw[0], 1, f); wmed = fd_atoi(f, l1)
150 let l2: i64 = fd_field(pqw[0] as *u8, lqw[0], 2, f); wwild = fd_atoi(f, l2)
151 }
152 let cap: i64 = ec_capture(roof_m2, rainfall_mm, 80)
153
154 var o: i64 = 0
155 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>Regenerative landscape</title><style>body{margin:0;font-family:system-ui,sans-serif;color:#1c2a1d;background:#eef4ea;line-height:1.55}header{background:#2e5b34;color:#fff;padding:26px 22px}header h1{margin:0;font-size:1.5rem}main{max-width:700px;margin:0 auto;padding:18px 18px 40px;display:grid;gap:14px}.tile{background:#fff;border-radius:12px;padding:16px 18px;box-shadow:0 1px 0 #d6e4cf}.tile h2{margin:0 0 8px;font-size:1.05rem;color:#2e5b34}.big{font-size:1.2rem;font-weight:700}table{border-collapse:collapse;width:100%;font-size:.92rem}th{text-align:left;background:#e6efe1;padding:6px 8px;color:#33503f}td{padding:6px 8px;border-top:1px solid #eef3ea}td.n{text-align:right;font-variant-numeric:tabular-nums}.muted{color:#5b6a52}</style></head><body><header><h1>Your regenerative landscape</h1></header><main>" as *u8)
156
157 // rainwater + 3D-printed concrete structure
158 o = as_append(out, o, "<div class='tile'><h2>Rainwater → 3D-printed concrete cistern</h2><div class='big'>" as *u8)
159 o = fd_apnum(out, o, cap); o = as_append(out, o, " litres / year</div><p class='muted'>captured from a " as *u8)
160 o = fd_apnum(out, o, roof_m2); o = as_append(out, o, " m² roof at " as *u8); o = fd_apnum(out, o, rainfall_mm)
161 o = as_append(out, o, " mm rainfall (80% runoff). Stored in a 3D-printed concrete cistern (≈ " as *u8)
162 o = fd_apnum(out, o, cap / 1000); o = as_append(out, o, " m³) whose wall doubles as a climbing trellis.</p></div>" as *u8)
163
164 let ids: *i64 = sys_mmap(8 * 64) as *i64
165 let nids: i64 = ec_list(prefix, ids)
166
167 // climbers on the structure
168 o = as_append(out, o, "<div class='tile'><h2>On the concrete wall (climbing, useful)</h2><table><tr><th>Plant</th><th>Why</th><th>Value</th></tr>" as *u8)
169 var i: i64 = 0
170 while i < nids {
171 let id: *u8 = ids[i] as *u8
172 if ec_climbing(prefix, id) == 1 {
173 o = as_append(out, o, "<tr><td>" as *u8)
174 let nm: *u8 = sys_mmap(48); ec_field_str(prefix, id, 0, nm); o = as_append_escaped(out, o, nm, as_len(nm))
175 o = as_append(out, o, "</td><td class='muted'>" as *u8)
176 if ec_edible(prefix, id) == 1 { o = as_append(out, o, "food " as *u8) }
177 if ec_med(prefix, id) >= 5 { o = as_append(out, o, "medicine " as *u8) }
178 if ec_wild(prefix, id) >= 6 { o = as_append(out, o, "wildlife" as *u8) }
179 o = as_append(out, o, "</td><td class='n'>" as *u8); o = fd_apnum(out, o, ec_value(prefix, id, wfood, wmed, wwild))
180 o = as_append(out, o, "</td></tr>" as *u8)
181 }
182 i = i + 1
183 }
184 o = as_append(out, o, "</table></div>" as *u8)
185
186 // wildlife guild that resists damage
187 o = as_append(out, o, "<div class='tile'><h2>Shares with wildlife, resists damage</h2><table><tr><th>Plant</th><th>Wildlife</th><th>Deer-proof</th><th>Value</th></tr>" as *u8)
188 i = 0
189 while i < nids {
190 let id: *u8 = ids[i] as *u8
191 if ec_share_safe(prefix, id) == 1 {
192 o = as_append(out, o, "<tr><td>" as *u8)
193 let nm: *u8 = sys_mmap(48); ec_field_str(prefix, id, 0, nm); o = as_append_escaped(out, o, nm, as_len(nm))
194 o = as_append(out, o, "</td><td class='n'>" as *u8); o = fd_apnum(out, o, ec_wild(prefix, id))
195 o = as_append(out, o, "</td><td class='n'>" as *u8); o = fd_apnum(out, o, ec_deer(prefix, id))
196 o = as_append(out, o, "</td><td class='n'>" as *u8); o = fd_apnum(out, o, ec_value(prefix, id, wfood, wmed, wwild))
197 o = as_append(out, o, "</td></tr>" as *u8)
198 }
199 i = i + 1
200 }
201 o = as_append(out, o, "</table><p class='muted'>High wildlife value + deer-resistant: feed the pollinators and birds without feeding the deer.</p></div>" as *u8)
202
203 o = as_append(out, o, "<p class='muted' style='text-align:center'>Plants valued across food + medicine + wildlife. Grounded in the Nishi permaculture corpus. Optimal use of the environment, while improving it.</p></main></body></html>" as *u8)
204 out[o] = 0 as u8
205 return o
206}