udpate filter metadata and make them all auto-rated

--- src/overtone/sc/ugen/filter.clj
+++ src/overtone/sc/ugen/filter.clj
@@ -8,161 +8,192 @@
 (def muladd-specs
   [
    {:name "Resonz",
-    :args [{:name "in", :default 0.0}
-           {:name "freq", :default 440.0}
-           {:name "bwr", :default 1.0}]
-    :doc "a two pole resonant filter"}
+    :args [{:name "in", :default 0.0 :doc "input signal to be processed"}
+           {:name "freq", :default 440.0 :doc "resonant frequency in Hertz"}
+           {:name "bwr", :default 1.0 :doc "bandwidth ratio (reciprocal of Q). rq = bandwidth / centerFreq"}]
+    :doc "A Note on Constant-Gain Digital Resonators,\" Computer Music Journal, vol 18, no. 4, pp. 8-10, Winter 1994.\" Computer Music Journal, vol 18, no. 4, pp. 8-10, Winter 1994."
+    :auto-rate true}

    {:name "OnePole",
-    :args [{:name "in", :default 0.0}
-           {:name "coef", :default 0.5}]
+    :args [{:name "in", :default 0.0 :doc "input signal to be processed"}
+           {:name "coef", :default 0.5 :doc "feedback coefficient. Should be between -1 and +1"}]
     :doc "A one pole filter. Implements the formula:
-out(i) = ((1 - abs(coef)) * in(i)) + (coef * out(i-1))"}
+out(i) = ((1 - abs(coef)) * in(i)) + (coef * out(i-1))"
+    :auto-rate true}

    {:name "OneZero",
-    :args [{:name "in", :default 0.0}
-           {:name "coef", :default 0.5}]
+    :args [{:name "in", :default 0.0 :doc "input signal to be processed"}
+           {:name "coef", :default 0.5 :doc "feed forward coefficient. +0.5 makes a two point averaging filter (see also lpz1), -0.5 makes a differentiator (see also hpz1), +1 makes a single sample delay (see also delay1), -1 makes an inverted single sample delay."}]
     :doc "A one zero filter. Implements the formula :
-out(i) = ((1 - abs(coef)) * in(i)) + (coef * in(i-1))"}
+out(i) = ((1 - abs(coef)) * in(i)) + (coef * in(i-1))"
+    :auto-rate true}

    {:name "TwoPole",
-    :args [{:name "in", :default 0.0}
-           {:name "freq", :default 440.0}
-           {:name "radius", :default 0.8}]
-    :doc "a two pole filter"}
+    :args [{:name "in", :default 0.0 :doc "input signal to be processed"}
+           {:name "freq", :default 440.0 :doc "frequency of pole angle"}
+           {:name "radius", :default 0.8 :doc "radius of pole. Should be between 0 and +1"}]
+    :doc "a two pole filter. This provides lower level access to setting of pole location. For general purposes Resonz is better."
+    :auto-rate true}

    {:name "TwoZero",
-    :args [{:name "in", :default 0.0}
-           {:name "freq", :default 440.0}
-           {:name "radius", :default 0.8}]
-    :doc "a two zero filter"}
+    :args [{:name "in", :default 0.0 :doc "input signal to be processed"}
+           {:name "freq", :default 440.0 :doc "frequency of zero angle"}
+           {:name "radius", :default 0.8 :doc "radios of zero"}]
+    :doc "a two zero filter"
+    :auto-rate true}

    ;; APF : TwoPole {}
    {:name "APF",
     :args [{:name "in", :default 0.0}
            {:name "freq", :default 440.0}
            {:name "radius", :default 0.8}]
-    :doc ""}
+    :doc ""
+    :auto-rate true}

    {:name "Integrator",
-    :args [{:name "in", :default 0.0}
-           {:name "coef", :default 1.0}]
-    :doc "leaky integrator"}
+    :args [{:name "in", :default 0.0 :doc "input signal"}
+           {:name "coef", :default 1.0 :doc "leak coefficient"}]
+    :doc "leaky integrator. Integrates an input signal with a leak. The formula implemented is: out(0) = in(0) + (coef * out(-1))"
+    :auto-rate true}

    {:name "Decay",
-    :args [{:name "in", :default 0.0}
-           {:name "decayTime", :default 1.0}]
-    :doc "triggered exponential decay"}
+    :args [{:name "in", :default 0.0 :doc "input signal"}
+           {:name "decayTime", :default 1.0 :doc "60 dB decay time in seconds"}]
+    :doc "triggered exponential decay. This is essentially the same as Integrator except that instead of supplying the coefficient directly, it is caculated from a 60 dB decay time. This is the time required for the integrator to lose 99.9 % of its value or -60dB. This is useful for exponential decaying envelopes triggered by impulses."
+    :auto-rate true}

    {:name "Decay2",
     :args [{:name "in", :default 0.0}
            {:name "attackTime", :default 0.01}
            {:name "decayTime", :default 1.0}]
-    :doc "triggered exponential attack and exponential decay"}
+    :doc "triggered exponential attack and exponential decay. Decay has a very sharp attack and can produce clicks. Decay2 rounds off the attack by subtracting one Decay from another. (decay in attack-time decay-time) equivalent to: (- (decay in attack-time decay-time) (decay in attack-time decay-time))"
+    :auto-rate true}

    {:name "Lag",
-    :args [{:name "in", :default 0.0}
-           {:name "lagTime", :default 0.1}]
-    :doc "exponential lag, useful for smoothing out control signals"}
+    :args [{:name "in", :default 0.0 :doc "input signal"}
+           {:name "lagTime", :default 0.1 :doc "60 dB lag time in seconds"}]
+    :doc "exponential lag, useful for smoothing out control signals. This is essentially the same as OnePole except that instead of supplying the coefficient directly, it is calculated from a 60 dB lag time. This is the time required for the filter to converge to within 0.01 % of a value. This is useful for smoothing out control signals."
+    :auto-rate true}

    {:name "Lag2",
-    :args [{:name "in", :default 0.0}
-           {:name "lagTime", :default 0.1}]
-    :doc "equivalent to Lag.kr(Lag.kr(in, time), time), resulting in a smoother transition"}
+    :args [{:name "in", :default 0.0 :doc "input signal"}
+           {:name "lagTime", :default 0.1 :doc "60 dB lag time in seconds"} ]
+    :doc "equivalent to Lag.kr(Lag.kr(in, time), time), resulting in a smoother transition. This saves on CPU as you only have to calculate the decay factor once instead of twice. See Lag for more details."
+    :auto-rate true}

    {:name "Lag3",
-    :args [{:name "in", :default 0.0}
-           {:name "lagTime", :default 0.1}]
-    :doc "equivalent to Lag.kr(Lag.kr(Lag.kr(in, time), time), time), resulting in a smoother transition"}
+    :args [{:name "in", :default 0.0 :doc "input signal"}
+           {:name "lagTime", :default 0.1 :doc "60 dB lag time in seconds"}]
+    :doc "Lag3 is equivalent to Lag.kr(Lag.kr(Lag.kr(in, time), time), time), thus resulting in a smoother transition. This saves on CPU as you only have to calculate the decay factor once instead of three times. See Lag for more details."
+    :auto-rate true}

    {:name "Ramp",
-    :args [{:name "in", :default 0.0}
-           {:name "lagTime", :default 0.1}]
-    :doc "similar to Lag but with a linear rather than exponential lag, useful for smoothing out control signals"}
+    :args [{:name "in", :default 0.0 :doc "input signal"}
+           {:name "lagTime", :default 0.1 :doc "60 dB lag time in seconds"}]
+    :doc "similar to Lag but with a linear rather than exponential lag, useful for smoothing out control signals"
+    :auto-rate true}

    {:name "LagUD",
-    :args [{:name "in", :default 0.0}
-           {:name "lagTimeU", :default 0.1}
-           {:name "lagTimeD", :default 0.1}]
-    :doc "the same as Lag except that you can supply a different 60 dB time for when the signal goes up, from when the signal goes down"}
+    :args [{:name "in", :default 0.0 :doc "input signal"}
+           {:name "lagTimeU", :default 0.1 :doc "60 dB lag time in seconds for the upgoing signal"}
+           {:name "lagTimeD", :default 0.1 :doc "60 dB lag time in seconds for the downgoing signal"}]
+    :doc "the same as Lag except that you can supply a different 60 dB time for when the signal goes up, from when the signal goes down"
+    :auto-rate true}

    {:name "Lag2UD",
-    :args [{:name "in", :default 0.0}
-           {:name "lagTimeU", :default 0.1}
-           {:name "lagTimeD", :default 0.1}]
-    :doc "Lag2 is equivalent to Lag.kr(Lag.kr(in, time), time)"}
+    :args [{:name "in", :default 0.0 :doc "input signal"}
+           {:name "lagTimeU", :default 0.1 :doc "60 dB lag time in seconds for the upgoing signal"}
+           {:name "lagTimeD", :default 0.1 :doc "60 dB lag time in seconds for the downgoing signal"}]
+    :doc "Lag2 is equivalent to Lag.kr(Lag.kr(in, time), time)"
+    :auto-rate true}

    {:name "Lag3UD",
-    :args [{:name "in", :default 0.0}
-           {:name "lagTimeU", :default 0.1}
-           {:name "lagTimeD", :default 0.1}]
-    :doc "Lag3UD is equivalent to LagUD.kr(LagUD.kr(LagUD.kr(in, timeU, timeD), timeU, timeD), timeU, timeD)"}
+    :args [{:name "in", :default 0.0 :doc "input signal"}
+           {:name "lagTimeU", :default 0.1 :doc "60 dB lag time in seconds for the upgoing signal"}
+           {:name "lagTimeD", :default 0.1 :doc "60 dB lag time in seconds for the downgoing signal"}]
+    :doc "Lag3UD is equivalent to LagUD.kr(LagUD.kr(LagUD.kr(in, timeU, timeD), timeU, timeD), timeU, timeD)"
+    :auto-rate true}

    {:name "LeakDC",
-    :args [{:name "in", :default 0.0}
-           {:name "coef", :default 0.995}]
-    :doc "removes a DC offset from signal"}
+    :args [{:name "in", :default 0.0 :doc "input signal"}
+           {:name "coef", :default 0.995 :doc "leak coefficient. Good starting point values are to 0.995 for audiorate and  0.9 for controlrate"}]
+    :doc "removes a DC offset from signal"
+    :auto-rate true}

    {:name "RLPF"
-    :args [{:name "in", :default 0.0}
-           {:name "freq", :default 440.0}
-           {:name "rq", :default 1.0}]
-    :doc "a resonant low pass filter"}
-
-   {:name "RHPF", :args [{:name "in", :default 0.0}
-                         {:name "freq", :default 440.0}
-                         {:name "rq", :default 1.0}]
-    :doc "a resonant high pass filter"}
+    :args [{:name "in", :default 0.0 :doc "input signal to be processed"}
+           {:name "freq", :default 440.0 :doc "cutoff frequency"}
+           {:name "rq", :default 1.0 :doc "the reciprocal of Q.  bandwidth / cutoffFreq"}]
+    :doc "a resonant low pass filter"
+    :auto-rate true}
+
+   {:name "RHPF", :args [{:name "in", :default 0.0 :doc "input signal to be processed"}
+                         {:name "freq", :default 440.0 :doc "cutoff frequency"}
+                         {:name "rq", :default 1.0 :doc "the reciprocal of Q.  bandwidth / cutoffFreq"}]
+    :doc "a resonant high pass filter"
+    :auto-rate true}

    {:name "LPF",
-    :args [{:name "in", :default 0.0}
-           {:name "freq", :default 440.0}]
-    :doc "a second order Butterworth low pass filter"}
+    :args [{:name "in", :default 0.0 :doc "input signal to be processed"}
+           {:name "freq", :default 440.0 :doc "cutoff frequency"}]
+    :doc "a second order Butterworth low pass filter"
+    :auto-rate true}

    {:name "HPF",
-    :args [{:name "in", :default 0.0}
-           {:name "freq", :default 440.0}]
-    :doc "a second order high pass filter"}
+    :args [{:name "in", :default 0.0 :doc "input signal to be processed"}
+           {:name "freq", :default 440.0 :doc "cutoff frequency"}]
+    :doc "a second order high pass filter"
+    :auto-rate true}

    {:name "BPF",
-    :args [{:name "in", :default 0.0}
-           {:name "freq", :default 440.0}
-           {:name "rq", :default 1.0}]
-    :doc "a second order Butterworth bandpass filter"}
+    :args [{:name "in", :default 0.0 :doc "input signal to be processed"}
+           {:name "freq", :default 440.0 :doc "centre frequency in Hertz"}
+           {:name "rq", :default 1.0 :doc "the reciprocal of Q.  bandwidth / cutoffFreq"}]
+    :doc "a second order Butterworth bandpass filter"
+    :auto-rate true}

    {:name "BRF",
-    :args [{:name "in", :default 0.0}
-           {:name "freq", :default 440.0}
-           {:name "rq", :default 1.0}]
-    :doc "a second order lowpass filter"}
+    :args [{:name "in", :default 0.0 :doc "input signal to be processed"}
+           {:name "freq", :default 440.0 :doc "centre frequency in Hertz"}
+           {:name "rq", :default 1.0 :doc "the reciprocal of Q.  bandwidth / cutoffFreq"}]
+    :doc "a second order lowpass filter"
+    :auto-rate true}

    {:name "MidEQ",
-    :args [{:name "in", :default 0.0}
-           {:name "freq", :default 440.0}
-           {:name "rq", :default 1.0}
-           {:name "db", :default 0.0}]
-    :doc "attenuates or boosts a frequency band"}
+    :args [{:name "in", :default 0.0 :doc "input signal to be processed"}
+           {:name "freq", :default 440.0 :doc "center frequency of the band in Hertz"}
+           {:name "rq", :default 1.0 :doc "the reciprocal of Q.  bandwidth / cutoffFreq"}
+           {:name "db", :default 0.0 :doc "amount of boost (db > 0) or attenuation (db < 0) of the frequency band"}]
+    :doc "attenuates or boosts a frequency band"
+    :auto-rate true}

    {:name "LPZ1", :args [{:name "in", :default 0.0}]
-    :doc "two point average filter"}
+    :doc "two point average filter. Implements the formula: out(i) = 0.5 * (in(i) + in(i-1))"
+    :auto-rate true}

    {:name "LPZ2", :args [{:name "in", :default 0.0}]
-    :doc "two zero fixed lowpass"}
+    :doc "two zero fixed lowpass. Implements the formula: out(i) = 0.25 * (in(i) + (2*in(i-1)) + in(i-2))"
+    :auto-rate true}

    {:name "HPZ1", :args [{:name "in", :default 0.0}]
-    :doc "two point difference filter"}
+    :doc "two point difference filter. Implements the formula: out(i) = 0.5 * (in(i) - in(i-1))"
+    :auto-rate true}

    {:name "HPZ2", :args [{:name "in", :default 0.0}]
-    :doc "two zero fixed highpass"}
-
-   {:name "Slope", :args [{:name "in", :default 0.0}]
-    :doc ""}
+    :doc "two zero fixed highpass. Implements the formula: out(i) = 0.25 * (in(i) - (2*in(i-1)) + in(i-2))"
+    :auto-rate true}
+
+   {:name "Slope", :args [{:name "in", :default 0.0 :doc "input signal to measure"}]
+    :doc "Measures the rate of change per second of a signal. Formula implemented is: out[i] = (in[i] - in[i-1]) * sampling_rate"
+    :auto-rate true}

    {:name "BPZ2", :args [{:name "in", :default 0.0}]
-    :doc "two zero fixed midpass"}
+    :doc "two zero fixed midpass which cuts out 0 Hz and the Nyquist frequency. Implements the formula: out(i) = 0.5 * (in(i) - in(i-2))"
+    :auto-rate true}

    {:name "BRZ2", :args [{:name "in", :default 0.0}]
-    :doc "two zero fixed midcut"}
+    :doc "two zero fixed midcut which cuts out frequencies around 1/2 of the Nyquist frequency. Implements the formula: out(i) = 0.5 * (in(i) + in(i-2))"
+    :auto-rate true}

    ;; Median : Filter {
    ;; 	*ar { arg length=3, in = 0.0, mul = 1.0, add = 0.0;
@@ -182,44 +213,51 @@
    ;; }

    {:name "Median",
-    :args [{:name "length", :default 3.0}
-           {:name "in", :default 0.0}]
-    :doc "returns the median of the last length input points"}
+    :args [{:name "length", :default 3.0 :doc "number of input points in which to find the median. Must be an odd number from 1 to 31. If length is 1 then Median has no effect."}
+           {:name "in", :default 0.0 :doc "Input signal to be processed"}]
+    :doc "returns the median of the last length input points. This non linear filter is good at reducing impulse noise  from a signal."
+    :auto-rate true}

    {:name "Slew",
-    :args [{:name "in", :default 0.0}
-           {:name "up", :default 1.0}
-           {:name "dn", :default 1.0}]
-    :doc "Smooth the curve by limiting the slope of the input signal to up and dn"}
+    :args [{:name "in", :default 0.0 :doc "input signal"}
+           {:name "up", :default 1.0 :doc "maximum upward slope"}
+           {:name "dn", :default 1.0 :doc "maximum downward slope"}]
+    :doc "Smooth the curve by limiting the slope of the input signal to up and dn"
+    :auto-rate true}

    {:name "FOS",
-    :args [{:name "in", :default 0.0}
-           {:name "a0", :default 0.0}
-           {:name "a1", :default 0.0}
-           {:name "b1", :default 0.0}]
-    :doc "first order filter section"}
+    :args [{:name "in", :default 0.0 :doc "input signal"}
+           {:name "a0", :default 0.0 :doc "first coefficient"}
+           {:name "a1", :default 0.0 :doc "second coefficient"}
+           {:name "b1", :default 0.0 :doc "third coefficient"}]
+    :doc "first order filter section. Formula is equivalent to: out(i) = (a0 * in(i)) + (a1 * in(i-1)) + (b1 * out(i-1))"
+    :auto-rate true}

    {:name "SOS",
-    :args [{:name "in", :default 0.0}
-           {:name "a0", :default 0.0}
-           {:name "a1", :default 0.0}
-           {:name "a2", :default 0.0}
-           {:name "b1", :default 0.0}
-           {:name "b2", :default 0.0}]
-    :doc "second order filter section (biquad)"}
+    :args [{:name "in", :default 0.0 :doc "input signal"}
+           {:name "a0", :default 0.0 :doc "1st coefficient"}
+           {:name "a1", :default 0.0 :doc "2nd coefficient"}
+           {:name "a2", :default 0.0 :doc "3rd coefficient"}
+           {:name "b1", :default 0.0 :doc "4th coefficient"}
+           {:name "b2", :default 0.0 :doc "5th coefficient"}]
+    :doc "second order filter section (biquad). Formula is equivalent to: out(i) = (a0 * in(i)) + (a1 * in(i-1)) + (a2 * in(i-2)) + (b1 * out(i-1)) + (b2 * out(i-2))"
+    :auto-rate true}

    {:name "Ringz",
-    :args [{:name "in", :default 0.0}
-           {:name "freq", :default 440.0}
-           {:name "decaytime", :default 1.0}]
-    :doc "Ringz is the same as Resonz, except that instead of a resonance parameter, the bandwidth is specified in a 60dB ring decay time"}
+    :args [{:name "in", :default 0.0 :doc "input signal to be processed"}
+           {:name "freq", :default 440.0 :doc "resonant frequency in Hertz"}
+           {:name "decaytime", :default 1.0 :doc "the 60 dB decay time of the filter"}]
+    :doc "Ringz is the same as Resonz, except that instead of a resonance parameter, the bandwidth is specified in a 60dB ring decay time. One Ringz is equivalent to one component of the Klank UGen"
+    :auto-rate true}

    {:name "Formlet",
-    :args [{:name "in", :default 0.0}
-           {:name "freq", :default 440.0}
-           {:name "attacktime", :default 1.0}
-           {:name "decaytime", :default 1.0}]
-    :doc "a resonant filter whose impulse response is like that of a sine wave with a Decay2 envelope over it"}])
+    :args [{:name "in", :default 0.0 :doc "input signal to be processed"}
+           {:name "freq", :default 440.0 :doc "resonant frequency in Hertz"}
+           {:name "attacktime", :default 1.0 :doc "60 dB attack time in seconds"}
+           {:name "decaytime", :default 1.0 :doc "60 dB decay time in seconds"}]
+    :doc "a resonant filter whose impulse response is like that of a sine wave with a Decay2 envelope over it. The great advantage to this filter over FOF is that there is no limit to the number of overlapping
+grains since the grain is just the impulse response of the filter. Note that if attacktime == decaytime then the signal cancels out and if attacktime > decaytime then the impulse response is inverted."
+    :auto-rate true}])

 ;; // the doneAction arg lets you cause the EnvGen to stop or end the
 ;; // synth without having to use a PauseSelfWhenDone or FreeSelfWhenDone ugen.
