code wiki / (root) / nx_intake_profile.nx

nx_intake_profile.nx source

↩ module page · 72 lines · 3167 B

1// nx_intake_profile.nx -- R6c: the LATEST-PROFILE loader, so the live dashboard + before-you-buy run on the 2// PERSON's submitted numbers, not the demo. When the intake handler records a profile (a content-addressed 3// survey record keyed by its CID), it ALSO writes a pointer "intake:latest:<respondent>" -> that CID (last- 4// wins). `ip_get` reads the pointer, loads the profile, and returns a field's value -- or a DEFAULT if the 5// person hasn't submitted yet (graceful fallback: real numbers when present, the worked example otherwise). 6// Reuses nx_survey (sv_load/sv_get/sv_atoi) + nx_seg_store. No floats, no hardware writes. license_tier: ORIGINAL 7import "nx_syscalls.nx" 8import "nx_seg_store.nx" 9import "nx_survey.nx" 10 11func ip_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 12 13// build the pointer key "intake:latest:<respondent>" into out (NUL-terminated); returns length. 14func ip_key(respondent: *u8, out: *u8) -> i64 { 15 var o: i64 = 0 16 let p: *u8 = "intake:latest:\x00" as *u8 17 var i: i64 = 0 18 while p[i] != (0 as u8) { out[o] = p[i]; o = o + 1; i = i + 1 } 19 i = 0 20 while respondent[i] != (0 as u8) { out[o] = respondent[i]; o = o + 1; i = i + 1 } 21 out[o] = 0 as u8 22 return o 23} 24 25// store the latest-profile pointer for a respondent (CID stored WITH its NUL so it reads back terminated). 26func ip_put_latest(prefix: *u8, respondent: *u8, cid: *u8) -> i64 { 27 let key: *u8 = sys_mmap(256) 28 ip_key(respondent, key) 29 let w: *i64 = ss_begin() 30 if ss_add(w, 1, key, cid, ip_len(cid) + 1) != 0 { return 0 - 1 } 31 if ss_commit(prefix, w, sys_now_us()) != 0 { return 0 - 2 } 32 return 0 33} 34 35// 1 if a profile exists for this respondent, else 0. 36func ip_exists(prefix: *u8, respondent: *u8) -> i64 { 37 let key: *u8 = sys_mmap(256) 38 ip_key(respondent, key) 39 let h: *i64 = ss_open(prefix) 40 if (h as i64) == 0 { return 0 } 41 let pp: *i64 = sys_mmap(16) as *i64 42 let ll: *i64 = sys_mmap(16) as *i64 43 if ss_hget(h, key, pp, ll) != 1 { return 0 } 44 return 1 45} 46 47// the latest profile's answer to `qid`, or `dflt` if no profile / field absent. 48func ip_get(prefix: *u8, respondent: *u8, qid: *u8, dflt: i64) -> i64 { 49 let key: *u8 = sys_mmap(256) 50 ip_key(respondent, key) 51 let h: *i64 = ss_open(prefix) 52 if (h as i64) == 0 { return dflt } 53 let pp: *i64 = sys_mmap(16) as *i64 54 let ll: *i64 = sys_mmap(16) as *i64 55 if ss_hget(h, key, pp, ll) != 1 { return dflt } 56 let cid: *u8 = pp[0] as *u8 57 let k: *i64 = sys_mmap(8 * 64) as *i64 58 let d: *i64 = sys_mmap(8 * 64) as *i64 59 let nf: i64 = sv_load(prefix, cid, k, d, 64) 60 if nf <= 0 { return dflt } 61 let v: *u8 = sv_get(k, d, nf, qid) 62 if (v as i64) == 0 { return dflt } 63 return sv_atoi(v) 64} 65 66// like ip_get, but treats a stored 0 as "unset" -> returns the default. For MONEY/RATE/PAYMENT fields where 67// 0 is meaningless (the handler stores absent number fields as 0). NOT for flags, where 0 is a real answer. 68func ip_get_pos(prefix: *u8, respondent: *u8, qid: *u8, dflt: i64) -> i64 { 69 let v: i64 = ip_get(prefix, respondent, qid, dflt) 70 if v <= 0 { return dflt } 71 return v 72}