code wiki / (root) / nx_browser_buyguard.nx

nx_browser_buyguard.nx source

↩ module page · 136 lines · 6557 B

1// nx_browser_buyguard.nx -- the Nishi BROWSER's "before you buy" pass, on REAL page HTML (operator: "part 2// of the nishi browser ... showing what you have vs what it will cost and help with the opportunity costs"). 3// Composes the browser's ACTUAL pipeline organ nx_html_to_text (fetch -> html_to_text -> render): the browser 4// hands this the page HTML; the pass strips it to text (the real renderer path), finds the price 5// (px_find_price), runs the grounded purchase-decision engine (nx_purchase: opportunity cost EXACT via 6// nx_debt), and emits a zero-JS overlay the browser shows -- WHAT YOU HAVE vs WHAT IT TRULY COSTS. Advisory 7// only (autonomy). No price on the page -> ALLOW + empty overlay (does nothing). license_tier: ORIGINAL 8import "nx_syscalls.nx" 9import "nx_money.nx" 10import "nx_debt_payoff.nx" 11import "nx_adhd.nx" 12import "nx_html_to_text.nx" 13import "nx_price_extract.nx" 14import "nx_purchase.nx" 15 16// profile array indices (the person's real numbers; the intake survey fills these). 17const BGW_AVAIL: i64 = 0 // available discretionary cash (cents) 18const BGW_BAL: i64 = 1 // highest-interest debt balance (cents) 19const BGW_APR: i64 = 2 // its APR (scaled) 20const BGW_PAY: i64 = 3 // monthly payment (cents) 21const BGW_WAGE: i64 = 4 // hourly wage (cents) 22const BGW_GOAL: i64 = 5 // savings/buffer goal (cents) 23const BGW_THRESH: i64 = 6 // impulse pause threshold (cents) 24 25func bgw_cat(out: *u8, off: i64, s: *u8) -> i64 { 26 var o: i64 = off; var i: i64 = 0 27 while s[i] != (0 as u8) { out[o] = s[i]; o = o + 1; i = i + 1 } 28 return o 29} 30func bgw_n(out: *u8, off: i64, v: i64) -> i64 { 31 if v == 0 { out[off] = 0x30 as u8; return off + 1 } 32 let tmp: *u8 = sys_mmap(24); var m: i64 = v; var k: i64 = 0 33 while m > 0 { tmp[k] = (0x30 + (m % 10)) as u8; m = m / 10; k = k + 1 } 34 var o: i64 = off; var i: i64 = k - 1 35 while i >= 0 { out[o] = tmp[i]; o = o + 1; i = i - 1 } 36 return o 37} 38func bgw_money(out: *u8, off: i64, cents: i64) -> i64 { 39 var o: i64 = off; var c: i64 = cents 40 if c < 0 { out[o] = 0x2d as u8; o = o + 1; c = 0 - c } 41 out[o] = 0x24 as u8; o = o + 1 42 let dollars: i64 = c / 100 43 let cc: i64 = c - dollars * 100 44 o = bgw_n(out, o, dollars) 45 out[o] = 0x2e as u8; o = o + 1 46 out[o] = (0x30 + (cc / 10)) as u8; o = o + 1 47 out[o] = (0x30 + (cc % 10)) as u8; o = o + 1 48 return o 49} 50 51// Run the before-you-buy pass on a page's HTML using the person's profile. Writes the zero-JS overlay HTML 52// (NUL-terminated) to out; returns the advisory decision (ADHD_ALLOW/PAUSE/WARN). No price -> ALLOW, empty. 53func bgw_scan(html: *u8, html_len: i64, prof: *i64, out: *u8, cap: i64) -> i64 { 54 let text: *u8 = sys_mmap(html_len + 8192) 55 let tn: i64 = nx_html_to_text(html, html_len, text, html_len + 8192) 56 let price: i64 = px_find_price(text, tn) 57 if price < 0 { out[0] = 0 as u8; return ADHD_ALLOW } 58 let avail: i64 = prof[BGW_AVAIL] 59 let bal: i64 = prof[BGW_BAL] 60 let apr: i64 = prof[BGW_APR] 61 let pay: i64 = prof[BGW_PAY] 62 let wage: i64 = prof[BGW_WAGE] 63 let thresh: i64 = prof[BGW_THRESH] 64 let saved: i64 = pur_interest_saved(bal, apr, pay, price) 65 let truecost: i64 = pur_true_cost(price, saved) 66 let hours: i64 = pur_hours(price, wage) 67 let decision: i64 = pur_recommend(price, 1, thresh, avail) 68 var o: i64 = 0 69 o = bgw_cat(out, o, "<div class=\"nishi-buyguard\"><strong>Before you buy</strong> &mdash; this page is asking " as *u8) 70 o = bgw_money(out, o, price) 71 o = bgw_cat(out, o, ". You have " as *u8) 72 o = bgw_money(out, o, avail) 73 o = bgw_cat(out, o, ". It truly costs " as *u8) 74 o = bgw_money(out, o, truecost) 75 o = bgw_cat(out, o, " &mdash; that " as *u8) 76 o = bgw_money(out, o, price) 77 o = bgw_cat(out, o, " would save " as *u8) 78 o = bgw_money(out, o, saved) 79 o = bgw_cat(out, o, " in interest on your debt, and it is " as *u8) 80 o = bgw_n(out, o, hours) 81 o = bgw_cat(out, o, " hours of your life. " as *u8) 82 if decision == ADHD_PAUSE { o = bgw_cat(out, o, "Sleep on it 24h?" as *u8) } 83 else { if decision == ADHD_WARN { o = bgw_cat(out, o, "This is over your budget." as *u8) } else { o = bgw_cat(out, o, "Within your means." as *u8) } } 84 o = bgw_cat(out, o, "</div>" as *u8) 85 out[o] = 0 as u8 86 return decision 87} 88 89// find the byte index JUST AFTER the first "<body...>" open tag, so the overlay is inserted as flow 90// content where the layout engine expects it. Returns 0 (prepend) if there is no <body> tag. 91func bgw_find_body(raw: *u8, raw_len: i64) -> i64 { 92 var i: i64 = 0 93 while i + 5 <= raw_len { 94 if raw[i] == (0x3c as u8) { // '<' 95 let c1: i64 = raw[i+1] as i64 96 // case-insensitive "body" 97 if (c1 == 0x62) | (c1 == 0x42) { 98 let c2: i64 = raw[i+2] as i64; let c3: i64 = raw[i+3] as i64; let c4: i64 = raw[i+4] as i64 99 if (c2==0x6f)|(c2==0x4f) { if (c3==0x64)|(c3==0x44) { if (c4==0x79)|(c4==0x59) { 100 var j: i64 = i + 5 101 while j < raw_len { if raw[j] == (0x3e as u8) { return j + 1 } j = j + 1 } 102 return i // unterminated <body -> insert at the tag 103 } } } 104 } 105 } 106 i = i + 1 107 } 108 return 0 109} 110 111// INJECT the before-you-buy overlay into a page's HTML so the browser lays it out as a top-of-page box. 112// out = raw[0..body) + overlay-div + raw[body..end]. No price on the page -> out = an untouched copy 113// of raw (no overlay, the browser shows the page exactly as fetched). Returns the new length, NUL-term. 114// PURE (no network): the browser calls this on the fetched body right before br_layout. license-safe to gate. 115func bgw_inject(raw: *u8, raw_len: i64, prof: *i64, out: *u8, cap: i64) -> i64 { 116 let overlay: *u8 = sys_mmap(8192) 117 bgw_scan(raw, raw_len, prof, overlay, 8192) 118 if overlay[0] == (0 as u8) { 119 var c: i64 = 0 120 while c < raw_len { if c < cap - 1 { out[c] = raw[c] } c = c + 1 } 121 var en: i64 = raw_len 122 if en > cap - 1 { en = cap - 1 } 123 out[en] = 0 as u8 124 return en 125 } 126 let ins: i64 = bgw_find_body(raw, raw_len) 127 var o: i64 = 0 128 var i: i64 = 0 129 while i < ins { if o < cap - 1 { out[o] = raw[i]; o = o + 1 } i = i + 1 } 130 var k: i64 = 0 131 while overlay[k] != (0 as u8) { if o < cap - 1 { out[o] = overlay[k]; o = o + 1 } k = k + 1 } 132 var j: i64 = ins 133 while j < raw_len { if o < cap - 1 { out[o] = raw[j]; o = o + 1 } j = j + 1 } 134 out[o] = 0 as u8 135 return o 136}