<commit_before>(ns afterglow.show
  "Encapsulates a synchronized light show, executing a varying
  collection of effects with output to a number of DMX universes.
  Assumes control of the assigned universes, so only one show at a
  time should be assigned a given universe. Of course, you can stack
  as many effects as you'd like in that show.

  The effects are maintained in a priority queue, with higher-priority
  effects running after lower-priority ones, so they can adjust or
  simply replace the channel assignments established by earlier
  effects. Some may choose to implement traditional channel-oriented
  highest-takes-prority or latest-takes-priority semantics, others do
  more sophisticated color blending or position averageing. The
  default priority when adding an effect is zero, but you can assign
  it any integer, and it will be inserted into the queue after any
  existing effects with the same priority.

  All effects are assigned a keyword when they are added, and adding a
  new effect with the same key as an existing effect will replace the
  former one."
  {:author "<NAME>"
   :doc/format :markdown}
  (:require [afterglow.channels :as chan]
            [afterglow.effects :as fx]
            [afterglow.effects.channel :refer [channel-assignment-resolver
                                               function-assignment-resolver]]
            [afterglow.effects.color :refer [color-assignment-resolver]]
            [afterglow.effects.dimmer :refer [master master-set-level]]
            [afterglow.effects.movement :refer [direction-assignment-resolver
                                                aim-assignment-resolver]]
            [afterglow.effects.params :refer [bind-keyword-param resolve-param]]
            [afterglow.fixtures :as fixtures]
            [afterglow.midi :as midi]
            [afterglow.ola-service :as ola]
            [afterglow.rhythm :refer :all]
            [afterglow.show-context :refer [*show* with-show]]
            [afterglow.transform :refer [transform-fixture]]
            [com.climate.claypoole :as cp]
            [environ.core :refer [env]]
            [overtone.at-at :as at-at]
            [taoensso.timbre :refer [error]]
            [taoensso.timbre.profiling :refer [p profile pspy]])
  (:import (afterglow.effects.dimmer Master)
           (afterglow.effects Assigner Effect)
           (afterglow.rhythm Metronome)
           (com.google.protobuf ByteString)))

(defonce ^{:doc "How often should frames of DMX data be sent out; this
  should be a supported frame rate for your interface. The default
  here is 30 Hz, thirty frames per second."}
  default-refresh-interval
  (/ 1000 30))

(defonce ^{:doc "Provides thread scheduling for all shows' DMX data generation."}
  scheduler
  (at-at/mk-pool))

(def resolution-handlers
  "The order in which assigners should be evaluated, and the functions
  which resolve them into DMX channel updates. A list of tuples which
  identify the assigner type key, and the function to invoke for such
  assigners."
  [[:channel channel-assignment-resolver]
   [:function function-assignment-resolver]
   [:color color-assignment-resolver]
   [:direction direction-assignment-resolver]
   [:aim aim-assignment-resolver]])

(defn- gather-assigners
  "Collect all of the assigners that are in effect at the current
  moment in the show, organized by type and the unique ID of the
  element they affect, sorted in priority order under those keys."
  [show snapshot]
  (pspy :gather-assigners
        (reduce (fn [altered-map assigner]
                  (let [key-path [(:kind assigner) (:target-id assigner)]]
                    (assoc-in altered-map key-path (conj (get-in altered-map key-path []) assigner))))
                {}
                (apply concat (cp/pmap @(:pool show) #(fx/generate % show snapshot)<commit_msg>Fix typo in comment, make scheduler private again.<commit_after>(ns afterglow.show
  "Encapsulates a synchronized light show, executing a varying
  collection of effects with output to a number of DMX universes.
  Assumes control of the assigned universes, so only one show at a
  time should be assigned a given universe. Of course, you can stack
  as many effects as you'd like in that show.

  The effects are maintained in a priority queue, with higher-priority
  effects running after lower-priority ones, so they can adjust or
  simply replace the channel assignments established by earlier
  effects. Some may choose to implement traditional channel-oriented
  highest-takes-prority or latest-takes-priority semantics, others do
  more sophisticated color blending or position averageing. The
  default priority when adding an effect is zero, but you can assign
  it any integer, and it will be inserted into the queue after any
  existing effects with the same priority.

  All effects are assigned a keyword when they are added, and adding a
  new effect with the same key as an existing effect will replace the
  former one."
  {:author "<NAME>"
   :doc/format :markdown}
  (:require [afterglow.channels :as chan]
            [afterglow.effects :as fx]
            [afterglow.effects.channel :refer [channel-assignment-resolver
                                               function-assignment-resolver]]
            [afterglow.effects.color :refer [color-assignment-resolver]]
            [afterglow.effects.dimmer :refer [master master-set-level]]
            [afterglow.effects.movement :refer [direction-assignment-resolver
                                                aim-assignment-resolver]]
            [afterglow.effects.params :refer [bind-keyword-param resolve-param]]
            [afterglow.fixtures :as fixtures]
            [afterglow.midi :as midi]
            [afterglow.ola-service :as ola]
            [afterglow.rhythm :refer :all]
            [afterglow.show-context :refer [*show* with-show]]
            [afterglow.transform :refer [transform-fixture]]
            [com.climate.claypoole :as cp]
            [environ.core :refer [env]]
            [overtone.at-at :as at-at]
            [taoensso.timbre :refer [error]]
            [taoensso.timbre.profiling :refer [p profile pspy]])
  (:import (afterglow.effects.dimmer Master)
           (afterglow.effects Assigner Effect)
           (afterglow.rhythm Metronome)
           (com.google.protobuf ByteString)))

(defonce ^{:doc "How often should frames of DMX data be sent out; this
  should be a supported frame rate for your interface. The default
  here is 30 Hz, thirty frames per second."}
  default-refresh-interval
  (/ 1000 30))

(defonce ^{:doc "Provides thread scheduling for all shows' DMX data generation."
           :private true}
  scheduler
  (at-at/mk-pool))

(def resolution-handlers
  "The order in which assigners should be evaluated, and the functions
  which resolve them into DMX channel updates. A list of tuples which
  identify the assigner type key, and the function to invoke for such
  assigners."
  [[:channel channel-assignment-resolver]
   [:function function-assignment-resolver]
   [:color color-assignment-resolver]
   [:direction direction-assignment-resolver]
   [:aim aim-assignment-resolver]])

(defn- gather-assigners
  "Collect all of the assigners that are in effect at the current
  moment in the show, organized by type and the unique ID of the
  element they affect, sorted in priority order under those keys."
  [show snapshot]
  (pspy :gather-assigners
        (reduce (fn [altered-map assigner]
                  (let [key-path [(:kind assigner) (:target-id assigner)]]
                    (assoc-in altered-map key-path (conj (get-in altered-map key-path []) assigner))))
                {}
                (apply concat (cp/pmap @(:pool show) #(fx/generate % show snapshot)
{'fraction_non_alphanumeric': 0.08131443298969072, 'fraction_numerical': 0.002061855670103093, 'mean_word_length': 2.78955078125, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1269912', 'n_tokens_mistral': 2164, 'n_tokens_neox': 2106, 'n_words': 812}