code wiki / _hdl_build / nx_swap_gate.nx

nx_swap_gate.nx source

↩ module page · 165 lines · 11245 B

1// nx_swap_gate.nx -- GATE: gamified community swap + sovereign ads. T1 species catalog + gardeners + empty dex. 2// T2 ask/give matching + AREA isolation (find offers near me, not across the country). T3 THE SWAP exchange 3// (claim an offer -> get the plant by swapping, not buying; dex grows). T4 gamification (XP -> LEVEL up). T5 4// SETS + BADGES ("gotta grow 'em all"; incomplete gardener gets no badge). T6 the sovereign board renders with 5// a CONTEXTUAL ad slot (selected by topic, labelled Sponsored, no tracking / no third-party JS) + ships. 6// license_tier: ORIGINAL 7import "nx_swap.nx" 8import "nx_ads.nx" 9import "nx_publisher.nx" 10import "nx_seg_store.nx" 11import "nx_syscalls.nx" 12import "nx_gate_verdict.nx" 13 14const SG_SWAP: *u8 = "knowledge/store/swap-" 15const SG_ADS: *u8 = "knowledge/store/ads-" 16const SG_STAGE_FILE: *u8 = "knowledge/staging/swap/board.html" 17const SG_LIVE_FILE: *u8 = "knowledge/publish/swap-live/board.html" 18 19func g_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 20func g_i(v: i64) -> i64 { 21 let bb: *u8 = sys_mmap(28); var m: i64 = v 22 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 23 let t: *u8 = sys_mmap(28); var k: i64 = 0 24 if m == 0 { t[0] = 48 as u8; k = 1 } 25 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 26 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(1, bb, k); return 0 27} 28func g_exists(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 } sys_close(fd); return 1 } 29 30func main() -> i64 { 31 g_p("=== nx_swap_gate (gamified community swap + sovereign ads) ===\n" as *u8) 32 sw_seed_config(SG_SWAP) 33 34 // species catalog (our own "creatures" = real plants) 35 sw_add_species(SG_SWAP, "basil" as *u8, "Basil" as *u8, "herb" as *u8, "common" as *u8) 36 sw_add_species(SG_SWAP, "rosemary" as *u8, "Rosemary" as *u8, "herb" as *u8, "common" as *u8) 37 sw_add_species(SG_SWAP, "thyme" as *u8, "Thyme" as *u8, "herb" as *u8, "common" as *u8) 38 sw_add_species(SG_SWAP, "oregano" as *u8, "Oregano" as *u8, "herb" as *u8, "common" as *u8) 39 sw_add_species(SG_SWAP, "sage" as *u8, "Sage" as *u8, "herb" as *u8, "common" as *u8) 40 sw_add_species(SG_SWAP, "saffron" as *u8, "Saffron Crocus" as *u8, "herb" as *u8, "rare" as *u8) 41 sw_add_set(SG_SWAP, "medherbs" as *u8, "Mediterranean Herbs\tbasil\trosemary\tthyme\toregano\tsage" as *u8) 42 43 // gardeners 44 sw_add_gardener(SG_SWAP, "alice" as *u8, "Alice" as *u8, "TX-Austin" as *u8) 45 sw_add_gardener(SG_SWAP, "bob" as *u8, "Bob" as *u8, "TX-Austin" as *u8) 46 sw_add_gardener(SG_SWAP, "cara" as *u8, "Cara" as *u8, "TX-Austin" as *u8) 47 sw_add_gardener(SG_SWAP, "dan" as *u8, "Dan" as *u8, "CA-LA" as *u8) 48 49 // alice grows the full Mediterranean herb garden and offers all 5 (TX-Austin) 50 sw_post_offer(SG_SWAP, "a_basil" as *u8, "alice" as *u8, "basil" as *u8, "cutting" as *u8, 3, "TX-Austin" as *u8, "fresh" as *u8) 51 sw_post_offer(SG_SWAP, "a_rose" as *u8, "alice" as *u8, "rosemary" as *u8, "cutting" as *u8, 3, "TX-Austin" as *u8, "-" as *u8) 52 sw_post_offer(SG_SWAP, "a_thyme" as *u8, "alice" as *u8, "thyme" as *u8, "seed" as *u8, 50, "TX-Austin" as *u8, "-" as *u8) 53 sw_post_offer(SG_SWAP, "a_oreg" as *u8, "alice" as *u8, "oregano" as *u8, "seed" as *u8, 50, "TX-Austin" as *u8, "-" as *u8) 54 sw_post_offer(SG_SWAP, "a_sage" as *u8, "alice" as *u8, "sage" as *u8, "cutting" as *u8, 2, "TX-Austin" as *u8, "-" as *u8) 55 // cara also offers basil in Austin; dan offers basil in LA (for area isolation) 56 sw_post_offer(SG_SWAP, "c_basil" as *u8, "cara" as *u8, "basil" as *u8, "seed" as *u8, 20, "TX-Austin" as *u8, "-" as *u8) 57 sw_post_offer(SG_SWAP, "d_basil" as *u8, "dan" as *u8, "basil" as *u8, "seed" as *u8, 20, "CA-LA" as *u8, "-" as *u8) 58 // bob asks for basil 59 sw_post_request(SG_SWAP, "b_req1" as *u8, "bob" as *u8, "basil" as *u8, "TX-Austin" as *u8) 60 61 // a contextual ad (indexed under the "herbs" topic, not under any viewer) 62 ads_add(SG_ADS, "seedlib" as *u8, "Nishi heirloom herb seeds" as *u8, "Start your own Mediterranean herb patch with open-pollinated, swap-friendly seed." as *u8, "Nishi Seed Library" as *u8, "herbs" as *u8) 63 ads_add(SG_ADS, "tomatoad" as *u8, "Brandywine tomato starts" as *u8, "-" as *u8, "Nishi Market" as *u8, "tomato" as *u8) 64 65 var pass: i64 = 0 66 var tot: i64 = 0 67 68 // T1 catalog + empty dex 69 let bn: *u8 = sys_mmap(48); sw_species_field(SG_SWAP, "basil" as *u8, 0, bn) 70 let bobdex0: i64 = sw_dex_count(SG_SWAP, "bob" as *u8) 71 g_p("species basil=" as *u8); g_p(bn); g_p(" bob dex=" as *u8); g_i(bobdex0); g_p("\n" as *u8) 72 tot = tot + 1 73 var ok1: i64 = 1 74 if fd_streq(bn, "Basil" as *u8) != 1 { ok1 = 0 } 75 if bobdex0 != 0 { ok1 = 0 } 76 if ok1 == 1 { pass = pass + 1; g_p("PASS T1 species catalog + gardeners; new gardener starts with an empty garden-dex\n" as *u8) } else { g_p("FAIL T1\n" as *u8) } 77 78 // T2 matching + area isolation 79 let m_atx: *i64 = sys_mmap(8 * 64) as *i64 80 let m_la: *i64 = sys_mmap(8 * 64) as *i64 81 let n_atx: i64 = sw_find_offers(SG_SWAP, "basil" as *u8, "TX-Austin" as *u8, m_atx) 82 let n_la: i64 = sw_find_offers(SG_SWAP, "basil" as *u8, "CA-LA" as *u8, m_la) 83 g_p("basil offers: Austin=" as *u8); g_i(n_atx); g_p(" LA=" as *u8); g_i(n_la); g_p("\n" as *u8) 84 tot = tot + 1 85 if n_atx == 2 { if n_la == 1 { pass = pass + 1; g_p("PASS T2 ask/give match + AREA isolation (Austin basil=2: Alice+Cara; LA basil=1: Dan, not mixed)\n" as *u8) } else { g_p("FAIL T2 la\n" as *u8) } } else { g_p("FAIL T2 atx=" as *u8); g_i(n_atx); g_p("\n" as *u8) } 86 87 // T3 THE SWAP: bob claims alice's 5 offers -> gets the plants by swapping 88 let c1: i64 = sw_claim_offer(SG_SWAP, "a_basil" as *u8, "bob" as *u8) 89 sw_claim_offer(SG_SWAP, "a_rose" as *u8, "bob" as *u8) 90 sw_claim_offer(SG_SWAP, "a_thyme" as *u8, "bob" as *u8) 91 sw_claim_offer(SG_SWAP, "a_oreg" as *u8, "bob" as *u8) 92 sw_claim_offer(SG_SWAP, "a_sage" as *u8, "bob" as *u8) 93 let bobdex: i64 = sw_dex_count(SG_SWAP, "bob" as *u8) 94 g_p("after swaps: bob dex=" as *u8); g_i(bobdex); g_p(" has rosemary=" as *u8); g_i(sw_dex_has(SG_SWAP, "bob" as *u8, "rosemary" as *u8)); g_p(" a_basil still open=" as *u8); g_i(sw_offer_open(SG_SWAP, "a_basil" as *u8)); g_p("\n" as *u8) 95 tot = tot + 1 96 var ok3: i64 = 1 97 if c1 != 1 { ok3 = 0 } 98 if bobdex != 5 { ok3 = 0 } 99 if sw_dex_has(SG_SWAP, "bob" as *u8, "rosemary" as *u8) != 1 { ok3 = 0 } 100 if sw_offer_open(SG_SWAP, "a_basil" as *u8) != 0 { ok3 = 0 } // claimed offer is no longer open 101 if ok3 == 1 { pass = pass + 1; g_p("PASS T3 the swap: Bob got 5 herbs incl rosemary by SWAPPING (not buying); offers marked claimed\n" as *u8) } else { g_p("FAIL T3\n" as *u8) } 102 103 // T4 gamification: XP -> level up 104 let bxp: i64 = sw_xp(SG_SWAP, "bob" as *u8) 105 let blv: i64 = sw_level(SG_SWAP, "bob" as *u8) 106 let alv: i64 = sw_level(SG_SWAP, "alice" as *u8) 107 g_p("bob xp=" as *u8); g_i(bxp); g_p(" level=" as *u8); g_i(blv); g_p(" | alice (gave 5) level=" as *u8); g_i(alv); g_p("\n" as *u8) 108 tot = tot + 1 109 var ok4: i64 = 1 110 if bxp != 175 { ok4 = 0 } // 5 x (receive 10 + new-species 25) 111 if blv != 4 { ok4 = 0 } // 1 + 175/50 112 if alv <= 1 { ok4 = 0 } // alice leveled up from giving 113 if ok4 == 1 { pass = pass + 1; g_p("PASS T4 gamification: Bob earned 175 XP -> Level 4; Alice leveled up from giving\n" as *u8) } else { g_p("FAIL T4\n" as *u8) } 114 115 // T5 sets + badges 116 let bcomplete: i64 = sw_set_complete(SG_SWAP, "bob" as *u8, "medherbs" as *u8) 117 let awarded: i64 = sw_award_badge(SG_SWAP, "bob" as *u8, "medherbs" as *u8) 118 let ccomplete: i64 = sw_set_complete(SG_SWAP, "cara" as *u8, "medherbs" as *u8) 119 let cawarded: i64 = sw_award_badge(SG_SWAP, "cara" as *u8, "medherbs" as *u8) 120 g_p("bob set-complete=" as *u8); g_i(bcomplete); g_p(" badge=" as *u8); g_i(sw_has_badge(SG_SWAP, "bob" as *u8, "medherbs" as *u8)); g_p(" | cara complete=" as *u8); g_i(ccomplete); g_p(" badge=" as *u8); g_i(cawarded); g_p("\n" as *u8) 121 tot = tot + 1 122 var ok5: i64 = 1 123 if bcomplete != 1 { ok5 = 0 } 124 if awarded != 1 { ok5 = 0 } 125 if sw_has_badge(SG_SWAP, "bob" as *u8, "medherbs" as *u8) != 1 { ok5 = 0 } 126 if ccomplete != 0 { ok5 = 0 } // cara only has basil 127 if cawarded != 0 { ok5 = 0 } 128 if ok5 == 1 { pass = pass + 1; g_p("PASS T5 set complete -> Bob earns the Mediterranean Herbs badge; Cara (1/5) earns nothing\n" as *u8) } else { g_p("FAIL T5\n" as *u8) } 129 130 // T6 sovereign board + contextual ad + ship 131 let page: *u8 = sys_mmap(65536) 132 let np: i64 = sw_render_board(SG_SWAP, SG_ADS, "TX-Austin" as *u8, "bob" as *u8, "medherbs" as *u8, page) 133 g_p("board = " as *u8); g_i(np); g_p(" bytes\n" as *u8) 134 tot = tot + 1 135 var ok6: i64 = 1 136 if as_has_thirdparty_js(page, np) != 0 { ok6 = 0 } 137 if as_contains(page, np, "Level " as *u8) != 1 { ok6 = 0 } 138 if as_contains(page, np, "5 / 5" as *u8) != 1 { ok6 = 0 } // set progress 139 if as_contains(page, np, "Sponsored" as *u8) != 1 { ok6 = 0 } // ad slot present 140 if as_contains(page, np, "Nishi heirloom herb seeds" as *u8) != 1 { ok6 = 0 } // contextual ad (herbs) 141 if as_contains(page, np, "not who you are" as *u8) != 1 { ok6 = 0 } // privacy stance shown 142 if as_contains(page, np, "from Cara" as *u8) != 1 { ok6 = 0 } // local open offer shown 143 if as_contains(page, np, "from Dan" as *u8) != 0 { ok6 = 0 } // LA offer NOT shown (area) 144 sys_mkdir("knowledge/staging" as *u8, 0x1ed) 145 sys_mkdir("knowledge/staging/swap" as *u8, 0x1ed) 146 let sfd: i64 = sys_openat_wr(SG_STAGE_FILE, 420); if sfd >= 0 { sys_write(sfd, page, np); sys_close(sfd) } 147 pub_init() 148 sys_mkdir("knowledge/publish/swap-stage" as *u8, 0x1ed) 149 sys_mkdir("knowledge/publish/swap-live" as *u8, 0x1ed) 150 pub_submit_to("knowledge/publish/swap-queue.tsv" as *u8, SG_STAGE_FILE, "board.html" as *u8, "nishifoodfamily" as *u8, "nishi-swap" as *u8, "internal" as *u8) 151 pub_run_full("knowledge/publish/swap-queue.tsv" as *u8, "knowledge/publish/swap-ledger.tsv" as *u8, "knowledge/publish/swap-stage" as *u8, "knowledge/publish/swap-live" as *u8, "publish:swap" as *u8) 152 if g_exists(SG_LIVE_FILE) != 1 { ok6 = 0 } 153 if ok6 == 1 { pass = pass + 1; g_p("PASS T6 sovereign gamified board + contextual ad (no tracking, no third-party JS), shipped\n" as *u8) } else { g_p("FAIL T6\n" as *u8) } 154 155 g_p("nx_swap_gate pass=" as *u8); g_i(pass); g_p("/" as *u8); g_i(tot) 156 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 157 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 158 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 159 let ctr__dry: *i64 = gv_ctr() 160 ctr__dry[0] = pass 161 ctr__dry[1] = tot 162 let rc__dry: i64 = gv_verdict("SWAP-GATE" as *u8, ctr__dry, "ask + give plants, gamified + fun, sovereign ads, our own IP, gift economy)" as *u8) 163 sys_exit(rc__dry) 164 return rc__dry 165}