code wiki / _hdl_build / nx_vizsla_remind.nx

nx_vizsla_remind.nx source

↩ module page · 762 lines · 28080 B

1// nx_vizsla_remind.nx -- NISHI VIZSLA REMINDER ENGINE (census PA18 core): birthday + 2// important-event reminders with lead times and a sent-once delivery ledger. 3// Operator 2026-07-07: "birthday and important event reminder". COMPOSES the existing planes: 4// calendar events + recurrences (nx_vizsla_calendar cal:/rec: records, YEARLY included) and the 5// relate contacts file (CONTACT <id> <display> <tier> <MM-DD|->). The organ computes WHAT is 6// due at which lead (14/7/1/0 days -- the leads are an ARGUMENT, data not magic numbers) and 7// the ledger guarantees each (kind,id,date) notice is delivered ONCE (additive snt: records, 8// CID-idempotent). Actual outward push (email/phone) composes the sovereign email stack behind 9// the operator's outward-facing consent -- this organ is the truth of what to send and whether 10// it was sent, deterministic (today is argv, never a clock). 11// 12// Commands: 13// due <calprefix|-> <contactsfile|-> <today> <leads> [sentprefix] 14// leads = comma ints e.g. 14,7,1,0 ; window = [today, today+max(leads)]. 15// calendar occurrence / next birthday occurrence (MM-DD; Feb-29 clamps to Feb-28 in 16// non-leap years, mirroring the calendar's YEARLY clamp) with days-until IN the leads set 17// -> VIZSLA-REM-DUE; already in the sent ledger -> VIZSLA-REM-SENT-SKIP (counted, shown). 18// mark <sentprefix> <event|birthday> <id> <date> [segid] 19// append the sent record (idempotent -> new=0 on re-mark). 20// Loud-fail: bad today/leads/date, missing named files, bad kind. 21// spec: knowledge/research/2026-06-22-vizsla-sclass-roadmap.md license_tier: ORIGINAL 22import "nx_syscalls.nx" 23import "nx_canon_cid.nx" 24import "nx_seg_store.nx" 25const K_MAGIC_1970: i64 = 1970 26const K_MAGIC_146097: i64 = 146097 27const K_MAGIC_719468: i64 = 719468 28const K_MAGIC_146096: i64 = 146096 29const K_MAGIC_1460: i64 = 1460 30const K_MAGIC_36524: i64 = 36524 31const K_MAGIC_2048: i64 = 2048 32const K_MAGIC_262144: i64 = 262144 33const K_MAGIC_1024: i64 = 1024 34 35func vr_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 36func vr_p(s: *u8) -> i64 { sys_write(1, s, vr_slen(s)); return 0 } 37 38func vr_eq(a: *u8, b: *u8) -> i64 { 39 var i: i64 = 0 40 var go: i64 = 1 41 while go == 1 { 42 if a[i] != b[i] { return 0 } 43 if a[i] == (0 as u8) { return 1 } 44 i = i + 1 45 } 46 return 0 47} 48 49func vr_dup(s: *u8) -> *u8 { 50 let n: i64 = vr_slen(s) 51 let d: *u8 = sys_mmap(n + 2) 52 var i: i64 = 0 53 while i <= n { d[i] = s[i]; i = i + 1 } 54 return d 55} 56 57func vr_atoi(s: *u8) -> i64 { 58 var v: i64 = 0 59 var i: i64 = 0 60 while s[i] != (0 as u8) { 61 let d: i64 = (s[i] as i64) - 48 62 if d >= 0 { if d <= 9 { v = v * 10 + d } } 63 i = i + 1 64 } 65 return v 66} 67 68func vr_digits(s: *u8) -> i64 { 69 if s[0] == (0 as u8) { return 0 } 70 var i: i64 = 0 71 while s[i] != (0 as u8) { 72 let d: i64 = (s[i] as i64) - 48 73 if d < 0 { return 0 } 74 if d > 9 { return 0 } 75 i = i + 1 76 } 77 return 1 78} 79 80func vr_isws(c: i64) -> i64 { 81 if c == 32 { return 1 } 82 if c == 13 { return 1 } 83 if c == 9 { return 1 } 84 return 0 85} 86 87func vr_tok(b: *u8, off: i64, lend: i64, dst: *u8, cap: i64) -> i64 { 88 var p: i64 = off 89 var go: i64 = 1 90 while go == 1 { 91 if p >= lend { go = 0 } else { 92 if vr_isws(b[p] as i64) == 1 { p = p + 1 } else { go = 0 } 93 } 94 } 95 var t: i64 = 0 96 go = 1 97 while go == 1 { 98 if p >= lend { go = 0 } else { 99 if vr_isws(b[p] as i64) == 1 { go = 0 } else { 100 if t < cap - 1 { dst[t] = b[p]; t = t + 1 } 101 p = p + 1 102 } 103 } 104 } 105 dst[t] = 0 as u8 106 return p 107} 108 109func vr_cat(dst: *u8, off: i64, s: *u8) -> i64 { 110 var i: i64 = 0 111 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 } 112 return off + i 113} 114 115func vr_catn(dst: *u8, off: i64, v: i64) -> i64 { 116 var o: i64 = off 117 var m: i64 = v 118 if m < 0 { dst[o] = 45 as u8; o = o + 1; m = 0 - m } 119 let t: *u8 = sys_mmap(28) 120 var k: i64 = 0 121 if m == 0 { t[0] = 48 as u8; k = 1 } 122 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 123 var i: i64 = 0 124 while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 } 125 return o + k 126} 127 128func vr_kmemeq(b: *u8, off: i64, n: i64, s: *u8) -> i64 { 129 if vr_slen(s) != n { return 0 } 130 var i: i64 = 0 131 while i < n { 132 if b[off + i] != s[i] { return 0 } 133 i = i + 1 134 } 135 return 1 136} 137 138func vr_field(rec: *u8, rl: i64, want: *u8, out: *u8, cap: i64) -> i64 { 139 if rl < 8 { return 0 } 140 let nf: i64 = ss_r32(rec, 4) 141 var off: i64 = 8 142 var fi: i64 = 0 143 while fi < nf { 144 if off + 8 > rl { return 0 } 145 let kl: i64 = ss_r32(rec, off) 146 let koff: i64 = off + 4 147 let vl: i64 = ss_r32(rec, koff + kl) 148 let voff: i64 = koff + kl + 4 149 if vr_kmemeq(rec, koff, kl, want) == 1 { 150 var t: i64 = 0 151 while t < vl { 152 if t < cap - 1 { out[t] = rec[voff + t] } 153 t = t + 1 154 } 155 if t > cap - 1 { t = cap - 1 } 156 out[t] = 0 as u8 157 return 1 158 } 159 off = voff + vl 160 fi = fi + 1 161 } 162 return 0 163} 164 165func vr_iskind(b: *u8, koff: i64, kl: i64, pfx: *u8) -> i64 { 166 if kl <= 4 { return 0 } 167 return vr_kmemeq(b, koff, 4, pfx) 168} 169 170func vr_datedays(s: *u8) -> i64 { 171 let nums: *i64 = sys_mmap(8 * 4) as *i64 172 var nn: i64 = 0 173 var cur: i64 = 0 174 var indig: i64 = 0 175 var i: i64 = 0 176 var go: i64 = 1 177 while go == 1 { 178 let c: i64 = s[i] as i64 179 var isd: i64 = 0 180 if c >= 48 { if c <= 57 { isd = 1 } } 181 if isd == 1 { cur = cur * 10 + (c - 48); indig = 1 } 182 if isd == 0 { 183 if indig == 1 { 184 if nn < 4 { nums[nn] = cur; nn = nn + 1 } 185 cur = 0 186 indig = 0 187 } 188 } 189 if c == 0 { go = 0 } 190 i = i + 1 191 } 192 if nn != 3 { return 0 - 1 } 193 var y: i64 = nums[0] 194 let m: i64 = nums[1] 195 let d: i64 = nums[2] 196 if y < K_MAGIC_1970 { return 0 - 1 } 197 if m < 1 { return 0 - 1 } 198 if m > 12 { return 0 - 1 } 199 if d < 1 { return 0 - 1 } 200 if d > 31 { return 0 - 1 } 201 if m <= 2 { y = y - 1 } 202 let era: i64 = y / 400 203 let yoe: i64 = y - era * 400 204 var mp: i64 = m - 3 205 if m <= 2 { mp = m + 9 } 206 let doy: i64 = (153 * mp + 2) / 5 + d - 1 207 let doe: i64 = yoe * 365 + yoe / 4 - yoe / 100 + doy 208 return era * K_MAGIC_146097 + doe - K_MAGIC_719468 209} 210 211func vr_ymd2days(y0: i64, m: i64, d: i64) -> i64 { 212 var y: i64 = y0 213 if m <= 2 { y = y0 - 1 } 214 let era: i64 = y / 400 215 let yoe: i64 = y - era * 400 216 var mp: i64 = m - 3 217 if m <= 2 { mp = m + 9 } 218 let doy: i64 = (153 * mp + 2) / 5 + d - 1 219 let doe: i64 = yoe * 365 + yoe / 4 - yoe / 100 + doy 220 return era * K_MAGIC_146097 + doe - K_MAGIC_719468 221} 222 223func vr_civil(z0: i64, out: *i64) -> i64 { 224 var z: i64 = z0 + K_MAGIC_719468 225 var era: i64 = z / K_MAGIC_146097 226 if z < 0 { era = (z - K_MAGIC_146096) / K_MAGIC_146097 } 227 let doe: i64 = z - era * K_MAGIC_146097 228 let yoe: i64 = (doe - doe / K_MAGIC_1460 + doe / K_MAGIC_36524 - doe / K_MAGIC_146096) / 365 229 let y0: i64 = yoe + era * 400 230 let doy: i64 = doe - (365 * yoe + yoe / 4 - yoe / 100) 231 let mp: i64 = (5 * doy + 2) / 153 232 let d: i64 = doy - (153 * mp + 2) / 5 + 1 233 var m: i64 = mp + 3 234 if mp >= 10 { m = mp - 9 } 235 var y: i64 = y0 236 if m <= 2 { y = y0 + 1 } 237 out[0] = y; out[1] = m; out[2] = d 238 return 0 239} 240 241func vr_dim(y: i64, m: i64) -> i64 { 242 if m == 2 { 243 var leap: i64 = 0 244 if y % 4 == 0 { leap = 1 } 245 if y % 100 == 0 { leap = 0 } 246 if y % 400 == 0 { leap = 1 } 247 if leap == 1 { return 29 } 248 return 28 249 } 250 if m == 4 { return 30 } 251 if m == 6 { return 30 } 252 if m == 9 { return 30 } 253 if m == 11 { return 30 } 254 return 31 255} 256 257func vr_occ(freq: *u8, sd0: i64, sy: i64, sm: i64, sd: i64, interval: i64, k: i64) -> i64 { 258 if vr_eq(freq, "DAILY" as *u8) == 1 { return sd0 + k * interval } 259 if vr_eq(freq, "WEEKLY" as *u8) == 1 { return sd0 + k * interval * 7 } 260 var mstep: i64 = interval 261 if vr_eq(freq, "YEARLY" as *u8) == 1 { mstep = interval * 12 } 262 let tot: i64 = (sm - 1) + k * mstep 263 let y2: i64 = sy + tot / 12 264 let m2: i64 = tot - (tot / 12) * 12 + 1 265 var d2: i64 = sd 266 let dim: i64 = vr_dim(y2, m2) 267 if d2 > dim { d2 = dim } 268 return vr_ymd2days(y2, m2, d2) 269} 270 271func vr_daystr(dst: *u8, off: i64, days: i64) -> i64 { 272 let ymd: *i64 = sys_mmap(8 * 4) as *i64 273 vr_civil(days, ymd) 274 var o: i64 = off 275 o = vr_catn(dst, o, ymd[0]) 276 dst[o] = 45 as u8; o = o + 1 277 if ymd[1] < 10 { dst[o] = 48 as u8; o = o + 1 } 278 o = vr_catn(dst, o, ymd[1]) 279 dst[o] = 45 as u8; o = o + 1 280 if ymd[2] < 10 { dst[o] = 48 as u8; o = o + 1 } 281 o = vr_catn(dst, o, ymd[2]) 282 return o 283} 284 285func vr_find(list: *i64, n: i64, s: *u8) -> i64 { 286 var i: i64 = 0 287 while i < n { 288 if vr_eq(list[i] as *u8, s) == 1 { return i } 289 i = i + 1 290 } 291 return 0 - 1 292} 293 294// day-number of the NEXT occurrence (>= today) of an MM-DD birthday; -1 malformed. 295// Feb-29 clamps to Feb-28 in non-leap years (mirrors the calendar's YEARLY clamp). 296func vr_bday_next(mmdd: *u8, today: i64) -> i64 { 297 var mm: i64 = 0 - 1 298 var dd: i64 = 0 - 1 299 if mmdd[0] == (0 as u8) { return 0 - 1 } 300 let c0: i64 = mmdd[0] as i64 301 let c1: i64 = mmdd[1] as i64 302 if c0 < 48 { return 0 - 1 } 303 if c0 > 57 { return 0 - 1 } 304 if c1 < 48 { return 0 - 1 } 305 if c1 > 57 { return 0 - 1 } 306 if (mmdd[2] as i64) != 45 { return 0 - 1 } 307 let c3: i64 = mmdd[3] as i64 308 let c4: i64 = mmdd[4] as i64 309 if c3 < 48 { return 0 - 1 } 310 if c3 > 57 { return 0 - 1 } 311 if c4 < 48 { return 0 - 1 } 312 if c4 > 57 { return 0 - 1 } 313 if mmdd[5] != (0 as u8) { return 0 - 1 } 314 mm = (c0 - 48) * 10 + (c1 - 48) 315 dd = (c3 - 48) * 10 + (c4 - 48) 316 if mm < 1 { return 0 - 1 } 317 if mm > 12 { return 0 - 1 } 318 if dd < 1 { return 0 - 1 } 319 if dd > 31 { return 0 - 1 } 320 let ymd: *i64 = sys_mmap(8 * 4) as *i64 321 vr_civil(today, ymd) 322 var y: i64 = ymd[0] 323 var d2: i64 = dd 324 let dim1: i64 = vr_dim(y, mm) 325 if d2 > dim1 { d2 = dim1 } 326 var cand: i64 = vr_ymd2days(y, mm, d2) 327 if cand < today { 328 y = y + 1 329 d2 = dd 330 let dim2: i64 = vr_dim(y, mm) 331 if d2 > dim2 { d2 = dim2 } 332 cand = vr_ymd2days(y, mm, d2) 333 } 334 return cand 335} 336 337func vr_put(keys: *i64, vals: *i64, nf: i64, kp: *u8, st: *i64) -> i64 { 338 let enc: *u8 = sys_mmap(K_MAGIC_2048) 339 let el: i64 = canon_encode(keys, vals, nf, enc) 340 let cid: *u8 = sys_mmap(96) 341 cid_of(enc, el, cid) 342 let kbuf: *u8 = sys_mmap(128) 343 var ko: i64 = 0 344 ko = vr_cat(kbuf, ko, kp) 345 ko = vr_cat(kbuf, ko, cid) 346 kbuf[ko] = 0 as u8 347 let seen: *i64 = st[1] as *i64 348 var fresh: i64 = 1 349 if vr_find(seen, st[2], kbuf) >= 0 { fresh = 0; st[4] = st[4] + 1 } 350 if fresh == 1 { 351 if st[2] < K_MAGIC_2048 { 352 let dk: *u8 = vr_dup(kbuf) 353 seen[st[2]] = dk as i64 354 st[2] = st[2] + 1 355 } 356 } 357 if fresh == 1 { 358 let pp: *i64 = sys_mmap(16) as *i64 359 let ll: *i64 = sys_mmap(16) as *i64 360 if ss_get_idx(st[6] as *u8, kbuf, pp, ll) == 1 { fresh = 0; st[5] = st[5] + 1 } 361 } 362 if fresh == 1 { 363 if ss_add(st[0] as *i64, 1, kbuf, enc, el) != 0 { return 0 - 1 } 364 st[3] = st[3] + 1 365 } 366 return 0 367} 368 369// gather sent ledger (kind,id,date) triples 370func vr_sent_gather(prefix: *u8, kk: *i64, ii: *i64, dd: *i64, np: *i64) -> i64 { 371 let segs: *i64 = sys_mmap(8 * 260) as *i64 372 let ns: i64 = ss_manifest(prefix, segs) 373 let f1: *u8 = sys_mmap(128) 374 let f2: *u8 = sys_mmap(256) 375 let f3: *u8 = sys_mmap(128) 376 var s: i64 = 0 377 while s < ns { 378 let path: *u8 = sys_mmap(512) 379 var po: i64 = 0 380 po = vr_cat(path, po, prefix) 381 po = vr_cat(path, po, segs[s] as *u8) 382 po = vr_cat(path, po, ".docs" as *u8) 383 path[po] = 0 as u8 384 let szp: *i64 = sys_mmap(16) as *i64 385 let b: *u8 = ss_readall(path, szp) 386 let sz: i64 = szp[0] 387 var j: i64 = 0 388 while j + 9 <= sz { 389 let kind: i64 = b[j] 390 let kl: i64 = ss_r32(b, j + 1) 391 let koff: i64 = j + 5 392 let vl: i64 = ss_r32(b, koff + kl) 393 let voff: i64 = koff + kl + 4 394 var take: i64 = 0 395 if kind == 1 { take = vr_iskind(b, koff, kl, "snt:" as *u8) } 396 if take == 1 { 397 let rec: *u8 = (b as i64 + voff) as *u8 398 if np[0] < 256 { 399 vr_field(rec, vl, "k" as *u8, f1, 128) 400 vr_field(rec, vl, "id" as *u8, f2, 256) 401 vr_field(rec, vl, "date" as *u8, f3, 128) 402 let d1: *u8 = vr_dup(f1) 403 let d2: *u8 = vr_dup(f2) 404 let d3: *u8 = vr_dup(f3) 405 kk[np[0]] = d1 as i64 406 ii[np[0]] = d2 as i64 407 dd[np[0]] = d3 as i64 408 np[0] = np[0] + 1 409 } 410 } 411 j = voff + vl 412 } 413 s = s + 1 414 } 415 return 0 416} 417 418func vr_sent_has(kk: *i64, ii: *i64, dd: *i64, n: i64, k: *u8, id: *u8, date: *u8) -> i64 { 419 var i: i64 = 0 420 while i < n { 421 if vr_eq(kk[i] as *u8, k) == 1 { 422 if vr_eq(ii[i] as *u8, id) == 1 { 423 if vr_eq(dd[i] as *u8, date) == 1 { return 1 } 424 } 425 } 426 i = i + 1 427 } 428 return 0 429} 430 431// ---------------- DUE ---------------- 432func vr_cmd_due(argc: i64, argv: *i64) -> i64 { 433 if argc < 6 { vr_p("VIZSLA-REM due needs <calprefix|-> <contacts|-> <today> <leads> [sentprefix] -- fail loud\n" as *u8); return 1 } 434 let calpfx: *u8 = argv[2] as *u8 435 let cfile: *u8 = argv[3] as *u8 436 let today: i64 = vr_datedays(argv[4] as *u8) 437 if today < 0 { vr_p("VIZSLA-REM bad today date -- fail loud\n" as *u8); return 1 } 438 // parse leads 439 let leads: *i64 = sys_mmap(8 * 16) as *i64 440 var nlead: i64 = 0 441 var maxlead: i64 = 0 - 1 442 let ls: *u8 = argv[5] as *u8 443 let tokb: *u8 = sys_mmap(64) 444 var li: i64 = 0 445 var lt: i64 = 0 446 var go: i64 = 1 447 while go == 1 { 448 let c: i64 = ls[li] as i64 449 var flush: i64 = 0 450 if c == 44 { flush = 1 } 451 if c == 0 { flush = 1 } 452 if flush == 1 { 453 tokb[lt] = 0 as u8 454 if lt > 0 { 455 if vr_digits(tokb) == 0 { vr_p("VIZSLA-REM leads not digits -- fail loud\n" as *u8); return 1 } 456 let v: i64 = vr_atoi(tokb) 457 if nlead < 16 { leads[nlead] = v; nlead = nlead + 1 } 458 if v > maxlead { maxlead = v } 459 } 460 lt = 0 461 } else { 462 if lt < 63 { tokb[lt] = c as u8; lt = lt + 1 } 463 } 464 if c == 0 { go = 0 } 465 li = li + 1 466 } 467 if nlead == 0 { vr_p("VIZSLA-REM leads empty -- fail loud\n" as *u8); return 1 } 468 var sentpfx: *u8 = "-" as *u8 469 if argc > 6 { sentpfx = argv[6] as *u8 } 470 471 // sent ledger 472 let skk: *i64 = sys_mmap(8 * 256) as *i64 473 let sii: *i64 = sys_mmap(8 * 256) as *i64 474 let sdd: *i64 = sys_mmap(8 * 256) as *i64 475 let snp: *i64 = sys_mmap(16) as *i64 476 snp[0] = 0 477 if vr_eq(sentpfx, "-" as *u8) == 0 { vr_sent_gather(sentpfx, skk, sii, sdd, snp) } 478 479 let rep: *u8 = sys_mmap(K_MAGIC_262144) 480 var o: i64 = 0 481 var due_ev: i64 = 0 482 var due_bd: i64 = 0 483 var skipped: i64 = 0 484 let dstr: *u8 = sys_mmap(64) 485 486 // calendar events + recurrences 487 if vr_eq(calpfx, "-" as *u8) == 0 { 488 let segs: *i64 = sys_mmap(8 * 260) as *i64 489 let ns: i64 = ss_manifest(calpfx, segs) 490 let fid: *u8 = sys_mmap(128) 491 let fdt: *u8 = sys_mmap(128) 492 let fst: *u8 = sys_mmap(128) 493 let fdu: *u8 = sys_mmap(128) 494 let ffr: *u8 = sys_mmap(64) 495 let fiv: *u8 = sys_mmap(64) 496 let fct: *u8 = sys_mmap(64) 497 let ftl: *u8 = sys_mmap(256) 498 let ymd: *i64 = sys_mmap(8 * 4) as *i64 499 var s: i64 = 0 500 while s < ns { 501 let path: *u8 = sys_mmap(512) 502 var po: i64 = 0 503 po = vr_cat(path, po, calpfx) 504 po = vr_cat(path, po, segs[s] as *u8) 505 po = vr_cat(path, po, ".docs" as *u8) 506 path[po] = 0 as u8 507 let szp: *i64 = sys_mmap(16) as *i64 508 let b: *u8 = ss_readall(path, szp) 509 let sz: i64 = szp[0] 510 var j: i64 = 0 511 while j + 9 <= sz { 512 let kind: i64 = b[j] 513 let kl: i64 = ss_r32(b, j + 1) 514 let koff: i64 = j + 5 515 let vl: i64 = ss_r32(b, koff + kl) 516 let voff: i64 = koff + kl + 4 517 let rec: *u8 = (b as i64 + voff) as *u8 518 var iscal: i64 = 0 519 var isrec: i64 = 0 520 if kind == 1 { iscal = vr_iskind(b, koff, kl, "cal:" as *u8) } 521 if kind == 1 { isrec = vr_iskind(b, koff, kl, "rec:" as *u8) } 522 if iscal == 1 { 523 var ddv: i64 = 0 - 1 524 if vr_field(rec, vl, "date" as *u8, fdt, 128) == 1 { ddv = vr_datedays(fdt) } 525 var inwin: i64 = 0 526 if ddv >= today { if ddv <= today + maxlead { inwin = 1 } } 527 if inwin == 1 { 528 let din: i64 = ddv - today 529 var hit: i64 = 0 530 var lk: i64 = 0 531 while lk < nlead { 532 if leads[lk] == din { hit = 1 } 533 lk = lk + 1 534 } 535 if hit == 1 { 536 vr_field(rec, vl, "id" as *u8, fid, 128) 537 vr_field(rec, vl, "title" as *u8, ftl, 256) 538 if vr_sent_has(skk, sii, sdd, snp[0], "event" as *u8, fid, fdt) == 1 { 539 o = vr_cat(rep, o, "VIZSLA-REM-SENT-SKIP kind=event id=" as *u8) 540 o = vr_cat(rep, o, fid) 541 o = vr_cat(rep, o, " date=" as *u8) 542 o = vr_cat(rep, o, fdt) 543 o = vr_cat(rep, o, "\n" as *u8) 544 skipped = skipped + 1 545 } else { 546 o = vr_cat(rep, o, "VIZSLA-REM-DUE kind=event id=" as *u8) 547 o = vr_cat(rep, o, fid) 548 o = vr_cat(rep, o, " date=" as *u8) 549 o = vr_cat(rep, o, fdt) 550 o = vr_cat(rep, o, " in=" as *u8) 551 o = vr_catn(rep, o, din) 552 o = vr_cat(rep, o, " title=" as *u8) 553 o = vr_cat(rep, o, ftl) 554 o = vr_cat(rep, o, "\n" as *u8) 555 due_ev = due_ev + 1 556 } 557 } 558 } 559 } 560 if isrec == 1 { 561 vr_field(rec, vl, "id" as *u8, fid, 128) 562 vr_field(rec, vl, "sdate" as *u8, fdt, 128) 563 vr_field(rec, vl, "freq" as *u8, ffr, 64) 564 vr_field(rec, vl, "interval" as *u8, fiv, 64) 565 vr_field(rec, vl, "count" as *u8, fct, 64) 566 vr_field(rec, vl, "title" as *u8, ftl, 256) 567 let sd0: i64 = vr_datedays(fdt) 568 vr_civil(sd0, ymd) 569 let iv: i64 = vr_atoi(fiv) 570 let ct: i64 = vr_atoi(fct) 571 var k: i64 = 0 572 while k < ct { 573 let occ: i64 = vr_occ(ffr, sd0, ymd[0], ymd[1], ymd[2], iv, k) 574 var inwin: i64 = 0 575 if occ >= today { if occ <= today + maxlead { inwin = 1 } } 576 if inwin == 1 { 577 let din: i64 = occ - today 578 var hit: i64 = 0 579 var lk: i64 = 0 580 while lk < nlead { 581 if leads[lk] == din { hit = 1 } 582 lk = lk + 1 583 } 584 if hit == 1 { 585 var dso: i64 = vr_daystr(dstr, 0, occ) 586 dstr[dso] = 0 as u8 587 if vr_sent_has(skk, sii, sdd, snp[0], "event" as *u8, fid, dstr) == 1 { 588 o = vr_cat(rep, o, "VIZSLA-REM-SENT-SKIP kind=event id=" as *u8) 589 o = vr_cat(rep, o, fid) 590 o = vr_cat(rep, o, " date=" as *u8) 591 o = vr_cat(rep, o, dstr) 592 o = vr_cat(rep, o, "\n" as *u8) 593 skipped = skipped + 1 594 } else { 595 o = vr_cat(rep, o, "VIZSLA-REM-DUE kind=event id=" as *u8) 596 o = vr_cat(rep, o, fid) 597 o = vr_cat(rep, o, " date=" as *u8) 598 o = vr_cat(rep, o, dstr) 599 o = vr_cat(rep, o, " in=" as *u8) 600 o = vr_catn(rep, o, din) 601 o = vr_cat(rep, o, " title=" as *u8) 602 o = vr_cat(rep, o, ftl) 603 o = vr_cat(rep, o, "\n" as *u8) 604 due_ev = due_ev + 1 605 } 606 } 607 } 608 if occ > today + maxlead { k = ct } 609 k = k + 1 610 } 611 } 612 j = voff + vl 613 } 614 s = s + 1 615 } 616 } 617 618 // contact birthdays 619 if vr_eq(cfile, "-" as *u8) == 0 { 620 let szp: *i64 = sys_mmap(16) as *i64 621 let cb: *u8 = ss_readall(cfile, szp) 622 let csz: i64 = szp[0] 623 if csz <= 0 { vr_p("VIZSLA-REM contacts file MISSING/EMPTY -- fail loud\n" as *u8); return 1 } 624 let t0: *u8 = sys_mmap(128) 625 let cid2: *u8 = sys_mmap(128) 626 let cdisp: *u8 = sys_mmap(256) 627 let ctier: *u8 = sys_mmap(128) 628 let cbd: *u8 = sys_mmap(64) 629 var i: i64 = 0 630 while i < csz { 631 var e: i64 = i 632 var go2: i64 = 1 633 while go2 == 1 { 634 if e >= csz { go2 = 0 } else { 635 if cb[e] == (10 as u8) { go2 = 0 } else { e = e + 1 } 636 } 637 } 638 var p: i64 = vr_tok(cb, i, e, t0, 128) 639 if vr_eq(t0, "CONTACT" as *u8) == 1 { 640 p = vr_tok(cb, p, e, cid2, 128) 641 p = vr_tok(cb, p, e, cdisp, 256) 642 p = vr_tok(cb, p, e, ctier, 128) 643 p = vr_tok(cb, p, e, cbd, 64) 644 if vr_eq(cbd, "-" as *u8) == 0 { if cbd[0] != (0 as u8) { 645 let nxt: i64 = vr_bday_next(cbd, today) 646 if nxt < 0 { vr_p("VIZSLA-REM bad birthday MM-DD -- fail loud\n" as *u8); return 1 } 647 let din: i64 = nxt - today 648 var hit: i64 = 0 649 var lk: i64 = 0 650 while lk < nlead { 651 if leads[lk] == din { hit = 1 } 652 lk = lk + 1 653 } 654 if hit == 1 { 655 var dso: i64 = vr_daystr(dstr, 0, nxt) 656 dstr[dso] = 0 as u8 657 if vr_sent_has(skk, sii, sdd, snp[0], "birthday" as *u8, cid2, dstr) == 1 { 658 o = vr_cat(rep, o, "VIZSLA-REM-SENT-SKIP kind=birthday id=" as *u8) 659 o = vr_cat(rep, o, cid2) 660 o = vr_cat(rep, o, " date=" as *u8) 661 o = vr_cat(rep, o, dstr) 662 o = vr_cat(rep, o, "\n" as *u8) 663 skipped = skipped + 1 664 } else { 665 o = vr_cat(rep, o, "VIZSLA-REM-DUE kind=birthday id=" as *u8) 666 o = vr_cat(rep, o, cid2) 667 o = vr_cat(rep, o, " date=" as *u8) 668 o = vr_cat(rep, o, dstr) 669 o = vr_cat(rep, o, " in=" as *u8) 670 o = vr_catn(rep, o, din) 671 o = vr_cat(rep, o, " title=" as *u8) 672 o = vr_cat(rep, o, cdisp) 673 o = vr_cat(rep, o, "\n" as *u8) 674 due_bd = due_bd + 1 675 } 676 } 677 } } 678 } 679 i = e + 1 680 } 681 } 682 683 o = vr_cat(rep, o, "VIZSLA-REM-VERDICT today=" as *u8) 684 o = vr_cat(rep, o, argv[4] as *u8) 685 o = vr_cat(rep, o, " maxlead=" as *u8) 686 o = vr_catn(rep, o, maxlead) 687 o = vr_cat(rep, o, " due=" as *u8) 688 o = vr_catn(rep, o, due_ev + due_bd) 689 o = vr_cat(rep, o, " due_events=" as *u8) 690 o = vr_catn(rep, o, due_ev) 691 o = vr_cat(rep, o, " due_birthdays=" as *u8) 692 o = vr_catn(rep, o, due_bd) 693 o = vr_cat(rep, o, " skipped_sent=" as *u8) 694 o = vr_catn(rep, o, skipped) 695 o = vr_cat(rep, o, "\n" as *u8) 696 sys_write(1, rep, o) 697 return 0 698} 699 700// ---------------- MARK (sent ledger) ---------------- 701func vr_cmd_mark(argc: i64, argv: *i64) -> i64 { 702 if argc < 6 { vr_p("VIZSLA-REM mark needs <sentprefix> <event|birthday> <id> <date> [segid] -- fail loud\n" as *u8); return 1 } 703 let prefix: *u8 = argv[2] as *u8 704 let k: *u8 = argv[3] as *u8 705 let id: *u8 = argv[4] as *u8 706 let date: *u8 = argv[5] as *u8 707 var okk: i64 = 0 708 if vr_eq(k, "event" as *u8) == 1 { okk = 1 } 709 if vr_eq(k, "birthday" as *u8) == 1 { okk = 1 } 710 if okk == 0 { vr_p("VIZSLA-REM mark kind not event|birthday -- fail loud\n" as *u8); return 1 } 711 if vr_datedays(date) < 0 { vr_p("VIZSLA-REM mark bad date -- fail loud\n" as *u8); return 1 } 712 var segid: i64 = 0 713 if argc > 6 { segid = vr_atoi(argv[6] as *u8) } 714 if segid == 0 { segid = sys_now_us() } 715 716 let keys: *i64 = sys_mmap(8 * 8) as *i64 717 let vals: *i64 = sys_mmap(8 * 8) as *i64 718 keys[0] = "kind" as *u8 as i64 719 keys[1] = "k" as *u8 as i64 720 keys[2] = "id" as *u8 as i64 721 keys[3] = "date" as *u8 as i64 722 vals[0] = "snt" as *u8 as i64 723 vals[1] = k as i64 724 vals[2] = id as i64 725 vals[3] = date as i64 726 727 let st: *i64 = sys_mmap(8 * 8) as *i64 728 st[0] = ss_begin() as i64 729 st[1] = sys_mmap(8 * K_MAGIC_2048) 730 st[2] = 0 731 st[3] = 0 732 st[4] = 0 733 st[5] = 0 734 st[6] = prefix as i64 735 if vr_put(keys, vals, 4, "snt:" as *u8, st) != 0 { vr_p("VIZSLA-REM writer full -- fail loud\n" as *u8); return 1 } 736 if st[3] > 0 { 737 if ss_commit(prefix, st[0] as *i64, segid) != 0 { vr_p("VIZSLA-REM commit FAILED -- fail loud\n" as *u8); return 1 } 738 } 739 740 let rep: *u8 = sys_mmap(K_MAGIC_1024) 741 var o: i64 = 0 742 o = vr_cat(rep, o, "VIZSLA-REM-MARK k=" as *u8) 743 o = vr_cat(rep, o, k) 744 o = vr_cat(rep, o, " id=" as *u8) 745 o = vr_cat(rep, o, id) 746 o = vr_cat(rep, o, " date=" as *u8) 747 o = vr_cat(rep, o, date) 748 o = vr_cat(rep, o, " new=" as *u8) 749 o = vr_catn(rep, o, st[3]) 750 o = vr_cat(rep, o, "\n" as *u8) 751 sys_write(1, rep, o) 752 return 0 753} 754 755func main(argc: i64, argv: *i64) -> i64 { 756 if argc < 2 { vr_p("VIZSLA-REM usage: due|mark -- fail loud\n" as *u8); return 1 } 757 let cmd: *u8 = argv[1] as *u8 758 if vr_eq(cmd, "due" as *u8) == 1 { return vr_cmd_due(argc, argv) } 759 if vr_eq(cmd, "mark" as *u8) == 1 { return vr_cmd_mark(argc, argv) } 760 vr_p("VIZSLA-REM unknown command (due|mark) -- fail loud\n" as *u8) 761 return 1 762}