code wiki / (root) / nx_motion_lib.nx

nx_motion_lib.nx source

↩ module page · 767 lines · 41671 B

1// nx_motion_lib.nx -- THE /motion SURFACE'S ONE SET OF RULERS (2026-09-06): content typing by MAGIC, the multipart 2// upload parser, query and form decoding, the job status rows, the row-file readers, the page renderers and the 3// fork runner -- shared by the daemon (nx_motion_serve), the job (nx_motion_rig) and the gate (nx_motion_serve_gate) 4// so a parse fixed in one cannot stay broken in another. Every function is pure over buffers except the named reads. 5// 6// WHY A LIB AND NOT THREE COPIES: the estate has measured, more than once, what happens when two organs must agree by 7// discipline -- they do not. The upload door types a file by its first bytes; the job names the same kinds; the gate 8// plants the same magics. One ruler, three callers. 9// license_tier: ORIGINAL 10import "nx_syscalls.nx" 11 12// content kinds -- decided by the FIRST BYTES, never by an extension a visitor typed 13const MO_KIND_UNKNOWN: i64 = 0 14const MO_KIND_GLB: i64 = 1 15const MO_KIND_FBX: i64 = 2 16const MO_KIND_NXA: i64 = 3 17const MO_KIND_OBJ: i64 = 4 // recognised so it can be REFUSED BY NAME: no sovereign OBJ door is composed yet (MO2) 18// THE DIRECT UPLOAD CAP, NAMED FOR ONE PURPOSE: the edge proxy (sites.elf) was crashed by oversized proxied POST 19// bodies on 2026-07-20, so one direct upload is bounded here and the bound is printed on the page; a larger model 20// belongs to the chunked door (motion.plan MO13). A bound on a NETWORK body is the one place a cap is legitimate, 21// and its truncation is never silent -- an over-cap body is refused by name with a status. 22const MO_UPLOAD_CAP: i64 = 8388608 23const MO_HDR_RESERVE: i64 = 65536 24const MO_REQ_CAP: i64 = 8453120 // MO_UPLOAD_CAP + MO_HDR_RESERVE, derived, so the request buffer cannot be a second guess 25const MO_PATH_CAP: i64 = 1024 26const MO_VAL_CAP: i64 = 512 27const MO_ROWS_CAP: i64 = 262144 28const MO_PAGE_CAP: i64 = 1048576 29const MO_ARGV_CAP: i64 = 16 30const MO_JOBS_DIR: *u8 = "knowledge/motion/jobs/" 31const MO_DEMOS_DIR: *u8 = "knowledge/motion/demos/" 32const MO_CLIPS_ROWS: *u8 = "knowledge/motion_clips.rows" 33const MO_DEMOS_ROWS: *u8 = "knowledge/motion_demos.rows" 34const MO_TMPL: *u8 = "knowledge/motion_page.tmpl" 35const MO_VERDICTS: *u8 = "knowledge/motion/verdicts.jrnl" 36const MO_A_NL: i64 = 10 37const MO_A_CR: i64 = 13 38const MO_A_SP: i64 = 32 39const MO_A_QUOTE: i64 = 34 40const MO_A_AMP: i64 = 38 41const MO_A_PLUS: i64 = 43 42const MO_A_DASH: i64 = 45 43const MO_A_DOT: i64 = 46 44const MO_A_SLASH: i64 = 47 45const MO_A_D0: i64 = 48 46const MO_A_D9: i64 = 57 47const MO_A_SEMI: i64 = 59 48const MO_A_LT: i64 = 60 49const MO_A_EQ: i64 = 61 50const MO_A_GT: i64 = 62 51const MO_A_QMARK: i64 = 63 52const MO_A_AT: i64 = 64 53const MO_A_PCT: i64 = 37 54const MO_A_PIPE: i64 = 124 55const MO_A_UNDER: i64 = 95 56const MO_O_APPEND_CREATE_WR: i64 = 1089 // O_WRONLY 1 + O_CREAT 64 + O_APPEND 1024, the estate's append-only journal open 57const MO_AT_FDCWD: i64 = 0 - 100 58const MO_SYS_OPENAT: i64 = 257 59 60// ---- bytes and strings ------------------------------------------------------------------------------------- 61func mo_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 62func mo_cat(b: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; var p: i64 = o; while s[i] != (0 as u8) { b[p] = s[i]; p = p + 1; i = i + 1 } return p } 63func mo_catb(b: *u8, o: i64, src: *u8, n: i64) -> i64 { var i: i64 = 0; while i < n { b[o + i] = src[i]; i = i + 1 } return o + n } 64func mo_num(b: *u8, o: i64, v: i64) -> i64 { 65 var m: i64 = v 66 var p: i64 = o 67 if m < 0 { b[p] = MO_A_DASH as u8; p = p + 1; m = 0 - m } 68 if m == 0 { b[p] = MO_A_D0 as u8; return p + 1 } 69 var d: i64 = 0 70 var y: i64 = m 71 while y > 0 { d = d + 1; y = y / 10 } 72 var i: i64 = d 73 while i > 0 { i = i - 1; b[p + i] = ((m % 10) + MO_A_D0) as u8; m = m / 10 } 74 return p + d 75} 76func mo_atoi(s: *u8, n: i64) -> i64 { 77 var v: i64 = 0 78 var i: i64 = 0 79 var neg: i64 = 0 80 if n > 0 { if s[0] == (MO_A_DASH as u8) { neg = 1; i = 1 } } 81 while i < n { 82 let c: i64 = s[i] as i64 83 if c < MO_A_D0 { return 0 - 0 + v * (1 - 2 * neg) } 84 if c > MO_A_D9 { return v * (1 - 2 * neg) } 85 v = v * 10 + (c - MO_A_D0) 86 i = i + 1 87 } 88 return v * (1 - 2 * neg) 89} 90func mo_streq(a: *u8, b: *u8) -> i64 { 91 var i: i64 = 0 92 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } 93 if b[i] != (0 as u8) { return 0 } 94 return 1 95} 96// first offset >= from where needle[0..nl) occurs in buf[0..n), else -1 97func mo_findfrom(buf: *u8, n: i64, from: i64, needle: *u8, nl: i64) -> i64 { 98 if nl <= 0 { return 0 - 1 } 99 var i: i64 = from 100 while i + nl <= n { 101 var j: i64 = 0 102 var ok: i64 = 1 103 while j < nl { if buf[i + j] != needle[j] { ok = 0; j = nl } else { j = j + 1 } } 104 if ok == 1 { return i } 105 i = i + 1 106 } 107 return 0 - 1 108} 109func mo_find(buf: *u8, n: i64, needle: *u8) -> i64 { return mo_findfrom(buf, n, 0, needle, mo_slen(needle)) } 110func mo_starts(buf: *u8, n: i64, pre: *u8) -> i64 { 111 var i: i64 = 0 112 while pre[i] != (0 as u8) { if i >= n { return 0 } if buf[i] != pre[i] { return 0 } i = i + 1 } 113 return 1 114} 115// digits only, at least one, at most 24 -- the shape of a job id, so a path can never carry a traversal 116func mo_digits_only(s: *u8) -> i64 { 117 var i: i64 = 0 118 while s[i] != (0 as u8) { 119 let c: i64 = s[i] as i64 120 if c < MO_A_D0 { return 0 } 121 if c > MO_A_D9 { return 0 } 122 i = i + 1 123 } 124 if i < 1 { return 0 } 125 if i > 24 { return 0 } 126 return 1 127} 128// an artifact name: letters, digits, underscore, dash and dot, never a slash, never two dots in a row, never empty 129func mo_safe_name(s: *u8) -> i64 { 130 var i: i64 = 0 131 var prevdot: i64 = 0 132 while s[i] != (0 as u8) { 133 let c: i64 = s[i] as i64 134 var ok: i64 = 0 135 if c >= MO_A_D0 { if c <= MO_A_D9 { ok = 1 } } 136 if c >= 97 { if c <= 122 { ok = 1 } } 137 if c >= 65 { if c <= 90 { ok = 1 } } 138 if c == MO_A_UNDER { ok = 1 } 139 if c == MO_A_DASH { ok = 1 } 140 if c == MO_A_DOT { if prevdot == 1 { return 0 } ok = 1; prevdot = 1 } else { prevdot = 0 } 141 if ok == 0 { return 0 } 142 i = i + 1 143 } 144 if i < 1 { return 0 } 145 if i > 96 { return 0 } 146 return 1 147} 148// HTML-escape n bytes of s into b at o (the four characters that can change a document's structure) 149func mo_esc(b: *u8, o: i64, s: *u8, n: i64) -> i64 { 150 var p: i64 = o 151 var i: i64 = 0 152 while i < n { 153 let c: i64 = s[i] as i64 154 if c == MO_A_LT { p = mo_cat(b, p, "&lt;" as *u8) } else { 155 if c == MO_A_GT { p = mo_cat(b, p, "&gt;" as *u8) } else { 156 if c == MO_A_AMP { p = mo_cat(b, p, "&amp;" as *u8) } else { 157 if c == MO_A_QUOTE { p = mo_cat(b, p, "&quot;" as *u8) } else { 158 b[p] = s[i]; p = p + 1 159 } } } } 160 i = i + 1 161 } 162 return p 163} 164 165// ---- content typing by magic -------------------------------------------------------------------------------- 166// GLB: "glTF" at 0 (the binary glTF container). FBX: "Kaydara FBX Binary" at 0. NXA: "NXANIM01" at 0 (nx_nxa.nx's 167// own magic). OBJ: a text file whose first non-space byte opens a v, o, g, mtllib or comment line -- named so it 168// can be refused with its real name instead of UNKNOWN. Anything else is UNKNOWN and refused. 169func mo_kind_of(b: *u8, n: i64) -> i64 { 170 if n >= 4 { if mo_starts(b, n, "glTF" as *u8) == 1 { return MO_KIND_GLB } } 171 if n >= 18 { if mo_starts(b, n, "Kaydara FBX Binary" as *u8) == 1 { return MO_KIND_FBX } } 172 if n >= 8 { if mo_starts(b, n, "NXANIM01" as *u8) == 1 { return MO_KIND_NXA } } 173 if n >= 2 { 174 var i: i64 = 0 175 while i < n { if i < 64 { let c: i64 = b[i] as i64; if c == MO_A_SP { i = i + 1 } else { if c == MO_A_NL { i = i + 1 } else { if c == MO_A_CR { i = i + 1 } else { break } } } } else { break } } 176 if i < n { 177 let c0: i64 = b[i] as i64 178 var txt: i64 = 1 179 var k: i64 = i 180 while k < n { if k < i + 64 { let ck: i64 = b[k] as i64; if ck < 9 { txt = 0 } if ck > 126 { txt = 0 } k = k + 1 } else { break } } 181 if txt == 1 { 182 if c0 == 118 { return MO_KIND_OBJ } // v 183 if c0 == 111 { return MO_KIND_OBJ } // o 184 if c0 == 103 { return MO_KIND_OBJ } // g 185 if c0 == 109 { return MO_KIND_OBJ } // m (mtllib) 186 if c0 == 35 { return MO_KIND_OBJ } // a comment line 187 } 188 } 189 } 190 return MO_KIND_UNKNOWN 191} 192func mo_kind_name(k: i64) -> *u8 { 193 if k == MO_KIND_GLB { return "glb" as *u8 } 194 if k == MO_KIND_FBX { return "fbx" as *u8 } 195 if k == MO_KIND_NXA { return "nxa" as *u8 } 196 if k == MO_KIND_OBJ { return "obj" as *u8 } 197 return "unknown" as *u8 198} 199func mo_kind_from_name(s: *u8) -> i64 { 200 if mo_streq(s, "glb" as *u8) == 1 { return MO_KIND_GLB } 201 if mo_streq(s, "fbx" as *u8) == 1 { return MO_KIND_FBX } 202 if mo_streq(s, "nxa" as *u8) == 1 { return MO_KIND_NXA } 203 if mo_streq(s, "obj" as *u8) == 1 { return MO_KIND_OBJ } 204 return MO_KIND_UNKNOWN 205} 206 207// ---- multipart/form-data -------------------------------------------------------------------------------------- 208// the boundary token from the request headers (req[0..hend)); returns its length into out, 0 if absent 209func mo_boundary(req: *u8, hend: i64, out: *u8, cap: i64) -> i64 { 210 let p: i64 = mo_find(req, hend, "boundary=" as *u8) 211 if p < 0 { return 0 } 212 var i: i64 = p + 9 213 var o: i64 = 0 214 if i < hend { if req[i] == (MO_A_QUOTE as u8) { i = i + 1 } } 215 while i < hend { 216 let c: i64 = req[i] as i64 217 if c == MO_A_CR { break } 218 if c == MO_A_NL { break } 219 if c == MO_A_SEMI { break } 220 if c == MO_A_SP { break } 221 if c == MO_A_QUOTE { break } 222 if o < cap - 1 { out[o] = req[i]; o = o + 1 } 223 i = i + 1 224 } 225 out[o] = 0 as u8 226 return o 227} 228// find the part whose Content-Disposition carries name="<name>"; writes data offset and length; 1 found / 0 absent / 229// -1 malformed (a part without a closing boundary is REFUSED, never half-read) 230func mo_part_find(body: *u8, n: i64, bnd: *u8, blen: i64, name: *u8, out_off: *i64, out_len: *i64) -> i64 { 231 out_off[0] = 0; out_len[0] = 0 232 let dash: *u8 = sys_mmap(blen + 8) 233 dash[0] = MO_A_DASH as u8; dash[1] = MO_A_DASH as u8 234 var i: i64 = 0 235 while i < blen { dash[2 + i] = bnd[i]; i = i + 1 } 236 let dl: i64 = blen + 2 237 let nm: *u8 = sys_mmap(mo_slen(name) + 16) 238 var o: i64 = mo_cat(nm, 0, "name=\"" as *u8) 239 o = mo_cat(nm, o, name) 240 nm[o] = MO_A_QUOTE as u8 241 let nml: i64 = o + 1 242 var pos: i64 = mo_findfrom(body, n, 0, dash, dl) 243 var guard: i64 = 0 244 while pos >= 0 { 245 guard = guard + 1 246 if guard > 64 { return 0 - 1 } 247 let after: i64 = pos + dl 248 if after + 2 > n { return 0 - 1 } 249 if body[after] == (MO_A_DASH as u8) { if body[after + 1] == (MO_A_DASH as u8) { return 0 } } // closing boundary: not found 250 let hstart: i64 = after + 2 251 let hend: i64 = mo_findfrom(body, n, hstart, "\r\n\r\n" as *u8, 4) 252 if hend < 0 { return 0 - 1 } 253 let dstart: i64 = hend + 4 254 let dend: i64 = mo_findfrom(body, n, dstart, "\r\n" as *u8, 2) 255 // the data ends at the next boundary line, which is preceded by CRLF; search boundaries from dstart 256 var nb: i64 = mo_findfrom(body, n, dstart, dash, dl) 257 if nb < 2 { return 0 - 1 } 258 if body[nb - 2] != (MO_A_CR as u8) { return 0 - 1 } 259 if body[nb - 1] != (MO_A_NL as u8) { return 0 - 1 } 260 let hit: i64 = mo_findfrom(body, hend, hstart, nm, nml) 261 if hit >= 0 { 262 out_off[0] = dstart 263 out_len[0] = nb - 2 - dstart 264 return 1 265 } 266 // (dend is informational: the data end is the CRLF before the next boundary, derived above) 267 pos = nb 268 } 269 return 0 270} 271 272// ---- url-encoded values ------------------------------------------------------------------------------------- 273func mo_hexval(c: i64) -> i64 { 274 if c >= 48 { if c <= 57 { return c - 48 } } 275 if c >= 97 { if c <= 102 { return c - 87 } } 276 if c >= 65 { if c <= 70 { return c - 55 } } 277 return 0 - 1 278} 279// decode src[0..n) into out (cap incl. terminator); returns length or -1 on a malformed escape (refused, never half-decoded) 280func mo_urldecode(src: *u8, n: i64, out: *u8, cap: i64) -> i64 { 281 var i: i64 = 0 282 var o: i64 = 0 283 while i < n { 284 if o >= cap - 1 { return 0 - 1 } 285 let c: i64 = src[i] as i64 286 if c == MO_A_PLUS { out[o] = MO_A_SP as u8; o = o + 1; i = i + 1 } else { 287 if c == MO_A_PCT { 288 if i + 2 >= n + 0 { if i + 2 > n - 1 { return 0 - 1 } } 289 let h: i64 = mo_hexval(src[i + 1] as i64) 290 let l: i64 = mo_hexval(src[i + 2] as i64) 291 if h < 0 { return 0 - 1 } 292 if l < 0 { return 0 - 1 } 293 out[o] = (h * 16 + l) as u8 294 o = o + 1 295 i = i + 3 296 } else { 297 out[o] = src[i]; o = o + 1; i = i + 1 298 } } 299 } 300 out[o] = 0 as u8 301 return o 302} 303// the value of key=... in an ampersand-separated string s[0..n); decoded into out; length, 0 absent, -1 malformed 304func mo_kv(s: *u8, n: i64, key: *u8, out: *u8, cap: i64) -> i64 { 305 let kl: i64 = mo_slen(key) 306 var p: i64 = 0 307 out[0] = 0 as u8 308 while p < n { 309 var e: i64 = p 310 while e < n { if s[e] == (MO_A_AMP as u8) { break } e = e + 1 } 311 if e - p > kl { 312 var j: i64 = 0 313 var ok: i64 = 1 314 while j < kl { if s[p + j] != key[j] { ok = 0; j = kl } else { j = j + 1 } } 315 if ok == 1 { if s[p + kl] == (MO_A_EQ as u8) { 316 return mo_urldecode(((s as i64) + p + kl + 1) as *u8, e - p - kl - 1, out, cap) 317 } } 318 } 319 p = e + 1 320 } 321 return 0 322} 323// the query string of a request path: value of key after the question mark 324func mo_qparam(path: *u8, plen: i64, key: *u8, out: *u8, cap: i64) -> i64 { 325 var q: i64 = 0 - 1 326 var i: i64 = 0 327 out[0] = 0 as u8 328 while i < plen { if path[i] == (MO_A_QMARK as u8) { q = i; i = plen } else { i = i + 1 } } 329 if q < 0 { return 0 } 330 return mo_kv(((path as i64) + q + 1) as *u8, plen - q - 1, key, out, cap) 331} 332// does the path (before any query) contain the segment `seg`? e.g. "/upload" -- prefix-agnostic on purpose: the edge 333// forwards /motion/upload and a loopback test sends /upload, and both must route the same way 334func mo_path_has(path: *u8, plen: i64, seg: *u8) -> i64 { 335 var end: i64 = plen 336 var i: i64 = 0 337 while i < plen { if path[i] == (MO_A_QMARK as u8) { end = i; i = plen } else { i = i + 1 } } 338 if mo_findfrom(path, end, 0, seg, mo_slen(seg)) >= 0 { return 1 } 339 return 0 340} 341// the last path segment before any query, e.g. /motion/job/123 -> 123, /motion/art/123/rig.glb -> rig.glb 342func mo_last_seg(path: *u8, plen: i64, out: *u8, cap: i64) -> i64 { 343 var end: i64 = plen 344 var i: i64 = 0 345 while i < plen { if path[i] == (MO_A_QMARK as u8) { end = i; i = plen } else { i = i + 1 } } 346 var s: i64 = end 347 while s > 0 { if path[s - 1] == (MO_A_SLASH as u8) { break } s = s - 1 } 348 var o: i64 = 0 349 i = s 350 while i < end { if o < cap - 1 { out[o] = path[i]; o = o + 1 } i = i + 1 } 351 out[o] = 0 as u8 352 return o 353} 354// the segment BEFORE the last one: /motion/art/123/rig.glb -> 123 355func mo_prev_seg(path: *u8, plen: i64, out: *u8, cap: i64) -> i64 { 356 var end: i64 = plen 357 var i: i64 = 0 358 while i < plen { if path[i] == (MO_A_QMARK as u8) { end = i; i = plen } else { i = i + 1 } } 359 var s: i64 = end 360 while s > 0 { if path[s - 1] == (MO_A_SLASH as u8) { break } s = s - 1 } 361 if s < 1 { out[0] = 0 as u8; return 0 } 362 let e2: i64 = s - 1 363 var s2: i64 = e2 364 while s2 > 0 { if path[s2 - 1] == (MO_A_SLASH as u8) { break } s2 = s2 - 1 } 365 var o: i64 = 0 366 i = s2 367 while i < e2 { if o < cap - 1 { out[o] = path[i]; o = o + 1 } i = i + 1 } 368 out[o] = 0 as u8 369 return o 370} 371 372// ---- files ------------------------------------------------------------------------------------------------------ 373func mo_exists(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 } sys_close(fd); return 1 } 374func mo_size(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 - 1 } let n: i64 = sys_lseek(fd, 0, 2); sys_close(fd); return n } 375// truncate-write n bytes; returns n or -1 376func mo_write_all(path: *u8, b: *u8, n: i64) -> i64 { 377 let fd: i64 = sys_openat_wr(path, 420) 378 if fd < 0 { return 0 - 1 } 379 var done: i64 = 0 380 while done < n { 381 let w: i64 = sys_write(fd, ((b as i64) + done) as *u8, n - done) 382 if w <= 0 { sys_close(fd); return 0 - 1 } 383 done = done + w 384 } 385 sys_close(fd) 386 return done 387} 388// append one row (ending in newline) to an append-only journal; returns bytes or -1 389func mo_append(path: *u8, b: *u8, n: i64) -> i64 { 390 let fd: i64 = __syscall(MO_SYS_OPENAT, MO_AT_FDCWD, path as i64, MO_O_APPEND_CREATE_WR, 420, 0, 0) 391 if fd < 0 { return 0 - 1 } 392 let w: i64 = sys_write(fd, b, n) 393 sys_close(fd) 394 return w 395} 396// read a whole file into a fresh buffer; len into lp[0]; 0 if unreadable 397func mo_read(path: *u8, lp: *i64) -> *u8 { lp[0] = 0; let b: *u8 = sys_read_file(path, lp); if (b as i64) == 0 { lp[0] = 0 } return b } 398// <dir>/<name> into a fresh path buffer 399func mo_join(dir: *u8, name: *u8) -> *u8 { 400 let out: *u8 = sys_mmap(MO_PATH_CAP) 401 var o: i64 = mo_cat(out, 0, dir) 402 if o > 0 { if out[o - 1] != (MO_A_SLASH as u8) { out[o] = MO_A_SLASH as u8; o = o + 1 } } 403 o = mo_cat(out, o, name) 404 out[o] = 0 as u8 405 return out 406} 407 408// ---- status rows (k=v per line) and log fields (k=v anywhere) ------------------------------------------------ 409// the integer after `key=` at a LINE START; -1 when absent -- line-anchored so a key that is a suffix of another cannot answer 410func mo_status_field(buf: *u8, n: i64, key: *u8) -> i64 { 411 let kl: i64 = mo_slen(key) 412 var p: i64 = 0 413 while p < n { 414 var e: i64 = p 415 while e < n { if buf[e] == (MO_A_NL as u8) { break } e = e + 1 } 416 if e - p > kl { if buf[p + kl] == (MO_A_EQ as u8) { 417 var j: i64 = 0 418 var ok: i64 = 1 419 while j < kl { if buf[p + j] != key[j] { ok = 0; j = kl } else { j = j + 1 } } 420 if ok == 1 { return mo_atoi(((buf as i64) + p + kl + 1) as *u8, e - p - kl - 1) } 421 } } 422 p = e + 1 423 } 424 return 0 - 1 425} 426// the string after `key=` at a LINE START into out; length or 0 427func mo_status_str(buf: *u8, n: i64, key: *u8, out: *u8, cap: i64) -> i64 { 428 let kl: i64 = mo_slen(key) 429 var p: i64 = 0 430 out[0] = 0 as u8 431 while p < n { 432 var e: i64 = p 433 while e < n { if buf[e] == (MO_A_NL as u8) { break } e = e + 1 } 434 if e - p > kl { if buf[p + kl] == (MO_A_EQ as u8) { 435 var j: i64 = 0 436 var ok: i64 = 1 437 while j < kl { if buf[p + j] != key[j] { ok = 0; j = kl } else { j = j + 1 } } 438 if ok == 1 { 439 var o: i64 = 0 440 var i: i64 = p + kl + 1 441 while i < e { if o < cap - 1 { out[o] = buf[i]; o = o + 1 } i = i + 1 } 442 out[o] = 0 as u8 443 return o 444 } 445 } } 446 p = e + 1 447 } 448 return 0 449} 450// the integer after ` key=` or `key=` at the FIRST occurrence anywhere (an organ's report line); -1 absent 451func mo_log_field(buf: *u8, n: i64, key: *u8) -> i64 { 452 let kl: i64 = mo_slen(key) 453 let nk: *u8 = sys_mmap(kl + 4) 454 var o: i64 = mo_cat(nk, 0, key) 455 nk[o] = MO_A_EQ as u8 456 let p: i64 = mo_findfrom(buf, n, 0, nk, kl + 1) 457 if p < 0 { return 0 - 1 } 458 var e: i64 = p + kl + 1 459 while e < n { let c: i64 = buf[e] as i64; if c < MO_A_D0 { if c != MO_A_DASH { break } } if c > MO_A_D9 { break } e = e + 1 } 460 return mo_atoi(((buf as i64) + p + kl + 1) as *u8, e - p - kl - 1) 461} 462 463// ---- pipe-separated row files ------------------------------------------------------------------------------------ 464// offset of the row that STARTS with key| (skipping comment and blank lines), else -1 465func mo_row_find(buf: *u8, n: i64, key: *u8) -> i64 { 466 let kl: i64 = mo_slen(key) 467 var p: i64 = 0 468 while p < n { 469 var e: i64 = p 470 while e < n { if buf[e] == (MO_A_NL as u8) { break } e = e + 1 } 471 if e - p > kl { if buf[p + kl] == (MO_A_PIPE as u8) { 472 var j: i64 = 0 473 var ok: i64 = 1 474 while j < kl { if buf[p + j] != key[j] { ok = 0; j = kl } else { j = j + 1 } } 475 if ok == 1 { return p } 476 } } 477 p = e + 1 478 } 479 return 0 - 1 480} 481// the idx-th pipe field of the row starting at rs, into out; its length (0 when the field is absent) 482func mo_row_field(buf: *u8, n: i64, rs: i64, idx: i64, out: *u8, cap: i64) -> i64 { 483 var p: i64 = rs 484 var f: i64 = 0 485 out[0] = 0 as u8 486 while f < idx { 487 while p < n { if buf[p] == (MO_A_PIPE as u8) { break } if buf[p] == (MO_A_NL as u8) { return 0 } p = p + 1 } 488 if p >= n { return 0 } 489 p = p + 1 490 f = f + 1 491 } 492 var o: i64 = 0 493 while p < n { 494 if buf[p] == (MO_A_PIPE as u8) { break } 495 if buf[p] == (MO_A_NL as u8) { break } 496 if buf[p] != (MO_A_CR as u8) { if o < cap - 1 { out[o] = buf[p]; o = o + 1 } } 497 p = p + 1 498 } 499 out[o] = 0 as u8 500 return o 501} 502// the offset of the next data row after pos (skips comments and blanks), or n when none remain 503func mo_row_next(buf: *u8, n: i64, pos: i64) -> i64 { 504 var p: i64 = pos 505 while p < n { 506 var e: i64 = p 507 while e < n { if buf[e] == (MO_A_NL as u8) { break } e = e + 1 } 508 if e > p { if buf[p] != (35 as u8) { if buf[p] != (MO_A_CR as u8) { return p } } } 509 p = e + 1 510 } 511 return n 512} 513 514// ---- run another organ --------------------------------------------------------------------------------------------- 515// argv words (NUL-terminated strings) beyond the elf itself; the child's stdout and stderr go to logpath (a durable 516// artifact the job page can show). Blocking: returns the child's exit code, 127 when the exec failed. 517func mo_run(elf: *u8, words: *i64, nw: i64, logpath: *u8) -> i64 { 518 let argv: *i64 = sys_mmap((nw + 2) * 8) as *i64 519 argv[0] = elf as i64 520 var i: i64 = 0 521 while i < nw { argv[i + 1] = words[i]; i = i + 1 } 522 argv[nw + 1] = 0 523 let envp: *i64 = sys_mmap(16) as *i64 524 envp[0] = 0 525 let pid: i64 = sys_fork() 526 if pid < 0 { return 0 - 1 } 527 if pid == 0 { 528 let fd: i64 = sys_openat_wr(logpath, 420) 529 if fd >= 0 { sys_dup3(fd, 1, 0); sys_dup3(fd, 2, 0) } 530 sys_execve(elf, argv, envp) 531 sys_exit(127) 532 } 533 let st: *i64 = sys_mmap(16) as *i64 534 st[0] = 0 535 sys_wait4(pid, st, 0) 536 return wait_status_rc(st[0]) 537} 538// DETACHED: double fork so the grandchild is reparented to init and the caller (a serving daemon) never waits on it 539// and never leaves a zombie. Returns 1 when the intermediate child was reaped, -1 when the fork failed. 540func mo_run_detached(elf: *u8, words: *i64, nw: i64, logpath: *u8) -> i64 { 541 let argv: *i64 = sys_mmap((nw + 2) * 8) as *i64 542 argv[0] = elf as i64 543 var i: i64 = 0 544 while i < nw { argv[i + 1] = words[i]; i = i + 1 } 545 argv[nw + 1] = 0 546 let envp: *i64 = sys_mmap(16) as *i64 547 envp[0] = 0 548 let pid: i64 = sys_fork() 549 if pid < 0 { return 0 - 1 } 550 if pid == 0 { 551 let p2: i64 = sys_fork() 552 if p2 != 0 { sys_exit(0) } 553 let fd: i64 = sys_openat_wr(logpath, 420) 554 if fd >= 0 { sys_dup3(fd, 1, 0); sys_dup3(fd, 2, 0) } 555 sys_execve(elf, argv, envp) 556 sys_exit(127) 557 } 558 let st: *i64 = sys_mmap(16) as *i64 559 st[0] = 0 560 sys_wait4(pid, st, 0) 561 return 1 562} 563 564// ---- the page renderers --------------------------------------------------------------------------------------------- 565// splice: copy tmpl into out replacing @HEAD@ with head, @BODY@ with body and @CAP_MB@ with the announced cap. Returns the 566// length, or -1 when the buffer would overflow (REFUSED, never a truncated page). 567func mo_splice(out: *u8, cap: i64, tmpl: *u8, tn: i64, head: *u8, hn: i64, body: *u8, bn: i64) -> i64 { 568 var o: i64 = 0 569 var i: i64 = 0 570 while i < tn { 571 if o + 16 >= cap { return 0 - 1 } 572 if tmpl[i] == (MO_A_AT as u8) { 573 if mo_findfrom(tmpl, tn, i, "@HEAD@" as *u8, 6) == i { if o + hn >= cap { return 0 - 1 } o = mo_catb(out, o, head, hn); i = i + 6 } else { 574 if mo_findfrom(tmpl, tn, i, "@BODY@" as *u8, 6) == i { if o + bn >= cap { return 0 - 1 } o = mo_catb(out, o, body, bn); i = i + 6 } else { 575 if mo_findfrom(tmpl, tn, i, "@CAP_MB@" as *u8, 8) == i { o = mo_num(out, o, MO_UPLOAD_CAP / 1048576); i = i + 8 } else { 576 out[o] = tmpl[i]; o = o + 1; i = i + 1 577 } } } 578 } else { out[o] = tmpl[i]; o = o + 1; i = i + 1 } 579 } 580 return o 581} 582// one clip <option> per row: key|donor|pose_id|title|licence|provenance 583func mo_clip_options(b: *u8, o: i64, rows: *u8, rn: i64) -> i64 { 584 var p: i64 = o 585 let key: *u8 = sys_mmap(MO_VAL_CAP) 586 let title: *u8 = sys_mmap(MO_VAL_CAP) 587 let lic: *u8 = sys_mmap(MO_VAL_CAP) 588 var r: i64 = mo_row_next(rows, rn, 0) 589 while r < rn { 590 let kl: i64 = mo_row_field(rows, rn, r, 0, key, MO_VAL_CAP) 591 let tl: i64 = mo_row_field(rows, rn, r, 3, title, MO_VAL_CAP) 592 let ll: i64 = mo_row_field(rows, rn, r, 4, lic, MO_VAL_CAP) 593 if kl > 0 { 594 p = mo_cat(b, p, "<option value=\"" as *u8) 595 p = mo_esc(b, p, key, kl) 596 p = mo_cat(b, p, "\">" as *u8) 597 p = mo_esc(b, p, title, tl) 598 p = mo_cat(b, p, " (" as *u8) 599 p = mo_esc(b, p, lic, ll) 600 p = mo_cat(b, p, ")</option>" as *u8) 601 } 602 var e: i64 = r 603 while e < rn { if rows[e] == (MO_A_NL as u8) { break } e = e + 1 } 604 r = mo_row_next(rows, rn, e + 1) 605 } 606 return p 607} 608// the clip library as a list with licence and provenance -- the page prints what it will apply, never a bare name 609func mo_clip_list(b: *u8, o: i64, rows: *u8, rn: i64) -> i64 { 610 var p: i64 = o 611 let key: *u8 = sys_mmap(MO_VAL_CAP) 612 let donor: *u8 = sys_mmap(MO_VAL_CAP) 613 let title: *u8 = sys_mmap(MO_VAL_CAP) 614 let lic: *u8 = sys_mmap(MO_VAL_CAP) 615 let prov: *u8 = sys_mmap(MO_VAL_CAP) 616 var count: i64 = 0 617 var r: i64 = mo_row_next(rows, rn, 0) 618 p = mo_cat(b, p, "<ul>" as *u8) 619 while r < rn { 620 let kl: i64 = mo_row_field(rows, rn, r, 0, key, MO_VAL_CAP) 621 let dl: i64 = mo_row_field(rows, rn, r, 1, donor, MO_VAL_CAP) 622 let tl: i64 = mo_row_field(rows, rn, r, 3, title, MO_VAL_CAP) 623 let ll: i64 = mo_row_field(rows, rn, r, 4, lic, MO_VAL_CAP) 624 let pl: i64 = mo_row_field(rows, rn, r, 5, prov, MO_VAL_CAP) 625 if kl > 0 { 626 count = count + 1 627 p = mo_cat(b, p, "<li><b>" as *u8); p = mo_esc(b, p, title, tl); p = mo_cat(b, p, "</b> key " as *u8); p = mo_esc(b, p, key, kl) 628 p = mo_cat(b, p, " - licence " as *u8); p = mo_esc(b, p, lic, ll) 629 p = mo_cat(b, p, " - donor " as *u8); p = mo_esc(b, p, donor, dl) 630 if mo_exists(donor) == 0 { p = mo_cat(b, p, " <span class=\"absent\">ABSENT</span>" as *u8) } 631 p = mo_cat(b, p, " - " as *u8); p = mo_esc(b, p, prov, pl) 632 p = mo_cat(b, p, "</li>" as *u8) 633 } 634 var e: i64 = r 635 while e < rn { if rows[e] == (MO_A_NL as u8) { break } e = e + 1 } 636 r = mo_row_next(rows, rn, e + 1) 637 } 638 p = mo_cat(b, p, "</ul><p>clips=" as *u8); p = mo_num(b, p, count); p = mo_cat(b, p, "</p>" as *u8) 639 return p 640} 641// demo cards: key|title|png|nxa|coverage_permil|joint_err_umm|top1_permil|cells|method|note -- the referee's numbers 642// travel with the picture; a demo whose referee fields are empty prints UNGRADED rather than a blank 643func mo_demo_cards(b: *u8, o: i64, rows: *u8, rn: i64) -> i64 { 644 var p: i64 = o 645 let f: *u8 = sys_mmap(MO_VAL_CAP) 646 let key: *u8 = sys_mmap(MO_VAL_CAP) 647 var r: i64 = mo_row_next(rows, rn, 0) 648 while r < rn { 649 let kl: i64 = mo_row_field(rows, rn, r, 0, key, MO_VAL_CAP) 650 if kl > 0 { 651 p = mo_cat(b, p, "<div class=\"card\"><h2>" as *u8) 652 let tl: i64 = mo_row_field(rows, rn, r, 1, f, MO_VAL_CAP); p = mo_esc(b, p, f, tl) 653 p = mo_cat(b, p, "</h2>" as *u8) 654 let pl: i64 = mo_row_field(rows, rn, r, 2, f, MO_VAL_CAP) 655 if pl > 0 { p = mo_cat(b, p, "<img src=\"/motion/demo/" as *u8); p = mo_esc(b, p, f, pl); p = mo_cat(b, p, "\" alt=\"three-view render of the rigged demo\">" as *u8) } 656 let cl: i64 = mo_row_field(rows, rn, r, 4, f, MO_VAL_CAP) 657 if cl > 0 { 658 p = mo_cat(b, p, "<p>referee: artist joints covered <b>" as *u8); p = mo_esc(b, p, f, cl); p = mo_cat(b, p, " permil</b>" as *u8) 659 let jl: i64 = mo_row_field(rows, rn, r, 5, f, MO_VAL_CAP); p = mo_cat(b, p, ", mean joint error <b>" as *u8); p = mo_num(b, p, mo_atoi(f, jl) / 100); p = mo_cat(b, p, " mm</b>" as *u8) 660 let t1: i64 = mo_row_field(rows, rn, r, 6, f, MO_VAL_CAP); p = mo_cat(b, p, ", top-1 weight agreement <b>" as *u8); p = mo_esc(b, p, f, t1); p = mo_cat(b, p, " permil</b>" as *u8) 661 let ce: i64 = mo_row_field(rows, rn, r, 7, f, MO_VAL_CAP); p = mo_cat(b, p, " at " as *u8); p = mo_esc(b, p, f, ce); p = mo_cat(b, p, " cells, " as *u8) 662 let me: i64 = mo_row_field(rows, rn, r, 8, f, MO_VAL_CAP); p = mo_esc(b, p, f, me); p = mo_cat(b, p, "</p>" as *u8) 663 } else { p = mo_cat(b, p, "<p class=\"absent\">UNGRADED: no referee row for this demo</p>" as *u8) } 664 let nl: i64 = mo_row_field(rows, rn, r, 3, f, MO_VAL_CAP) 665 if nl > 0 { p = mo_cat(b, p, "<p><a href=\"/motion/demo/" as *u8); p = mo_esc(b, p, f, nl); p = mo_cat(b, p, "\">rigged asset (NXA)</a></p>" as *u8) } 666 let ntl: i64 = mo_row_field(rows, rn, r, 9, f, MO_VAL_CAP) 667 if ntl > 0 { p = mo_cat(b, p, "<p>" as *u8); p = mo_esc(b, p, f, ntl); p = mo_cat(b, p, "</p>" as *u8) } 668 p = mo_cat(b, p, "</div>" as *u8) 669 } 670 var e: i64 = r 671 while e < rn { if rows[e] == (MO_A_NL as u8) { break } e = e + 1 } 672 r = mo_row_next(rows, rn, e + 1) 673 } 674 return p 675} 676// the index body: the upload form, the demo cards, the clip library, how it works 677func mo_body_index(b: *u8, clips: *u8, cn: i64, demos: *u8, dn: i64) -> i64 { 678 var p: i64 = 0 679 p = mo_cat(b, p, "<h1>NISHI MOTION - UPLOAD, RIG, ANIMATE, EXPORT</h1>" as *u8) 680 p = mo_cat(b, p, "<p class=\"lead\">Drop a mesh. The sovereign auto-rig peels a skeleton from its VOLUME with no archetype to pick and no learned model, solves geodesic bone-heat weights, renders it from three sides with its own numbers, and exports a GLB any engine loads. Then apply a library clip. Every step is a NishiLang organ on this server; nothing runs in your browser and nothing of yours leaves it. The referee grade and the operator's verdict live on the same page as the result -- presence is not completion here.</p>" as *u8) 681 p = mo_cat(b, p, "<div class=\"card\"><h2>UPLOAD A MESH</h2><form method=\"post\" action=\"/motion/upload\" enctype=\"multipart/form-data\">" as *u8) 682 p = mo_cat(b, p, "<p><input type=\"file\" name=\"model\" accept=\".glb,.fbx,.nxa\" required></p>" as *u8) 683 p = mo_cat(b, p, "<p><label>rig resolution <select name=\"cells\"><option value=\"96\">96 cells - fast, coarse (house rig: 461 permil of artist joints)</option><option value=\"128\">128 cells</option><option value=\"192\" selected>192 cells - referee-measured 923 permil on the house rig</option></select></label></p>" as *u8) 684 p = mo_cat(b, p, "<p><button type=\"submit\">RIG IT</button></p>" as *u8) 685 p = mo_cat(b, p, "<p>Accepted by magic bytes, never by extension: GLB (binary glTF), binary FBX, NXA. Up to " as *u8) 686 p = mo_num(b, p, MO_UPLOAD_CAP / 1048576) 687 p = mo_cat(b, p, " MB through this door (the edge proxy's measured budget); larger models take the chunked door, a queued rung. OBJ is recognised and refused by name until its reader is composed. A sheet with no volume is refused at the skeleton stage.</p></form></div>" as *u8) 688 p = mo_cat(b, p, "<h2>DEMO RIGS - THE REFEREE'S OWN NUMBERS</h2>" as *u8) 689 if dn > 0 { p = mo_demo_cards(b, p, demos, dn) } else { p = mo_cat(b, p, "<p class=\"absent\">no demo rows yet</p>" as *u8) } 690 p = mo_cat(b, p, "<div class=\"card\"><h2>CLIP LIBRARY</h2>" as *u8) 691 if cn > 0 { p = mo_clip_list(b, p, clips, cn) } else { p = mo_cat(b, p, "<p class=\"absent\">no clip rows yet</p>" as *u8) } 692 p = mo_cat(b, p, "</div>" as *u8) 693 p = mo_cat(b, p, "<div class=\"card\"><h2>HOW IT WORKS</h2><p>1. nx_gltf2mesh or nx_fbx2nxa carries your mesh into the estate's NXA container. 2. nx_autorig_mesh runs the curve-skeleton peel (geodesic farthest-point over the voxelised volume, the local medial radius as the significance bar) then geodesic bone heat for the weights. 3. nx_nxa_texbake view renders three views with the software rasteriser. 4. nx_mesh2glb writes the GLB with its skin. 5. A clip retargets through nx_nxa_retarget (topology plus normalised bind position, your bone lengths preserved by construction) and bakes through nx_nxa_play. Every stage's own report is kept with the job. Measured on the house rig at 192 cells: 923 permil of the artist's joints within one bone length, 40.1 mm mean joint error, 233 permil top-1 weight agreement -- coverage is competitive, weight topology is not yet, and the board at /compare/motion says so.</p></div>" as *u8) 694 return p 695} 696// the job body: status rows, renders, exports, the clip form, applied clips, the verdict form 697func mo_body_job(b: *u8, id: *u8, st: *u8, sn: i64, done: i64, clips: *u8, cn: i64, applied: *u8, an: i64, verdicts: *u8, vn: i64) -> i64 { 698 var p: i64 = 0 699 let f: *u8 = sys_mmap(MO_VAL_CAP) 700 p = mo_cat(b, p, "<h1>NISHI MOTION - JOB " as *u8); p = mo_cat(b, p, id); p = mo_cat(b, p, "</h1>" as *u8) 701 let stl: i64 = mo_status_str(st, sn, "stage" as *u8, f, MO_VAL_CAP) 702 if done == 0 { 703 p = mo_cat(b, p, "<p class=\"lead\">RUNNING - stage " as *u8); p = mo_esc(b, p, f, stl); p = mo_cat(b, p, ". This page reloads itself every few seconds; the job keeps its own logs and finishes with a done marker, so a job that died reads as stuck at a named stage, never as green.</p>" as *u8) 704 } else { 705 let ok: i64 = mo_status_field(st, sn, "ok" as *u8) 706 if ok == 1 { p = mo_cat(b, p, "<p class=\"lead ok\">DONE - rigged" as *u8) } else { p = mo_cat(b, p, "<p class=\"lead absent\">FAILED at stage " as *u8); p = mo_esc(b, p, f, stl) } 707 p = mo_cat(b, p, " in " as *u8); p = mo_num(b, p, mo_status_field(st, sn, "ms" as *u8)); p = mo_cat(b, p, " ms</p>" as *u8) 708 } 709 p = mo_cat(b, p, "<div class=\"card\"><h2>STATUS</h2><p>" as *u8) 710 p = mo_cat(b, p, "kind <b>" as *u8); let kl: i64 = mo_status_str(st, sn, "kind" as *u8, f, MO_VAL_CAP); p = mo_esc(b, p, f, kl); p = mo_cat(b, p, "</b> - cells <b>" as *u8); p = mo_num(b, p, mo_status_field(st, sn, "cells" as *u8)) 711 p = mo_cat(b, p, "</b> - verts <b>" as *u8); p = mo_num(b, p, mo_status_field(st, sn, "verts" as *u8)); p = mo_cat(b, p, "</b> - tris <b>" as *u8); p = mo_num(b, p, mo_status_field(st, sn, "tris" as *u8)) 712 p = mo_cat(b, p, "</b> - limbs <b>" as *u8); p = mo_num(b, p, mo_status_field(st, sn, "limbs" as *u8)); p = mo_cat(b, p, "</b> - joints <b>" as *u8); p = mo_num(b, p, mo_status_field(st, sn, "joints" as *u8)) 713 p = mo_cat(b, p, "</b> - branches <b>" as *u8); p = mo_num(b, p, mo_status_field(st, sn, "branches" as *u8)); p = mo_cat(b, p, "</b> - mixed-weight verts <b>" as *u8); p = mo_num(b, p, mo_status_field(st, sn, "mixed_verts" as *u8)) 714 p = mo_cat(b, p, "</b> - rig sha256 <b>" as *u8); let hl: i64 = mo_status_str(st, sn, "rig_sha256" as *u8, f, MO_VAL_CAP); p = mo_esc(b, p, f, hl) 715 p = mo_cat(b, p, "</b> - stage exit codes convert <b>" as *u8); p = mo_num(b, p, mo_status_field(st, sn, "rc_convert" as *u8)); p = mo_cat(b, p, "</b> rig <b>" as *u8); p = mo_num(b, p, mo_status_field(st, sn, "rc_rig" as *u8)); p = mo_cat(b, p, "</b> view <b>" as *u8); p = mo_num(b, p, mo_status_field(st, sn, "rc_view" as *u8)); p = mo_cat(b, p, "</b> glb <b>" as *u8); p = mo_num(b, p, mo_status_field(st, sn, "rc_glb" as *u8)); p = mo_cat(b, p, "</b></p>" as *u8) 716 p = mo_cat(b, p, "<p>logs: <a href=\"/motion/art/" as *u8); p = mo_cat(b, p, id); p = mo_cat(b, p, "/log_convert.txt\">convert</a> <a href=\"/motion/art/" as *u8); p = mo_cat(b, p, id); p = mo_cat(b, p, "/log_rig.txt\">rig</a> <a href=\"/motion/art/" as *u8); p = mo_cat(b, p, id); p = mo_cat(b, p, "/log_view.txt\">view</a> <a href=\"/motion/art/" as *u8); p = mo_cat(b, p, id); p = mo_cat(b, p, "/log_glb.txt\">glb</a></p></div>" as *u8) 717 if done == 1 { 718 p = mo_cat(b, p, "<div class=\"card\"><h2>THE RIG</h2><img src=\"/motion/art/" as *u8); p = mo_cat(b, p, id); p = mo_cat(b, p, "/rig_view.png\" alt=\"three-view render of the rigged upload\">" as *u8) 719 p = mo_cat(b, p, "<p><a href=\"/motion/art/" as *u8); p = mo_cat(b, p, id); p = mo_cat(b, p, "/rig.glb\">download rig.glb (skinned, engine-ready)</a> - <a href=\"/motion/art/" as *u8); p = mo_cat(b, p, id); p = mo_cat(b, p, "/rig.nxa\">rig.nxa</a> - <a href=\"/motion/art/" as *u8); p = mo_cat(b, p, id); p = mo_cat(b, p, "/skel.nxa\">skeleton only</a></p></div>" as *u8) 720 p = mo_cat(b, p, "<div class=\"card\"><h2>APPLY A CLIP</h2><form method=\"get\" action=\"/motion/anim\"><input type=\"hidden\" name=\"job\" value=\"" as *u8); p = mo_cat(b, p, id); p = mo_cat(b, p, "\"><select name=\"clip\">" as *u8) 721 if cn > 0 { p = mo_clip_options(b, p, clips, cn) } 722 p = mo_cat(b, p, "</select> <button type=\"submit\">APPLY</button></form>" as *u8) 723 if an > 0 { 724 let ck: *u8 = sys_mmap(MO_VAL_CAP) 725 var r: i64 = mo_row_next(applied, an, 0) 726 while r < an { 727 let ckl: i64 = mo_row_field(applied, an, r, 0, ck, MO_VAL_CAP) 728 if ckl > 0 { 729 p = mo_cat(b, p, "<p><b>clip " as *u8); p = mo_esc(b, p, ck, ckl); p = mo_cat(b, p, "</b> retarget rc " as *u8) 730 let v1: i64 = mo_row_field(applied, an, r, 1, f, MO_VAL_CAP); p = mo_esc(b, p, f, v1) 731 p = mo_cat(b, p, " - play rc " as *u8); let v2: i64 = mo_row_field(applied, an, r, 2, f, MO_VAL_CAP); p = mo_esc(b, p, f, v2) 732 p = mo_cat(b, p, " - joints posed " as *u8); let v3: i64 = mo_row_field(applied, an, r, 3, f, MO_VAL_CAP); p = mo_esc(b, p, f, v3) 733 p = mo_cat(b, p, " - verts moved " as *u8); let v4: i64 = mo_row_field(applied, an, r, 4, f, MO_VAL_CAP); p = mo_esc(b, p, f, v4) 734 p = mo_cat(b, p, " - max displacement " as *u8); let v5: i64 = mo_row_field(applied, an, r, 5, f, MO_VAL_CAP); p = mo_num(b, p, mo_atoi(f, v5) / 100); p = mo_cat(b, p, " mm</p>" as *u8) 735 p = mo_cat(b, p, "<img src=\"/motion/art/" as *u8); p = mo_cat(b, p, id); p = mo_cat(b, p, "/posed_" as *u8); p = mo_esc(b, p, ck, ckl); p = mo_cat(b, p, ".png\" alt=\"posed render\"><p><a href=\"/motion/art/" as *u8); p = mo_cat(b, p, id); p = mo_cat(b, p, "/posed_" as *u8); p = mo_esc(b, p, ck, ckl); p = mo_cat(b, p, ".glb\">posed_" as *u8); p = mo_esc(b, p, ck, ckl); p = mo_cat(b, p, ".glb</a></p>" as *u8) 736 } 737 var e: i64 = r 738 while e < an { if applied[e] == (MO_A_NL as u8) { break } e = e + 1 } 739 r = mo_row_next(applied, an, e + 1) 740 } 741 } 742 p = mo_cat(b, p, "</div>" as *u8) 743 p = mo_cat(b, p, "<div class=\"card\"><h2>OPERATOR VERDICT</h2><form method=\"post\" action=\"/motion/verdict\"><input type=\"hidden\" name=\"job\" value=\"" as *u8); p = mo_cat(b, p, id) 744 p = mo_cat(b, p, "\"><select name=\"v\"><option value=\"accept\">ACCEPT</option><option value=\"reject\">REJECT</option></select> <input name=\"words\" maxlength=\"200\" placeholder=\"why, in your words\"> <button type=\"submit\">RECORD</button></form>" as *u8) 745 if vn > 0 { 746 p = mo_cat(b, p, "<p>verdicts on this job:</p><ul>" as *u8) 747 var r2: i64 = mo_row_next(verdicts, vn, 0) 748 while r2 < vn { 749 let jl: i64 = mo_row_field(verdicts, vn, r2, 0, f, MO_VAL_CAP) 750 if mo_streq(f, id) == 1 { 751 p = mo_cat(b, p, "<li>" as *u8) 752 let w1: i64 = mo_row_field(verdicts, vn, r2, 1, f, MO_VAL_CAP); p = mo_esc(b, p, f, w1); p = mo_cat(b, p, " at " as *u8) 753 let w2: i64 = mo_row_field(verdicts, vn, r2, 2, f, MO_VAL_CAP); p = mo_esc(b, p, f, w2); p = mo_cat(b, p, ": " as *u8) 754 let w3: i64 = mo_row_field(verdicts, vn, r2, 3, f, MO_VAL_CAP); p = mo_esc(b, p, f, w3); p = mo_cat(b, p, "</li>" as *u8) 755 } 756 // (jl is the job-id field length; the match above is by string equality, so its value is informational) 757 var e2: i64 = r2 758 while e2 < vn { if verdicts[e2] == (MO_A_NL as u8) { break } e2 = e2 + 1 } 759 r2 = mo_row_next(verdicts, vn, e2 + 1) 760 } 761 p = mo_cat(b, p, "</ul>" as *u8) 762 } else { p = mo_cat(b, p, "<p class=\"absent\">no verdict yet -- shipped is not accepted</p>" as *u8) } 763 p = mo_cat(b, p, "</div>" as *u8) 764 } 765 p = mo_cat(b, p, "<p class=\"lead\"><a href=\"/motion\">back to /motion</a> - <a href=\"/compare/motion\">the board</a></p>" as *u8) 766 return p 767}