code wiki / _hdl_build / nx_ad_emitter_apply.nx

nx_ad_emitter_apply.nx source

↩ module page · 70 lines · 4845 B

1// nx_ad_emitter_apply.nx -- LIB: the builder CONSUMES its learned catalog. ab_emit_from_registry resolves a 2// size/theme/accent/animation BY ID from the emitter registry and renders the banner through the shared core 3// (ab_emit_banner_c). So a GROWN emitter (e.g. theme "ocean" + accent "star" + animation "slide") is actually 4// USABLE -- growing the catalog grows what the builder can emit, with no code change. This CLOSES the 5// emitter-of-emitters loop: build -> teach (register) -> grow -> consume. license_tier: ORIGINAL 6import "nx_ad_banner.nx" 7import "nx_ad_emitter_registry.nx" 8import "nx_nishi_builder.nx" 9import "nx_ad_serve.nx" 10import "nx_syscalls.nx" 11const K_MAGIC_4096: i64 = 4096 12 13// parse "WxH" -> w,h (defaults 300x250). 14func ap_wh(s: *u8, wbox: *i64, hbox: *i64) -> i64 { 15 var w: i64 = 0; var h: i64 = 0; var seen_x: i64 = 0; var i: i64 = 0 16 while s[i] != (0 as u8) { 17 let c: i64 = s[i] as i64 18 if c == 120 { seen_x = 1 } else { if c >= 48 { if c <= 57 { if seen_x == 0 { w = w*10 + (c-48) } else { h = h*10 + (c-48) } } } } 19 i = i + 1 20 } 21 if w == 0 { w = 300 } if h == 0 { h = 250 } 22 wbox[0] = w; hbox[0] = h; return 1 23} 24// split "a|b|c|d" into 4 NUL-terminated buffers. 25func ap_split4(s: *u8, b0: *u8, b1: *u8, b2: *u8, b3: *u8) -> i64 { 26 var field: i64 = 0; var o: i64 = 0; var i: i64 = 0 27 while s[i] != (0 as u8) { 28 if s[i] == (124 as u8) { 29 if field == 0 { b0[o] = 0 as u8 } if field == 1 { b1[o] = 0 as u8 } if field == 2 { b2[o] = 0 as u8 } 30 field = field + 1; o = 0 31 } else { 32 if field == 0 { b0[o] = s[i] } if field == 1 { b1[o] = s[i] } if field == 2 { b2[o] = s[i] } if field == 3 { b3[o] = s[i] } 33 o = o + 1 34 } 35 i = i + 1 36 } 37 if field == 0 { b0[o] = 0 as u8 } if field == 1 { b1[o] = 0 as u8 } if field == 2 { b2[o] = 0 as u8 } if field == 3 { b3[o] = 0 as u8 } 38 return field + 1 39} 40 41// render a banner by resolving emitters from the registry at `path` by id. NUL-terminated into out; len returned. 42func ab_emit_from_registry(path: *u8, business: *u8, headline: *u8, body: *u8, cta: *u8, link: *u8, 43 size_id: *u8, theme_id: *u8, accent_id: *u8, anim_id: *u8, out: *u8) -> i64 { 44 let sztpl: *u8 = sys_mmap(64); let wbox: *i64 = sys_mmap(16) as *i64; let hbox: *i64 = sys_mmap(16) as *i64 45 if er_lookup(path, "size" as *u8, size_id, sztpl) == 1 { ap_wh(sztpl, wbox, hbox) } else { wbox[0] = 300; hbox[0] = 250 } 46 let thtpl: *u8 = sys_mmap(256) 47 let bg: *u8 = sys_mmap(32); let fg: *u8 = sys_mmap(32); let ac: *u8 = sys_mmap(32); let at: *u8 = sys_mmap(32) 48 if er_lookup(path, "theme" as *u8, theme_id, thtpl) == 1 { ap_split4(thtpl, bg, fg, ac, at) } 49 else { ap_split4("#ffffff|#16202e|#0b2545|#ffffff" as *u8, bg, fg, ac, at) } 50 let actpl: *u8 = sys_mmap(K_MAGIC_4096); if er_lookup(path, "accent" as *u8, accent_id, actpl) == 0 { actpl[0] = 0 as u8 } 51 let antpl: *u8 = sys_mmap(K_MAGIC_4096); if er_lookup(path, "animation" as *u8, anim_id, antpl) == 0 { antpl[0] = 0 as u8 } 52 return ab_emit_banner_c(business, headline, body, cta, link, wbox[0], hbox[0], bg, fg, ac, at, actpl, antpl, out) 53} 54 55// THE FOLD: the SAME banner consume, but resolving ad emitters from the UNIVERSAL builder catalog (nb_lookup, 56// domain="ad") instead of the ad-only ad_emitters.tsv -- so the one Nishi-builder catalog is the SSOT for the ad 57// domain too, exactly as it already is for web (nx_web_render) and game (nx_game_render). Byte-identical output 58// to ab_emit_from_registry given the same emitters (the fold gate proves it). Additive: the er_* path is unchanged. 59func ab_emit_from_nb(path: *u8, business: *u8, headline: *u8, body: *u8, cta: *u8, link: *u8, 60 size_id: *u8, theme_id: *u8, accent_id: *u8, anim_id: *u8, out: *u8) -> i64 { 61 let sztpl: *u8 = sys_mmap(64); let wbox: *i64 = sys_mmap(16) as *i64; let hbox: *i64 = sys_mmap(16) as *i64 62 if nb_lookup(path, "ad" as *u8, "size" as *u8, size_id, sztpl) == 1 { ap_wh(sztpl, wbox, hbox) } else { wbox[0] = 300; hbox[0] = 250 } 63 let thtpl: *u8 = sys_mmap(256) 64 let bg: *u8 = sys_mmap(32); let fg: *u8 = sys_mmap(32); let ac: *u8 = sys_mmap(32); let at: *u8 = sys_mmap(32) 65 if nb_lookup(path, "ad" as *u8, "theme" as *u8, theme_id, thtpl) == 1 { ap_split4(thtpl, bg, fg, ac, at) } 66 else { ap_split4("#ffffff|#16202e|#0b2545|#ffffff" as *u8, bg, fg, ac, at) } 67 let actpl: *u8 = sys_mmap(K_MAGIC_4096); if nb_lookup(path, "ad" as *u8, "accent" as *u8, accent_id, actpl) == 0 { actpl[0] = 0 as u8 } 68 let antpl: *u8 = sys_mmap(K_MAGIC_4096); if nb_lookup(path, "ad" as *u8, "animation" as *u8, anim_id, antpl) == 0 { antpl[0] = 0 as u8 } 69 return ab_emit_banner_c(business, headline, body, cta, link, wbox[0], hbox[0], bg, fg, ac, at, actpl, antpl, out) 70}