@@ -246,12 +284,14 @@

 (def detect-silence
   {:name "DetectSilence",
-   :args [{:name "in", :default 0.0}
-          {:name "amp", :default 0.0001}
-          {:name "time", :default 0.1}
+   :args [{:name "in", :default 0.0 :doc "any source"}
+          {:name "amp", :default 0.0001 :doc "when input falls below this, evaluate doneAction"}
+          {:name "time", :default 0.1 :doc "the minimum duration of the for which input must fall below thresh before this triggers. The default is 0.1 seconds"}
           {:name "action", :default 0 :map DONE-ACTIONS}],
    :num-outs 0
-   :check-inputs same-rate-as-first-input})
+   :check-inputs same-rate-as-first-input
+   :doc "If the signal input starts with silence at the beginning of the synth's duration, then DetectSilence will wait indefinitely until the first sound before starting to monitor for silence. This UGen outputs 1 if silence is detected, otherwise 0."
+   :auto-rate true})

 (def specs
      (conj (map #(assoc % :muladd true


Remove debug message

Remove debug message

--- src/overtone/sc/ugen/fn_gen.clj
+++ src/overtone/sc/ugen/fn_gen.clj
@@ -128,7 +128,6 @@
   and if so unwraps it.# Otherwise applies f directly with args"
   [f]
   (fn [& args]
-    (println "unwrapper: " args)
     (if (and
          (= 1 (count args))
          (not (sc-ugen? (first args)))


call output-directory fn instead of accessing the property on opts in cljs.closure/build

--- src/clj/cljs/closure.clj
+++ src/clj/cljs/closure.clj
@@ -761,7 +761,7 @@
                   (sm/encode merged
                     {:lines (+ (:lineCount sm-json) 2)
                      :file (:file sm-json)
-                     :output-dir (:output-dir opts)
+                     :output-dir (output-directory opts)
                      :relpaths relpaths}))))))
         source)
       (report-failure result))))


Use fs/file as opposed to io/file where appropriate

--- src/clj/mdr2/dtb/xml.clj
+++ src/clj/mdr2/dtb/xml.clj
@@ -120,12 +120,12 @@
   "Update the master smil file of `volume` for `production` in-place
   with the meta data from `production`"
   [production volume]
