; feed/aggregate — group-by / counting via key-reduce. Keys must be strings ; (dict keys), so composite keys (actor, day) are joined into one string. ; ; Requires: lib/feed/normalize.sx, lib/feed/stream.sx. ; group activities into a dict: key-string -> (list of activities), order-preserving (define feed/group-by (fn (stream key-fn) (reduce (fn (g a) (let ((k (key-fn a))) (assoc g k (append (get g k (list)) (list a))))) {} (feed/items stream)))) ; key-string -> count (define feed/group-count (fn (stream key-fn) (reduce (fn (g a) (let ((k (key-fn a))) (assoc g k (+ (get g k 0) 1)))) {} (feed/items stream)))) ; --- composite keys --------------------------------------------------------- (define feed/day (fn (at window) (floor (/ at window)))) ; (actor, day-bucket) -> "actor#day" (define feed/actor-day-key (fn (window) (fn (a) (string-append (get a :actor) "#" (number->string (feed/day (get a :at) window)))))) (define feed/by-actor-day (fn (stream window) (feed/group-count stream (feed/actor-day-key window)))) ; per-actor activity counts (define feed/actor-counts (fn (stream) (feed/group-count stream feed/actor))) ; per-object activity counts (engagement) (define feed/object-counts (fn (stream) (feed/group-count stream feed/object)))