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}