code wiki / _hdl_build / nx_swap_gate.nx
nx_swap_gate.nx source
↩ module page · 158 lines · 10852 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"
12
13const SG_SWAP: *u8 = "knowledge/store/swap-"
14const SG_ADS: *u8 = "knowledge/store/ads-"
15const SG_STAGE_FILE: *u8 = "knowledge/staging/swap/board.html"
16const SG_LIVE_FILE: *u8 = "knowledge/publish/swap-live/board.html"
17
18func 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 }
19func g_i(v: i64) -> i64 {
20 let bb: *u8 = sys_mmap(28); var m: i64 = v
21 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
22 let t: *u8 = sys_mmap(28); var k: i64 = 0
23 if m == 0 { t[0] = 48 as u8; k = 1 }
24 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
25 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(1, bb, k); return 0
26}
27func g_exists(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 } sys_close(fd); return 1 }
28
29func main() -> i64 {
30 g_p("=== nx_swap_gate (gamified community swap + sovereign ads) ===\n" as *u8)
31 sw_seed_config(SG_SWAP)
32
33 // species catalog (our own "creatures" = real plants)
34 sw_add_species(SG_SWAP, "basil" as *u8, "Basil" as *u8, "herb" as *u8, "common" as *u8)
35 sw_add_species(SG_SWAP, "rosemary" as *u8, "Rosemary" as *u8, "herb" as *u8, "common" as *u8)
36 sw_add_species(SG_SWAP, "thyme" as *u8, "Thyme" as *u8, "herb" as *u8, "common" as *u8)
37 sw_add_species(SG_SWAP, "oregano" as *u8, "Oregano" as *u8, "herb" as *u8, "common" as *u8)
38 sw_add_species(SG_SWAP, "sage" as *u8, "Sage" as *u8, "herb" as *u8, "common" as *u8)
39 sw_add_species(SG_SWAP, "saffron" as *u8, "Saffron Crocus" as *u8, "herb" as *u8, "rare" as *u8)
40 sw_add_set(SG_SWAP, "medherbs" as *u8, "Mediterranean Herbs\tbasil\trosemary\tthyme\toregano\tsage" as *u8)
41
42 // gardeners
43 sw_add_gardener(SG_SWAP, "alice" as *u8, "Alice" as *u8, "TX-Austin" as *u8)
44 sw_add_gardener(SG_SWAP, "bob" as *u8, "Bob" as *u8, "TX-Austin" as *u8)
45 sw_add_gardener(SG_SWAP, "cara" as *u8, "Cara" as *u8, "TX-Austin" as *u8)
46 sw_add_gardener(SG_SWAP, "dan" as *u8, "Dan" as *u8, "CA-LA" as *u8)
47
48 // alice grows the full Mediterranean herb garden and offers all 5 (TX-Austin)
49 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)
50 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)
51 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)
52 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)
53 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)
54 // cara also offers basil in Austin; dan offers basil in LA (for area isolation)
55 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)
56 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)
57 // bob asks for basil
58 sw_post_request(SG_SWAP, "b_req1" as *u8, "bob" as *u8, "basil" as *u8, "TX-Austin" as *u8)
59
60 // a contextual ad (indexed under the "herbs" topic, not under any viewer)
61 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)
62 ads_add(SG_ADS, "tomatoad" as *u8, "Brandywine tomato starts" as *u8, "-" as *u8, "Nishi Market" as *u8, "tomato" as *u8)
63
64 var pass: i64 = 0
65 var tot: i64 = 0
66
67 // T1 catalog + empty dex
68 let bn: *u8 = sys_mmap(48); sw_species_field(SG_SWAP, "basil" as *u8, 0, bn)
69 let bobdex0: i64 = sw_dex_count(SG_SWAP, "bob" as *u8)
70 g_p("species basil=" as *u8); g_p(bn); g_p(" bob dex=" as *u8); g_i(bobdex0); g_p("\n" as *u8)
71 tot = tot + 1
72 var ok1: i64 = 1
73 if fd_streq(bn, "Basil" as *u8) != 1 { ok1 = 0 }
74 if bobdex0 != 0 { ok1 = 0 }
75 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) }
76
77 // T2 matching + area isolation
78 let m_atx: *i64 = sys_mmap(8 * 64) as *i64
79 let m_la: *i64 = sys_mmap(8 * 64) as *i64
80 let n_atx: i64 = sw_find_offers(SG_SWAP, "basil" as *u8, "TX-Austin" as *u8, m_atx)
81 let n_la: i64 = sw_find_offers(SG_SWAP, "basil" as *u8, "CA-LA" as *u8, m_la)
82 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)
83 tot = tot + 1
84 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) }
85
86 // T3 THE SWAP: bob claims alice's 5 offers -> gets the plants by swapping
87 let c1: i64 = sw_claim_offer(SG_SWAP, "a_basil" as *u8, "bob" as *u8)
88 sw_claim_offer(SG_SWAP, "a_rose" as *u8, "bob" as *u8)
89 sw_claim_offer(SG_SWAP, "a_thyme" as *u8, "bob" as *u8)
90 sw_claim_offer(SG_SWAP, "a_oreg" as *u8, "bob" as *u8)
91 sw_claim_offer(SG_SWAP, "a_sage" as *u8, "bob" as *u8)
92 let bobdex: i64 = sw_dex_count(SG_SWAP, "bob" as *u8)
93 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)
94 tot = tot + 1
95 var ok3: i64 = 1
96 if c1 != 1 { ok3 = 0 }
97 if bobdex != 5 { ok3 = 0 }
98 if sw_dex_has(SG_SWAP, "bob" as *u8, "rosemary" as *u8) != 1 { ok3 = 0 }
99 if sw_offer_open(SG_SWAP, "a_basil" as *u8) != 0 { ok3 = 0 } // claimed offer is no longer open
100 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) }
101
102 // T4 gamification: XP -> level up
103 let bxp: i64 = sw_xp(SG_SWAP, "bob" as *u8)
104 let blv: i64 = sw_level(SG_SWAP, "bob" as *u8)
105 let alv: i64 = sw_level(SG_SWAP, "alice" as *u8)
106 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)
107 tot = tot + 1
108 var ok4: i64 = 1
109 if bxp != 175 { ok4 = 0 } // 5 x (receive 10 + new-species 25)
110 if blv != 4 { ok4 = 0 } // 1 + 175/50
111 if alv <= 1 { ok4 = 0 } // alice leveled up from giving
112 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) }
113
114 // T5 sets + badges
115 let bcomplete: i64 = sw_set_complete(SG_SWAP, "bob" as *u8, "medherbs" as *u8)
116 let awarded: i64 = sw_award_badge(SG_SWAP, "bob" as *u8, "medherbs" as *u8)
117 let ccomplete: i64 = sw_set_complete(SG_SWAP, "cara" as *u8, "medherbs" as *u8)
118 let cawarded: i64 = sw_award_badge(SG_SWAP, "cara" as *u8, "medherbs" as *u8)
119 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)
120 tot = tot + 1
121 var ok5: i64 = 1
122 if bcomplete != 1 { ok5 = 0 }
123 if awarded != 1 { ok5 = 0 }
124 if sw_has_badge(SG_SWAP, "bob" as *u8, "medherbs" as *u8) != 1 { ok5 = 0 }
125 if ccomplete != 0 { ok5 = 0 } // cara only has basil
126 if cawarded != 0 { ok5 = 0 }
127 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) }
128
129 // T6 sovereign board + contextual ad + ship
130 let page: *u8 = sys_mmap(65536)
131 let np: i64 = sw_render_board(SG_SWAP, SG_ADS, "TX-Austin" as *u8, "bob" as *u8, "medherbs" as *u8, page)
132 g_p("board = " as *u8); g_i(np); g_p(" bytes\n" as *u8)
133 tot = tot + 1
134 var ok6: i64 = 1
135 if as_has_thirdparty_js(page, np) != 0 { ok6 = 0 }
136 if as_contains(page, np, "Level " as *u8) != 1 { ok6 = 0 }
137 if as_contains(page, np, "5 / 5" as *u8) != 1 { ok6 = 0 } // set progress
138 if as_contains(page, np, "Sponsored" as *u8) != 1 { ok6 = 0 } // ad slot present
139 if as_contains(page, np, "Nishi heirloom herb seeds" as *u8) != 1 { ok6 = 0 } // contextual ad (herbs)
140 if as_contains(page, np, "not who you are" as *u8) != 1 { ok6 = 0 } // privacy stance shown
141 if as_contains(page, np, "from Cara" as *u8) != 1 { ok6 = 0 } // local open offer shown
142 if as_contains(page, np, "from Dan" as *u8) != 0 { ok6 = 0 } // LA offer NOT shown (area)
143 sys_mkdir("knowledge/staging" as *u8, 0x1ed)
144 sys_mkdir("knowledge/staging/swap" as *u8, 0x1ed)
145 let sfd: i64 = sys_openat_wr(SG_STAGE_FILE, 420); if sfd >= 0 { sys_write(sfd, page, np); sys_close(sfd) }
146 pub_init()
147 sys_mkdir("knowledge/publish/swap-stage" as *u8, 0x1ed)
148 sys_mkdir("knowledge/publish/swap-live" as *u8, 0x1ed)
149 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)
150 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)
151 if g_exists(SG_LIVE_FILE) != 1 { ok6 = 0 }
152 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) }
153
154 g_p("nx_swap_gate pass=" as *u8); g_i(pass); g_p("/" as *u8); g_i(tot)
155 if pass == tot { g_p(" verdict=GREEN (ask + give plants, gamified + fun, sovereign ads, our own IP, gift economy)\n" as *u8); return 0 }
156 g_p(" verdict=RED\n" as *u8)
157 return 1
158}