nx_civicmap.nx source
↩ module page · 393 lines · 16374 B
1// nx_civicmap.nx -- the VERBS of the civic quality-of-life map. All judgement lives in
2// nx_civicmap_lib.nx; this file is argv, defaults and exit codes, so the logic stays testable
3// in-process by nx_civicmap_gate and reachable by the mutation harness.
4//
5// admit [layers.conf] -- CM1: run the refusing door over every layer row
6// join <counties.conf> <lat_ud> <lon_ud> -- CM2: which county contains this point
7// emit <title> [out] [counties] [values] [layers] -- CM3: render the honest choropleth
8//
9// EXIT CODES: 0 ran, 1 a partition did not sum (an internal leak, never a data verdict), 3 UNPROVEN --
10// a conf that could not be read is "I could not look", which is not "there is nothing there".
11// A REFUSED LAYER IS NOT A FAILURE OF THIS ORGAN: refusing an unlicensed or unmirrored row IS the
12// organ working, so refusals are reported and counted, never turned into a non-zero exit.
13// license_tier: ORIGINAL No hardware writes (Rule 26).
14import "nx_syscalls.nx"
15import "nx_estate_path.nx"
16import "nx_civicmap_lib.nx"
17func cm_usage() -> i64 {
18 cm_w(1, "usage: nx_civicmap admit [layers.conf] | join <counties.conf> <lat_microdeg> <lon_microdeg> | emit <title> [out] [counties.conf] [values.conf] [layers.conf]\n" as *u8)
19 return 0
20}
21
22// ---- verb: admit. CM1 over the whole layer file, with the reason on every refused row. --------------
23func cm_do_admit(path: *u8) -> i64 {
24 let ap: *u8 = sys_mmap(CM_PATHCAP)
25 if ep_artifact_path(ap, path) == 0 {
26 cm_w(1, "CIVICMAP admit UNPROVEN: layer conf not found from any estate root: " as *u8)
27 cm_w(1, path)
28 cm_w(1, "\n (this is 'I could not look', not 'there are no layers' -- no admission claim is made)\n" as *u8)
29 return 3
30 }
31 let ln: *i64 = sys_mmap(8) as *i64
32 let buf: *u8 = sys_read_file(ap, ln)
33 let n: i64 = ln[0]
34 if n <= 0 {
35 cm_w(1, "CIVICMAP admit UNPROVEN: layer conf is empty\n" as *u8)
36 return 3
37 }
38 let f: *i64 = sys_mmap(CM_SCRATCH) as *i64
39 var rows: i64 = 0
40 var admitted: i64 = 0
41 var refused: i64 = 0
42 var p: i64 = 0
43 while p < n {
44 let le: i64 = cm_to(buf, p, n, CM_NL)
45 if le > p {
46 if cm_starts(buf, p, le, "layer|" as *u8) == 1 {
47 rows = rows + 1
48 let v: i64 = cm_layer_admit(buf, p, le, f)
49 if v == CM_ADMIT {
50 admitted = admitted + 1
51 if cm_fld(buf, p, le, CM_LF_KEY, f) == 1 {
52 cm_w(1, " ADMIT " as *u8)
53 cm_span(1, buf, f[0], f[1])
54 if cm_fld(buf, p, le, CM_LF_LICENCE, f) == 1 {
55 cm_w(1, " licence=" as *u8)
56 cm_span(1, buf, f[0], f[1])
57 }
58 if cm_fld(buf, p, le, CM_LF_RES, f) == 1 {
59 cm_w(1, " resolution=" as *u8)
60 cm_span(1, buf, f[0], f[1])
61 }
62 if cm_fld(buf, p, le, CM_LF_CADENCE, f) == 1 {
63 cm_w(1, " cadence=" as *u8)
64 cm_span(1, buf, f[0], f[1])
65 }
66 cm_w(1, "\n" as *u8)
67 }
68 } else {
69 refused = refused + 1
70 cm_w(1, " " as *u8)
71 cm_w(1, cm_refuse_name(v))
72 cm_w(1, " row=" as *u8)
73 if cm_fld(buf, p, le, CM_LF_KEY, f) == 1 { cm_span(1, buf, f[0], f[1]) } else { cm_w(1, "<unparseable>" as *u8) }
74 cm_w(1, "\n" as *u8)
75 }
76 }
77 }
78 p = le + 1
79 }
80 cm_w(1, "CIVICMAP admit rows=" as *u8)
81 cm_n(1, rows)
82 cm_w(1, " admitted=" as *u8)
83 cm_n(1, admitted)
84 cm_w(1, " refused=" as *u8)
85 cm_n(1, refused)
86 cm_w(1, " parts_sum=" as *u8)
87 if admitted + refused == rows { cm_w(1, "OK" as *u8) } else { cm_w(1, "LEAK" as *u8) }
88 cm_w(1, "\n" as *u8)
89 if admitted + refused != rows { return 1 }
90 return 0
91}
92
93func cm_do_join(cpath: *u8, lat: i64, lon: i64) -> i64 {
94 let ctx: *i64 = sys_mmap(CM_CTX_BYTES) as *i64
95 let nc: i64 = cm_load_counties(cpath, ctx)
96 if nc < 0 {
97 cm_w(1, "CIVICMAP join UNPROVEN: county conf unreadable\n" as *u8)
98 return 3
99 }
100 cm_load_report(1, ctx)
101 if nc == 0 {
102 cm_w(1, "CIVICMAP join UNPROVEN: zero counties loaded -- a join over an empty base proves nothing\n" as *u8)
103 return 3
104 }
105 let pts: *i64 = sys_mmap(16) as *i64
106 pts[0] = lat
107 pts[1] = lon
108 let out: *i64 = sys_mmap(8) as *i64
109 let hit: i64 = cm_fips_join(pts, 1, ctx[0] as *i64, ctx[1] as *i64, ctx[2] as *i64, nc, ctx[3] as *i64, out)
110 cm_w(1, "CIVICMAP join counties=" as *u8)
111 cm_n(1, nc)
112 cm_w(1, " lat=" as *u8)
113 cm_n(1, lat)
114 cm_w(1, " lon=" as *u8)
115 cm_n(1, lon)
116 if hit == 1 {
117 cm_w(1, " fips=" as *u8)
118 cm_n(1, out[0])
119 cm_w(1, " verdict=JOINED\n" as *u8)
120 return 0
121 }
122 cm_w(1, " fips=none verdict=OUTSIDE-LOADED-COVERAGE (not a zero: the point lies outside the counties loaded)\n" as *u8)
123 return 0
124}
125
126// ---- verb: emit. The whole M0 pipeline: admit layers, load counties, load values, render. ------------
127func cm_do_emit(title: *u8, outpath: *u8, cpath: *u8, vpath: *u8, lpath: *u8) -> i64 {
128 let ctx: *i64 = sys_mmap(CM_CTX_BYTES) as *i64
129 let nc: i64 = cm_load_counties(cpath, ctx)
130 if nc < 0 {
131 cm_w(1, "CIVICMAP emit UNPROVEN: county conf unreadable\n" as *u8)
132 return 3
133 }
134 cm_load_report(1, ctx)
135 if nc == 0 {
136 cm_w(1, "CIVICMAP emit UNPROVEN: zero counties loaded -- refusing to publish a map of nothing\n" as *u8)
137 return 3
138 }
139 // SIZED FROM THE ACTUAL COUNTY COUNT, not from a ceiling. Removing the loader's guessed cap exposed
140 // these two as the second place that depended on it -- and nc is strictly more correct, because these
141 // arrays are indexed by county index 0..nc-1 and can never legitimately need a slot beyond that.
142 // nc >= 1 is guaranteed here: the zero case returned UNPROVEN above rather than reaching this line.
143 let val: *i64 = sys_mmap(8 * nc) as *i64
144 let st: *i64 = sys_mmap(8 * nc) as *i64
145 var i: i64 = 0
146 while i < nc {
147 val[i] = 0
148 st[i] = CM_V_ABSENT
149 i = i + 1
150 }
151 // values: every county starts ABSENT and is only promoted by an actual observation. The default is
152 // the honest one -- a county nobody measured must not inherit a number from anywhere.
153 var vlo: i64 = 0
154 var vhi: i64 = 0
155 var seen: i64 = 0
156 // the value lane gets the SAME drop accounting the county lane already has. It had none, so a typo
157 // in a FIPS or a short row vanished and the county then rendered as never-measured.
158 var v_rows: i64 = 0
159 var v_shape: i64 = 0
160 var v_nocounty: i64 = 0
161 var v_unreadable: i64 = 0
162 let ap: *u8 = sys_mmap(CM_PATHCAP)
163 if ep_artifact_path(ap, vpath) == 1 {
164 let ln: *i64 = sys_mmap(8) as *i64
165 let vb: *u8 = sys_read_file(ap, ln)
166 let vn: i64 = ln[0]
167 let f: *i64 = sys_mmap(CM_SCRATCH) as *i64
168 var p: i64 = 0
169 while p < vn {
170 let le: i64 = cm_to(vb, p, vn, CM_NL)
171 if le > p {
172 if cm_starts(vb, p, le, "value|" as *u8) == 1 {
173 v_rows = v_rows + 1
174 if cm_nfields(vb, p, le) < CM_VF_MIN { v_shape = v_shape + 1 }
175 if cm_nfields(vb, p, le) >= CM_VF_MIN {
176 if cm_fld(vb, p, le, CM_VF_FIPS, f) == 1 {
177 let fp: i64 = cm_fips_parse(vb, f[0], f[1])
178 let ci: i64 = cm_fips_index(ctx[3] as *i64, nc, fp)
179 if ci < 0 { v_nocounty = v_nocounty + 1 }
180 if ci >= 0 {
181 var used: i64 = 0
182 if cm_fld(vb, p, le, CM_VF_VAL, f) == 1 {
183 if cm_eqlit(vb, f[0], f[1], "SUPPRESSED" as *u8) == 1 {
184 st[ci] = CM_V_SUPPRESSED
185 used = 1
186 } else {
187 if cm_empty(vb, f[0], f[1]) == 0 {
188 let v: i64 = cm_int(vb, f[0], f[1])
189 val[ci] = v
190 st[ci] = CM_V_PRESENT
191 used = 1
192 if seen == 0 { vlo = v; vhi = v; seen = 1 } else {
193 if v < vlo { vlo = v }
194 if v > vhi { vhi = v }
195 }
196 }
197 }
198 }
199 // A ROW WAS OFFERED FOR A COUNTY ON THIS MAP AND COULD NOT BE READ.
200 // Leaving it CM_V_ABSENT would publish 'no-observation' -- a FALSE named
201 // reason -- so it is marked REJECTED and says so on the page instead.
202 if used == 0 {
203 st[ci] = CM_V_REJECTED
204 v_unreadable = v_unreadable + 1
205 }
206 }
207 }
208 }
209 }
210 }
211 p = le + 1
212 }
213 }
214 // bbox over the loaded counties, then the projection.
215 let pool: *i64 = ctx[0] as *i64
216 let off: *i64 = ctx[1] as *i64
217 let cnt: *i64 = ctx[2] as *i64
218 var latmin: i64 = 0
219 var latmax: i64 = 0
220 var lonmin: i64 = 0
221 var lonmax: i64 = 0
222 var first: i64 = 0
223 var c: i64 = 0
224 while c < nc {
225 var k: i64 = 0
226 while k < cnt[c] {
227 let la: i64 = pool[(off[c] + k) * 2]
228 let lo: i64 = pool[(off[c] + k) * 2 + 1]
229 if first == 0 { latmin = la; latmax = la; lonmin = lo; lonmax = lo; first = 1 } else {
230 if la < latmin { latmin = la }
231 if la > latmax { latmax = la }
232 if lo < lonmin { lonmin = lo }
233 if lo > lonmax { lonmax = lo }
234 }
235 k = k + 1
236 }
237 c = c + 1
238 }
239 var lonrange: i64 = lonmax - lonmin
240 var latrange: i64 = latmax - latmin
241 if lonrange <= 0 { lonrange = 1 }
242 if latrange <= 0 { latrange = 1 }
243 var wpx: i64 = CM_H * lonrange * CM_ASPECT_NUM / (latrange * CM_ASPECT_DEN)
244 if wpx < CM_W_MIN { wpx = CM_W_MIN }
245 if wpx > CM_W_MAX { wpx = CM_W_MAX }
246 let pj: *i64 = sys_mmap(8 * 8) as *i64
247 pj[0] = lonmin
248 pj[1] = latmax
249 pj[2] = lonrange
250 pj[3] = latrange
251 pj[4] = wpx
252 pj[5] = CM_H
253 pj[6] = vlo
254 pj[7] = vhi
255 // the provenance block: the admitted layers, printed onto the page itself. A page that renders data
256 // whose terms it cannot state is the thing this domain exists to refuse.
257 let prov: *u8 = sys_mmap(CM_PROVCAP)
258 var po: i64 = 0
259 let lp: *u8 = sys_mmap(CM_PATHCAP)
260 var nlay: i64 = 0
261 var nref: i64 = 0
262 if ep_artifact_path(lp, lpath) == 1 {
263 let ln2: *i64 = sys_mmap(8) as *i64
264 let lb: *u8 = sys_read_file(lp, ln2)
265 let lnn: i64 = ln2[0]
266 let f2: *i64 = sys_mmap(CM_SCRATCH) as *i64
267 var q: i64 = 0
268 var opened: i64 = 0
269 while q < lnn {
270 let le2: i64 = cm_to(lb, q, lnn, CM_NL)
271 if le2 > q {
272 if cm_starts(lb, q, le2, "layer|" as *u8) == 1 {
273 let v2: i64 = cm_layer_admit(lb, q, le2, f2)
274 if v2 == CM_ADMIT {
275 nlay = nlay + 1
276 if opened == 0 {
277 po = cm_cat(prov, po, "<table><tr><th>layer</th><th>licence</th><th>resolution</th><th>cadence</th><th>evidence mirror</th></tr>\n" as *u8, CM_PROVCAP)
278 opened = 1
279 }
280 po = cm_cat(prov, po, "<tr><td>" as *u8, CM_PROVCAP)
281 var fldi: i64 = CM_LF_TITLE
282 while fldi <= CM_LF_MIRROR {
283 if fldi != CM_LF_URL {
284 if cm_fld(lb, q, le2, fldi, f2) == 1 {
285 po = cm_cat_span(prov, po, lb, f2[0], f2[1], CM_PROVCAP)
286 }
287 if fldi < CM_LF_MIRROR {
288 po = cm_cat(prov, po, "</td><td>" as *u8, CM_PROVCAP)
289 }
290 }
291 fldi = fldi + 1
292 }
293 po = cm_cat(prov, po, "</td></tr>\n" as *u8, CM_PROVCAP)
294 } else {
295 nref = nref + 1
296 }
297 }
298 }
299 q = le2 + 1
300 }
301 if opened == 1 { po = cm_cat(prov, po, "</table>\n" as *u8, CM_PROVCAP) }
302 }
303 let drawn: i64 = cm_choropleth_emit(outpath, pool, off, cnt, ctx[3] as *i64, val, st, nc, pj, title, prov, po)
304 if drawn < 0 {
305 cm_w(1, "CIVICMAP emit FAILED rc=" as *u8)
306 cm_n(1, drawn)
307 cm_w(1, " (-1 cannot open output, -2 the coverage partition did not sum)\n" as *u8)
308 return 1
309 }
310 var np: i64 = 0
311 var nu: i64 = 0
312 i = 0
313 while i < nc {
314 if st[i] == CM_V_PRESENT { np = np + 1 } else { nu = nu + 1 }
315 i = i + 1
316 }
317 cm_w(1, "CIVICMAP emit wrote=" as *u8)
318 cm_w(1, outpath)
319 cm_w(1, " counties=" as *u8)
320 cm_n(1, nc)
321 cm_w(1, " drawn=" as *u8)
322 cm_n(1, drawn)
323 cm_w(1, " present=" as *u8)
324 cm_n(1, np)
325 cm_w(1, " unobservable=" as *u8)
326 cm_n(1, nu)
327 cm_w(1, " layers_admitted=" as *u8)
328 cm_n(1, nlay)
329 cm_w(1, " layers_refused=" as *u8)
330 cm_n(1, nref)
331 cm_w(1, " vlo=" as *u8)
332 cm_n(1, vlo)
333 cm_w(1, " vhi=" as *u8)
334 cm_n(1, vhi)
335 cm_w(1, " parts_sum=" as *u8)
336 if np + nu == nc { cm_w(1, "OK" as *u8) } else { cm_w(1, "LEAK" as *u8) }
337 cm_w(1, " value_rows=" as *u8)
338 cm_n(1, v_rows)
339 cm_w(1, " v_dropped_shape=" as *u8)
340 cm_n(1, v_shape)
341 cm_w(1, " v_dropped_no_such_county=" as *u8)
342 cm_n(1, v_nocounty)
343 cm_w(1, " v_unreadable=" as *u8)
344 cm_n(1, v_unreadable)
345 cm_w(1, " SCOPE=exactly-the-counties-loaded-no-national-claim\n" as *u8)
346 if np + nu != nc { return 1 }
347 return 0
348}
349
350func main(argc: i64, argv: *i64) -> i64 {
351 if argc < 2 { cm_usage(); sys_exit(3); return 3 }
352 let v: *u8 = argv[1] as *u8
353 var vn: i64 = 0
354 while v[vn] != (0 as u8) { vn = vn + 1 }
355 if cm_eqlit(v, 0, vn, "admit" as *u8) == 1 {
356 var lp: *u8 = "knowledge/civicmap_layers.conf" as *u8
357 if argc > 2 { lp = argv[2] as *u8 }
358 let rc: i64 = cm_do_admit(lp)
359 sys_exit(rc)
360 return rc
361 }
362 if cm_eqlit(v, 0, vn, "join" as *u8) == 1 {
363 if argc < 5 { cm_usage(); sys_exit(3); return 3 }
364 let cp: *u8 = argv[2] as *u8
365 let la: *u8 = argv[3] as *u8
366 let lo: *u8 = argv[4] as *u8
367 var lan: i64 = 0
368 while la[lan] != (0 as u8) { lan = lan + 1 }
369 var lon: i64 = 0
370 while lo[lon] != (0 as u8) { lon = lon + 1 }
371 let rc: i64 = cm_do_join(cp, cm_int(la, 0, lan), cm_int(lo, 0, lon))
372 sys_exit(rc)
373 return rc
374 }
375 if cm_eqlit(v, 0, vn, "emit" as *u8) == 1 {
376 if argc < 3 { cm_usage(); sys_exit(3); return 3 }
377 let ti: *u8 = argv[2] as *u8
378 var op: *u8 = "/tmp/civicmap.html" as *u8
379 if argc > 3 { op = argv[3] as *u8 }
380 var cp: *u8 = "knowledge/civicmap_counties.conf" as *u8
381 if argc > 4 { cp = argv[4] as *u8 }
382 var vp: *u8 = "knowledge/civicmap_values.conf" as *u8
383 if argc > 5 { vp = argv[5] as *u8 }
384 var lp: *u8 = "knowledge/civicmap_layers.conf" as *u8
385 if argc > 6 { lp = argv[6] as *u8 }
386 let rc: i64 = cm_do_emit(ti, op, cp, vp, lp)
387 sys_exit(rc)
388 return rc
389 }
390 cm_usage()
391 sys_exit(3)
392 return 3
393}