Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 42s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
161 lines
3.8 KiB
Plaintext
161 lines
3.8 KiB
Plaintext
; Phase 3 — aggregation + ranking. (feed-test name got expected)
|
|
|
|
; ---------- aggregation ----------
|
|
|
|
(define
|
|
A
|
|
(feed/stream
|
|
(list
|
|
(feed/activity "alice" "post" "p1" 5 (list))
|
|
(feed/activity "alice" "post" "p2" 15 (list))
|
|
(feed/activity "bob" "post" "p3" 25 (list))
|
|
(feed/activity "alice" "like" "p1" 35 (list)))))
|
|
|
|
(feed-test "actor-counts" (feed/actor-counts A) {:alice 3 :bob 1})
|
|
(feed-test "object-counts" (feed/object-counts A) {:p2 1 :p3 1 :p1 2})
|
|
(feed-test
|
|
"group-by actor alice len"
|
|
(len (get (feed/group-by A feed/actor) "alice"))
|
|
3)
|
|
(feed-test
|
|
"group-count empty"
|
|
(feed/group-count feed/empty feed/actor)
|
|
{})
|
|
|
|
; day bucketing
|
|
(define
|
|
D
|
|
(feed/stream
|
|
(list
|
|
(feed/activity "alice" "post" "p1" 5 (list))
|
|
(feed/activity "alice" "post" "p2" 8 (list))
|
|
(feed/activity "alice" "post" "p3" 12 (list)))))
|
|
|
|
(feed-test "feed/day floor" (feed/day 12 10) 1)
|
|
(feed-test "feed/day same bucket" (feed/day 8 10) 0)
|
|
(feed-test "by-actor-day" (feed/by-actor-day D 10) {:alice#0 2 :alice#1 1})
|
|
|
|
; ---------- recency ----------
|
|
|
|
(define rec (feed/recency 100 10))
|
|
(feed-test
|
|
"recency at=now -> 1"
|
|
(rec (feed/activity "x" "post" "o" 100 (list)))
|
|
1)
|
|
(feed-test
|
|
"recency age=hl -> .5"
|
|
(rec (feed/activity "x" "post" "o" 90 (list)))
|
|
0.5)
|
|
(feed-test
|
|
"recency age=2hl -> .25"
|
|
(rec (feed/activity "x" "post" "o" 80 (list)))
|
|
0.25)
|
|
|
|
; ---------- velocity ----------
|
|
|
|
(define vel (feed/velocity D 10))
|
|
(feed-test
|
|
"velocity burst (at=12)"
|
|
(vel (feed/activity "alice" "post" "z" 12 (list)))
|
|
3)
|
|
(feed-test
|
|
"velocity mid (at=8)"
|
|
(vel (feed/activity "alice" "post" "z" 8 (list)))
|
|
2)
|
|
(feed-test
|
|
"velocity first (at=5)"
|
|
(vel (feed/activity "alice" "post" "z" 5 (list)))
|
|
1)
|
|
(feed-test
|
|
"velocity other actor"
|
|
(vel (feed/activity "bob" "post" "z" 12 (list)))
|
|
0)
|
|
|
|
; ---------- engagement ----------
|
|
|
|
(define eng (feed/engagement A))
|
|
(feed-test
|
|
"engagement p1"
|
|
(eng (feed/activity "x" "post" "p1" 0 (list)))
|
|
2)
|
|
(feed-test
|
|
"engagement p2"
|
|
(eng (feed/activity "x" "post" "p2" 0 (list)))
|
|
1)
|
|
|
|
; ---------- composite ----------
|
|
|
|
(define
|
|
cmp1
|
|
(feed/composite (list (list 2 (fn (a) (get a :at))))))
|
|
(feed-test
|
|
"composite single part"
|
|
(cmp1 (feed/activity "x" "post" "o" 5 (list)))
|
|
10)
|
|
(define
|
|
cmp2
|
|
(feed/composite
|
|
(list
|
|
(list 2 (fn (a) (get a :at)))
|
|
(list 3 (fn (a) 1)))))
|
|
(feed-test
|
|
"composite two parts"
|
|
(cmp2 (feed/activity "x" "post" "o" 5 (list)))
|
|
13)
|
|
|
|
; ---------- ranking ----------
|
|
|
|
(define
|
|
R
|
|
(feed/stream
|
|
(list
|
|
(feed/activity "u" "post" "oC" 80 (list))
|
|
(feed/activity "u" "post" "oA" 100 (list))
|
|
(feed/activity "u" "post" "oB" 90 (list)))))
|
|
|
|
(feed-test
|
|
"rank by recency objects"
|
|
(map (fn (a) (get a :object)) (feed/items (feed/rank R rec)))
|
|
(list "oA" "oB" "oC"))
|
|
(feed-test
|
|
"top-2 by recency"
|
|
(map (fn (a) (get a :object)) (feed/items (feed/top R rec 2)))
|
|
(list "oA" "oB"))
|
|
(feed-test "top-2 count" (feed/count (feed/top R rec 2)) 2)
|
|
|
|
; constant score -> tiebreak by :at descending
|
|
(define
|
|
T
|
|
(feed/stream
|
|
(list
|
|
(feed/activity "u" "post" "f" 10 (list))
|
|
(feed/activity "u" "post" "g" 30 (list))
|
|
(feed/activity "u" "post" "h" 20 (list)))))
|
|
(feed-test
|
|
"tiebreak at-desc"
|
|
(map
|
|
(fn (a) (get a :object))
|
|
(feed/items (feed/rank T (fn (a) 0))))
|
|
(list "g" "h" "f"))
|
|
|
|
; equal score AND equal :at -> stable input order
|
|
(define
|
|
E
|
|
(feed/stream
|
|
(list
|
|
(feed/activity "u" "post" "first" 50 (list))
|
|
(feed/activity "u" "post" "second" 50 (list)))))
|
|
(feed-test
|
|
"stable equal-key input order"
|
|
(map
|
|
(fn (a) (get a :object))
|
|
(feed/items (feed/rank E (fn (a) 0))))
|
|
(list "first" "second"))
|
|
|
|
(feed-test
|
|
"with-scores attaches score"
|
|
(get (nth (feed/items (feed/with-scores R rec)) 1) :score)
|
|
1)
|
|
|
|
(feed-test "rank preserves count" (feed/count (feed/rank A rec)) 4)
|