code wiki / _hdl_build / nx_activities.nx

nx_activities.nx source

↩ module page · 171 lines · 9606 B

1// nx_activities.nx -- LIB: the REAL VALUE of popular homestead activities (operator: "gamification for LOTS of 2// these popular activities but not dumb rewards but real rewards and real positives and real capabilities"). For 3// each activity a person does, this computes the REAL, MEASURED positive -- money kept or value created -- from 4// REFERENCE PRICES (grounded, each with a source), NEVER an invented number. The output feeds nx_rewards as a 5// real VALUE reward. Activities: compost (fertilizer not bought), cook-from-pantry (takeout not bought), 6// seed-saving (seed packets not bought), preserve/can (out-of-season value), rainwater (water not bought). 7// Sovereign seg-store (knowledge/store/act-*, NO TSV), integer cents. license_tier: ORIGINAL 8import "nx_food_science.nx" 9import "nx_seg_store.nx" 10import "nx_syscalls.nx" 11 12func ac_put(prefix: *u8, key: *u8, val: *u8) -> i64 { 13 let vl: i64 = as_len(val) 14 if fd_streq_store(prefix, key, val, vl) == 1 { return 0 } 15 let w: *i64 = ss_begin() 16 ss_add(w, 1, key, val, vl) 17 let seg: i64 = fd_seg_next(prefix) 18 ss_commit(prefix, w, seg) 19 return 1 20} 21func ac_money(dst: *u8, off: i64, cents: i64) -> i64 { 22 var o: i64 = off 23 dst[o] = 36 as u8; o = o + 1 24 o = fd_apnum(dst, o, cents / 100) 25 dst[o] = 46 as u8; o = o + 1 26 let r: i64 = cents % 100 27 dst[o] = (48 + (r / 10)) as u8; o = o + 1 28 dst[o] = (48 + (r % 10)) as u8; o = o + 1 29 return o 30} 31 32// reference price (grounded): act:ref:<item> -> price_cents <t> unit <t> source 33func ac_set_ref(prefix: *u8, item: *u8, price_cents: i64, unit: *u8, source: *u8) -> i64 { 34 let key: *u8 = sys_mmap(96); var o: i64 = 0; o = as_append(key, o, "act:ref:" as *u8); o = as_append(key, o, item); key[o] = 0 as u8 35 let val: *u8 = sys_mmap(160); var v: i64 = 0 36 v = fd_apnum(val, v, price_cents); val[v] = 9 as u8; v = v + 1 37 v = as_append(val, v, unit); val[v] = 9 as u8; v = v + 1 38 v = as_append(val, v, source); val[v] = 0 as u8 39 return ac_put(prefix, key, val) 40} 41// reference price in cents, or -1 if not set (un-grounded -> value calc returns 0, never invents). 42func ac_ref(prefix: *u8, item: *u8) -> i64 { 43 let key: *u8 = sys_mmap(96); var o: i64 = 0; o = as_append(key, o, "act:ref:" as *u8); o = as_append(key, o, item); key[o] = 0 as u8 44 let pq: *i64 = sys_mmap(16) as *i64 45 let lq: *i64 = sys_mmap(16) as *i64 46 if ss_get(prefix, key, pq, lq) != 1 { return 0 - 1 } 47 let fb: *u8 = sys_mmap(24) 48 let fl: i64 = fd_field(pq[0] as *u8, lq[0], 0, fb) 49 return fd_atoi(fb, fl) 50} 51 52// the REAL value (cents) of doing `activity` at `quantity`, computed from reference prices. Unknown activity or 53// a missing reference -> 0 (honest: no grounding, no value; never a fabricated number). 54func ac_value_of(prefix: *u8, activity: *u8, quantity: i64) -> i64 { 55 if quantity <= 0 { return 0 } 56 if fd_streq(activity, "compost" as *u8) == 1 { // cubic feet of finished compost not bought 57 let p: i64 = ac_ref(prefix, "compost_cuft" as *u8) 58 if p < 0 { return 0 } 59 return quantity * p 60 } 61 if fd_streq(activity, "seedsave" as *u8) == 1 { // seed packets not bought next season 62 let p: i64 = ac_ref(prefix, "seed_packet" as *u8) 63 if p < 0 { return 0 } 64 return quantity * p 65 } 66 if fd_streq(activity, "cookpantry" as *u8) == 1 { // meals: takeout avoided minus home ingredient cost 67 let t: i64 = ac_ref(prefix, "takeout_meal" as *u8) 68 let h: i64 = ac_ref(prefix, "home_meal" as *u8) 69 if t < 0 { return 0 } 70 if h < 0 { return 0 } 71 let net: i64 = t - h 72 if net <= 0 { return 0 } 73 return quantity * net 74 } 75 if fd_streq(activity, "preserve" as *u8) == 1 { // jars of preserved/canned produce value 76 let p: i64 = ac_ref(prefix, "preserve_jar" as *u8) 77 if p < 0 { return 0 } 78 return quantity * p 79 } 80 if fd_streq(activity, "rainwater" as *u8) == 1 { // 100-gallon units of water not bought 81 let p: i64 = ac_ref(prefix, "water_100gal" as *u8) 82 if p < 0 { return 0 } 83 return quantity * p 84 } 85 return 0 86} 87 88// additive activity log: act:log:<uid>:<seq> -> activity <t> quantity <t> day <t> note ; act:logn:<uid> count 89func ac_logn_key(uid: *u8, out: *u8) -> i64 { var o: i64 = 0; o = as_append(out, o, "act:logn:" as *u8); o = as_append(out, o, uid); out[o] = 0 as u8; return o } 90func ac_log_key(uid: *u8, seq: i64, out: *u8) -> i64 { var o: i64 = 0; o = as_append(out, o, "act:log:" as *u8); o = as_append(out, o, uid); out[o] = 58 as u8; o = o + 1; o = fd_apnum(out, o, seq); out[o] = 0 as u8; return o } 91func ac_logn(prefix: *u8, uid: *u8) -> i64 { 92 let key: *u8 = sys_mmap(96); ac_logn_key(uid, key) 93 let pq: *i64 = sys_mmap(16) as *i64 94 let lq: *i64 = sys_mmap(16) as *i64 95 if ss_get(prefix, key, pq, lq) != 1 { return 0 } 96 return fd_atoi(pq[0] as *u8, lq[0]) 97} 98func ac_log(prefix: *u8, uid: *u8, activity: *u8, quantity: i64, day: i64, note: *u8) -> i64 { 99 let seq: i64 = ac_logn(prefix, uid) 100 let key: *u8 = sys_mmap(96); ac_log_key(uid, seq, key) 101 let val: *u8 = sys_mmap(256); var v: i64 = 0 102 v = as_append(val, v, activity); val[v] = 9 as u8; v = v + 1 103 v = fd_apnum(val, v, quantity); val[v] = 9 as u8; v = v + 1 104 v = fd_apnum(val, v, day); val[v] = 9 as u8; v = v + 1 105 v = as_append(val, v, note); val[v] = 0 as u8 106 ac_put(prefix, key, val) 107 let nk: *u8 = sys_mmap(96); ac_logn_key(uid, nk) 108 let nv: *u8 = sys_mmap(16); var no: i64 = fd_apnum(nv, 0, seq + 1); nv[no] = 0 as u8 109 ac_put(prefix, nk, nv) 110 return seq 111} 112func ac_log_str(prefix: *u8, uid: *u8, seq: i64, f: i64, out: *u8) -> i64 { 113 let key: *u8 = sys_mmap(96); ac_log_key(uid, seq, key) 114 let pq: *i64 = sys_mmap(16) as *i64 115 let lq: *i64 = sys_mmap(16) as *i64 116 if ss_get(prefix, key, pq, lq) != 1 { out[0] = 0 as u8; return 0 } 117 return fd_field(pq[0] as *u8, lq[0], f, out) 118} 119func ac_log_int(prefix: *u8, uid: *u8, seq: i64, f: i64) -> i64 { 120 let fb: *u8 = sys_mmap(24) 121 let fl: i64 = ac_log_str(prefix, uid, seq, f, fb) 122 if fl == 0 { return 0 } 123 return fd_atoi(fb, fl) 124} 125 126// total REAL value across everything the user has logged (the real positive of their habits). 127func ac_user_value(prefix: *u8, uid: *u8) -> i64 { 128 let n: i64 = ac_logn(prefix, uid) 129 var s: i64 = 0 130 var i: i64 = 0 131 while i < n { 132 let act: *u8 = sys_mmap(48); ac_log_str(prefix, uid, i, 0, act) 133 let q: i64 = ac_log_int(prefix, uid, i, 1) 134 s = s + ac_value_of(prefix, act, q) 135 i = i + 1 136 } 137 return s 138} 139 140func ac_activity_label(activity: *u8) -> *u8 { 141 if fd_streq(activity, "compost" as *u8) == 1 { return "Composting" as *u8 } 142 if fd_streq(activity, "seedsave" as *u8) == 1 { return "Seed saving" as *u8 } 143 if fd_streq(activity, "cookpantry" as *u8) == 1 { return "Cooking from the pantry" as *u8 } 144 if fd_streq(activity, "preserve" as *u8) == 1 { return "Preserving &amp; canning" as *u8 } 145 if fd_streq(activity, "rainwater" as *u8) == 1 { return "Rainwater harvesting" as *u8 } 146 return "Activity" as *u8 147} 148 149// render the user's REAL positives (each activity + measured value + total). Sovereign, honest grounding note. 150func ac_render(prefix: *u8, uid: *u8, out: *u8) -> i64 { 151 var o: i64 = 0 152 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>Real positives</title><style>body{margin:0;font-family:system-ui,sans-serif;color:#1a2616;background:#eef6ea;line-height:1.5}header{background:#3a6b2f;color:#fff;padding:22px}header h1{margin:0;font-size:1.4rem}header p{margin:4px 0 0;color:#d7efce}main{max-width:680px;margin:0 auto;padding:16px}section{background:#fff;border-radius:14px;padding:16px 18px;margin-top:16px;box-shadow:0 1px 0 #dcebd3}h2{font-size:1.1rem;margin:0 0 8px;color:#3a6b2f}.tot{font-size:1.7rem;font-weight:800;color:#2f7a1f}table{border-collapse:collapse;width:100%}td,th{padding:8px 10px;text-align:left;border-top:1px solid #eef3e2}th{background:#e6efe1;color:#33503f}td.n{text-align:right;font-variant-numeric:tabular-nums;font-weight:700;color:#2f7a1f}.muted{color:#5b6a52;font-size:.88rem}</style></head><body><header><h1>Your real positives</h1><p>The measured value of the good things you actually did.</p></header><main>" as *u8) 153 o = as_append(out, o, "<section><h2>Value created this season</h2><p class='tot'>" as *u8) 154 o = ac_money(out, o, ac_user_value(prefix, uid)) 155 o = as_append(out, o, "</p></section><section><h2>How you earned it</h2><table><tr><th>Activity</th><th>Amount</th><th>Real value</th></tr>" as *u8) 156 let n: i64 = ac_logn(prefix, uid) 157 var i: i64 = 0 158 while i < n { 159 let act: *u8 = sys_mmap(48); ac_log_str(prefix, uid, i, 0, act) 160 let q: i64 = ac_log_int(prefix, uid, i, 1) 161 o = as_append(out, o, "<tr><td>" as *u8) 162 o = as_append(out, o, ac_activity_label(act)) 163 o = as_append(out, o, "</td><td>" as *u8); o = fd_apnum(out, o, q) 164 o = as_append(out, o, "</td><td class='n'>" as *u8); o = ac_money(out, o, ac_value_of(prefix, act, q)) 165 o = as_append(out, o, "</td></tr>" as *u8) 166 i = i + 1 167 } 168 o = as_append(out, o, "</table></section><p class='muted'>Each value is measured from reference prices (what you'd have paid), each with a source &mdash; not points, not invented. Real positives, real money kept.</p></main></body></html>" as *u8) 169 out[o] = 0 as u8 170 return o 171}