; feed/trending — what's hot right now: objects (or actors) ranked by activity
; count within a recency window. Deterministic: count descending, ties broken by
; key ascending (entries are pre-sorted by key, then stable grade-down by count).
;
; Requires: lib/feed/stream.sx, lib/feed/aggregate.sx (object/actor-counts),
; lib/feed/rank.sx (feed/-desc-by).

; activities within (now-window, now]
(define
  feed/-recent
  (fn
    (stream now window)
    (feed/filter
      stream
      (fn (a) (and (<= (get a :at) now) (> (get a :at) (- now window)))))))

; counts dict -> top-N entries {label key, :count n}, count desc, key asc
(define
  feed/-top-counts
  (fn
    (counts label n)
    (let
      ((entries (map (fn (k) (assoc {:count (get counts k)} label k)) (sort (keys counts)))))
      (take (feed/-desc-by entries (fn (e) (get e :count))) n))))

; top-N trending objects in the window
(define
  feed/trending
  (fn
    (stream now window n)
    (feed/-top-counts
      (feed/object-counts (feed/-recent stream now window))
      :object n)))

; top-N most active actors in the window
(define
  feed/trending-actors
  (fn
    (stream now window n)
    (feed/-top-counts
      (feed/actor-counts (feed/-recent stream now window))
      :actor n)))
