code wiki / _hdl_build / nx_batt_planner_test.nx

nx_batt_planner_test.nx source

↩ module page · 98 lines · 6592 B

1import "nx_gate_gn.nx" 2// nx_batt_planner_test.nx -- gate for the R4 profit/risk planner. Runs the 4 candidate business models head-to-head 3// with ESTIMATED (illustrative) inputs, asserts the exact no-float economics, proves the risk flags surface the 4// fire/capital traps, catches a money-losing model, + LIAR-KILL (more volume flips a loss to a profit = data-driven, 5// not a hardcoded verdict) + NEG-CONTROL (price<cogs always loses). expect_exit: 0 6import "nx_syscalls.nx" 7import "nx_batt_planner.nx" 8 9func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 10 11func mk_cfg() -> *RiskCfg { 12 let c: *RiskCfg = (sys_mmap(128)) as *RiskCfg 13 c.w_fire = 35; c.w_capital = 20; c.w_reg = 15; c.w_demand = 15; c.w_labor = 15 14 c.fire_high_line = 70; c.capital_line = 70; c.slow_breakeven_months = 36 15 return c 16} 17func mk_fin(id: i64, jobs: i64, price: i64, cogs: i64, labor: i64, fixed: i64, upfront: i64) -> *ModelScenario { 18 let m: *ModelScenario = (sys_mmap(128)) as *ModelScenario 19 m.id = id; m.monthly_jobs = jobs; m.avg_price_c = price; m.avg_cogs_c = cogs 20 m.monthly_labor_c = labor; m.monthly_fixed_c = fixed; m.upfront_c = upfront 21 m.fire = 0; m.capital = 0; m.regulatory = 0; m.demand = 0; m.labor_dep = 0 22 return m 23} 24func prow(name: *u8, r: *PlanResult) -> i64 { 25 gp(name); gp(" net$/mo=" as *u8); gn(r.net_monthly_c/100) 26 gp(" margin/1000=" as *u8); gn(r.margin_permille) 27 gp(" breakeven_mo=" as *u8); gn(r.breakeven_months) 28 gp(" risk=" as *u8); gn(r.risk_score) 29 gp(" flags[netneg=" as *u8); gn(r.flag_net_neg); gp(" fire=" as *u8); gn(r.flag_high_fire) 30 gp(" cap=" as *u8); gn(r.flag_capital_heavy); gp(" slow=" as *u8); gn(r.flag_slow_breakeven); gp("]\n" as *u8) 31 return 0 32} 33 34func main() -> i64 { 35 var pass: i64=0; var fail: i64=0 36 let cfg: *RiskCfg = mk_cfg() 37 gp("=== nx_batt_planner_test: profit/risk across the 4 candidate business models (inputs = ESTIMATES) ===\n" as *u8) 38 39 // M0 HYBRID drop-off + express 40 let m0: *ModelScenario = mk_fin(0, 240, 9000, 3000, 600000, 450000, 6000000) 41 m0.fire=35; m0.capital=50; m0.regulatory=45; m0.demand=50; m0.labor_dep=55 42 let r0: *PlanResult = (sys_mmap(128)) as *PlanResult 43 nx_plan_eval(m0, cfg, r0); prow("M0 HYBRID drop-off+express" as *u8, r0) 44 45 // M1 FULL SELF-SERVICE laundromat 46 let m1: *ModelScenario = mk_fin(1, 320, 5500, 1800, 300000, 700000, 12000000) 47 m1.fire=80; m1.capital=80; m1.regulatory=70; m1.demand=45; m1.labor_dep=25 48 let r1: *PlanResult = (sys_mmap(128)) as *PlanResult 49 nx_plan_eval(m1, cfg, r1); prow("M1 FULL self-service " as *u8, r1) 50 51 // M2 DROP-OFF / mail-in shop (low volume) 52 let m2: *ModelScenario = mk_fin(2, 130, 11000, 4200, 750000, 350000, 4500000) 53 m2.fire=25; m2.capital=35; m2.regulatory=35; m2.demand=55; m2.labor_dep=70 54 let r2: *PlanResult = (sys_mmap(128)) as *PlanResult 55 nx_plan_eval(m2, cfg, r2); prow("M2 DROP-OFF shop " as *u8, r2) 56 57 // M3 CORE-EXCHANGE / reman 58 let m3: *ModelScenario = mk_fin(3, 280, 9500, 4600, 650000, 600000, 9500000) 59 m3.fire=45; m3.capital=70; m3.regulatory=50; m3.demand=40; m3.labor_dep=50 60 let r3: *PlanResult = (sys_mmap(128)) as *PlanResult 61 nx_plan_eval(m3, cfg, r3); prow("M3 CORE-EXCHANGE " as *u8, r3) 62 63 // ===== assertions ===== 64 // exact no-float economics on the winner 65 if r0.net_monthly_c==390000 { pass=pass+1 } else { fail=fail+1; gp(" FAIL m0 net\n" as *u8) } 66 if r0.breakeven_months==16 { pass=pass+1 } else { fail=fail+1; gp(" FAIL m0 breakeven\n" as *u8) } 67 if r0.risk_score==44 { pass=pass+1 } else { fail=fail+1; gp(" FAIL m0 risk\n" as *u8) } 68 // winner is clean (no flags) 69 if r0.flag_net_neg==0 { if r0.flag_high_fire==0 { if r0.flag_capital_heavy==0 { if r0.flag_slow_breakeven==0 { pass=pass+1 } else { fail=fail+1; gp(" FAIL m0 slow\n" as *u8) } } else { fail=fail+1; gp(" FAIL m0 cap\n" as *u8) } } else { fail=fail+1; gp(" FAIL m0 fire\n" as *u8) } } else { fail=fail+1; gp(" FAIL m0 netneg\n" as *u8) } 70 // full self-service surfaces the HIGH-FIRE trap (the operator's #1 concern) 71 if r1.flag_high_fire==1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL m1 fire flag\n" as *u8) } 72 // low-volume pure drop-off LOSES money -> caught, never breaks even 73 if r2.flag_net_neg==1 { if r2.breakeven_months== -1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL m2 breakeven\n" as *u8) } } else { fail=fail+1; gp(" FAIL m2 netneg\n" as *u8) } 74 // core-exchange is capital-heavy -> flagged 75 if r3.flag_capital_heavy==1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL m3 cap flag\n" as *u8) } 76 // ranking: hybrid best, dropoff worst (data-driven, the engine discriminates) 77 if r0.net_monthly_c>r1.net_monthly_c { if r1.net_monthly_c>r3.net_monthly_c { if r3.net_monthly_c>r2.net_monthly_c { pass=pass+1 } else { fail=fail+1; gp(" FAIL rank3\n" as *u8) } } else { fail=fail+1; gp(" FAIL rank2\n" as *u8) } } else { fail=fail+1; gp(" FAIL rank1\n" as *u8) } 78 79 // LIAR-KILL: bump drop-off VOLUME 130->300 -> the loss flips to a profit (proves verdict tracks data, not hardcoded) 80 let m2b: *ModelScenario = mk_fin(2, 300, 11000, 4200, 750000, 350000, 4500000) 81 m2b.fire=25; m2b.capital=35; m2b.regulatory=35; m2b.demand=55; m2b.labor_dep=70 82 let r2b: *PlanResult = (sys_mmap(128)) as *PlanResult 83 nx_plan_eval(m2b, cfg, r2b) 84 gp(" LIAR dropoff@130 netneg=" as *u8); gn(r2.flag_net_neg); gp(" -> @300 netneg=" as *u8); gn(r2b.flag_net_neg); gp(" (must be 1 then 0)\n" as *u8) 85 if r2.flag_net_neg==1 { if r2b.flag_net_neg==0 { pass=pass+1 } else { fail=fail+1; gp(" FAIL liar\n" as *u8) } } else { fail=fail+1; gp(" FAIL liar-base\n" as *u8) } 86 87 // NEG-CONTROL: price < cogs always loses, regardless of volume 88 let mn: *ModelScenario = mk_fin(9, 1000, 1000, 4000, 0, 0, 100) 89 mn.fire=10; mn.capital=10; mn.regulatory=10; mn.demand=10; mn.labor_dep=10 90 let rn: *PlanResult = (sys_mmap(128)) as *PlanResult 91 nx_plan_eval(mn, cfg, rn) 92 gp(" NEGCTL price<cogs netneg=" as *u8); gn(rn.flag_net_neg); gp(" (must be 1)\n" as *u8) 93 if rn.flag_net_neg==1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL negctl\n" as *u8) } 94 95 gp("BATT-PLANNER pass=" as *u8); gn(pass); gp(" fail=" as *u8); gn(fail) 96 if fail==0 { gp(" verdict=GREEN -- RECOMMENDED = M0 HYBRID (best net + only model with no risk flags; full self-service = highest fire risk; pure drop-off loses at low volume)\n" as *u8); sys_exit(0); return 0 } 97 gp(" verdict=RED\n" as *u8); sys_exit(1); return 1 98}