code wiki / (root) / nx_spend_analyze_gate.nx

nx_spend_analyze_gate.nx source

↩ module page · 57 lines · 3611 B

1// nx_spend_analyze_gate.nx -- proves the spend analyzer on a hand-computed monthly budget: 2// housing $1500 (need,recurring), groceries $400 (need), dining $300 (want), subscriptions $80 (want,recurring), 3// entertainment $120 (want), savings $200 (save,recurring). Total $2600. 4// Verifies class totals + 50/30/20 percentages, the largest-want cut target, subscription drain (+ annual cost), 5// and the situation-aware "how much to cut from wants to hit a savings goal". Exit 0 iff all pass. license_tier: ORIGINAL 6import "nx_gate.nx" 7import "nx_spend_analyze.nx" 8 9func chk(name: *u8, got: i64, want: i64, st: *i64) -> i64 { 10 if got == want { st[0] = st[0] + 1; gw(" PASS " as *u8); gw(name); gw("\n" as *u8) } 11 else { st[1] = st[1] + 1; gw(" FAIL " as *u8); gw(name); gw(" got=" as *u8); gn(got); gw(" want=" as *u8); gn(want); gw("\n" as *u8) } 12 return 0 13} 14 15func main() -> i64 { 16 let st: *i64 = sys_mmap(16) as *i64 17 st[0] = 0; st[1] = 0 18 19 let cats: *i64 = sys_mmap(8 * SP_FIELDS * 8) as *i64 20 cats[0] = 150000; cats[1] = SP_NEED; cats[2] = 1 // housing 21 cats[3] = 40000; cats[4] = SP_NEED; cats[5] = 0 // groceries 22 cats[6] = 30000; cats[7] = SP_WANT; cats[8] = 0 // dining 23 cats[9] = 8000; cats[10] = SP_WANT; cats[11] = 1 // subscriptions 24 cats[12] = 12000; cats[13] = SP_WANT; cats[14] = 0 // entertainment 25 cats[15] = 20000; cats[16] = SP_SAVE; cats[17] = 1 // savings 26 let n: i64 = 6 27 28 chk("total spend = $2600" as *u8, sp_total(cats, n), 260000, st) 29 chk("needs total = $1900" as *u8, sp_total_by_class(cats, n, SP_NEED), 190000, st) 30 chk("wants total = $500" as *u8, sp_total_by_class(cats, n, SP_WANT), 50000, st) 31 chk("savings total = $200" as *u8, sp_total_by_class(cats, n, SP_SAVE), 20000, st) 32 33 chk("needs = 7307 bps (73.07%)" as *u8, sp_class_pct_bps(cats, n, SP_NEED), 7307, st) 34 chk("wants = 1923 bps (19.23%)" as *u8, sp_class_pct_bps(cats, n, SP_WANT), 1923, st) 35 chk("savings = 769 bps (7.69%)" as *u8, sp_class_pct_bps(cats, n, SP_SAVE), 769, st) 36 chk("savings gap vs 20% = -1231 bps (under-saving)" as *u8, sp_class_gap_bps(cats, n, SP_SAVE, B5030_SAVE), 0 - 1231, st) 37 chk("needs gap vs 50% = +2307 bps (housing-heavy)" as *u8, sp_class_gap_bps(cats, n, SP_NEED, B5030_NEEDS), 2307, st) 38 39 chk("largest want = idx 2 (dining $300)" as *u8, sp_largest_want(cats, n), 2, st) 40 41 chk("recurring total = $1780" as *u8, sp_recurring_total(cats, n), 178000, st) 42 chk("cancellable subscriptions = $80" as *u8, sp_recurring_want_total(cats, n), 8000, st) 43 chk("subscription annual drain = $960" as *u8, sp_recurring_want_annual(cats, n), 96000, st) 44 45 chk("cutting wants 30% frees $150" as *u8, sp_potential_savings(cats, n, 3000), 15000, st) 46 47 // situation-aware: to lift savings from $200 to $500, cut $300 from wants (feasible: wants = $500) 48 chk("required want-cut for $500 goal = $300" as *u8, sp_required_want_cut(50000, 20000, 50000), 30000, st) 49 chk("$500 goal reachable by wants = 1" as *u8, sp_target_reachable_by_wants(50000, 20000, 50000), 1, st) 50 // to lift to $800 would need $600 cut but only $500 of wants exist -> not reachable by wants alone 51 chk("$800 goal reachable by wants = 0" as *u8, sp_target_reachable_by_wants(80000, 20000, 50000), 0, st) 52 53 gw("nx_spend_analyze_gate: PASS=" as *u8); gn(st[0]); gw(" FAIL=" as *u8); gn(st[1]); gw("\n" as *u8) 54 if st[1] == 0 { gw("nx_spend_analyze: GREEN (categorize / 50-30-20 / subscription drain / situation-aware cut)\n" as *u8); return 0 } 55 gw("nx_spend_analyze: RED\n" as *u8) 56 return 1 57}