-  (let [smil (io/file (path/recorded-path production volume) "master.smil")
+  (let [smil (fs/file (path/recorded-path production volume) "master.smil")
         updated (with-open [r (io/reader smil)]
                   (update-meta-data
                    (xml/parse r :support-dtd false)
                    production handle-smil-node))]
-    (let [tmp-file (io/file (fs/create-temp-file {:prefix "mdr2-" :suffix ".smil"}))]
+    (let [tmp-file (fs/file (fs/create-temp-file {:prefix "mdr2-" :suffix ".smil"}))]
       (with-open [w (io/writer tmp-file)]
         (xml/emit updated w :doctype smil-doctype))
       (xml-format! tmp-file smil)
@@ -135,8 +135,8 @@
   "Format all smil files. OBI now produces unformated smil files and
   some old players don't seem to like this"
   [production volume]
-  (let [formatted (io/file "/tmp/formatted.smil")
-        dir (io/file (path/recorded-path production volume))
+  (let [formatted (fs/file "/tmp/formatted.smil")
+        dir (fs/file (path/recorded-path production volume))
         files (->> dir
                    file-seq
                    (filter #(str/ends-with? (.getName %) ".smil")))]
@@ -159,4 +159,4 @@
   touched"
   [production volume]
   (update-mainfest! production volume
-   (io/file (path/encoded-path production volume) path/manifest-member)))
+   (fs/file (path/encoded-path production volume) path/manifest-member)))


Movement now determined by dx (and soon dy)

I think this will mean that we don't need to store the time anymore when
jumping. If we take each iteration of the loop as a frame, the
information needed to determine the characters next position is just the
velocity, which is provided when the user presses a key.

TIL: the `->` macro in clojure DOES take partial functions, but they
need to be in extra brackets:

```
> (defn foo [a b] (+a b))
> (-> 2 (partial 1)) ;; returns the function
> (-> 2 ((partial 1)));; returns 3
```

--- src/cljs/kenny/core.cljs
+++ src/cljs/kenny/core.cljs
@@ -49,6 +49,8 @@

 (def app-state (atom {:text "Hello Chestnut!"
                       :hero {:move false
+                             :dx 0
+                             :dy 0
                              :life 100
                              :position (hero-start-position grid-content)
                              :jump {:time nil :bottom nil}
@@ -76,7 +78,21 @@
      ]
     ))

-(defn current-blocks [position]
+(defn vertical-coord [position]
+  (let [bottom (position :bottom)]
+     (floor (/ bottom 70))
+     ))
+
+(defn horizontal-coords [position]
+  (let [left (position :left)]
+    {
+     :left (floor (/ (+ left 20) 70))
+     :right (floor (/ (+ left 54) 70))
+     }
+
+    ))
+
+(defn blocks [position]
   (let [[left right] (hero-feet-coords position)
         app @app-state]
     [(get-in app (into [:grid] left)) (get-in app (into [:grid] right))]
@@ -115,57 +131,10 @@
   (not= 1 (get-in app (into [:grid] (second (hero-feet-coords (right-1px position))))))
   )

-(defn new-gravity [current-vertical jump-time app]
-  (let [last-bottom (get-in @app [:hero :position :bottom])
-        initial-bottom (get-in @app [:hero :jump :bottom])
-        dt (/ (- (.getTime (js/Date.)) jump-time) 1000)
-        vforce (* 530 dt)
-        gforce (/ (* 1000 dt dt) 2)
-        gv (/ (* 1000 dt) 2)
-        height (+ (- vforce gforce) initial-bottom)
-        ]
-    (if (< height last-bottom)
-      (do
-        (* 70 (quot height 70))
-        )
-      height
-      )
-    )
-  )
-
-(defn gravity [current-vertical jump-time hero]
-  (let [last-bottom (get-in hero [:position :bottom])
-        initial-bottom (get-in hero [:jump :bottom])
-        dt (/ (- (.getTime (js/Date.)) jump-time) 1000)
-        vforce (* 530 dt)
-        gforce (/ (* 1000 dt dt) 2)
-        gv (/ (* 1000 dt) 2)
-        height (+ (- vforce gforce) initial-bottom)
-        ]
-    (console-log (hero :jump))
-    (console-log (hero :position))
-     (console-log (* 70 (quot height 70)))
-    (if (< last-bottom height)
-      (update-in hero [:position :bottom] (fn [_] (* 70 (quot height 70))))
-      (do
-        (update-in hero [:position :bottom] (fn [_] height))
-        (update-in hero [:jump :start] (fn [_] false))
-        )
-      )
-    )
-  )
-
-(defn vertical-position [app]
-  (let [current-vertical (get-in @app [:hero :position :bottom])
-        current-block-no (most-supportive-block (beneath-1px (get-in @app [:hero :position])))]
-    (if-let [jump-time (get-in @app [:hero :jump :start])]
-      (new-gravity current-vertical jump-time app)
-      (if (on-solid-ground? (get-in @app [:hero :position]))
-        current-vertical
-        (- current-vertical 5)
-        )
-      )
-    ))
+
+(defn moving? [hero]
+  (not= 0 (hero :dx))
+  )

 (defn step-class [app]
   (let [left-offset (get-in app [:hero :position :left])]
@@ -174,10 +143,10 @@

 (defn hero-classes [app]
   (let [
-        left-class (when (= :left (get-in app [:hero :move]))
+        left-class (when (> 0 (get-in app [:hero :dx]))
           "left "
           )]
-    (if (get-in app [:hero :move])
+    (if (moving? (app :hero))
       (str "hero " left-class "step-" (step-class app))
       (str "hero " left-class)
       )
@@ -193,69 +162,84 @@

 (defn in-lava [app]
   (let [position (get-in app [:hero :position])]
-    (some #{4} (current-blocks position))
+    (some #{4} (blocks position))
     )
   )

 (defn move-horizontally [hero]
   (let [left-position (get-in hero [:position :left])]
-    (condp = (hero :move)
-      :left (when (can-move :left @app-state)
-              (update-in hero [:position :left] - 5)
-              )
-      :right (when (can-move :left @app-state)
-               (update-in hero [:position :left] + 5)
-               )
+    (if (moving? hero)
+      (update-in hero [:position :left] (fn [old-left] (+ old-left (hero :dx))))
       hero
       )))

+(defn gravity [current-vertical jump-time hero]
+  (let [last-bottom (get-in hero [:position :bottom])
+        initial-bottom (get-in hero [:jump :bottom])
+        dt (/ (- (.getTime (js/Date.)) jump-time) 1000)
+        vforce (* 1000 dt)
+        gforce (/ (* 2000 dt dt) 2)
+        height (+ (- vforce gforce) initial-bottom)
+        ]
+      (update-in hero [:position :bottom] (fn [_] height))
+
+      )
+  )
+
+;; (defn grav [hero]
+;;   (let [vertical-velocity (get-in hero [:vertical-velocity])]
+;;     (if vertical-velocity
+;;       (let [new-hero (update-in hero [:vertical-velocity] (fn [original] (- original 5)))
+;;             new-velocity (get-in new-hero [:vertical-velocity])]
+;;         (update-in (get-in hero [:position :bottom] (fn [original] (+ original new-velocity))))
+;;         )
+;;       hero
+;;       )
+;;     )
+;;   )
+
 (defn move-vertically [hero]
   (let [current-vertical (get-in hero [:position :bottom])
-        current-block-no (most-supportive-block (beneath-1px (get-in hero [:position])))
         jump-time (get-in hero [:jump :start])]
     (if jump-time
       (gravity current-vertical jump-time hero)
-      (if (on-solid-ground? (get-in hero [:position]))
-        hero
-        (update-in hero [:position :bottom] - 5)
-        )
-      )
-    )
-  )
-
-(defn x-move-vertically [hero]
-  (let [current-vertical (get-in hero [:position :bottom])
-        current-block-no (most-supportive-block (beneath-1px (get-in hero [:position])))
-        jump-time (get-in hero [:jump :start])]
-    (if (on-solid-ground? (get-in hero [:position]))
-      (if jump-time
-        (let [new-hero (update-in hero [:position :bottom] (fn [_] (new-gravity current-vertical jump-time app-state)))]
-          (if (< (get-in new-hero [:position :bottom]) -5)
-            (update-in new-hero [:jump :start] (fn [_] nil))
-            new-hero
-            )
-          )
-        hero
-        )
-
-      )
-
-    ;; (if-let [jump-time (get-in hero [:jump :start])]
-    ;;   (update-in hero [:position :bottom] (fn [_] (new-gravity current-vertical jump-time app-state)))
-    ;;   (if (on-solid-ground? (get-in hero [:position]))
-    ;;     hero
-    ;;     (let [new-hero (update-in hero [:position :bottom] - 5)]
-    ;;       (if (< (get-in new-hero [:position :bottom]) current-vertical)
-    ;;         (println "FALLING")
-    ;;         (update-in new-hero [:jump :start] (fn [_] nil))
-    ;;         new-hero
-    ;;         ))
-    ;;     )
-    ;;   )
-    ))
-
-(defn update-hero [app new-hero]
-  (om/update! app [:hero] new-hero))
+      hero
+      )
+    )
+  )
+
+(defn ground-resistance [hero]
+  (let [position (get-in hero [:position])
+        coord-y (vertical-coord position)
+        current-tiles (blocks position)]
+    (if (some #{1} current-tiles)
+      (let [new-hero (update-in hero [:position :bottom] (fn [_] (* (+ 1 coord-y) 70)))]
+        (update-in new-hero [:jump :start] (fn [_] nil)))
+      hero
+      )
+    ))
+
+(defn block-resistance [hero]
+  (let [position (get-in hero [:position])
+        coords-x (horizontal-coords position)
+        current-tiles (blocks position)]
+    (if (some #{1} current-tiles)
+      (condp = (moving? hero)
+        :left (update-in hero [:position :left] (fn [_] (* (+ (coords-x :left) 1) 70)))
+
+        :right (update-in hero [:position :left] (fn [_] (* (- (coords-x :left) 1) 70))))
+      hero
+      )
+    ))
+
+(defn lava-damage [hero]
+  hero)
+
+(defn spike-damage [hero]
+  hero)
+
+(defn off-screen [hero]
+  hero)

 (defn hero [app owner]
   (reify
@@ -265,13 +249,20 @@
         (om/update! app [:game-over] true)
         (go-loop []

-          (let [new-hero (-> (get-in @app [:hero])
-                              move-horizontally
-
-                              move-vertically
-                              ;;(partial update-hero app)
-                              )]
-            ;;(console-log (new-hero :position))
+          (let [original-hero (get-in @app [:hero])
+                new-hero (-> original-hero
+                             move-horizontally
+                             ;; move-vertically
+                             ;; lava-damage
+                             ;; spike-damage
+                             ;; off-screen
+                             ;; ground-resistance
+                             ;; block-resistance
+
+
+                             ;;((partial partial-check original-hero))
+                             )]
+
             ;;(console-log (new-hero :jump))
             (om/update! app [:hero] new-hero)
             )
@@ -345,8 +336,8 @@

 (defn start-moving [e app]
   (condp = (aget e "keyCode")
-    88 (om/update! app [:hero :move] :right)
-    90 (om/update! app [:hero :move] :left)
+    88 (om/update! app [:hero :dx] 5)
+    90 (om/update! app [:hero :dx] -5)
     32 (when (and (on-solid-ground? (get-in @app [:hero :position])) (nil? (get-in @app [:hero :jump :start])))
          (om/update! app [:hero :jump :start] (.getTime (js/Date.)))
          (om/update! app [:hero :jump :bottom] (get-in @app [:hero :position :bottom])))
@@ -356,8 +347,8 @@

 (defn stop-moving [e app]
   (condp = (aget e "keyCode")
-    88 (om/update! app [:hero :move] false)
-    90 (om/update! app [:hero :move] false)
+    88 (om/update! app [:hero :dx] 0)
+    90 (om/update! app [:hero :dx] 0)
     nil
     )
   )


General scene object EDN specs

General scene object EDN specs

--- src/clojure/yaw/spec.clj
+++ src/clojure/yaw/spec.clj
@@ -119,6 +119,11 @@
                                  :params (s/keys :req-un [:params/pos :params/color]
                                                  :opt-un [:params/i])))

+(s/def :scene/light (s/or :ambient :scene/ambient-light
+                          :sun :scene/sun-light
+                          :spot :scene/spot-light
+                          :point :scene/point-light))
+
 ;; (s/conform :scene/ambient-light [:ambient {:color :blue :i 0.3}])
 ;; => {:tag :ambient, :params {:color [:kw :blue], :i 0.3}}

@@ -131,3 +136,23 @@
 ;; (s/conform :scene/point-light [:light :test/point1 {:color [0 1 0] :pos [0 0 2]}])
 ;; => {:tag :light, :id-kw :test/point1, :params {:color [:rgb [0 1 0]], :pos [0 0 2]}}

+;; (s/conform :scene/light [:light :test/point2 {:color :red :pos [0 0 0] :i 0.3}])
+;; => [:point {:tag :light, :id-kw :test/point2, :params {:color [:kw :red], :pos [0 0 0], :i 0.3}}]
+
+;; (s/conform :scene/light [:sun {:dir [0 0 -1] :color :blue}])
+;; => [:sun {:tag :sun, :params {:dir [0 0 -1], :color [:kw :blue]}}]
+
+;; GENERAL
+(s/def :scene/object (s/or :camera :scene/camera
+                           :item :scene/item
+                           :light :scene/light))
+
+;; (s/conform :scene/object [:camera :test/cam {:pos [0 2 -5] :target [0 0 0]}])
+;; => [:camera {:tag :camera, :id-kw :test/cam, :params {:pos [0 2 -5], :target [:vec [0 0 0]]}}]
+
+;; (s/conform :scene/object [:light :test/light {:pos [0 0 1] :color :yellow :i 0.3}])
+;; => [:light [:point {:tag :light, :id-kw :test/light, :params {:pos [0 0 1], :color [:kw :yellow], :i 0.3}}]]
+
+;; (s/conform :scene/object [:item :test/item {:pos [0 0 0] :mesh :mesh/box}])
+;; => [:item {:tag :item, :id-kw :test/item, :params {:pos [0 0 0], :mesh :mesh/box}}]
+


Experiment more with meta-errors

Experiment more with meta-errors

--- src/clojush/evaluate.clj
+++ src/clojush/evaluate.clj
@@ -741,6 +741,16 @@
                          (= e (max p1e p2e)) 2
                          :else 3)))
                 (vec (repeat (count (:errors ind)) 3)))
+              #_(if (:parent1-errors ind)
+                (vec (for [[e p1e] (mapv #(vector %1 %2)
+                                         (:errors ind)
+                                         (:parent1-errors ind))]
+                       (cond
+                         (zero? e) 0
+                         (< e p1e) 1
+                         (= e p1e) 2
+                         :else 3)))
+                (vec (repeat (count (:errors ind)) 3)))
               (if (:parent1-errors ind)
                 (vec (for [[e p1e] (mapv #(vector %1 %2)
                                          (:errors ind)
@@ -748,9 +758,9 @@
                        (cond
                          (zero? e) 0
                          (< e p1e) 1
-                         (= e p1e) 2
-                         :else 3)))
-                (vec (repeat (count (:errors ind)) 3)))
+                         (= e p1e) 3
+                         :else 2)))
+                (vec (repeat (count (:errors ind)) 2)))
               ;
               (= cat :error-neglect)
               #_(if (and (:parent1-errors ind) (:parent2-errors ind))


CMR-183: Updated funciton name

CMR-183: Updated funciton name

--- src/cmr/common/cache.clj
+++ src/cmr/common/cache.clj
@@ -8,7 +8,7 @@
   "The key used to store the general cache in the system cache map."
   :general)

-(defn cache-from-context
+(defn cache->context
   "Get the cache for the given key from the context"
   [context cache-key]
   (get-in context [:system :caches cache-key]))


Update words.clj

Update words.clj

--- src/iyye/bios/words.clj
+++ src/iyye/bios/words.clj
@@ -52,11 +52,27 @@
               (ioframes/process-output IO (str "Can't set " name " to " value))))
         (ioframes/process-output IO (str "failed to parse: too many matched setters to " name))))))

+(defn shutdown-func [IO arg]
+  (ioframes/process-output IO (str "Shutting down!"))
+  (task/shutdown))
+
+(defn pause-func [IO arg]
+  (task/pause)
+  (ioframes/process-output IO (str "Paused")))
+
+(defn resume-func [IO arg]
+  (task/resume)
+  (ioframes/process-output IO (str "Resumed")))
+
 (def get-action (action-word. "get" getter-func nil))
 (def set-action (action-word. "set" setter-func nil))
+(def shutdown-action (action-word. "shutdown" shutdown-func nil))
+(def pause-action (action-word. "pause" pause-func nil))
+(def resume-action (action-word. "resume" resume-func nil))
+

 ; FIXME to add runtime configuring
-(def action-words (ref (list get-action set-action)))
+(def action-words (ref (list get-action set-action shutdown-action pause-action resume-action)))

 (defn action [cmd params IO]
   (let [actions


Separating File I/O from music generation

--- src/aeolian/core.clj
+++ src/aeolian/core.clj
@@ -1,31 +1,8 @@
 (ns aeolian.core
 	(:require [aeolian.parser :as parser]
 						[aeolian.tempo :as tempo]
+						[aeolian.composer :as composer]
 						[clojure.java.io :as io]))
-
-(def c-major-notes ["C" "E" "G" "B" "z" "c" "e" "g" "b" "z" "c'" "e'" "g'" "b'" "z"])
-(def c-major-chords ["\"C\"" "\"F\"" "\"G\"" "\"Am\""])
-(def c-major-root "\"Am\"")
-(def drum-beat "%%MIDI program 0\n%%MIDI drum zd 60\n%%MIDI drumon\n%%MIDI gchord c")
-(def header (str "X:1\nT:Hello World\nM:4/4\nL:1/4\nK:C\n" drum-beat "\n" tempo/abc-template tempo/default-tempo "\n"))
-
-
-(defn- metric-to-note-index [metric]
-	(mod (parser/line-length-from-metric metric) (count c-major-notes)))
-
-(defn- metric-to-note [metric]
-	(let [complexity (parser/complexity-from-metric metric)
-				note (nth c-major-notes (metric-to-note-index metric))]
-		(cond (> complexity 1)
-			(str "\n" (tempo/as-abc complexity) "\n" note)
-			; note
-			:else note)))
-
-(defn- generate-notation [notes-per-measure line-metrics notation-file-name]
-	(let [mapped-notes (map #(metric-to-note %1) line-metrics)
-		notes-in-measures (apply str (flatten (interpose (str "|\n" c-major-root) (partition notes-per-measure mapped-notes))))
-		completed-score (str header "|" c-major-root notes-in-measures "|") ]
-		(spit notation-file-name, completed-score) ) )

 (defn notation-file-name [original-file-name]
 	(str original-file-name ".abc"))
@@ -34,7 +11,7 @@
 	; (println (str "Generating ABC Notation from " metrics-file-name "..."))
 	(with-open [rdr (clojure.java.io/reader metrics-file-name)]
      (let [notation-file-name (notation-file-name metrics-file-name)
-     		_ (generate-notation 4 (line-seq rdr) notation-file-name)]
+     		_ (composer/compose 4 (line-seq rdr) notation-file-name)]
      		(println (str "Generated " notation-file-name))))
 	)


Replace throw with an assert

Replace throw with an assert

--- src/play_clj/core_graphics.clj
+++ src/play_clj/core_graphics.clj
@@ -64,10 +64,8 @@
            :y 10
            :angle 45)"
   [type & options]
-  (when (seq (clojure.set/intersection #{:begin :end} (set options)))
-    (-> "No need to call :begin or :end, because it's done for you."
-        Throwable.
-        throw))
+  (assert (empty? (clojure.set/intersection #{:begin :end} (set options)))
+          "No need to call :begin or :end, because it's done for you.")
   `(let [entity# ~(if (keyword? type)
                     `(assoc (shape*) :type (shape-type ~type))
                     type)


Added support for log namespaces.

Added support for log namespaces.

--- src/dragon/config.clj
+++ src/dragon/config.clj
@@ -26,3 +26,7 @@
 (defn log-level
   []
   (:log-level (cli)))
+
+(defn log-ns
+  []
+  (:log-ns (cli)))


No errors. Balance is acheived.

No errors. Balance is acheived.

--- src/random_access_map/core.clj
+++ src/random_access_map/core.clj
@@ -18,10 +18,10 @@
 (defn color
   "Gets the color of a tree node."
   [tree]
-  (match tree
-         [color _ _ _] color
-         :black-leaf :black
-         :double-black-leaf :double-black))
+  (match [tree]
+         [[color _ _ _]] color
+         [:black-leaf] :black
+         [:double-black-leaf] :double-black))

 (defn ltree
   "Gets the left tree of a tree node."
@@ -124,12 +124,12 @@

 (defn- bubble
   "Suds and bath water!"
-  [color left elem right]
+  [c l e r]
   (if
-      (or (= (color left) :double-black)
-          (= (color right) :double-black))
-    (balance [(incblack color) (lighten left) elem (lighten right)])
-    [color left elem right]))
+      (or (= (color l) :double-black)
+          (= (color r) :double-black))
+    (balance [(incblack c) (lighten l) e (lighten r)])
+    [c l e r]))

 (declare remove-raw)
 (defn remove-max


added sets for opening/closing brackets

added sets for opening/closing brackets

--- exercises/bracket-push/src/example.clj
+++ exercises/bracket-push/src/example.clj
@@ -1,11 +1,13 @@
 (ns bracket-push)

 (defn valid? [s]
-  (let [pairs { \) \( \] \[ \} \{ }]
+  (let [pairs { \) \( \] \[ \} \{ }
+        opening (set (vals pairs))
+        closing (set (keys pairs))]
     (loop [stack [] [x & xs :as s] s]
       (cond (empty? s) (empty? stack)
-            (#{ \( \[ \{ } x) (recur (conj stack x) xs)
-            (#{ \) \] \} } x) (if (= (peek stack) (pairs x))
-                                (recur (pop stack) xs)
-                                false)
+            (opening x) (recur (conj stack x) xs)
+            (closing x) (if (= (peek stack) (pairs x))
+                          (recur (pop stack) xs)
+                          false)
             :else (recur stack xs)))))


put sincerely in customers section

put sincerely in customers section


set the scrollbar width for the navbar

set the scrollbar width for the navbar

--- frontend/components/landing_b.cljs
+++ frontend/components/landing_b.cljs
@@ -1,6 +1,7 @@
 (ns frontend.components.landing-b
   (:require [cljs.core.async :as async :refer [>! <! alts! chan sliding-buffer close!]]
             [clojure.string :as str]
+            [dommy.core :as dommy]
             [frontend.async :refer [put!]]
             [frontend.components.common :as common]
             [frontend.components.crumbs :as crumbs]
@@ -13,12 +14,13 @@
             [frontend.utils.github :refer [auth-url]]
             [goog.events]
             [goog.dom]
+            [goog.style]
             [om.core :as om :include-macros true]
             [om.dom :as dom :include-macros true]
             [sablono.core :as html :refer-macros [html]])
   (:require-macros [frontend.utils :refer [defrender]]
                    [cljs.core.async.macros :as am :refer [go go-loop alt!]]
-                   [dommy.macros :refer [sel1]]))
+                   [dommy.macros :refer [sel1 node]]))

 (defn mount-header-logo-scroll [owner]
   (let [logo (om/get-node owner "center-logo")
@@ -45,9 +47,20 @@
                     "scroll"
                     scroll-callback))))

+(defn calculate-scrollbar-width
+  "Inserts and removes an out-of-view element to let us calculate the width of the scrollbar"
+  [owner]
+  (let [el (node [:div {:style "width: 100px; height: 100px; overflow: scroll; position: fixed; top: -200px"}])]
+    (dommy/append! (om/get-node owner) el)
+    (om/set-state! owner [:scrollbar-width] (utils/inspect (- (.-offsetWidth el) (.-clientWidth el))))
+    (dommy/remove! el)))
+
 (defn home [app owner]
   (reify
-    om/IDidMount (did-mount [_] (mount-header-logo-scroll owner))
+    om/IDidMount
+    (did-mount [_]
+      (mount-header-logo-scroll owner)
+      (calculate-scrollbar-width owner))
     om/IInitState
     (init-state [_]
       {:header-logo-visible false
@@ -57,13 +70,16 @@
        :header-bkg-invisible false
        :first-fig-animate false
        :first-fig-visible false
+       :scrollbar-width 0
        :scroll-ch (chan (sliding-buffer 1))})
     om/IRenderState
     (render-state [_ state]
       (let [ab-tests (:ab-tests app)
             controls-ch (om/get-shared owner [:comms :controls])]
         (html [:div.home.page
-               [:nav.home-nav {:style (merge {}
+               [:nav.home-nav {:style (merge {:width (if (< 0 (:scrollbar-width state))
+                                                       (str "calc(100% - " (:scrollbar-width state) "px)")
+                                                       "100%")}
                                              (when (> 70 (:header-bkg-scroller state))
                                                {:background-size (str "100% " (:header-bkg-scroller state) "px")}))
                                :class (concat


Fix dead links.

Fix dead links.

--- frontend/components/pricing-b.cljs
+++ frontend/components/pricing-b.cljs
@@ -62,7 +62,7 @@
              [:article
               [:h1 "Transparent pricing, built to scale."]
               [:h3 "The first container is free and each additional one is $50/mo. "
-                   [:a "Need enterprise pricing?"]]]
+                   [:a {:href "/enterprise"} "Need enterprise pricing?" ]]]
              [:div.pricing-calculator
               [:div.pricing-calculator-controls
                [:div.controls-containers
@@ -115,7 +115,9 @@
                 [:div.value (if (> total-cost 0)
                               (str "$" total-cost)
                               "Free")]]
-               [:a.pricing-action {:role "button"} "Sign Up Free"]]]
+               [:a.pricing-action {:href (auth-url)
+                                   :on-click #(raise! owner [:track-external-link-clicked {:path (auth-url) :event "Auth GitHub" :properties {:source "pricing page sign-up" :url js/window.location.pathname}}])
+                                   :title "Sign up with Github"} "Sign Up Free"]]]
              [:article.pricing-features
               [:div.pricing-feature
                [:h3 "Easy Debugging"]


Add missing event for select object matched by selrect.

--- frontend/uxbox/data/workspace.cljs
+++ frontend/uxbox/data/workspace.cljs
@@ -84,6 +84,41 @@
           (update-in state [:workspace :selected] disj id)
           (update-in state [:workspace :selected] conj id))))))

+(defn contained-in-selrect?
+  [shape selrect]
+  (let [sx1 (:x selrect)
+        sx2 (+ sx1 (:width selrect))
+        sy1 (:y selrect)
+        sy2 (+ sy1 (:height selrect))
+        rx1 (:x shape)
+        rx2 (+ rx1 (:width shape))
+        ry1 (:y shape)
+        ry2 (+ ry1 (:height shape))]
+    (and (neg? (- (:y selrect) (:y shape)))
+         (neg? (- (:x selrect) (:x shape)))
+         (pos? (- (+ (:y selrect)
+                     (:height selrect))
+                  (+ (:y shape)
+                     (:height shape))))
+         (pos? (- (+ (:x selrect)
+                     (:width selrect))
+                  (+ (:x shape)
+                     (:width shape)))))))
+
+(defn select-shapes
+  "Select shapes that matches the select rect."
+  [selrect]
+  (reify
+    rs/UpdateEvent
+    (-apply-update [_ state]
+      (println "select-shapes" selrect)
+      (let [pid (get-in state [:workspace :page])
+            shapes (->> (vals (:shapes-by-id state))
+                        (filter #(= (:page %) pid))
+                        (filter #(contained-in-selrect? % selrect))
+                        (map :id))]
+        (assoc-in state [:workspace :selected] (into #{} shapes))))))
+
 (defn deselect-all
   "Mark a shape selected for drawing in the canvas."
   []


get rid of unnecessary imports

get rid of unnecessary imports

--- src/duratom/utils.clj
+++ src/duratom/utils.clj
@@ -1,8 +1,7 @@
 (ns duratom.utils
   (:require [clojure.java.io :as jio]
-            [clojure.edn :as edn]
-            [clojure.java.io :as io])
-  (:import (java.io PushbackReader BufferedWriter DataOutputStream DataInputStream)
+            [clojure.edn :as edn])
+  (:import (java.io PushbackReader BufferedWriter)
            (java.nio.file StandardCopyOption Files)
            (java.util.concurrent.locks Lock)
            (java.util.concurrent.atomic AtomicBoolean)


Remove println

Remove println

--- src/edge/examples.clj
+++ src/edge/examples.clj
@@ -141,7 +141,6 @@
               :password String}}
       :response
       (fn [ctx]
-        (println "response!" (-> ctx :parameters :form))
         (let [{:keys [user password]} (-> ctx :parameters :form)]
           (merge
            (:response ctx)


Define types and specs in one uniform interface (a spec is now a composition of types).

--- src/bytebuf/spec.clj
+++ src/bytebuf/spec.clj
@@ -1,15 +1,15 @@
 (ns bytebuf.spec
   (:refer-clojure :exclude [type read])
-  (:require [bytebuf.types :as types]
-            [bytebuf.proto :as proto :refer [IStaticSize]]
-            [bytebuf.buffer :as buffer]))
+  (:require [bytebuf.proto :as proto :refer [IStaticSize]]
+            [bytebuf.buffer :as buffer])
+  (:import java.util.Arrays))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Abstraction definition
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-;; (defprotocol ISpec
-;;   (type [_] "Get the type of spec."))
+(defprotocol ISpecType
+  (tag [_] "Get the type tag."))

 (defprotocol IReadableSpec
   (read [_ buff start] "Read all data from buffer."))
@@ -17,72 +17,164 @@
 (defprotocol IWritableSpec
   (write [_ buff start data] "Read all data from buffer."))

-;; (defprotocol IAssocReadableSpec
-;;   (read-field [_ buff field] "Read one concrete field from buffer."))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Spec Constructors
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-;; (defprotocol IAssocWritableSpec
-;;   (write-field [_ buff field data] "Read one concrete field from buffer."))
+(defmulti spec
+  (fn [& params]
+    (let [numparams (count params)]
+      (cond
+        (and (even? numparams)
+             (keyword? (first params))
+             (satisfies? ISpecType (second params)))
+        :associative
+
+        (every? #(satisfies? ISpecType %) params)
+        :indexed))))
+
+(defmethod spec :associative
+  [& params]
+  (let [data (mapv vec (partition 2 params))
+        dict (into {} data)
+        types (map second data)]
+    (reify
+      clojure.lang.Counted
+      (count [_]
+        (count types))
+
+      ISpecType
+      (tag [_] :static)
+
+      IStaticSize
+      (size [_]
+        (reduce #(+ %1 (proto/size %2)) 0 types))
+
+      IReadableSpec
+      (read [_ buff pos]
+        (loop [index pos result {} pairs data]
+          (if-let [[fieldname type] (first pairs)]
+            (let [[readeddata readedbytes] (read type buff index)]
+              (recur (+ index readedbytes)
+                     (assoc result fieldname readeddata)
+                     (rest pairs)))
+            [(- index pos) result])))
+
+      IWritableSpec
+      (write [_ buff pos data']
+        (let [written (reduce (fn [index [fieldname type]]
+                                (let [value (get data' fieldname nil)
+                                      written (write type buff index value)]
+                                  (+ index written)))
+                              pos data)]
+          (- written pos))))))
+
+(defmethod spec :indexed
+  [& types]
+  (reify
+    clojure.lang.Counted
+    (count [_]
+      (count types))
+
+    ISpecType
+    (tag [_] :static)
+
+    IStaticSize
+    (size [_]
+      (reduce #(+ %1 (proto/size %2)) 0 types))
+
+      IReadableSpec
+      (read [_ buff pos]
+        (loop [index pos result [] types types]
+          (if-let [type (first types)]
+            (let [[readeddata readedbytes] (read type buff index)]
+              (recur (+ index readedbytes)
+                     (conj result readeddata)
+                     (rest types)))
+            [(- index pos) result])))
+
+      IWritableSpec
+      (write [_ buff pos data']
+        (let [indexedtypes (map-indexed vector types)
+              written (reduce (fn [pos [index type]]
+                                (let [value (nth data' index nil)
+                                      written (write type buff pos value)]
+                                  (+ pos written)))
+                              pos indexedtypes)]
+          (- written pos)))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Types implementation
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-(defn associative-static-spec
-  [data dict types]
-  (reify
-    clojure.lang.Counted
-    (count [_]
-      (count types))
+(defn int32
+  "Create a int32 indexed data type."
+  ([] (int32 0))
+  ([default]
+   (reify
+     ISpecType
+     (tag [_] :static)
+
+     IReadableSpec
+     (read [_ buff pos]
+       [(buffer/read-int buff pos)
+        (Integer/BYTES)])
+
+     IWritableSpec
+     (write [_ buff pos value]
+       (let [value (or value default)]
+         (buffer/write-int buff pos value)
+         (Integer/BYTES)))

     IStaticSize
     (size [_]
-      (reduce #(+ %1 (types/size %2)) 0 types))
+      (Integer/BYTES)))))

-    IReadableSpec
-    (read [_ buff offset]
-      (loop [index offset result {} pairs data]
-        (if-let [[fieldname type] (first pairs)]
-          (let [[readeddata readedbytes] (types/read type buff index)]
-            (recur (+ index readedbytes)
-                   (assoc result fieldname readeddata)
-                   (rest pairs)))
-          [(- index offset) result])))
+(defn int64
+  "Create a int64 indexed data type."
+  ([] (int64 0))
+  ([default]
+   (reify
+     ISpecType
+     (tag [_] :static)

-    IWritableSpec
-    (write [_ buff offset data']
-      (let [written (reduce (fn [index [fieldname type]]
-                              (let [value (get data' fieldname nil)
-                                    written (types/write type buff index value)]
-                                (+ index written)))
-                            offset data)]
-        (- written offset)))))
+     IReadableSpec
+     (read [_ buff pos]
+       [(buffer/read-long buff pos)
+        (Long/BYTES)])

-    ;; IAssocReadableSpec
-    ;; (read-field [_ buff field]
-    ;;   (let [ftype (get dict field)
-    ;;         startpos (reduce (fn [acc [key val]]
-    ;;                            (if (= key field)
-    ;;                              (reduced acc)
-    ;;                              (+ acc (types/size val))))
-    ;;                          0 data)]
-    ;;     ;; Set the buffer position
-    ;;     (buffer/seek buff startpos)
-    ;;     (types/read ftype buff)))))
+     IWritableSpec
+     (write [_ buff pos value]
+       (let [value (or value default)]
+         (buffer/write-long buff pos value)
+         (Long/BYTES)))

-(defn associative-dynamic-spec
-  [])
+     IStaticSize
+     (size [_]
+       (Long/BYTES)))))

-(defn associative-spec
-  [params]
-  {:pre [(even? (count params))]}
-  (let [data (mapv vec (partition 2 params))
-        dict (into {} data)
-        types (map second data)]
-    (if (every? #(satisfies? types/IStaticType %) types)
-      (associative-static-spec data dict types)
-      (associative-dynamic-spec data dict types))))
+(defn string
+  ([^long size]
+   (reify
+     ISpecType
+     (tag [_] :static)

-(defn spec
-  "Create a new spec instance."
-  [& params]
-  (associative-spec params))
+     IReadableSpec
+     (read [_ buff pos]
+       (let [data (buffer/read-bytes buff pos size)]
+         [(String. data "UTF-8") size]))
+
+     IWritableSpec
+     (write [_ buff pos value]
+       (let [input (.getBytes value "UTF-8")
+             length (count input)
+             tmpbuf (byte-array size)]
+         (System/arraycopy input 0 tmpbuf 0 size)
+         (when (< length size)
+           (Arrays/fill tmpbuf length size (byte 0)))
+
+         (buffer/write-bytes buff pos size tmpbuf)
+         size))
+
+     IStaticSize
+     (size [_] size))))


Bools in tseitin - removed changes

Bools in tseitin - removed changes

--- src/logic/tseitin.clj
+++ src/logic/tseitin.clj
@@ -114,28 +114,7 @@
                                         (filter (complement literal?) (vals gen-map))))]
     {:formula formula
      :lits lits
-     :tseitin-formula (cond  ; care about booleans as own symbols
-                        (and (contains? lits true)
-                          (contains? lits false))
-                        (conj (conj (conj (rest tseitin-formula)
-                                      (list 'or (lits true)))
-                                (list 'or (list 'not (lits 'false))))
-                          'and)
-
-                        (and (contains? lits true)
-                          (not (contains? lits false)))
-                        (conj (conj (rest tseitin-formula)
-                                (list 'or (lits true)))
-                          'and)
-
-                        (and (not (contains? lits true))
-                          (contains? lits false))
-                        (conj (conj (rest tseitin-formula)
-                                (list 'or (list 'not (lits false))))
-                          'and)
-
-                        :else tseitin-formula
-                        )}))
+     :tseitin-formula tseitin-formula}))

 (defn retransform-tseitin
   "Takes a map as produced by transform-tseitin and a solver result and removes all tseitin
@@ -147,13 +126,7 @@
                            lits
                            (if (literal? %) % (second %)))
                  result)]
-    (filter #(cond ; remove booleans
-                           (boolean? %) false
-                           (and (coll? %)
-                             (boolean? (second %))) false
-                           :else true
-                           )
-      (map #(if (seq? %)
-              (list 'not (get subs (second %)))
-              (get subs %))
-        cln-res))))+    (map #(if (seq? %)
+            (list 'not (get subs (second %)))
+            (get subs %))
+      cln-res)))


Remove type-specific builders

Remove type-specific builders

--- src/omnibus/core.clj
+++ src/omnibus/core.clj
@@ -91,62 +91,6 @@
         software-descs (reduce mapper  {}  (load-forms OMNIBUS-SOFTWARE-DIR))]
     (build-software (software-descs software-name))))

-(defn build-deb
-  "Builds a deb"
-  [project-name version iteration os-data]
-  (let [
-        asset-name (str project-name "_" version "-" iteration "_" (if (= (os-data :machine) "x86_64") "amd64" "i386") ".deb")
-        asset-path (.toString (file-str OMNIBUS-PKG-DIR "/" asset-name))
-        status (sh "fpm" "-s" "dir" "-t" "deb" "-v" version "--iteration" iteration "-n" project-name "/opt/opscode" "-m" "Opscode, Inc." "--post-install" (str OMNIBUS-SOURCE-DIR "/postinst") "--post-uninstall" (str OMNIBUS-SOURCE-DIR "/postrm") "--description" "The full stack install of Opscode Chef" "--url" "http://www.opscode.com" :dir "./pkg") ]
-    (log-sh-result status
-                   (do
-                     (put-in-bucket asset-path @*bucket-name* (str (os-data :platform) "-" (os-data :platform_version) "-" (os-data :machine) "/" asset-name) @*s3-access-key* @*s3-secret-key*)
-                     (str "Created debian package"))
-                   (str "Failed to create debian package"))))
-
-(defn build-rpm
-  "Builds a rpm"
-  [project-name version iteration os-data]
-  (let [
-        asset-name (str project-name "-" version "-" iteration "." (os-data :machine) ".rpm")
-        asset-path (.toString (file-str OMNIBUS-PKG-DIR "/" asset-name))
-        status (sh "fpm" "-s" "dir" "-t" "rpm" "-v" version "--iteration" iteration "-n" project-name "/opt/opscode" "-m" "Opscode, Inc." "--post-install" (str OMNIBUS-SOURCE-DIR "/postinst") "--post-uninstall" (str OMNIBUS-SOURCE-DIR "/postrm") "--description" "The full stack install of Opscode Chef" "--url" "http://www.opscode.com" :dir "./pkg")]
-    (log-sh-result status
-                   (do
-                     (put-in-bucket asset-path @*bucket-name* (str (os-data :platform) "-" (os-data :platform_version) "-" (os-data :machine) "/" asset-name) @*s3-access-key* @*s3-secret-key*)
-                     (str "Created rpm package"))
-                   (str "Failed to create rpm package"))))
-
-(defn build-tarball
-  "Builds a tarball of the entire mess"
-  [project-name version iteration os-data]
-  (let [
-        asset-name (str project-name "-" version "-" iteration "-" (os-data :platform) "-" (os-data :platform_version) "-" (os-data :machine) ".tar.gz")
-        asset-path (.toString (file-str OMNIBUS-PKG-DIR "/" asset-name))
-        status (sh "tar" "czf" asset-path "opscode" :dir "/opt")]
-    (log-sh-result status
-                   (do
-                     (put-in-bucket asset-path @*bucket-name* (str (os-data :platform) "-" (os-data :platform_version) "-" (os-data :machine) "/" asset-name) @*s3-access-key* @*s3-secret-key*)
-                     (str "Created tarball package for " project-name " on " (os-data :platform) " " (os-data :platform_version) " " (os-data :machine)))
-                   (str "Failed to create tarball package for " project-name " on " (os-data :os) " " (os-data :machine)))))
-
-(defn build-makeself
-  [project-name version iteration os-data]
-  (let [
-        asset-name (str project-name "-" version "-" iteration "-" (os-data :platform) "-" (os-data :platform_version) "-" (os-data :machine) ".sh")
-        asset-path (.toString (file-str OMNIBUS-PKG-DIR "/" asset-name))
-        status (sh (.toString (file-str OMNIBUS-MAKESELF-DIR "/makeself.sh"))
-                   "--gzip"
-                   "/opt/opscode"
-                   asset-path
-                   (str "'Opscode " project-name " " version "'")
-                   "./setup.sh"
-                   :dir OMNIBUS-HOME-DIR)]
-    (log-sh-result status
-                   (do
-                     (put-in-bucket asset-path @*bucket-name* (str (os-data :platform) "-" (os-data :platform_version) "-" (os-data :machine) "/" asset-name) @*s3-access-key* @*s3-secret-key*)
-                     (str "Created shell archive for " project-name " on " (os-data :platform) " " (os-data :platform_version) " " (os-data :machine)))
-                   (str "Failed to create shell archive for " project-name " on " (os-data :platform) " " (os-data :platform_version) " " (os-data :machine)))))
 (defn fork-on-type
   "Multimethod dispatch function; just returns the first argument."
   [type & _]
@@ -271,22 +215,38 @@
 (defn build-fat-binary
   "Build a fat binary"
   [project-name]
-  (let [mapper #(assoc %1 (%2 :name) %2)
-        software-descs (reduce mapper  {}  (load-forms OMNIBUS-SOFTWARE-DIR))
-        projects  (reduce mapper {} (load-forms OMNIBUS-PROJECTS-DIR))]
-    (do
-      (try
-        (build-project (projects project-name) software-descs)
-        (catch NullPointerException e
-          (do
-            (println (str "Can't find project '" project-name "'!"))
-            (System/exit -2))))
-      (build-tarball project-name ((projects project-name) :version) ((projects project-name) :iteration) os-and-machine)
-      (build-makeself project-name ((projects project-name) :version) ((projects project-name) :iteration) os-and-machine)
-      (if (or (= (os-and-machine :platform) "debian") (= (os-and-machine :platform) "ubuntu"))
-        (build-deb project-name ((projects project-name) :version) ((projects project-name) :iteration) os-and-machine))
-      (if (or (= (os-and-machine :platform) "el") (= (os-and-machine :platform) "fedora"))
-        (build-rpm project-name ((projects project-name) :version) ((projects project-name) :iteration) os-and-machine)))))
+  (let [loader (fn [dir] ; create a map of software-name to DSL recipe form
+                 (reduce (fn [m spec]
+                           (assoc m (:name spec) spec))
+                         {}
+                         (load-forms dir)))
+
+        software-descs (loader OMNIBUS-SOFTWARE-DIR)
+        projects (loader OMNIBUS-PROJECTS-DIR)
+
+        {:keys [version iteration] :as the-project} (get projects project-name)
+        project-spec {:project-name project-name
+                      :version version
+                      :iteration iteration
+                      :os-data (os-and-machine)}
+
+        platform (get-in project-spec [:os-data :platform])]
+
+    (try (build-project the-project software-descs)
+         (catch NullPointerException e
+           (do
+             (println (str "Can't find project '" project-name "'!"))
+             (System/exit -2))))
+
+    ;; Build these always, regardless of platform
+    (doseq [type [::tarball ::makeself]]
+      (build-and-bucket-package type project-spec))
+
+    ;; If we're on a Linux platform, build the appropriate kind of package
+    (cond (contains? #{"debian" "ubuntu"} platform)
+          (build-and-bucket-package ::deb project-spec)
+          (contains? #{"el" "fedora"} platform)
+          (build-and-bucket-package ::rpm project-spec))))

 (defn -main
   "Main entry point when run from command line"


Shutdown agents on app shutdown

Shutdown agents on app shutdown

--- src/exploud/setup.clj
+++ src/exploud/setup.clj
@@ -149,4 +149,5 @@
 (defn -main
   "The entry point for the application."
   [& args]
+  (.addShutdownHook (Runtime/getRuntime) (Thread. #(shutdown-agents)))
   (start))


Rework some index functions.

Rework some index functions.

--- src/merkle_db/index.clj
+++ src/merkle_db/index.clj
@@ -92,7 +92,7 @@
       (->>
         {:data/type data-type
          ::height height
-         ::keys (vec (drop 1 child-keys))
+         ::keys (vec (rest child-keys))
          ::children new-children
          ::record/count record-count
          ::record/first-key (first child-keys)
@@ -110,7 +110,7 @@
     (if (<= (count layer) 1)
       (first layer)
       (let [index-groups (part/partition-limited
-                           (::branching-factor params)
+                           (::branching-factor params default-branching-factor)
                            layer)]
         (recur (mapv (partial store-index! store height) index-groups)
                (inc height))))))
@@ -386,10 +386,7 @@
   "Rewrite a vector of childen into numbered links."
   [children]
   (into []
-        (map-indexed
-          #(mdag/link
-             (format "%03d" %1)
-             (if (mdag/link? %2) %2 (meta %2))))
+        (map-indexed #(mdag/link (format "%03d" %1) %2))
         children))

@@ -400,31 +397,38 @@
   `:merkle-db.data/families`. Returns an updated persisted root node if any
   records remain in the tree."
   [store params root changes]
-  (if (nil? root)
+  (cond
+    ; No changes, return root as-is.
+    (empty? changes)
+      root
+
     ; Empty tree.
-    (->> changes
-         (part/partition-records store params)
-         (from-partitions store params))
-    ; Check root node type.
-    (condp = (:data/type root)
-      part/data-type
-        (if (seq changes)
-          (some->>
-            (part/update-root! store params root changes)
-            (from-partitions store params))
-          root)
-      data-type
-        (letfn [(store!  ; TODO: factor out?
-                  [node]
-                  (if (mdag/link? node)
-                    node
-                    (->> (::children node)
-                         (map store!)
-                         (relink-children)
-                         (assoc node ::children)
-                         (mdag/store-node! store nil)
-                         (::node/data))))]
-          (store! (update-index-node store params nil [root changes])))
+    (nil? root)
+      (->> changes
+           (part/partition-records store params)
+           (from-partitions store params))
+
+    ; Root is a partition node.
+    (= part/data-type (:data/type root))
+      (some->>
+        (part/update-root! store params root changes)
+        (from-partitions store params))
+
+    ; Root is an index node.
+    (= data-type (:data/type root))
+      (letfn [(store!  ; TODO: very similar to `store-index!`
+                [node]
+                (if (mdag/link? node)
+                  node
+                  (->> (::children node)
+                       (map store!)
+                       (relink-children)
+                       (assoc node ::children)
+                       (mdag/store-node! store nil)
+                       (::node/data))))]
+        (store! (update-index-node store params nil [root changes])))
+
+    :else
       (throw (ex-info (str "Unsupported index-tree node type: "
                            (pr-str (:data/type root)))
-                      {:data/type (:data/type root)})))))
+                      {:data/type (:data/type root)}))))


Use core library

Use core library

--- src/cljam/io/wig.clj
+++ src/cljam/io/wig.clj
@@ -80,8 +80,8 @@
   [lines]
   (letfn [(deserialize [lines pre-start current-track]
             (lazy-seq
-             (when (some? (first lines))
-               (let [fields (-> lines first cstr/trim (cstr/split #"\s+"))]
+             (when-first [line lines]
+               (let [fields (-> line cstr/trim (cstr/split #"\s+"))]
                  (case (first fields)
                    ; declaration line of variableStep
                    "variableStep"
@@ -161,9 +161,8 @@
                     (- (:end wig) (:start wig)))))
           (serialize [wigs]
             (lazy-seq
-             (when (some? (first wigs))
-               (let [[track rest-wigs] (split-with (partial same-track?
-                                                            (first wigs))
+             (when-first [wig wigs]
+               (let [[track rest-wigs] (split-with (partial same-track? wig)
                                                    wigs)
                      track (case (-> track first :format)
                              :variable-step
@@ -184,7 +183,7 @@

                              :fixed-step
                              (let [{:keys [chr start end]} (first track)
-                                   step (- (-> track rest first :start) start)
+                                   step (- (-> track second :start) start)
                                    span (inc (- end start))
                                    declaration-line (->> (cond-> ["fixedStep"
                                                                   (str "chrom=" chr)


Run over squished and partitioned wav data. Toying with overlapping window. Might effect other results...

--- src/clojure/core.clj
+++ src/clojure/core.clj
@@ -157,12 +157,18 @@
 (defn peek-inside
   ([sample-path] (peek-inside sample-path DEFAULT_BLOCK_SIZE))
   ([sample-path block-size]
+
    (let [SAMPLE_RATE (sample-rate sample-path)
          half-block-size (/ block-size 2)
          SAMPLE_RATE_RATIO (/ SAMPLE_RATE block-size)

-         s          (sample/read-sound sample-path)
-         data-chunks (sample/chunks s SAMPLE_RATE)
+         s           (ssample/read-sound sample-path block-size)
+         data-chunks (ssample/chunks s SAMPLE_RATE)
+         ;;TODO: Merging channels?
+         ;;with sliding window, overlap
+         data (partition block-size half-block-size (mapcat (fn [bit] bit) (flatten (flatten ch))))         ;;seperate
+         ;;data (partition block-size (mapcat (fn [bit] bit) (flatten (flatten ch))))
+
          mel-filters  (xtract/create_filterbank  MFCC_FREQ_BANDS block-size)

          ;;bark-band-limits (xtract/new_int_array 0)
@@ -177,6 +183,8 @@
                               MFCC_FREQ_BANDS
                               (xtract_mel_filter/.getFilters mel-filters))

+     (xtract/xtract_init_wavelet_f0_state)
+
      ;;public static int xtract_init_bark(int N, double sr, SWIGTYPE_p_int band_limits) {
      ;;(xtract/xtract_init_bark block-size SAMPLERATE bark-band-limits)
      ;;(println (xtract/int_array_getitem bark-band-limits 0))
@@ -184,104 +192,105 @@
      (let [full-window (xtract/xtract_init_window block-size xtract-hann)
            half-window (xtract/xtract_init_window half-block-size xtract-hann)]

-       (xtract/xtract_init_wavelet_f0_state)
-
        (let [stats
              (map-indexed
-              (fn [idx s]
-                (map
-                 (fn [v]
-                   (let [wav-data (clojure->c-double (vec v))
-                         f0       (extract-fundemental-frequency wav-data block-size SAMPLE_RATE)
-                         cents    (frequency->cents f0)
-                         midi     (if (> f0 0.0)
-                                    (Integer/parseInt (format "%.0f" (/ cents 100)))
-                                    0)
-
-                         windowed (c-double block-size)
-                         spectrum (c-double block-size)
-                         peaks    (c-double block-size)]
-
-                     (xtract/xtract_windowed wav-data block-size (xtract/doublea_to_voidp full-window) windowed)
-                     (xtract/xtract_init_fft block-size xtract-spectrum)
-                     (xtract/xtract_spectrum windowed block-size (xtract-args SAMPLE_RATE_RATIO xtract-spectrum-magnitude 0.0 0.0)
-                                             spectrum)
-                     (xtract/xtract_free_fft)
-
-                     (xtract/xtract_peak_spectrum spectrum
-                                                  half-block-size
-                                                  (xtract-args SAMPLE_RATE_RATIO 10.0 0.0 0.0)
-                                                  peaks)
-
-                     (let [rms                   (double-array [0])
-                           spectral-irregularity (double-array [0])
-                           spectral-centroid     (double-array [0])
-                           spectral-variance     (double-array [0])
-
-                           ;;TODO
-                           noiseness             (double-array [0])
-                           loudness              (double-array [0])
-                           tonality              (double-array [0])
-
-                           spectral-inharmonicity (spectral-inharmonicity
-                                                   peaks block-size
-                                                   f0 0.5 NUM_HARMONICS 0)]
-
-                       (xtract/xtract_rms_amplitude wav-data block-size (xtract-args SAMPLE_RATE_RATIO) rms)
-
-                       (xtract/xtract_spectral_centroid spectrum block-size (xtract-args 0.0) spectral-centroid)
-                       (xtract/xtract_irregularity_j    spectrum half-block-size nil spectral-irregularity)
-
-                       (let [spectral-skewness      (double-array [0])
-                             spectral-std-deviation (double-array [0])
-                             spectral-mean          (double-array [0])
-                             spectral-kurtosis      (double-array [0])]
-
-                         (xtract/xtract_spectral_mean spectrum block-size nil spectral-mean)
-                         (xtract/xtract_variance spectrum block-size (xtract-args (first spectral-mean)) spectral-variance)
-                         (xtract/xtract_spectral_standard_deviation spectrum block-size (xtract-args (first spectral-variance)) spectral-std-deviation)
-
-                         (let [argv (xtract-args (first spectral-mean) (first spectral-std-deviation))]
-                           (xtract/xtract_spectral_skewness spectrum block-size argv spectral-skewness)
-                           (xtract/xtract_spectral_kurtosis spectrum block-size argv spectral-kurtosis))
-
-                         ;;(xtract/xtract_noisiness     wav-data block-size (xtract-args NUM_HARMONICS ) noiseness)
-
-                         (let [_ 10
-                               ;;bark-cofficents (clojure->c-double (range 0 xtract-bark-bands))
-                               ]
-
-                           ;;(xtract/xtract_bark_coefficients spectrum half-block-size (xtract-args ) bark-cofficents)
-                           ;;(xtract/xtract_loudness      wav-data block-size (apply xtract-args argv) loudness)
-                           )
-
-                         ;;TODO
-                         ;;(xtract/xtract_tonality      wav-data block-size (xtract-args ) tonality)
-
-                         ;;TODO: More memory, probably slower... Re-using variables faster but sad
-                         (xtract/delete_double_array wav-data)
-                         (xtract/delete_double_array windowed)
-                         (xtract/delete_double_array spectrum)
-                         (xtract/delete_double_array peaks)
-
-                         {(* idx (int SAMPLE_RATE))
-                          {:spectral-inharmonicity spectral-inharmonicity
-                           :spectral-irregularity  (first spectral-irregularity)
-                           :spectral-centroid      (first spectral-centroid)
-                           :spectral-skewness      (first spectral-skewness)
-                           :spectral-kurtosis      (first spectral-kurtosis)
-                           :rms-amplitude          (first rms)
-
-                           :todo {:noisiness (first noiseness)
-                                  :loudness (first loudness)
-                                  :tonality (first tonality)}
-                           :midi midi
-                           :f0 f0}
-                          }))
-                     ;;(println "Magnitude Spectrum: " (pr-str (double->clojure spectrum block-size)))
-                     ))
-                 s))
-              data-chunks)]
+              (fn [idx v]
+
+                (let [wav-data (clojure->c-double v)
+                      f0       (extract-fundemental-frequency wav-data block-size SAMPLE_RATE)
+                      cents    (frequency->cents f0)
+                      midi     (if (> f0 0.0)
+                                 (Integer/parseInt (format "%.0f" (/ cents 100)))
+                                 0)
+
+                      windowed (c-double block-size)
+                      spectrum (c-double block-size)
+                      peaks    (c-double block-size)
+
+                      wa (c-double 1)]
+
+                  ;;(xtract/double_array_setitem wa 0 0.0)
+
+                  (xtract/xtract_windowed wav-data block-size (xtract/doublea_to_voidp full-window) windowed)
+                  (xtract/xtract_init_fft block-size xtract-spectrum)
+                  (xtract/xtract_spectrum windowed block-size (xtract-args SAMPLE_RATE_RATIO xtract-spectrum-magnitude 0.0 0.0)
+                                          spectrum)
+                  (xtract/xtract_free_fft)
+
+                  (xtract/xtract_peak_spectrum spectrum
+                                               half-block-size
+                                               (xtract-args SAMPLE_RATE_RATIO 10.0 0.0 0.0)
+                                               peaks)
+
+                  (let [rms                   (double-array [0])
+                        spectral-irregularity (double-array [0])
+                        spectral-centroid     (double-array [0])
+                        spectral-variance     (double-array [0])
+
+                        ;;TODO
+                        noiseness             (double-array [0])
+                        loudness              (double-array [0])
+                        tonality              (double-array [0])
+
+                        spectral-inharmonicity (spectral-inharmonicity
+                                                peaks block-size
+                                                f0 0.5 NUM_HARMONICS 0)]
+
+                    (xtract/xtract_rms_amplitude wav-data block-size (xtract-args SAMPLE_RATE_RATIO) rms)
+
+                    (xtract/xtract_spectral_centroid spectrum block-size (xtract-args 0.0) spectral-centroid)
+                    (xtract/xtract_irregularity_j    spectrum half-block-size nil spectral-irregularity)
+
+                    (let [spectral-skewness      (double-array [0])
+                          spectral-std-deviation (double-array [0])
+                          spectral-mean          (double-array [0])
+                          spectral-kurtosis      (double-array [0])]
+
+                      (xtract/xtract_spectral_mean spectrum block-size nil spectral-mean)
+                      (xtract/xtract_variance spectrum block-size (xtract-args (first spectral-mean)) spectral-variance)
+                      (xtract/xtract_spectral_standard_deviation spectrum block-size (xtract-args (first spectral-variance)) spectral-std-deviation)
+
+                      (let [argv (xtract-args (first spectral-mean) (first spectral-std-deviation))]
+                        (xtract/xtract_spectral_skewness spectrum block-size argv spectral-skewness)
+                        (xtract/xtract_spectral_kurtosis spectrum block-size argv spectral-kurtosis))
+
+                      ;;(xtract/xtract_noisiness     wav-data block-size (xtract-args NUM_HARMONICS ) noiseness)
+
+                      (let [_ 10
+                            ;;bark-cofficents (clojure->c-double (range 0 xtract-bark-bands))
+                            ]
+
+                        ;;(xtract/xtract_bark_coefficients spectrum half-block-size (xtract-args ) bark-cofficents)
+                        ;;(xtract/xtract_loudness      wav-data block-size (apply xtract-args argv) loudness)
+                        )
+
+                      ;;TODO
+                      ;;(xtract/xtract_tonality      wav-data block-size (xtract-args ) tonality)
+
+                      ;;TODO: More memory, probably slower... Re-using variables faster but sad
+                      (xtract/delete_double_array wav-data)
+                      (xtract/delete_double_array windowed)
+                      (xtract/delete_double_array spectrum)
+                      (xtract/delete_double_array peaks)
+
+                      {
+                       (format "%.6f" (/  (* idx half-block-size) SAMPLE_RATE))
+
+                       {:spectral-inharmonicity spectral-inharmonicity
+                        :spectral-irregularity  (first spectral-irregularity)
+                        :spectral-centroid      (first spectral-centroid)
+                        :spectral-skewness      (first spectral-skewness)
+                        :spectral-kurtosis      (first spectral-kurtosis)
+                        :rms-amplitude          (first rms)
+
+                        :todo {:noisiness (first noiseness)
+                               :loudness (first loudness)
+                               :tonality (first tonality)}
+                        :midi midi
+                        :f0 f0}
+                       }
+                      ))))
+              data)]

          (xtract/xtract_free_window full-window)
          (xtract/xtract_free_window half-window)


fix compile result text for tag

fix compile result text for tag

--- src/misaki/server.clj
+++ src/misaki/server.clj
@@ -72,7 +72,7 @@
         ; compile tag
         (if-let [tags (-> file get-post-options :tag)]
           (doseq [tag tags]
-            (print " * compiling tag:" tag)
+            (print " * compiling tag:" (:name tag))
             (print-result (compile-tag tag))))))))

 ;; ## Template Watcher


update db name

update db name

--- src/clj/battlebots/services/mongodb.clj
+++ src/clj/battlebots/services/mongodb.clj
@@ -1,6 +1,6 @@
 (ns battlebots.services.mongodb
   (:require [monger.core :as mg]))

-(def conn (atom (mg/connect-via-uri "mongodb://127.0.0.1/monger-test")))
+(def conn (atom (mg/connect-via-uri "mongodb://127.0.0.1/battlebots")))

 (defn get-db [] (:db @conn))


Enable polling of stats every 2 seconds and store into vec

--- src/cljs/sidequarter_frontend/core.cljs
+++ src/cljs/sidequarter_frontend/core.cljs
@@ -44,10 +44,45 @@
                    (dom/strong nil "Redis URL: ")
                    (dom/span nil (data :redis_url))))))

+(defn sidekiq-poll-stats [data owner]
+  (reify
+    om/IInitState
+    (init-state [_]
+      {:graph [] :interval-id nil})
+    om/IDidMount
+    (did-mount [_]
+      (let [interval-id
+            (js/setInterval
+             (fn []
+               (go
+                 (let [response ((<! (api/get-stats (data :id))) :body)
+                       stats (:stats response)]
+                   (om/update-state! owner [:graph] #(conj % stats))))
+               ) 2000)]
+        (om/set-state! owner [:interval-id] interval-id)))
+    om/IRenderState
+    (render-state [_ {:keys [graph]}]
+      (.log js/console (pr-str graph))
+      (dom/div #js {:className "col s12"}
+               (dom/h5 nil "Live stats")))
+    om/IWillUnmount
+    (will-unmount [_]
+      (js/clearInterval (om/get-state owner [:interval-id])))))
+
 (defn sidekiq-read-more [data owner]
-  (om/component
-   (dom/a #js {:className "sidekiq-read-more" :id (data :id)}
-          (dom/i #js {:className "material-icons"} "expand_more"))))
+  (reify
+    om/IInitState
+    (init-state [_]
+      {:polling false})
+    om/IRenderState
+    (render-state [_ {:keys [polling]}]
+      (dom/div nil
+               (dom/div #js {:className "col s1"}
+                        (dom/a #js {:onClick (fn [_] (om/set-state! owner :polling (not polling)))}
+                               (dom/i #js {:className "material-icons"} "expand_more")))
+               (if polling
+                 (om/build sidekiq-poll-stats data)
+                 (dom/div #js {:className "hidden"} nil))))))

 (defn sidekiq-view [data owner]
   (reify
@@ -62,8 +97,7 @@
                                  (om/build sidekiq-redis-view data))
                         (dom/div #js {:className "col s11"}
                                  (om/build sidekiq-stats-view data))
-                        (dom/div #js {:className "col s1"}
-                                 (om/build sidekiq-read-more data)))))))
+                        (om/build sidekiq-read-more data))))))

 (defn sidekiq-list [data owner]
   (om/component


Save log to file after adding new entry.

--- src/clojure/my/stuff/fitlogger/main.clj
+++ src/clojure/my/stuff/fitlogger/main.clj
@@ -74,6 +74,22 @@
   (set-elmt activity ::water "")
   (set-elmt activity ::muscle ""))

+
+(def logfile "test.csv")
+
+(defn write-logfile [activity t]
+  (let [file (File. (.getFilesDir activity) logfile)]
+    (do (when (not (.exists file))
+          (.createNewFile file))
+        (with-open [wrt (io/writer file)]
+          (.write wrt t)))))
+
+(defn read-logfile [activity]
+  (let [file (File. (.getFilesDir activity) logfile)]
+    (when (.exists file)
+      (with-open [rdr (io/reader file)]
+        (slurp rdr)))))
+
 (defn add-event [activity]
   (let [date-key (try
                    (read-string (get-elmt activity ::date))
@@ -83,6 +99,7 @@
              #(reduce (fn [l k] (assoc-in l [date-key k] (read-string (get-elmt activity k))))
                       %
                       [::date ::weight ::bf ::water ::muscle]))
+      (write-logfile activity (listing->csv @listing))
       (update-ui activity))))

 (defn date-picker [activity]
@@ -100,19 +117,6 @@
 (defn show-picker [^Activity activity dp]
   (. dp show (. activity getFragmentManager) "datePicker"))

-(def logfile "test.csv")
-
-(defn write-file [activity t]
-  (let [file (File. (.getFilesDir activity) logfile)]
-    (do (when (not (.exists file))
-          (.createNewFile file))
-        (with-open [wrt (io/writer file)]
-          (.write wrt t)))))
-
-(defn read-file [activity]
-  (let [file (File. (.getFilesDir activity) logfile)]
-    (when (.exists file)
-      (set-elmt activity ::test  (slurp file)))))

 (defn main-layout [activity]
   [:linear-layout {:orientation :vertical}


Fix how asset manager loads bitmap font

Fix how asset manager loads bitmap font

--- src/play_clj/g2d.clj
+++ src/play_clj/g2d.clj
@@ -13,12 +13,10 @@
   [path]
   (if (nil? path)
     (BitmapFont.)
-    (let [^Files files (Gdx/files)
-          ^FileHandle fh (if (string? path)
-                           (.internal files path)
-                           path)]
-      (or (u/load-asset (.path fh) BitmapFont)
-          (BitmapFont. fh)))))
+    (or (u/load-asset path BitmapFont)
+        (BitmapFont. (if (string? path)
+                       (.internal (Gdx/files) path)
+                       path)))))

 (defmacro bitmap-font
   "Returns a [BitmapFont](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/g2d/BitmapFont.html).


Added support for buffered commands

Added support for buffered commands

--- src/multi_repl/core.clj
+++ src/multi_repl/core.clj
@@ -84,18 +84,36 @@
   (binding [*out* (:out console)]
     (apply println args)))

+(defn drop-first-and-last [v]
+  (subvec v 1 (- (count v) 1)))
+
+(defn eval-and-print [system line]
+  (let [{:keys [repl console]} system
+        {:keys [error result]} (eval-in-repl repl line)]
+    (if error
+      (println-console console "ERROR:" error)
+      (println-console console result))))
+
 (defmulti run-line (fn [system line] line))
+
+(defmethod run-line "%b" [system line]
+  (let [console (:console system)]
+    (loop [buffer [line]]
+      (print-err "buffer" buffer)
+      (if (= (last buffer) "%r")
+        (->> buffer
+             drop-first-and-last
+             (clojure.string/join "\n")
+             (eval-and-print system))
+        (recur (->> (read-console-line console)
+                    (conj buffer)))))))

 (defmethod run-line "exit" [system _]
   (component/stop system)
   (System/exit 0))

 (defmethod run-line :default [system line]
-  (let [{:keys [repl console]} system
-        {:keys [error result]} (eval-in-repl repl line)]
-    (if error
-      (println-console console "ERROR:" error)
-      (println-console console result))))
+  (eval-and-print system line))

 (defn start-python-repl []
   (-> (new-repl ["python" "-u" "python-repl.py"])


Remove clojure.conrib.def

Remove clojure.conrib.def

--- src/control/core.clj
+++ src/control/core.clj
@@ -2,12 +2,11 @@
   (:use [clojure.java.io :only [reader]]
         [clojure.java.shell :only [sh]]
         [clojure.string :only [join blank?]]
-        [clojure.walk :only [walk postwalk]]
-        [clojure.contrib.def :only [defvar- defvar]]))
+        [clojure.walk :only [walk postwalk]]))

 (def ^:dynamic *enable-color* true)
 (def ^{:dynamic true} *enable-logging* true)
-(defvar ^:dynamic  *debug* false)
+(def ^:dynamic  *debug* false)
 (def ^:private bash-reset "\033[0m")
 (def ^:private bash-bold "\033[1m")
 (def ^:private bash-redbold "\033[1;31m")
@@ -134,11 +133,11 @@
         rt))))

 ;;All tasks defined in control file
-(defvar tasks (atom (hash-map)))
+(def tasks (atom (hash-map)))
 ;;All clusters defined in control file
-(defvar clusters (atom (hash-map)))
-
-(defvar- system-functions
+(def clusters (atom (hash-map)))
+
+(def ^:private system-functions
   #{(symbol "scp") (symbol "ssh") (symbol "rsync") (symbol "call") (symbol "exists?")})

 (defmacro


Alpha channel should not be weighted

Alpha channel should not be weighted

--- src/inkspot/color.clj
+++ src/inkspot/color.clj
@@ -124,7 +124,7 @@
   [ (* weight (red color))
     (* weight (green color))
     (* weight (blue color))
-    (* weight (alpha color))])
+    (alpha color)])

 (defn mix
   "Mix the colors in RGB space in the proportions given, else if


Fix class issue on tabs.  Looks much better now.

--- src/re_com/tabs.cljs
+++ src/re_com/tabs.cljs
@@ -72,7 +72,8 @@
          [:button.btn.btn-default
           {:type     "button"
            :key      (str id)
-           :style    (if selected? {:background-color "#aaa"  :color "white"} {})
+           :class    (str "btn btn-default "  (if selected? "active"))
+           ;;:style    (if selected? {:background-color "#aaa"  :color "white"} {})
            :on-click #(reset! model id)}
           label]))]))


Changed to use re-com.util.real-value.

Changed to use re-com.util.real-value.

--- src/re_com/time.cljs
+++ src/re_com/time.cljs
@@ -3,7 +3,7 @@
     [reagent.core :as reagent]
     [clojure.string :as cljstring]
     [re-com.box      :refer  [h-box gap]]
-    [re-com.util :refer [pad-zero-number]]))
+    [re-com.util :refer [pad-zero-number real-value]]))

 ; --- Private functions ---
@@ -36,7 +36,7 @@
         val))))

 (defn string->time-integer
-  "Return a TimeRecord from the passed string."
+  "Return a time integer from the passed string."
   [s]
   (let [matches (re-matches #"^(\d{0,2})()()$|^(\d{0,1})(:{0,1})(\d{0,2})$|^(\d{0,2})(:{0,1})(\d{0,2})$" s)
        vals (filter #(not (nil? %))(rest matches))]
@@ -151,16 +151,10 @@
     (reset! tmp-model (display-string (time-int->hour-minute (validated-time-integer time-int @min @max))))
   (when callback (callback time-int))))

-(defn dereffed-model
-  [model]
-  (if (satisfies? cljs.core/IDeref model)
-    @model
-    model))
-
 (defn atom-on
   [model default]
   (reagent/atom (if model
-                  (dereffed-model model)
+                  (real-value model)
                    default)))

 ;; --- Components ---
@@ -177,7 +171,7 @@
     on-change - function to call when model has changed - parameter will be the new value
     style - css"
   [& {:keys [model minimum maximum]}]
-  (let [deref-model (dereffed-model model)
+  (let [deref-model (real-value model)
         tmp-model (atom-on (display-string (time-int->hour-minute deref-model)) "")
         min (atom-on minimum 0)
         max (atom-on maximum 2359)]


Require proper attributes ns on transaction impl.

--- src/continuo/postgresql/transaction.clj
+++ src/continuo/postgresql/transaction.clj
@@ -15,7 +15,7 @@
 (ns continuo.postgresql.transaction
   (:require [suricatta.core :as sc]
             [taoensso.nippy :as nippy]
-            [continuo.postgresql.schema :as schema]
+            [continuo.postgresql.attributes :as attrs]
             [continuo.util.template :as tmpl]
             [continuo.util.codecs :as codecs]
             [continuo.executor :as exec]))
@@ -54,7 +54,6 @@
           sqlv  [sql eid txid value]]
       (sc/execute conn sqlv))))

-
 (deftype RetractOperation [partition attr value]
   IOperation
   (-execute [_ conn txid]
@@ -88,7 +87,7 @@
   the appropiate default materialized view."
   [context partition [op eid attrname value]]
   ;; resolve-attr :: context -> string -> Attribute
-  (let [attr (resolve-attr context attrname)]
+  (let [attr (attrs/resolve-attr context attrname)]
     (case op
       :db/add (AddOperation. partition eid attr value)
       :db/retract (RetractOperation. partition eid attr value)


test/lookup: update docstring

test/lookup: update docstring

--- src/riemann/test.clj
+++ src/riemann/test.clj
@@ -151,17 +151,17 @@
             persistent!)))))

 (defn lookup
-  "Lookup an event in a pseudo-index returned by inject!.
-  The equivalent to index/lookup, for tests.
-  "
-  [index host service]
+  "Lookup an event by host/service in a vector of tapped events returned by
+  inject!. If several matching events have passed through the tap, the last one
+  will be returned."
+  [events host service]
   (last
     (filter
       identity
       (map #(when
               (and (= host (:host %))
                    (= service (:service %))) %)
-           index))))
+           events))))

 (defmacro deftest
   "Like clojure.test deftest, but establishes a fresh time context and a fresh


Simplify sentry-capture

Simplify sentry-capture

By merging extra context prior to sentry-capture, we can make it 'dumb'
function that just sends along whatever it's given.

--- src/overseer/errors.clj
+++ src/overseer/errors.clj
@@ -35,13 +35,15 @@
   (when-let [data (ex-data ex)]
     (filter-serializable data)))

-(defn sentry-capture [dsn ex extra-info]
-  (let [ex-map
-        (-> {:message (.getMessage ex)
-             :extra (merge (or extra-info {})
-                           (or (sanitized-ex-data ex) {}))}
-            (raven.interface/stacktrace ex))]
-    (try (raven/capture dsn ex-map)
+(defn sentry-capture
+  "Send an exception and an optional map of additional context
+   info to Sentry"
+  [dsn ex extra]
+  (let [event-map {:message (.getMessage ex) :extra (or extra {})}]
+    (try
+      (->> ex
+           (raven.interface/stacktrace event-map)
+           (raven/capture dsn))
       (catch Exception ex'
         (timbre/error "Sentry exception handler failed")
         (timbre/error ex')))))
@@ -50,12 +52,14 @@
   "Construct an handler function that by default logs exceptions
    and optionally sends to Sentry if configured"
   [config job]
-  (fn [ex]
-    (timbre/error ex)
-    (when-not (= :aborted (:overseer/status (ex-data ex)))
-      (if-let [dsn (get-in config [:sentry :dsn])]
-        (sentry-capture dsn ex (select-keys job [:job/type :job/id]))))
-    nil))
+  (if-let [dsn (get-in config [:sentry :dsn])]
+    (fn [ex]
+      (when-not (= :aborted (:overseer/status (ex-data ex)))
+        (let [extra (merge (select-keys job [:job/type :job/id])
+                           (or (sanitized-ex-data ex) {}))]
+          (sentry-capture dsn ex extra))))
+    (fn [ex]
+      (timbre/error ex))))

 (defn failure-info
   "Construct a map of information about an exception, including


start accepting team transactions again

start accepting team transactions again

--- src/pc/http/sente.clj
+++ src/pc/http/sente.clj
@@ -472,6 +472,30 @@
     (when ?reply-fn
       (?reply-fn {:rejected-datoms rejects}))))

+(defmethod ws-handler :team/transaction [{:keys [client-id ?data ?reply-fn] :as req}]
+  (let [team-uuid (-> ?data :team/uuid)]
+    (check-team-access team-uuid req :admin)
+    (let [datoms (->> ?data
+                   :datoms
+                   (remove (comp nil? :v))
+                   (remove #(= "document" (name (:a %)))))
+          cust-uuid (-> req :ring-req :auth :cust :cust/uuid)
+          ;; note that these aren't all of the rejected datoms, just the ones not on the whitelist
+          rejects (remove (comp (partial datomic2/whitelisted? :admin)
+                                pcd/datom->transaction)
+                          datoms)
+          team-id (:db/id (team-model/find-by-uuid (:db req) team-uuid))]
+      (log/infof "transacting %s datoms (minus %s rejects) on %s for %s" (count datoms) (count rejects) team-id client-id)
+      (datomic2/transact! datoms
+                          {:team-id team-id
+                           :access-scope :admin
+                           :client-id client-id
+                           :cust-uuid cust-uuid
+                           :session-uuid (UUID/fromString (get-in req [:ring-req :session :sente-id]))
+                           :timestamp (:receive-instant req)})
+      (when ?reply-fn
+        (?reply-fn {:rejected-datoms rejects})))))
+
 (defmethod ws-handler :frontend/mouse-position [{:keys [client-id ?data] :as req}]
   (check-document-access (-> ?data :document/id) req :read)
   (let [document-id (-> ?data :document/id)