code wiki / (root) / nx_twincard_lib.nx

nx_twincard_lib.nx source

↩ module page · 644 lines · 28843 B

1// nx_twincard_lib.nx -- THE TWIN CARD: one declared person or synth, every value on a declared axis with its SIDE, unit, method 2// and source (aesthetictwin AT23, symbol tc_card_check, 2026-09-16). Operator: "a system that is more comprehensive than the 3// illusion cards", then "minute variation between left and right ... down to the smallest unit ... each freckle or smaller is 4// reproducible". An Illusion character card is a PNG carrying about a hundred unitless sliders and no provenance; this card is DATA 5// (knowledge/twincard/<slug>.card) whose axes are declared in knowledge/twincard.axes (identity, body, soft tissue, skin, hair, 6// eyes, ears, lips, teeth, hands, feet, body hair, nails) and, for the face, ARE the canon ids of knowledge/facecanon.conf -- one 7// ruler for the face, never two. A PAIRED axis is recorded per side (L and R are two values, never one), an unpaired axis is C. 8// Individual surface features (freckle, mole, scar, vein, tattoo, birthmark) are one row each in a declared body-surface region 9// with permil chart coordinates, a diameter in mm100 and a CIELAB colour, so a freckle field is reproducible feature by feature. 10// Every axis may name its RULER (the sovereign organ and symbol that measures it); the CLI censuses which rulers exist today, so 11// the measurement investment is a number rather than a wish. Every row carries a METHOD (measured, observed, declared, generated) 12// and a SOURCE, so the card reports what it knows and how; coverage, the method partition and the completed left-right pairs are 13// numbers a page can print. 14// Card rows: card|<slug>|<display>|<class>|<sex>|<licence>|<schema> 15// axis|<section>|<id>|<side L R C>|<value>|<method>|<source>|<when> 16// feature|<kind>|<side>|<region>|<u permil>|<v permil>|<diam mm100>|<L10>|<a10>|<b10>|<method>|<source> 17// ref|<key>|<mirror>|<sha>|<licence>|<note> 18// shot|<refkey>|<date>|<age>|<pose>|<expression>|<light>|<backdrop>|<camera>|<accessories> 19// Schema rows: axis|<section>|<id>|<unit>|<lo>|<hi>|<paired 0 1>|<note> class|<section>|<id>|<word> 20// ruler|<section>|<id or *>|<organ path>|<symbol> region|<word>|<note> 21// Refusals are named: an undeclared axis (a group label is not an axis), a value outside its band, a class word not declared, a 22// method outside the four, a side that contradicts the pairing, a duplicate axis-and-side, a feature of unknown kind or region or 23// out of its chart, a shot naming no ref, a malformed ref or header. A canon band is a hypothesis under test, so a face value is 24// never range-checked against it. Composes nx_refintake_lib for the row helpers (the intake is the card's media leg). 25// LIB, no main. license_tier: ORIGINAL No hw writes (Rule 26). 26import "nx_syscalls.nx" 27import "nx_refintake_lib.nx" 28import "nx_symdecl_lib.nx" 29 30const TC_AXES: *u8 = "knowledge/twincard.axes" 31const TC_BUILDROOT: *u8 = "buildroot/" 32const TC_C_ROWS: i64 = 0 33const TC_C_PRESENT: i64 = 1 34const TC_C_ABSENT: i64 = 2 35const TC_C_UNJUDGED: i64 = 3 36const TC_DIR: *u8 = "knowledge/twincard" 37const TC_CANON: *u8 = "knowledge/facecanon.conf" 38const TC_SCHEMA_V: i64 = 1 39const TC_FACE: *u8 = "face" 40const TC_METHODS: *u8 = " measured observed declared generated " 41const TC_CLASSES: *u8 = " real anime fantasy synth " 42const TC_SEXES: *u8 = " F M X " 43const TC_LICENCES: *u8 = " REVIEW SHIP_OK REFUSED " 44const TC_SIDES: *u8 = " L R C " 45const TC_SIDE_C: *u8 = "C" 46const TC_SIDE_L: *u8 = "L" 47const TC_SIDE_R: *u8 = "R" 48const TC_FEATURE_KINDS: *u8 = " freckle mole scar vein tattoo birthmark " 49const TC_UNIT_CLASS: *u8 = "class" 50const TC_DASHWORD: *u8 = "-" 51const TC_STAR: *u8 = "*" 52const TC_LISTB: i64 = 8192 53const TC_POS_N: i64 = 2 54const TC_PERMIL: i64 = 1000 55const TC_UV_MAX: i64 = 1000 56const TC_DIAM_MAX: i64 = 100000 57const TC_LAB_L_MAX: i64 = 1000 58const TC_LAB_AB: i64 = 500 59// card axis fields 60const TC_F_SECTION: i64 = 1 61const TC_F_ID: i64 = 2 62const TC_F_SIDE: i64 = 3 63const TC_F_VALUE: i64 = 4 64const TC_F_METHOD: i64 = 5 65const TC_F_SOURCE: i64 = 6 66const TC_F_WHEN: i64 = 7 67// card header, ref, shot fields 68const TC_F_CARD_SLUG: i64 = 1 69const TC_F_CARD_DISPLAY: i64 = 2 70const TC_F_CARD_CLASS: i64 = 3 71const TC_F_CARD_SEX: i64 = 4 72const TC_F_CARD_LIC: i64 = 5 73const TC_F_REF_KEY: i64 = 1 74const TC_F_REF_MIRROR: i64 = 2 75const TC_F_REF_SHA: i64 = 3 76const TC_F_REF_LIC: i64 = 4 77const TC_F_SHOT_REF: i64 = 1 78// shot state: four declared class words after the accessories field (presentation, makeup, hair_state, retouch) 79const TC_F_SHOT_STATE0: i64 = 10 80const TC_SHOT_STATE_N: i64 = 4 81const TC_SHOT: *u8 = "shot" 82// card feature fields 83const TC_F_FEAT_KIND: i64 = 1 84const TC_F_FEAT_SIDE: i64 = 2 85const TC_F_FEAT_REGION: i64 = 3 86const TC_F_FEAT_U: i64 = 4 87const TC_F_FEAT_V: i64 = 5 88const TC_F_FEAT_DIAM: i64 = 6 89const TC_F_FEAT_L: i64 = 7 90const TC_F_FEAT_A: i64 = 8 91const TC_F_FEAT_B: i64 = 9 92const TC_F_FEAT_METHOD: i64 = 10 93// schema fields 94const TC_F_SCHEMA_UNIT: i64 = 3 95const TC_F_SCHEMA_LO: i64 = 4 96const TC_F_SCHEMA_HI: i64 = 5 97const TC_F_SCHEMA_PAIRED: i64 = 6 98const TC_F_RULER_ORGAN: i64 = 3 99const TC_F_RULER_SYMBOL: i64 = 4 100// report slots filled by tc_validate 101const TC_R_AXES: i64 = 0 102const TC_R_VALID: i64 = 1 103const TC_R_UNDECLARED: i64 = 2 104const TC_R_RANGE: i64 = 3 105const TC_R_METHOD: i64 = 4 106const TC_R_CLASSWORD: i64 = 5 107const TC_R_DUP: i64 = 6 108const TC_R_MEASURED: i64 = 7 109const TC_R_OBSERVED: i64 = 8 110const TC_R_DECLARED: i64 = 9 111const TC_R_GENERATED: i64 = 10 112const TC_R_HEADER: i64 = 11 113const TC_R_REFS: i64 = 12 114const TC_R_BADREF: i64 = 13 115const TC_R_SHOTS: i64 = 14 116const TC_R_BADSHOT: i64 = 15 117const TC_R_CARDS: i64 = 16 118const TC_R_SIDE: i64 = 17 119const TC_R_FEATURES: i64 = 18 120const TC_R_BADFEATURE: i64 = 19 121const TC_R_N: i64 = 20 122// tc_ruler_for answers 123const TC_RULER_NONE: i64 = 0 124const TC_RULER_EXACT: i64 = 1 125const TC_RULER_WILDCARD: i64 = 2 126 127// the card's generation stamp, the symbol the board contracts (AT23 tc_card_check) 128func tc_card_check() -> i64 { return TC_SCHEMA_V } 129 130// whole-word membership in a space-delimited list 131func tc_word_in(list: *u8, w: *u8) -> i64 { 132 let ww: *u8 = sys_mmap(RI_PATHB) 133 var o: i64 = 0 134 ww[o] = RI_SP as u8; o = o + 1 135 o = ri_cat(ww, o, w) 136 ww[o] = RI_SP as u8; o = o + 1 137 ww[o] = 0 as u8 138 return ri_contains(list, ri_slen(list), ww) 139} 140func tc_atoi_signed(s: *u8) -> i64 { 141 if s[0] == (RI_DASH as u8) { return 0 - ri_atoi((s as i64 + 1) as *u8) } 142 return ri_atoi(s) 143} 144func tc_in_band(v: i64, lo: i64, hi: i64) -> i64 { 145 if v < lo { return 0 } 146 if v > hi { return 0 } 147 return 1 148} 149func tc_permil(num: i64, den: i64) -> i64 { 150 if den <= 0 { return 0 } 151 return num * TC_PERMIL / den 152} 153func tc_card_path(slug: *u8, out: *u8) -> i64 { 154 var o: i64 = ri_cat(out, 0, TC_DIR) 155 out[o] = RI_SLASH as u8; o = o + 1 156 o = ri_cat(out, o, slug) 157 o = ri_cat(out, o, ".card" as *u8) 158 return o 159} 160// the first row starting with prefix; pos[0] = start, pos[1] = end 161func tc_row_find(buf: *u8, n: i64, prefix: *u8, pos: *i64) -> i64 { 162 var i: i64 = 0 163 while i < n { 164 let e: i64 = ri_line_end(buf, n, i) 165 if ri_starts(buf, n, i, prefix) == 1 { pos[0] = i; pos[1] = e; return 1 } 166 i = e + 1 167 } 168 pos[0] = 0 169 pos[1] = 0 170 return 0 171} 172func tc_count_prefix(buf: *u8, n: i64, prefix: *u8) -> i64 { 173 var i: i64 = 0 174 var c: i64 = 0 175 while i < n { 176 let e: i64 = ri_line_end(buf, n, i) 177 if ri_starts(buf, n, i, prefix) == 1 { c = c + 1 } 178 i = e + 1 179 } 180 return c 181} 182// "<kind>|<a>|", "<kind>|<a>|<b>|" and "<kind>|<a>|<b>|<c>|" 183func tc_key1(out: *u8, kind: *u8, a: *u8) -> i64 { 184 var o: i64 = ri_cat(out, 0, kind) 185 out[o] = RI_PIPE as u8; o = o + 1 186 o = ri_cat(out, o, a) 187 out[o] = RI_PIPE as u8; o = o + 1 188 out[o] = 0 as u8 189 return o 190} 191func tc_key2(out: *u8, kind: *u8, a: *u8, b: *u8) -> i64 { 192 var o: i64 = tc_key1(out, kind, a) 193 o = ri_cat(out, o, b) 194 out[o] = RI_PIPE as u8; o = o + 1 195 out[o] = 0 as u8 196 return o 197} 198func tc_key3(out: *u8, kind: *u8, a: *u8, b: *u8, c: *u8) -> i64 { 199 var o: i64 = tc_key2(out, kind, a, b) 200 o = ri_cat(out, o, c) 201 out[o] = RI_PIPE as u8; o = o + 1 202 out[o] = 0 as u8 203 return o 204} 205// is <section>/<id> declared? face ids are the canon rows; every other section is a schema axis row. pos = the declaring row 206func tc_axis_declared(schema: *u8, sn: i64, canon: *u8, kn: i64, section: *u8, id: *u8, pos: *i64) -> i64 { 207 let key: *u8 = sys_mmap(RI_ROWB) 208 if ri_streq(section, TC_FACE) == 1 { 209 tc_key1(key, "canon" as *u8, id) 210 return tc_row_find(canon, kn, key, pos) 211 } 212 tc_key2(key, "axis" as *u8, section, id) 213 return tc_row_find(schema, sn, key, pos) 214} 215// unit, band and pairing of a schema axis (never a face axis); returns 1 when declared 216func tc_unit_band(schema: *u8, sn: i64, section: *u8, id: *u8, unit: *u8, lo: *i64, hi: *i64, paired: *i64) -> i64 { 217 let key: *u8 = sys_mmap(RI_ROWB) 218 let pos: *i64 = sys_mmap(TC_POS_N * RI_I64) as *i64 219 let f: *u8 = sys_mmap(RI_PATHB) 220 tc_key2(key, "axis" as *u8, section, id) 221 if tc_row_find(schema, sn, key, pos) == 0 { unit[0] = 0 as u8; lo[0] = 0; hi[0] = 0; paired[0] = 0; return 0 } 222 ri_field(schema, pos[0], pos[1], TC_F_SCHEMA_UNIT, unit, RI_PATHB) 223 ri_field(schema, pos[0], pos[1], TC_F_SCHEMA_LO, f, RI_PATHB) 224 lo[0] = tc_atoi_signed(f) 225 ri_field(schema, pos[0], pos[1], TC_F_SCHEMA_HI, f, RI_PATHB) 226 hi[0] = tc_atoi_signed(f) 227 ri_field(schema, pos[0], pos[1], TC_F_SCHEMA_PAIRED, f, RI_PATHB) 228 paired[0] = ri_atoi(f) 229 return 1 230} 231func tc_paired(schema: *u8, sn: i64, section: *u8, id: *u8) -> i64 { 232 let unit: *u8 = sys_mmap(RI_PATHB) 233 let lo: *i64 = sys_mmap(RI_I64) as *i64 234 let hi: *i64 = sys_mmap(RI_I64) as *i64 235 let paired: *i64 = sys_mmap(RI_I64) as *i64 236 if tc_unit_band(schema, sn, section, id, unit, lo, hi, paired) == 0 { return 0 } 237 return paired[0] 238} 239// is <word> a declared word of the class axis <section>/<id>? whole-line match on class|section|id|word 240func tc_class_ok(schema: *u8, sn: i64, section: *u8, id: *u8, word: *u8) -> i64 { 241 let line: *u8 = sys_mmap(RI_ROWB) 242 var o: i64 = tc_key2(line, "class" as *u8, section, id) 243 o = ri_cat(line, o, word) 244 return ri_has_line(schema, sn, line) 245} 246func tc_region_ok(schema: *u8, sn: i64, word: *u8) -> i64 { 247 let key: *u8 = sys_mmap(RI_ROWB) 248 let pos: *i64 = sys_mmap(TC_POS_N * RI_I64) as *i64 249 tc_key1(key, "region" as *u8, word) 250 return tc_row_find(schema, sn, key, pos) 251} 252// the ruler declared for an axis: an exact ruler row, else the section's * row; copies organ and symbol 253func tc_ruler_for(schema: *u8, sn: i64, section: *u8, id: *u8, organ: *u8, symbol: *u8) -> i64 { 254 let key: *u8 = sys_mmap(RI_ROWB) 255 let pos: *i64 = sys_mmap(TC_POS_N * RI_I64) as *i64 256 tc_key2(key, "ruler" as *u8, section, id) 257 var how: i64 = TC_RULER_EXACT 258 if tc_row_find(schema, sn, key, pos) == 0 { 259 how = TC_RULER_WILDCARD 260 tc_key2(key, "ruler" as *u8, section, TC_STAR) 261 if tc_row_find(schema, sn, key, pos) == 0 { organ[0] = 0 as u8; symbol[0] = 0 as u8; return TC_RULER_NONE } 262 } 263 ri_field(schema, pos[0], pos[1], TC_F_RULER_ORGAN, organ, RI_PATHB) 264 ri_field(schema, pos[0], pos[1], TC_F_RULER_SYMBOL, symbol, RI_PATHB) 265 return how 266} 267func tc_ref_exists(card: *u8, cn: i64, key: *u8) -> i64 { 268 let k: *u8 = sys_mmap(RI_ROWB) 269 let pos: *i64 = sys_mmap(TC_POS_N * RI_I64) as *i64 270 tc_key1(k, "ref" as *u8, key) 271 return tc_row_find(card, cn, k, pos) 272} 273// an earlier axis row (before byte <upto>) with the same section, id and side? 274func tc_dup_before(card: *u8, upto: i64, section: *u8, id: *u8, side: *u8) -> i64 { 275 let key: *u8 = sys_mmap(RI_ROWB) 276 tc_key3(key, "axis" as *u8, section, id, side) 277 var i: i64 = 0 278 while i < upto { 279 let e: i64 = ri_line_end(card, upto, i) 280 if ri_starts(card, upto, i, key) == 1 { return 1 } 281 i = e + 1 282 } 283 return 0 284} 285// an earlier axis row with the same section and id on ANY side (face coverage counts ids) 286func tc_dup_id_before(card: *u8, upto: i64, section: *u8, id: *u8) -> i64 { 287 let key: *u8 = sys_mmap(RI_ROWB) 288 tc_key2(key, "axis" as *u8, section, id) 289 var i: i64 = 0 290 while i < upto { 291 let e: i64 = ri_line_end(card, upto, i) 292 if ri_starts(card, upto, i, key) == 1 { return 1 } 293 i = e + 1 294 } 295 return 0 296} 297// the k-th shot-state axis name, in the order the shot row carries them 298func tc_shot_axis(k: i64) -> *u8 { 299 if k == 0 { return "presentation" as *u8 } 300 if k == 1 { return "makeup" as *u8 } 301 if k == 2 { return "hair_state" as *u8 } 302 return "retouch" as *u8 303} 304// RULER COVERAGE: every declared axis (schema sections and the canon face ids) must have a ruler row, exact or wildcard. 305// out[0] axes, out[1] ruled, out[2] unruled; with announce=1 every unruled axis is printed as a worklist row 306func tc_ruler_coverage(schema: *u8, sn: i64, canon: *u8, kn: i64, announce: i64, out: *i64) -> i64 { 307 let sect: *u8 = sys_mmap(RI_PATHB) 308 let id: *u8 = sys_mmap(RI_PATHB) 309 let organ: *u8 = sys_mmap(RI_PATHB) 310 let symbol: *u8 = sys_mmap(RI_PATHB) 311 out[0] = 0 312 out[1] = 0 313 out[2] = 0 314 var i: i64 = 0 315 while i < sn { 316 let e: i64 = ri_line_end(schema, sn, i) 317 if ri_starts(schema, sn, i, "axis|" as *u8) == 1 { 318 ri_field(schema, i, e, TC_F_SECTION, sect, RI_PATHB) 319 ri_field(schema, i, e, TC_F_ID, id, RI_PATHB) 320 out[0] = out[0] + 1 321 if tc_ruler_for(schema, sn, sect, id, organ, symbol) == TC_RULER_NONE { 322 out[2] = out[2] + 1 323 if announce == 1 { ri_puts("TWINCARD unruled section=" as *u8); ri_puts(sect); ri_puts(" id=" as *u8); ri_puts(id); ri_puts("\n" as *u8) } 324 } else { out[1] = out[1] + 1 } 325 } 326 i = e + 1 327 } 328 var j: i64 = 0 329 while j < kn { 330 let e2: i64 = ri_line_end(canon, kn, j) 331 if ri_starts(canon, kn, j, "canon|" as *u8) == 1 { 332 ri_field(canon, j, e2, 1, id, RI_PATHB) 333 out[0] = out[0] + 1 334 if tc_ruler_for(schema, sn, TC_FACE, id, organ, symbol) == TC_RULER_NONE { 335 out[2] = out[2] + 1 336 if announce == 1 { ri_puts("TWINCARD unruled section=face id=" as *u8); ri_puts(id); ri_puts("\n" as *u8) } 337 } else { out[1] = out[1] + 1 } 338 } 339 j = e2 + 1 340 } 341 return out[2] 342} 343// the first offender is remembered as <section>/<id>; later ones only count 344func tc_bad(bad: *u8, section: *u8, id: *u8) -> i64 { 345 if bad[0] != (0 as u8) { return 0 } 346 var o: i64 = ri_cat(bad, 0, section) 347 bad[o] = RI_SLASH as u8; o = o + 1 348 o = ri_cat(bad, o, id) 349 return o 350} 351// does the side agree with the pairing? face rows may carry any side; a paired axis needs L or R; an unpaired axis needs C 352func tc_side_ok(section: *u8, paired: i64, side: *u8) -> i64 { 353 if tc_word_in(TC_SIDES, side) == 0 { return 0 } 354 if ri_streq(section, TC_FACE) == 1 { return 1 } 355 if paired == 1 { 356 if ri_streq(side, TC_SIDE_C) == 1 { return 0 } 357 return 1 358 } 359 if ri_streq(side, TC_SIDE_C) == 1 { return 1 } 360 return 0 361} 362// one feature row: kind, side, region, chart coordinates, diameter, colour, method 363func tc_feature_ok(card: *u8, i: i64, e: i64, schema: *u8, sn: i64) -> i64 { 364 let f: *u8 = sys_mmap(RI_ROWB) 365 var ok: i64 = 1 366 ri_field(card, i, e, TC_F_FEAT_KIND, f, RI_ROWB) 367 if tc_word_in(TC_FEATURE_KINDS, f) == 0 { ok = 0 } 368 ri_field(card, i, e, TC_F_FEAT_SIDE, f, RI_ROWB) 369 if tc_word_in(TC_SIDES, f) == 0 { ok = 0 } 370 ri_field(card, i, e, TC_F_FEAT_REGION, f, RI_ROWB) 371 if tc_region_ok(schema, sn, f) == 0 { ok = 0 } 372 ri_field(card, i, e, TC_F_FEAT_U, f, RI_ROWB) 373 if tc_in_band(tc_atoi_signed(f), 0, TC_UV_MAX) == 0 { ok = 0 } 374 ri_field(card, i, e, TC_F_FEAT_V, f, RI_ROWB) 375 if tc_in_band(tc_atoi_signed(f), 0, TC_UV_MAX) == 0 { ok = 0 } 376 ri_field(card, i, e, TC_F_FEAT_DIAM, f, RI_ROWB) 377 if tc_in_band(tc_atoi_signed(f), 0, TC_DIAM_MAX) == 0 { ok = 0 } 378 ri_field(card, i, e, TC_F_FEAT_L, f, RI_ROWB) 379 if tc_in_band(tc_atoi_signed(f), 0, TC_LAB_L_MAX) == 0 { ok = 0 } 380 ri_field(card, i, e, TC_F_FEAT_A, f, RI_ROWB) 381 if tc_in_band(tc_atoi_signed(f), 0 - TC_LAB_AB, TC_LAB_AB) == 0 { ok = 0 } 382 ri_field(card, i, e, TC_F_FEAT_B, f, RI_ROWB) 383 if tc_in_band(tc_atoi_signed(f), 0 - TC_LAB_AB, TC_LAB_AB) == 0 { ok = 0 } 384 ri_field(card, i, e, TC_F_FEAT_METHOD, f, RI_ROWB) 385 if tc_word_in(TC_METHODS, f) == 0 { ok = 0 } 386 return ok 387} 388// VALIDATE a card against the schema and the canon. Fills rep[TC_R_*], names the first offender in bad, returns the defect count. 389func tc_validate(card: *u8, cn: i64, schema: *u8, sn: i64, canon: *u8, kn: i64, rep: *i64, bad: *u8) -> i64 { 390 var k: i64 = 0 391 while k < TC_R_N { rep[k] = 0; k = k + 1 } 392 bad[0] = 0 as u8 393 let sect: *u8 = sys_mmap(RI_PATHB) 394 let id: *u8 = sys_mmap(RI_PATHB) 395 let side: *u8 = sys_mmap(RI_PATHB) 396 let val: *u8 = sys_mmap(RI_ROWB) 397 let meth: *u8 = sys_mmap(RI_PATHB) 398 let unit: *u8 = sys_mmap(RI_PATHB) 399 let pos: *i64 = sys_mmap(TC_POS_N * RI_I64) as *i64 400 let lo: *i64 = sys_mmap(RI_I64) as *i64 401 let hi: *i64 = sys_mmap(RI_I64) as *i64 402 let paired: *i64 = sys_mmap(RI_I64) as *i64 403 var headers_ok: i64 = 0 404 var i: i64 = 0 405 while i < cn { 406 let e: i64 = ri_line_end(card, cn, i) 407 if ri_starts(card, cn, i, "card|" as *u8) == 1 { 408 rep[TC_R_CARDS] = rep[TC_R_CARDS] + 1 409 var okh: i64 = 1 410 ri_field(card, i, e, TC_F_CARD_CLASS, val, RI_ROWB) 411 if tc_word_in(TC_CLASSES, val) == 0 { okh = 0 } 412 ri_field(card, i, e, TC_F_CARD_SEX, val, RI_ROWB) 413 if tc_word_in(TC_SEXES, val) == 0 { okh = 0 } 414 ri_field(card, i, e, TC_F_CARD_LIC, val, RI_ROWB) 415 if tc_word_in(TC_LICENCES, val) == 0 { okh = 0 } 416 if okh == 1 { headers_ok = headers_ok + 1 } else { tc_bad(bad, "card" as *u8, "header" as *u8) } 417 } 418 if ri_starts(card, cn, i, "axis|" as *u8) == 1 { 419 rep[TC_R_AXES] = rep[TC_R_AXES] + 1 420 ri_field(card, i, e, TC_F_SECTION, sect, RI_PATHB) 421 ri_field(card, i, e, TC_F_ID, id, RI_PATHB) 422 ri_field(card, i, e, TC_F_SIDE, side, RI_PATHB) 423 ri_field(card, i, e, TC_F_VALUE, val, RI_ROWB) 424 ri_field(card, i, e, TC_F_METHOD, meth, RI_PATHB) 425 var ok: i64 = 1 426 if tc_axis_declared(schema, sn, canon, kn, sect, id, pos) == 0 { 427 ok = 0 428 rep[TC_R_UNDECLARED] = rep[TC_R_UNDECLARED] + 1 429 tc_bad(bad, sect, id) 430 } else { 431 if tc_dup_before(card, i, sect, id, side) == 1 { ok = 0; rep[TC_R_DUP] = rep[TC_R_DUP] + 1; tc_bad(bad, sect, id) } 432 if tc_word_in(TC_METHODS, meth) == 0 { ok = 0; rep[TC_R_METHOD] = rep[TC_R_METHOD] + 1; tc_bad(bad, sect, id) } 433 paired[0] = 0 434 if ri_streq(sect, TC_FACE) == 0 { 435 tc_unit_band(schema, sn, sect, id, unit, lo, hi, paired) 436 if ri_streq(unit, TC_UNIT_CLASS) == 1 { 437 if tc_class_ok(schema, sn, sect, id, val) == 0 { ok = 0; rep[TC_R_CLASSWORD] = rep[TC_R_CLASSWORD] + 1; tc_bad(bad, sect, id) } 438 } else { 439 var banded: i64 = 1 440 if lo[0] == 0 { if hi[0] == 0 { banded = 0 } } 441 if banded == 1 { 442 if tc_in_band(tc_atoi_signed(val), lo[0], hi[0]) == 0 { ok = 0; rep[TC_R_RANGE] = rep[TC_R_RANGE] + 1; tc_bad(bad, sect, id) } 443 } 444 } 445 } 446 if tc_side_ok(sect, paired[0], side) == 0 { ok = 0; rep[TC_R_SIDE] = rep[TC_R_SIDE] + 1; tc_bad(bad, sect, id) } 447 } 448 if ok == 1 { 449 rep[TC_R_VALID] = rep[TC_R_VALID] + 1 450 if ri_streq(meth, "measured" as *u8) == 1 { rep[TC_R_MEASURED] = rep[TC_R_MEASURED] + 1 } 451 if ri_streq(meth, "observed" as *u8) == 1 { rep[TC_R_OBSERVED] = rep[TC_R_OBSERVED] + 1 } 452 if ri_streq(meth, "declared" as *u8) == 1 { rep[TC_R_DECLARED] = rep[TC_R_DECLARED] + 1 } 453 if ri_streq(meth, "generated" as *u8) == 1 { rep[TC_R_GENERATED] = rep[TC_R_GENERATED] + 1 } 454 } 455 } 456 if ri_starts(card, cn, i, "feature|" as *u8) == 1 { 457 rep[TC_R_FEATURES] = rep[TC_R_FEATURES] + 1 458 if tc_feature_ok(card, i, e, schema, sn) == 0 { 459 rep[TC_R_BADFEATURE] = rep[TC_R_BADFEATURE] + 1 460 ri_field(card, i, e, TC_F_FEAT_KIND, id, RI_PATHB) 461 tc_bad(bad, "feature" as *u8, id) 462 } 463 } 464 if ri_starts(card, cn, i, "ref|" as *u8) == 1 { 465 rep[TC_R_REFS] = rep[TC_R_REFS] + 1 466 var okr: i64 = 1 467 ri_field(card, i, e, TC_F_REF_SHA, val, RI_ROWB) 468 if ri_streq(val, TC_DASHWORD) == 0 { if ri_slen(val) != RI_SHA_HEX { okr = 0 } } 469 ri_field(card, i, e, TC_F_REF_LIC, val, RI_ROWB) 470 if tc_word_in(TC_LICENCES, val) == 0 { okr = 0 } 471 if okr == 0 { 472 rep[TC_R_BADREF] = rep[TC_R_BADREF] + 1 473 ri_field(card, i, e, TC_F_REF_KEY, id, RI_PATHB) 474 tc_bad(bad, "ref" as *u8, id) 475 } 476 } 477 if ri_starts(card, cn, i, "shot|" as *u8) == 1 { 478 rep[TC_R_SHOTS] = rep[TC_R_SHOTS] + 1 479 ri_field(card, i, e, TC_F_SHOT_REF, id, RI_PATHB) 480 var oks: i64 = 1 481 if tc_ref_exists(card, cn, id) == 0 { oks = 0 } 482 // the presentation state of the shot (operator 2026-09-16: the natural nude-art state AND the glamorised state 483 // are both wanted, so every shot says which it is): four declared class words, refused by name when undeclared 484 var sx: i64 = 0 485 while sx < TC_SHOT_STATE_N { 486 ri_field(card, i, e, TC_F_SHOT_STATE0 + sx, val, RI_ROWB) 487 if tc_class_ok(schema, sn, TC_SHOT, tc_shot_axis(sx), val) == 0 { oks = 0 } 488 sx = sx + 1 489 } 490 if oks == 0 { rep[TC_R_BADSHOT] = rep[TC_R_BADSHOT] + 1; tc_bad(bad, "shot" as *u8, id) } 491 } 492 i = e + 1 493 } 494 var hdr: i64 = 0 495 if rep[TC_R_CARDS] == 1 { if headers_ok == 1 { hdr = 1 } } 496 rep[TC_R_HEADER] = hdr 497 var defects: i64 = rep[TC_R_UNDECLARED] + rep[TC_R_RANGE] + rep[TC_R_METHOD] + rep[TC_R_CLASSWORD] + rep[TC_R_DUP] + rep[TC_R_SIDE] 498 defects = defects + rep[TC_R_BADREF] + rep[TC_R_BADSHOT] + rep[TC_R_BADFEATURE] 499 if hdr == 0 { defects = defects + 1 } 500 return defects 501} 502// the number of values a section declares: a paired axis counts twice (L and R); face = the canon rows 503func tc_declared_count(schema: *u8, sn: i64, canon: *u8, kn: i64, section: *u8) -> i64 { 504 let key: *u8 = sys_mmap(RI_ROWB) 505 let f: *u8 = sys_mmap(RI_PATHB) 506 if ri_streq(section, TC_FACE) == 1 { return tc_count_prefix(canon, kn, "canon|" as *u8) } 507 tc_key1(key, "axis" as *u8, section) 508 var i: i64 = 0 509 var c: i64 = 0 510 while i < sn { 511 let e: i64 = ri_line_end(schema, sn, i) 512 if ri_starts(schema, sn, i, key) == 1 { 513 ri_field(schema, i, e, TC_F_SCHEMA_PAIRED, f, RI_PATHB) 514 c = c + 1 515 if ri_atoi(f) == 1 { c = c + 1 } 516 } 517 i = e + 1 518 } 519 return c 520} 521// the number of DECLARED values the card fills in a section: distinct (id, side) off the face, distinct ids on the face 522func tc_filled_count(card: *u8, cn: i64, schema: *u8, sn: i64, canon: *u8, kn: i64, section: *u8) -> i64 { 523 let key: *u8 = sys_mmap(RI_ROWB) 524 let id: *u8 = sys_mmap(RI_PATHB) 525 let side: *u8 = sys_mmap(RI_PATHB) 526 let pos: *i64 = sys_mmap(TC_POS_N * RI_I64) as *i64 527 let isface: i64 = ri_streq(section, TC_FACE) 528 tc_key1(key, "axis" as *u8, section) 529 var i: i64 = 0 530 var c: i64 = 0 531 while i < cn { 532 let e: i64 = ri_line_end(card, cn, i) 533 if ri_starts(card, cn, i, key) == 1 { 534 ri_field(card, i, e, TC_F_ID, id, RI_PATHB) 535 ri_field(card, i, e, TC_F_SIDE, side, RI_PATHB) 536 if tc_axis_declared(schema, sn, canon, kn, section, id, pos) == 1 { 537 var fresh: i64 = 0 538 if isface == 1 { if tc_dup_id_before(card, i, section, id) == 0 { fresh = 1 } } 539 else { if tc_dup_before(card, i, section, id, side) == 0 { fresh = 1 } } 540 c = c + fresh 541 } 542 } 543 i = e + 1 544 } 545 return c 546} 547// paired axes (off the face) that carry BOTH a left and a right row: the asymmetry the operator asked for is recordable only there 548func tc_pairs_complete(card: *u8, cn: i64, schema: *u8, sn: i64, pairs: *i64) -> i64 { 549 let sect: *u8 = sys_mmap(RI_PATHB) 550 let id: *u8 = sys_mmap(RI_PATHB) 551 let f: *u8 = sys_mmap(RI_PATHB) 552 let kl: *u8 = sys_mmap(RI_ROWB) 553 let kr: *u8 = sys_mmap(RI_ROWB) 554 let pos: *i64 = sys_mmap(TC_POS_N * RI_I64) as *i64 555 pairs[0] = 0 556 var i: i64 = 0 557 var done: i64 = 0 558 while i < sn { 559 let e: i64 = ri_line_end(schema, sn, i) 560 if ri_starts(schema, sn, i, "axis|" as *u8) == 1 { 561 ri_field(schema, i, e, TC_F_SCHEMA_PAIRED, f, RI_PATHB) 562 if ri_atoi(f) == 1 { 563 pairs[0] = pairs[0] + 1 564 ri_field(schema, i, e, TC_F_SECTION, sect, RI_PATHB) 565 ri_field(schema, i, e, TC_F_ID, id, RI_PATHB) 566 tc_key3(kl, "axis" as *u8, sect, id, TC_SIDE_L) 567 tc_key3(kr, "axis" as *u8, sect, id, TC_SIDE_R) 568 if tc_row_find(card, cn, kl, pos) == 1 { if tc_row_find(card, cn, kr, pos) == 1 { done = done + 1 } } 569 } 570 } 571 i = e + 1 572 } 573 return done 574} 575// RULER CENSUS through the estate's ONE symbol ruler (nx_symdecl_lib.sd_present, never a second substring ruler): out[0] ruler rows, 576// out[1] present (declared in the named organ), out[2] absent (the organ read and the symbol not declared), out[3] unjudged (no organ 577// file at the path or under buildroot/, or the ruler abstained). An organ path is tried as given, then under buildroot/, because the 578// serving root and the build tree are two CWDs for the same relative spelling. 579func tc_ruler_census(schema: *u8, sn: i64, out: *i64) -> i64 { 580 let organ: *u8 = sys_mmap(RI_PATHB) 581 let alt: *u8 = sys_mmap(RI_PATHB) 582 let symbol: *u8 = sys_mmap(RI_PATHB) 583 let rule: *i64 = sys_mmap(RI_I64) as *i64 584 out[TC_C_ROWS] = 0 585 out[TC_C_PRESENT] = 0 586 out[TC_C_ABSENT] = 0 587 out[TC_C_UNJUDGED] = 0 588 var i: i64 = 0 589 while i < sn { 590 let e: i64 = ri_line_end(schema, sn, i) 591 if ri_starts(schema, sn, i, "ruler|" as *u8) == 1 { 592 out[TC_C_ROWS] = out[TC_C_ROWS] + 1 593 ri_field(schema, i, e, TC_F_RULER_ORGAN, organ, RI_PATHB) 594 ri_field(schema, i, e, TC_F_RULER_SYMBOL, symbol, RI_PATHB) 595 var r: i64 = sd_present(organ, symbol, rule) 596 if r < 0 { 597 var o: i64 = ri_cat(alt, 0, TC_BUILDROOT) 598 o = ri_cat(alt, o, organ) 599 r = sd_present(alt, symbol, rule) 600 } 601 if r == 1 { out[TC_C_PRESENT] = out[TC_C_PRESENT] + 1 } 602 else { if r == 0 { out[TC_C_ABSENT] = out[TC_C_ABSENT] + 1 } else { out[TC_C_UNJUDGED] = out[TC_C_UNJUDGED] + 1 } } 603 } 604 i = e + 1 605 } 606 return out[TC_C_ROWS] 607} 608// NUL-separated word lists (the section list) 609func tc_list_has(list: *u8, count: i64, w: *u8) -> i64 { 610 var k: i64 = 0 611 var p: i64 = 0 612 while k < count { 613 if ri_streq((list as i64 + p) as *u8, w) == 1 { return 1 } 614 p = p + ri_slen((list as i64 + p) as *u8) + 1 615 k = k + 1 616 } 617 return 0 618} 619func tc_list_at(list: *u8, k: i64) -> *u8 { 620 var j: i64 = 0 621 var p: i64 = 0 622 while j < k { p = p + ri_slen((list as i64 + p) as *u8) + 1; j = j + 1 } 623 return (list as i64 + p) as *u8 624} 625// the distinct sections the schema declares, in first-seen order, NUL-separated in out; returns the count. face is NOT here: it 626// lives in the canon, and the caller appends it 627func tc_sections(schema: *u8, sn: i64, out: *u8, cap: i64) -> i64 { 628 let sect: *u8 = sys_mmap(RI_PATHB) 629 var i: i64 = 0 630 var count: i64 = 0 631 var o: i64 = 0 632 while i < sn { 633 let e: i64 = ri_line_end(schema, sn, i) 634 if ri_starts(schema, sn, i, "axis|" as *u8) == 1 { 635 ri_field(schema, i, e, TC_F_SECTION, sect, RI_PATHB) 636 if tc_list_has(out, count, sect) == 0 { 637 let sl: i64 = ri_slen(sect) 638 if o + sl + 1 < cap { o = ri_cat(out, o, sect); o = o + 1; count = count + 1 } 639 } 640 } 641 i = e + 1 642 } 643 return count 644}