Allows overriding domain name sent to client in write-cljs!

Additionally adds ns require boot.core as b to fix build broken from 5a9042f

--- src/adzerk/boot_reload.clj
+++ src/adzerk/boot_reload.clj
@@ -1,8 +1,10 @@
 (ns adzerk.boot-reload
   {:boot/export-tasks true}
   (:require
+   [boot.core          :as b]
    [clojure.java.io    :as io]
    [clojure.set        :as set]
+   [clojure.string     :as string]
    [boot.pod           :as pod]
    [boot.file          :as file]
    [boot.util          :as util]
@@ -21,10 +23,10 @@
          (sort-by :dependency-order)
          (map tmp-path))))

-(defn- start-server [pod {:keys [ip port] :as opts}]
+(defn- start-server [pod {:keys [ip port] :as opts} domain]
   (let [{:keys [ip port]}
         (pod/with-call-in pod (adzerk.boot-reload.server/start ~opts))
-        host (if-not (= ip "0.0.0.0") ip "localhost")]
+        host (if-not (string/blank? domain) domain (if-not (= ip "0.0.0.0") ip "localhost"))]
     (util/with-let [url (format "ws://%s:%d" host port)]
       (util/info "<< started reload server on %s >>\n" url))))

@@ -75,6 +77,7 @@
   [b ids BUILD_IDS #{str} "Only inject reloading into these builds (= .cljs.edn files)"
    i ip ADDR         str  "The (optional) IP address for the websocket server to listen on."
    p port PORT       int  "The (optional) port the websocket server listens on."
+   d domain DOMAIN   str  "The (optional) server domain name to pass through requests."
    j on-jsload SYM   sym  "The (optional) callback to call when JS files are reloaded."
    a asset-path PATH str  "The (optional) asset-path. This is removed from the start of reloaded urls."]

@@ -82,9 +85,10 @@
         src  (tmp-dir!)
         tmp  (tmp-dir!)
         prev (atom nil)
-        out  (doto (io/file src "adzerk" "boot_reload.cljs") io/make-parents)]
+        out  (doto (io/file src "adzerk" "boot_reload.cljs") io/make-parents)
+        url  (start-server @pod {:ip ip :port port} domain)]
     (set-env! :source-paths #(conj % (.getPath src)))
-    (write-cljs! out (start-server @pod {:ip ip :port port}) on-jsload)
+    (write-cljs! out url on-jsload)
     (comp
       (with-pre-wrap fileset
         (doseq [f (relevant-cljs-edn fileset ids)]
@@ -95,5 +99,4 @@
         (-> fileset (add-resource tmp) commit!))
       (with-post-wrap fileset
         (send-changed! @pod asset-path (changed @prev fileset))
-        (reset! prev fileset)))))
-
+        (reset! prev fileset)))))


Add phase to dimmer oscillator cues.

Add phase to dimmer oscillator cues.

Also simplify the passing of keyword parameters, since oscillators
already accept them.

--- src/afterglow/examples.clj
+++ src/afterglow/examples.clj
@@ -428,31 +428,22 @@
   group of fixtures, with cue parameters to adjust the beat ratio,
   starting with default values established by show parameters."
   [group x y color]
-  (when-not (= (type (show/get-variable :sawtooth-down?)) Boolean)
-    ;; If the default sawtooth direction has not yet been set, establish it as down
-    (show/set-variable! :sawtooth-down? true))
-  (when-not (= (type (show/get-variable :starting-beats)) Long)
-    ;; If the default beat ratio numerator has not yet been set, establish it as 2
-    (show/set-variable! :starting-beats 2))
-  (when-not (= (type (show/get-variable :starting-cycles)) Long)
-    ;; If the default beat ratio denominator has not yet been set, establish it as 1
-    (show/set-variable! :starting-cycles 1))
-
   (let [[effect-key fixtures end-keys effect-name] (build-group-cue-elements group "dimmers" "saw")]
     (ct/set-cue! (:cue-grid *show*) x y
                  (cues/cue effect-key
                            (fn [var-map] (dimmer-effect
                                           (oscillators/build-oscillated-param
-                                           (oscillators/sawtooth :down? (params/bind-keyword-param (:down var-map)
-                                                                                Boolean true)
-                                                                 :interval-ratio (build-ratio-param var-map)))
+                                           (oscillators/sawtooth :down? (:down var-map)
+                                                                 :interval-ratio (build-ratio-param var-map)
+                                                                 :phase (:phase var-map)))
                                           fixtures
                                           :effect-name effect-name))
                            :color color
                            :variables [{:key "beats" :min 1 :max 32 :type :integer :start :starting-beats :name "Beats"}
                                        {:key "down" :type :boolean :start :sawtooth-down? :name "Down?"}
                                        {:key "cycles" :min 1 :max 10 :type :integer :start :starting-cycles
-                                        :name "Cycles"}]
+                                        :name "Cycles"}
+                                       {:key "phase" :min 0 :max 1 :start :starting-phase :name "Phase"}]
                            :end-keys end-keys))))

 (defn make-triangle-cue
@@ -460,25 +451,20 @@
   set of fixtures, with cue parameters to adjust the beat ratio,
   starting with default values established by show parameters."
   [group x y color]
-  (when-not (= (type (show/get-variable :starting-beats)) Long)
-    ;; If the default beat ratio numerator has not yet been set, establish it as 2
-    (show/set-variable! :starting-beats 2))
-  (when-not (= (type (show/get-variable :starting-cycles)) Long)
-    ;; If the default beat ratio denominator has not yet been set, establish it as 1
-    (show/set-variable! :starting-cycles 1))
-
   (let [[effect-key fixtures end-keys effect-name] (build-group-cue-elements group "dimmers" "triangle")]
     (ct/set-cue! (:cue-grid *show*) x y
                (cues/cue effect-key
                          (fn [var-map] (dimmer-effect
                                         (oscillators/build-oscillated-param
-                                         (oscillators/triangle :interval-ratio (build-ratio-param var-map)))
+                                         (oscillators/triangle :interval-ratio (build-ratio-param var-map)
+                                                               :phase (:phase var-map)))
                                         fixtures
                                         :effect-name effect-name))
                          :color color
                          :variables [{:key "beats" :min 1 :max 32 :type :integer :start :starting-beats :name "Beats"}
                                      {:key "cycles" :min 1 :max 10 :type :integer :start :starting-cycles
-                                      :name "Cycles"}]
+                                      :name "Cycles"}
+                                     {:key "phase" :min 0 :max 1 :start :starting-phase :name "Phase"}]
                          :end-keys end-keys))))

 (defn make-sine-cue
@@ -486,25 +472,21 @@
   set of fixtures, with cue parameters to adjust the beat ratio,
   starting with default values established by show parameters."
   [group x y color]
-  (when-not (= (type (show/get-variable :starting-beats)) Long)
-    ;; If the default beat ratio numerator has not yet been set, establish it as 2
-    (show/set-variable! :starting-beats 2))
-  (when-not (= (type (show/get-variable :starting-cycles)) Long)
-    ;; If the default beat ratio denominator has not yet been set, establish it as 1
-    (show/set-variable! :starting-cycles 1))
-
   (let [[effect-key fixtures end-keys effect-name] (build-group-cue-elements group "dimmers" "sine")]
     (ct/set-cue! (:cue-grid *show*) x y
                  (cues/cue effect-key
                            (fn [var-map] (dimmer-effect
                                           (oscillators/build-oscillated-param
-                                           (oscillators/sine :interval-ratio (build-ratio-param var-map)) :min 1)
+                                           (oscillators/sine :interval-ratio (build-ratio-param var-map)
+                                                             :phase (:phase var-map))
+                                           :min 1)
                                           fixtures
                                           :effect-name effect-name))
                            :color color
                            :variables [{:key "beats" :min 1 :max 32 :type :integer :start :starting-beats :name "Beats"}
-                                     {:key "cycles" :min 1 :max 10 :type :integer :start :starting-cycles
-                                      :name "Cycles"}]
+                                       {:key "cycles" :min 1 :max 10 :type :integer :start :starting-cycles
+                                        :name "Cycles"}
+                                       {:key "phase" :min 0 :max 1 :start :starting-phase :name "Phase"}]
                          :end-keys end-keys))))

 (defn make-square-cue
@@ -512,35 +494,22 @@
   of fixtures, with cue parameters to adjust the beat ratio and pulse
   width, starting with default values established by show parameters."
   [group x y color]
-  (when-not (= (type (show/get-variable :starting-beats)) Long)
-    ;; If the default beat ratio numerator has not yet been set, establish it as 2
-    (show/set-variable! :starting-beats 2))
-  (when-not (= (type (show/get-variable :starting-cycles)) Long)
-    ;; If the default beat ratio denominator has not yet been set, establish it as 1
-    (show/set-variable! :starting-cycles 1))
-  (when-not (= (type (show/get-variable :starting-width)) Double)
-    ;; If the default pulse width has not yet been set, establish it as 0.5
-    (show/set-variable! :starting-width 0.5))
-  (when-not (= (type (show/get-variable :starting-phase)) Double)
-    ;; If the default pulse phase has not yet been set, establish it as 0.0
-    (show/set-variable! :starting-phase 0.0))
-
-  ;; TODO: Make width and phase adjustable params. Is blowing up in oscillators/square right now
   (let [[effect-key fixtures end-keys effect-name] (build-group-cue-elements group "dimmers" "square")]
     (ct/set-cue! (:cue-grid *show*) x y
                (cues/cue effect-key
                          (fn [var-map] (dimmer-effect
                                         (oscillators/build-oscillated-param
                                          (oscillators/square :interval-ratio (build-ratio-param var-map)
-                                                             :width (params/bind-keyword-param (:width var-map)
-                                                                                Number 0.5)))
+                                                             :width (:width var-map)
+                                                             :phase (:phase var-map)))
                                         fixtures
                                         :effect-name effect-name))
                          :color color
                          :variables [{:key "beats" :min 1 :max 32 :type :integer :start :starting-beats :name "Beats"}
                                      {:key "width" :min 0 :max 1 :start :starting-width :name "Width"}
                                      {:key "cycles" :min 1 :max 10 :type :integer :start :starting-cycles
-                                      :name "Cycles"}]
+                                      :name "Cycles"}
+                                     {:key "phase" :min 0 :max 1 :start :starting-phase :name "Phase"}]
                          :end-keys end-keys))))

 (defn x-phase
@@ -674,6 +643,23 @@
                            :variables [{:key "chance" :min 0.0 :max 0.4 :start 0.05 :velocity true}
                                        {:key "fade-time" :name "Fade" :min 1 :max 2000 :start 50 :type :integer}]))

+
+    ;; Set up default starting values for oscillators driving dimmer cues
+    (when-not (= (type (show/get-variable :starting-beats)) Long)
+      ;; If the default beat ratio numerator has not yet been set, establish it as 2
+      (show/set-variable! :starting-beats 2))
+    (when-not (= (type (show/get-variable :starting-cycles)) Long)
+      ;; If the default beat ratio denominator has not yet been set, establish it as 1
+      (show/set-variable! :starting-cycles 1))
+    (when-not (= (type (show/get-variable :starting-phase)) Double)
+      ;; If the default pulse phase has not yet been set, establish it as 0.0
+      (show/set-variable! :starting-phase 0.0))
+    (when-not (= (type (show/get-variable :sawtooth-down?)) Boolean)
+      ;; If the default sawtooth direction has not yet been set, establish it as down
+      (show/set-variable! :sawtooth-down? true))
+    (when-not (= (type (show/get-variable :starting-width)) Double)
+      ;; If the default pulse width has not yet been set, establish it as 0.5
+      (show/set-variable! :starting-width 0.5))

     ;; Dimmer oscillator cues: Sawtooth
     (make-sawtooth-cue nil 0 3 :yellow)


Updating name and docstring for computing frequent, pseudoclosed itemsets

Signed-off-by: Daniel Borchmann <25857343a15bf1edafebc2912e82ecf775c585c1@mailbox.tu-dresden.de>

--- src/conexp/fca/implications.clj
+++ src/conexp/fca/implications.clj
@@ -385,9 +385,9 @@

 ;;;

-(defn- extended-iceberg-intent-seq
-  "Computes for the given closure operator for given minimal support minsupp the corresponding
-  extended iceberg intent seq, which is the iceberg lattice of all intents and pseudo-intents."
+(defn- frequent-pseudoclosed-itemsets
+  "Computes for the given context all closed and pseudoclosed sets of attributes whose support is
+  not less than minsupp."
   ;; UNTESTED!
   [context minsupp]
   (let [mincount (ceil (* minsupp (count (objects context))))]


Change implementation of Luxenburgers Base

Signed-off-by: Daniel Borchmann <25857343a15bf1edafebc2912e82ecf775c585c1@mailbox.tu-dresden.de>

--- src/conexp/fca/implications.clj
+++ src/conexp/fca/implications.clj
@@ -392,11 +392,11 @@
   "Computes the luxenburger-basis for context with minimal support minsupp and minimal confidence
   minconf. The result returned will be a lazy sequence."
   [context minsupp minconf]
-  (let [closed-intents (frequent-closed-itemsets context minsupp)]
-    (for [[B_1, B_2] (transitive-reduction closed-intents proper-subset?)
-          :let [impl (make-implication B_1 B_2)]
-          :when (>= (confidence impl context) minconf)]
-      impl)))
+  (for [B_2  (frequent-closed-itemsets context minsupp),
+        B_1  (map second (direct-upper-concepts context [(aprime context B_2) B_2])),
+        :let [impl (make-implication B_1 B_2)]
+        :when (>= (confidence impl context) minconf)]
+    impl))

 ;;;


Added Accession bench results.

Added Accession bench results.

--- src/carmine/benchmarks.clj
+++ src/carmine/benchmarks.clj
@@ -39,7 +39,7 @@
   (println "Benching redis-clojure...")
   (time-laps
    opts
-   (redis-clojure/with-server {} ; Uses pool behind-the-scenes
+   (redis-clojure/with-server {}
      ;; SET pipeline
      (redis-clojure-pipeline/pipeline
       (redis-clojure/ping)
@@ -136,13 +136,17 @@
   (let [times {:redis-clojure (bench-redis-clojure opts)
                :clj-redis     (bench-clj-redis     opts)
                ;; Doesn't seem to close its sockets!
-               ;;:accession     (bench-accession     opts)
+               ;; :accession  (bench-accession     opts)
                :carmine       (bench-carmine       opts)}]
     (println "Done!" "\n")
     (println "Raw times:" times "\n")
     (println "Sorted relative times (smaller is better):" (sort-times times))))

 (comment
+
+  ;; Easy (required to get Accession to bench)
+  (bench-and-compare-clients (make-benching-options :num-laps 100))
+  ;; '([:carmine 1.0] [:redis-clojure 1.06] [:clj-redis 1.12] [:accession 1.84])

   ;; Standard
   (bench-and-compare-clients (make-benching-options :num-laps 10000))


Add better error reporting for context mixin for either monad.

--- src/cats/monad/either.cljc
+++ src/cats/monad/either.cljc
@@ -175,6 +175,8 @@
       (right v))

     (-mbind [_ s f]
+      (assert (either? mv) (str "Context mismatch: " (p/-repr mv)
+                               " is not allowed to use with either context."))
       (if (right? s)
         (f (.-v ^Right s))
         s))


replace function takes a single match argument

--- src/outpace/remote/service.cljc
+++ src/outpace/remote/service.cljc
@@ -36,7 +36,7 @@
      ([s {:keys [regex]}]
       (fn [m]
         (string/replace s regex
-                        (fn a-replace [$0 $1]
+                        (fn a-replace [[$0 $1]]
                           (let [k (keyword $1)
                                 v (get m k)]
                             (if v


Update stringed macro. - make single string instrument work with midi-poly-player. - add documentation string for the generated stringed instruments. Create single string instrument "ektara" & midi-poly-player example in comments. Add now+ fn to eliminate most "late" messages.

--- src/overtone/synth/stringed.clj
+++ src/overtone/synth/stringed.clj
@@ -21,14 +21,18 @@
    before a gate -> 1 transition activates it.  Testing
    showed it needed > 25 ms between these transitions to be effective."
   [name num-strings]
-  (let [note-ins (apply vector
-                        (map #(symbol (format "note-%d" %)) (range num-strings)))
+  (let [note-ins (if (= num-strings 1)
+                   [(symbol "note")]
+                   (apply vector
+                          (map #(symbol (format "note-%d" %)) (range num-strings))))
         note-default-ins (apply vector
                                 (flatten (map vector
                                               note-ins
                                               (repeat num-strings {:default 60 :min 0 :max 127}))))
-        gate-ins (apply vector
-                        (map #(symbol (format "gate-%d" %)) (range num-strings)))
+        gate-ins (if (= num-strings 1)
+                   [(symbol "gate")]
+                   (apply vector
+                          (map #(symbol (format "gate-%d" %)) (range num-strings))))
         gate-default-ins (apply vector (flatten (map vector
                                                      gate-ins
                                                      (repeat num-strings {:default 0}))))
@@ -36,6 +40,13 @@
         note-gate-pairs (apply vector (map vector note-ins gate-ins))
         ]
     `(defsynth ~name
+       ~(str "a stringed instrument synth with " num-strings
+             " strings mixed and sent thru
+  distortion and reverb effects followed by a low-pass filter.  Use
+  the pluck-strings and strum-strings helper functions to play the
+  instrument. Note: the strings need to be silenced with a gate -> 0
+  transition before a gate -> 1 transition activates it.")
+
        [~@both-default-ins
         ~'dur       {:default 10.0  :min 1.0 :max 100.0}
         ~'decay     {:default 30    :min 1   :max 100} ;; pluck decay
@@ -90,6 +101,11 @@
   [s i]
   (keyword (format "%s-%d" s i)))

+(defn- now+
+  "add an epsilon of time to (now) to avoid lots of 'late' error messages"
+  []
+  (+ (now) 21)) ;; 21ms seems to get rid of most for me.
+
 ;; ======================================================================
 ;; Main helper functions used to play the instrument: pick or strum
 (defn pick-string
@@ -109,7 +125,7 @@
                            (mkarg "note" string-index) the-note
                            (mkarg "gate" string-index) 1)))))
   ([the-chord-frets the-inst string-index fret]
-     (pick-string the-chord-frets the-inst string-index fret (now))))
+     (pick-string the-chord-frets the-inst string-index fret (now+))))

 ;; ======================================================================
 (defn strum-strings
@@ -150,13 +166,13 @@
                         (+ t (* fret-delta dt)))))))
   ([chord-fret-map the-strings the-inst the-chord direction strum-time]
      (strum-strings chord-fret-map the-strings the-inst the-chord
-                    direction strum-time (now)))
+                    direction strum-time (now+)))
   ([chord-fret-map the-strings the-inst the-chord direction]
      (strum-strings chord-fret-map the-strings the-inst the-chord
-                    direction 0.05 (now)))
+                    direction 0.05 (now+)))
   ([chord-fret-map the-strings the-inst the-chord]
      (strum-strings chord-fret-map the-strings the-inst the-chord
-                    :down 0.05 (now))))
+                    :down 0.05 (now+))))

 ;; ======================================================================
 ;; The Guitar Instrument Code
@@ -262,3 +278,16 @@
 ;; ======================================================================
 ;; Create the guitar defsynth.  Now via the power of macros
 (gen-stringed-synth guitar 6)
+
+;; ======================================================================
+;; Ektara - a single-string synth.  Mainly for use with the midi-poly-player.
+;;
+;; Since "string" was too generic a name, I asked the google for some
+;; help.  Wikipedia tells me that there is a single-stringed
+;; instrument called the "Ektara", so that is where the name comes
+;; from.
+;;
+;; For use with midi-poly-player, we need to make the default gate 1.
+;; Example:
+;;   (def mpp (midi-poly-player (partial ektara :gate 1)))
+(gen-stringed-synth ektara 1)


refactor insights cards render function

refactor insights cards render function

--- src-cljs/frontend/components/insights.cljs
+++ src-cljs/frontend/components/insights.cljs
@@ -335,55 +335,61 @@
         (#(assoc % :sort-category (project-sort-category %)))
         (#(assoc % :latest-build-time (project-latest-build-time %))))))

-(defrender build-insights [{{:keys [selected-filter selected-sorting]} :insights :as state} owner]
-  (let [plans (get-in state state/user-plans-path)
-        projects (get-in state state/projects-path)]
+(defrender cards [{:keys [plans projects selected-filter selected-sorting]} owner]
+  (let [decorated-projects (map (partial decorate-project plans) projects)
+        categories (group-by :sort-category decorated-projects)
+        filtered-projects (if (= selected-filter :all)
+                            decorated-projects
+                            (selected-filter categories))
+        sorted-projects (case selected-sorting
+                          :name (->> filtered-projects
+                                     (sort-by formatted-project-name))
+                          :recency (->> filtered-projects
+                                        (sort-by :latest-build-time)
+                                        reverse))]
+    (html
+     [:div
+      [:div.controls
+       [:span.filtering
+        [:input {:id "insights-filter-all"
+                 :type "radio"
+                 :name "selected-filter"
+                 :checked (= selected-filter :all)
+                 :on-change #(raise! owner [:insights-filter-changed {:new-filter :all}])}]
+        [:label {:for "insights-filter-all"}
+         (gstring/format"All (%s)" (count decorated-projects))]
+        [:input {:id "insights-filter-success"
+                 :type "radio"
+                 :name "selected-filter"
+                 :checked (= selected-filter :success)
+                 :on-change #(raise! owner [:insights-filter-changed {:new-filter :success}])}]
+        [:label {:for "insights-filter-success"}
+         (gstring/format"Success (%s)" (count (:success categories)))]
+        [:input {:id "insights-filter-failed"
+                 :type "radio"
+                 :name "selected-filter"
+                 :checked (= selected-filter :failed)
+                 :on-change #(raise! owner [:insights-filter-changed {:new-filter :failed}])}]
+        [:label {:for "insights-filter-failed"}
+         (gstring/format"failed (%s)" (count (:failed categories)))]]
+       [:span.sorting
+        [:label "Sort: "]
+        [:select {:class "toggle-sorting"
+                  :on-change #(raise! owner [:insights-sorting-changed {:new-sorting (keyword (.. % -target -value))}])
+                  :value selected-sorting}
+         [:option {:value :name} "By Repo"]
+         [:option {:value :recency} "Recent"]]]]
+      [:div.blocks-container
+       (om/build-all project-insights sorted-projects)]])))
+
+(defrender build-insights [state owner]
+  (let [projects (get-in state state/projects-path)]
     (html
      [:div#build-insights {}
       (cond
         (nil? projects)    [:div.loading-spinner-big common/spinner]
         (empty? projects)  (om/build no-projects state)
-        :else              (let [projects' (map (partial decorate-project plans) projects)
-                                 categories (group-by :sort-category projects')
-                                 filtered-projects (if (= selected-filter :all)
-                                                     projects'
-                                                     (selected-filter categories))
-                                 sorted-projects (case selected-sorting
-                                                   :name (->> filtered-projects
-                                                              (sort-by formatted-project-name))
-                                                   :recency (->> filtered-projects
-                                                                 (sort-by :latest-build-time)
-                                                                 reverse))]
-                             (list
-                              [:div.controls
-                               [:span.filtering
-                                [:input {:id "insights-filter-all"
-                                         :type "radio"
-                                         :name "selected-filter"
-                                         :checked (= selected-filter :all)
-                                         :on-change #(raise! owner [:insights-filter-changed {:new-filter :all}])}]
-                                [:label {:for "insights-filter-all"}
-                                 (gstring/format"All (%s)" (count projects'))]
-                                [:input {:id "insights-filter-success"
-                                         :type "radio"
-                                         :name "selected-filter"
-                                         :checked (= selected-filter :success)
-                                         :on-change #(raise! owner [:insights-filter-changed {:new-filter :success}])}]
-                                [:label {:for "insights-filter-success"}
-                                 (gstring/format"Success (%s)" (count (:success categories)))]
-                                [:input {:id "insights-filter-failed"
-                                         :type "radio"
-                                         :name "selected-filter"
-                                         :checked (= selected-filter :failed)
-                                         :on-change #(raise! owner [:insights-filter-changed {:new-filter :failed}])}]
-                                [:label {:for "insights-filter-failed"}
-                                 (gstring/format"failed (%s)" (count (:failed categories)))]]
-                               [:span.sorting
-                                [:label "Sort: "]
-                                [:select {:class "toggle-sorting"
-                                          :on-change #(raise! owner [:insights-sorting-changed {:new-sorting (keyword (.. % -target -value))}])
-                                          :value selected-sorting}
-                                 [:option {:value :name} "By Repo"]
-                                 [:option {:value :recency} "Recent"]]]]
-                              [:div.blocks-container
-                               (om/build-all project-insights sorted-projects)])))])))
+        :else              (om/build cards {:plans (get-in state state/user-plans-path)
+                                            :projects (get-in state state/projects-path)
+                                            :selected-filter (get-in state state/insights-filter-path)
+                                            :selected-sorting (get-in state state/insights-sorting-path)}))])))


Clean up cljs.repl.node

Clean up cljs.repl.node

--- src/clj/cljs/repl/node.clj
+++ src/clj/cljs/repl/node.clj
@@ -9,18 +9,14 @@
 (ns cljs.repl.node
   (:require [clojure.string :as string]
             [clojure.java.io :as io]
-            [cljs.env :as env]
             [cljs.analyzer :as ana]
             [cljs.compiler :as comp]
             [cljs.repl :as repl]
-            [cljs.closure :as cljsc]
-            [cljs.closure :as closure]
-            [cljs.util :as util])
-  (:import cljs.repl.IJavaScriptEnv
-           java.net.Socket
+            [cljs.closure :as closure])
+  (:import java.net.Socket
            java.lang.StringBuilder
            [java.io File BufferedReader BufferedWriter]
-           [java.lang ProcessBuilder UNIXProcess ProcessBuilder$Redirect]))
+           [java.lang ProcessBuilder ProcessBuilder$Redirect]))

 (defn socket [host port]
   (let [socket (Socket. host port)
@@ -93,6 +89,8 @@
                         (closure/src-file->target-file core)
                         :static-fns true))
             deps    (closure/add-dependencies opts core-js)]
+        ;; output unoptimized code and the deps file
+        ;; for all compiled namespaces
         (apply closure/output-unoptimized
           (assoc opts
             :output-to (.getPath (io/file output-dir "node_repl_deps.js")))
@@ -104,6 +102,7 @@
           (string/replace "__dirname"
             (str "\"" (str rewrite-path File/separator "bootstrap") "\""))
           (string/replace "./.." rewrite-path)))
+      ;; load the deps file so we can goog.require cljs.core etc.
       (node-eval repl-env
         (str "require('"
           (.getPath root-path)
@@ -111,6 +110,7 @@
       ;; monkey-patch isProvided_ to avoid useless warnings - David
       (node-eval repl-env
         (str "goog.isProvided_ = function(x) { return false; };"))
+      ;; load cljs.core, setup printing
       (repl/evaluate-form repl-env env "<cljs repl>"
         '(do
            (.require js/goog "cljs.core")
@@ -137,8 +137,3 @@
   [& options]
   (repl-env* options))

-(comment
-
-  (def bldr (ProcessBuilder. (into-array ["node"])))
-
-  )


implement Shiro

implement Shiro

Works with R&D Interface(s)

--- src/clj/game/cards-ice.clj
+++ src/clj/game/cards-ice.clj
@@ -492,6 +492,16 @@
                 {:label "Trace 3 - Do 3 net damage"
                  :trace {:base 3 :msg "do 3 net damage" :effect (effect (damage :net 3 {:card card}))}}]}

+   "Shiro"
+   {:abilities [{:label "Rearrange the top 3 cards of R&D"
+                 :msg "rearrange the top 3 cards of R&D"
+                 :effect (req (doseq [c (take 3 (:deck corp))]
+                                (move state side c :play-area)))}
+                {:label "Force the Runner to access the top card of R&D"
+                 :effect (req (doseq [c (take (get-in @state [:runner :rd-access]) (:deck corp))]
+                                (system-msg state :runner (str "accesses " (:title c)))
+                                (handle-access state side [c])))}]}
+
    "Snoop"
    {:abilities [{:msg "place 1 power counter on Snoop" :effect (effect (add-prop card :counter 1))}
                 {:counter-cost 1 :label "Look at all cards in Grip and trash 1 card"
@@ -632,4 +642,4 @@
                 {:msg "look at the top card of R&D"
                  :optional {:prompt (msg "Add " (:title (first (:deck corp))) " to bottom of R&D?")
                             :msg "add the top card of R&D to the bottom"
-                            :effect (effect (move (first (:deck corp)) :deck))}}]}})+                            :effect (effect (move (first (:deck corp)) :deck))}}]}})


Support FASTA-TwoBit conversion

Support FASTA-TwoBit conversion

--- src/cljam/algo/convert.clj
+++ src/cljam/algo/convert.clj
@@ -1,14 +1,17 @@
 (ns cljam.algo.convert
-  "Format converter from SAM to BAM, and vice versa."
+  "Converters between equivalent formats: SAM/BAM and FASTA/TwoBit."
   (:require [clojure.tools.logging :as logging]
             [cljam.common :refer [*n-threads* get-exec-n-threads]]
             [cljam.io.sam :as sam]
             [cljam.io.bam.encoder :as encoder]
             [cljam.io.sam.util :as sam-util]
+            [cljam.io.sequence :as cseq]
             [cljam.io.util :as io-util]
             [com.climate.claypoole :as cp])
   (:import [java.nio ByteBuffer]
            [cljam.io.bam.writer BAMWriter]))
+
+;;; SAM <-> BAM

 (def ^:private default-num-block 100000)

@@ -30,22 +33,45 @@
                             (partition-all num-block (sam/read-alignments rdr {})))]
       (sam/write-blocks wtr blocks))))

-(defn- _convert!
+(defn- convert-sam*
   [rdr wtr num-block write-alignments-fn]
   (let [hdr (sam/read-header rdr)]
     (sam/write-header wtr hdr)
     (sam/write-refs wtr hdr)
     (write-alignments-fn rdr wtr hdr num-block)))

-(defn convert
-  "Converts file format from input file to output file by the file extension."
+(defn convert-sam
+  "Converts file format between SAM and BAM based on the file extension."
   [in out & {:keys [n-threads num-block]
              :or {n-threads 0, num-block default-num-block}}]
   (with-open [rdr (sam/reader in)
               wtr (sam/writer out)]
     (binding [*n-threads* n-threads]
       (cond
-        (io-util/sam-writer? wtr) (_convert! rdr wtr num-block sam-write-alignments)
-        (io-util/bam-writer? wtr) (_convert! rdr wtr num-block bam-write-alignments)
+        (io-util/sam-writer? wtr) (convert-sam* rdr wtr num-block sam-write-alignments)
+        (io-util/bam-writer? wtr) (convert-sam* rdr wtr num-block bam-write-alignments)
         :else (throw (ex-info (str "Unsupported output file format " out) {})))))
   nil)
+
+;;; FASTA <-> TwoBit
+
+(defn convert-sequence
+  "Converts file format between FASTA and TwoBit based on the file extension."
+  [in out]
+  (with-open [rdr (cseq/reader in)
+              wtr (cseq/writer out)]
+    (cseq/write-sequences wtr (cseq/read-all-sequences rdr {:mask? true}))))
+
+;;; General converter
+
+(def ^:private alignment-io? (every-pred (comp #{:sam :bam} io-util/file-type)))
+
+(def ^:private sequence-io? (every-pred (comp #{:fasta :2bit} io-util/file-type)))
+
+(defn convert
+  "Converts file format from input file to output file by the file extension."
+  [in out & opts]
+  (cond
+    (alignment-io? in out) (apply convert-sam in out opts)
+    (sequence-io? in out) (convert-sequence in out)
+    :else (throw (ex-info (str "Unsupported I/O pair: " in " and " out) {}))))


fixed keyboard events

fixed keyboard events

--- src/cljs/redditv/core.cljs
+++ src/cljs/redditv/core.cljs
@@ -78,7 +78,8 @@
                        37 ;; Left Arrow Key
                        (playlist/select-prev app-state)
                        39 ;; Right Arrow Key
-                       (playlist/select-next app-state))))))})
+                       (playlist/select-next app-state)
+                       nil)))))})

 (rum/defc app
   < mixin-keyboard-controls


adapt to search for the new core updates

--- src/cljs/smgui/search.cljs
+++ src/cljs/smgui/search.cljs
@@ -26,8 +26,8 @@

 (def status-map { :init       (define-status "time"        (fn [] ["Iniciando a busca..."]))
                   :info       (define-status "time"        (fn [] ["Carregando informações do vídeo..."]))
-                  :upload     (define-status "upload"      (fn [status] ["Enviando " (:upload status) " ..."]))
-                  :search     (define-status "search"      (fn [status] [(str "Buscando legendas nos idiomas: " (get-in status [:search :languages]))]))
+                  :upload     (define-status "upload"      (fn [status] ["Enviando " nil " ..."]))
+                  :search     (define-status "search"      (fn [status] [(str "Buscando legendas nos idiomas: " (get-in status [:search-languages]))]))
                   :download   (define-status "download"    (fn [status] ["Baixando legenda do servidor: " (-> status :download :source-name) "..."]))
                   :downloaded (define-status "check"       (fn [status] ["Baixado do servidor " (-> status :download :source-name) " (" (status-website-link status) ")"]))
                   :not-found  (define-status "error"       (fn [] ["Nenhuma legenda encontrada, tente novamente mais tarde"]))
@@ -44,10 +44,9 @@
              (>! out state)
              (if-let [data (<! in)]
                (let [[status info] data
-                     new-info (merge state {:status (if (contains? status-map status)
-                                                      status
-                                                      (:status state))
-                                            status info})]
+                     new-info (assoc info :status (if (contains? status-map status)
+                                                    status
+                                                    (:status state)))]
                  (if (trackable-states status) (track/search (name status)))
                  (recur new-info))
                (close! out)))


-has -> -hash typo

-has -> -hash typo

--- src/cognitect/transit.cljs
+++ src/cognitect/transit.cljs
@@ -40,11 +40,11 @@
     (eq/hashCode this))

   ty/UUID
-  (-has [this]
+  (-hash [this]
     (eq/hashCode this))

   ty/TaggedValue
-  (-has [this]
+  (-hash [this]
     (eq/hashCode this)))

 (defn opts-merge [a b]


fix #8639

fix #8639

Signed-off-by: Andrey Shovkoplyas <b713972e59b8e606e23253c4a13e948139fea4d1@gmail.com>

--- src/status_im/ui/screens/wallet/send/views.cljs
+++ src/status_im/ui/screens/wallet/send/views.cljs
@@ -21,21 +21,19 @@
    [toolbar/nav-button (actions/back-white #(actions/default-handler))]
    [toolbar/content-title {:color :white} title]])

-(defn- sign-transaction-button [amount-error amount sufficient-funds? online?]
-  (let [sign-enabled? (and (nil? amount-error)
-                           (not (nil? amount))
-                           sufficient-funds?
-                           online?)]
-    [bottom-buttons/bottom-buttons
-     styles/sign-buttons
-     [react/view]
-     [button/button {:style               components.styles/flex
-                     :disabled?           (not sign-enabled?)
-                     :on-press            #(re-frame/dispatch [:wallet.ui/sign-transaction-button-clicked])
-                     :text-style          {:color :white}
-                     :accessibility-label :sign-transaction-button}
-      (i18n/label :t/transactions-sign-transaction)
-      [vector-icons/icon :main-icons/next {:color (if sign-enabled? colors/white colors/white-light-transparent)}]]]))
+(defn- sign-transaction-button [sign-enabled?]
+  [bottom-buttons/bottom-buttons
+   styles/sign-buttons
+   [react/view]
+   [button/button {:style               components.styles/flex
+                   :disabled?           (not sign-enabled?)
+                   :on-press            #(re-frame/dispatch [:wallet.ui/sign-transaction-button-clicked])
+                   :text-style          {:color :white}
+                   :accessibility-label :sign-transaction-button}
+    (i18n/label :t/transactions-sign-transaction)
+    [vector-icons/icon :main-icons/next {:color (if sign-enabled?
+                                                  colors/white
+                                                  colors/white-light-transparent)}]]])

 (defn- render-send-transaction-view [{:keys [chain transaction scroll all-tokens amount-input network-status]}]
   (let [{:keys [amount amount-text amount-error asset-error to to-name sufficient-funds? symbol]} transaction
@@ -64,7 +62,11 @@
           :amount-text   amount-text
           :input-options {:on-change-text #(re-frame/dispatch [:wallet.send/set-and-validate-amount % symbol decimals])
                           :ref            (partial reset! amount-input)}} token]]]
-      [sign-transaction-button amount-error amount sufficient-funds? online?]]]))
+      [sign-transaction-button (and to
+                                    (nil? amount-error)
+                                    (not (nil? amount))
+                                    sufficient-funds?
+                                    online?)]]]))

 (defn- send-transaction-view [{:keys [scroll]}]
   (let [amount-input (atom nil)


Implement groups shape collapsing persistence.

With additional cosmetic improvemens.

--- src/uxbox/main/ui/workspace/sidebar/layers.cljs
+++ src/uxbox/main/ui/workspace/sidebar/layers.cljs
@@ -74,15 +74,6 @@
     (if blocked?
       (rs/emit! (uds/unblock-shape id))
       (rs/emit! (uds/block-shape id)))))
-
-(defn- toggle-locking
-  [item event]
-  (dom/stop-propagation event)
-  (let [id (:id item)
-        locked? (:locked item)]
-    (if locked?
-      (rs/emit! (uds/unlock-shape id))
-      (rs/emit! (uds/lock-shape id)))))

 (defn- element-icon
   [item]
@@ -221,24 +212,30 @@

 (mx/defcs layer-group
   {:mixins [mx/static mx/reactive (mx/local)]}
-  [own item selected]
+  [own {:keys [id] :as item} selected]
   (let [local (:rum/local own)
         selected? (contains? selected (:id item))
-        open? (:open @local true)
-        select #(select-shape selected item %)
-        toggle-visibility #(toggle-visibility selected item %)
-        toggle-blocking #(toggle-blocking item %)
-        toggle-locking #(toggle-locking item %)
-        toggle-open (fn [event]
-                      (dom/stop-propagation event)
-                      (swap! local assoc :open (not open?)))
-        shapes-by-id (mx/react wb/shapes-by-id-ref)
+        collapsed? (:collapsed item true)
+        shapes-map (mx/react wb/shapes-by-id-ref)
         classes (classnames
                  :selected selected?
                  :drag-top (= :top (:over @local))
                  :drag-bottom (= :bottom (:over @local))
-                 :drag-inside (= :middle (:over @local)))]
-    (letfn [(on-drag-start [event]
+                 :drag-inside (= :middle (:over @local)))
+        select #(select-shape selected item %)
+        toggle-visibility #(toggle-visibility selected item %)
+        toggle-blocking #(toggle-blocking item %)]
+    (letfn [(toggle-collapse [event]
+              (dom/stop-propagation event)
+              (if (:collapsed item)
+                (rs/emit! (uds/uncollapse-shape id))
+                (rs/emit! (uds/collapse-shape id))))
+            (toggle-locking [event]
+              (dom/stop-propagation event)
+              (if (:locked item)
+                (rs/emit! (uds/unlock-shape id))
+                (rs/emit! (uds/lock-shape id))))
+            (on-drag-start [event]
               (let [target (dom/event->target event)]
                 (dnd/set-allowed-effect! event "move")
                 (dnd/set-data! event (:id item))
@@ -247,12 +244,12 @@
               (swap! local assoc :dragging false :over nil))
             (on-drop [event]
               (dom/stop-propagation event)
-              (let [id (dnd/get-data event)
+              (let [coming-id (dnd/get-data event)
                     over (:over @local)]
                 (case (:over @local)
-                  :top (rs/emit! (uds/drop-shape id (:id item) :before))
-                  :bottom (rs/emit! (uds/drop-shape id (:id item) :after))
-                  :middle (rs/emit! (uds/drop-shape id (:id item) :inside)))
+                  :top (rs/emit! (uds/drop-shape coming-id id :before))
+                  :bottom (rs/emit! (uds/drop-shape coming-id id :after))
+                  :middle (rs/emit! (uds/drop-shape coming-id id :inside)))
                 (swap! local assoc :dragging false :over nil)))
             (on-drag-over [event]
               (dom/prevent-default event)
@@ -263,7 +260,7 @@
               (swap! local assoc :over true))
             (on-drag-leave [event]
               (swap! local assoc :over false))]
-      [:li.group {:class (when open? "open")}
+      [:li.group {:class (when-not collapsed? "open")}
        [:div.element-list-body
         {:class classes
          :draggable true
@@ -290,12 +287,12 @@
         [:div.element-icon i/folder]
         (shape-name item)
         [:span.toggle-content
-         {:on-click toggle-open
-          :class (when open? "inverse")}
+         {:on-click toggle-collapse
+          :class (when-not collapsed? "inverse")}
          i/arrow-slide]]
-       (if open?
+       (if-not collapsed?
          [:ul
-          (for [shape (map #(get shapes-by-id %) (:items item))
+          (for [shape (map #(get shapes-map %) (:items item))
                 :let [key (str (:id shape))]]
             (if (= (:type shape) :group)
               (-> (layer-group shape selected)
@@ -310,7 +307,7 @@
   []
   (let [workspace (mx/react wb/workspace-ref)
         selected (:selected workspace)
-        shapes-by-id (mx/react wb/shapes-by-id-ref)
+        shapes-map (mx/react wb/shapes-by-id-ref)
         page (mx/react (focus-page (:page workspace)))
         close #(rs/emit! (udw/toggle-flag :layers))
         duplicate #(rs/emit! (uds/duplicate-selected))
@@ -325,7 +322,7 @@
       [:div.tool-window-close {:on-click close} i/close]]
      [:div.tool-window-content
       [:ul.element-list {}
-       (for [shape (map #(get shapes-by-id %) (:shapes page))
+       (for [shape (map #(get shapes-map %) (:shapes page))
              :let [key (str (:id shape))]]
          (if (= (:type shape) :group)
            (-> (layer-group shape selected)


dec the initial-value instead of the result of inc

I believe this clarifies the function's body

--- src/vip/data_processor/db/translations/util.clj
+++ src/vip/data_processor/db/translations/util.clj
@@ -19,9 +19,9 @@
   Iteration 4 yields 17
   nil"
   [initial-value]
-  (let [counter (atom initial-value)]
+  (let [counter (atom (dec initial-value))]
     (fn []
-      (dec (swap! counter inc)))))
+      (swap! counter inc))))

 (defn column->xml-elment [column-name]
   (as-> column-name ?


Updating web-template

Updating web-template

--- modules/web-template/project.clj
+++ modules/web-template/project.clj
@@ -1,10 +1,10 @@
 ;; Copyright © 2014 JUXT LTD.

-(defproject juxt.modular/web-template "0.5.2"
+(defproject juxt.modular/web-template "0.6.2"
   :description "A modular extension that supports template data that is determined by the web request"
   :url "https://github.com/juxt/modular/tree/master/modules/template"
   :license {:name "The MIT License"
             :url "http://opensource.org/licenses/MIT"}
-  :dependencies [[com.stuartsierra/component "0.2.1"]
-                 [juxt.modular/template "0.5.0"]
+  :dependencies [[com.stuartsierra/component "0.2.2"]
+                 [juxt.modular/template "0.6.2"]
                  ])


handle vec of strings as property

handle vec of strings as property

--- src/crucible/resources.clj
+++ src/crucible/resources.clj
@@ -32,7 +32,9 @@

 (defn encode-resource-properties
   [template properties]
-  (into {} (map (fn [[k v]] [(encode-key k) (encode-value template v)]) (seq properties))))
+  (if (string? properties)
+    properties
+    (into {} (map (fn [[k v]] (when v [(encode-key k) (encode-value template v)])) (seq properties)))))

 (defn encode-resource
   [template {:keys [name properties creation-policy deletion-policy update-policy depends-on]}]


limit top-level validation to just generic res

--- src/crucible/resources.clj
+++ src/crucible/resources.clj
@@ -14,7 +14,7 @@

 (defmethod properties-type ::generic [_] ::generic)

-(s/def ::properties (s/multi-spec properties-type ::props-type))
+(s/def ::properties ::s/any)

 (s/def ::type (s/and string? #(re-matches #"([a-zA-Z0-9]+::)+[a-zA-Z0-9]+" %)))


Refactor naive factorial implementation.

--- src/dsbdp/experiment_helper.clj
+++ src/dsbdp/experiment_helper.clj
@@ -64,10 +64,11 @@
        n))))

 (defn factorial
-  [n]
-  (loop [result 1N i 1N]
+  ([n]
+    (factorial 1N 1N n))
+  ([result i n]
     (if (<= i n)
-      (recur (* result i) (inc i))
+      (recur (* result i) (inc i) n)
       result)))

 (defn create-factorial-proc-fns


Better debug info

Better debug info

--- src/yada/body.clj
+++ src/yada/body.clj
@@ -165,12 +165,12 @@

 (defmethod render-map :default
   [m representation]
-  (throw (ex-info (format "Attempt to call render-map without a media-type: %s" (pr-str representation))
+  (throw (ex-info (format "No implementation for render-map for media-type: %s" (mt/media-type (:media-type representation)))
                   {:representation representation})))

 (defmethod render-seq :default
   [m representation]
-  (throw (ex-info (format "Attempt to call render-seq without a media-type: %s" (pr-str representation))
+  (throw (ex-info (format "No implementation for render-seq for media-type: %s" (mt/media-type (:media-type representation)))
                   {:representation representation})))


Conneg promoted to much further up the chain

--- src/yada/core.clj
+++ src/yada/core.clj
@@ -195,8 +195,8 @@
       trace                             ; async-supported

       ;; Service overrides
-      body                              ; async-supported
-      last-modified                     ; async-supported (in the future)
+      body                             ; async-supported
+      last-modified                    ; async-supported (in the future)

       produces
       produces-charsets
@@ -241,6 +241,105 @@
                       (ex-info "" (merge {:status 503
                                           ::http-response true}
                                          (when-let [retry-after (service/retry-after res)] {:headers {"retry-after" retry-after}})))))))
+
+
+               ;; Content-type and charset negotiation - done here to throw back to the client any errors
+               ;; conneg is done just after service availability, which is done first to allow attack mitigation
+               ;; We want to know the user-agent's capabilities early on in order to throw back errors, if they occur, in the correct format.
+               (fn [ctx]
+                 (let [available-content-types
+                       (map mime/string->media-type (remove nil?
+                                                            (or (service/produces produces ctx)
+                                                                (res/produces resource ctx))))]
+
+                   ;; Check to see if the server-specified charset is
+                   ;; recognized (registered with IANA). If it isn't we
+                   ;; throw a 500, as this is a server error. (It might be
+                   ;; necessary to disable this check in future but a
+                   ;; balance should be struck between giving the
+                   ;; developer complete control to dictate charsets, and
+                   ;; error-proofing. It might be possible to disable
+                   ;; this check for advanced users if a reasonable case
+                   ;; is made.)
+                   (when-let [bad-charset
+                              (some (fn [mt] (when-let [charset (some-> mt :parameters (get "charset"))]
+                                              (when-not (charset/valid-charset? charset) charset)))
+                                    available-content-types)]
+                     (throw (ex-info (format "Resource or service declares it produces an unknown charset: %s" bad-charset) {:charset bad-charset})))
+
+
+                   ;; Negotiate the content type
+                   (if-let [content-type
+                            (conneg/negotiate-content-type
+                             ;; TODO: Check, if no Accept header, does it really default to */* ?
+                             (or (get-in req [:headers "accept"]) "*/*")
+                             available-content-types)]
+
+                     (assoc-in ctx [:response :content-type] content-type)
+
+                     ;; No content type negotiated means a 406
+                     (if (not-empty available-content-types)
+                       ;; If there is a produces specification, but not
+                       ;; matched content-type, it's a 406.
+                       (d/error-deferred
+                        (ex-info ""
+                                 {:status 406
+                                  ::debug {:message "No acceptable content-type"
+                                           :available-content-types available-content-types}
+                                  ::http-response true}))
+                       ;; Otherwise return the context unchanged
+                       ctx))))
+
+               (link ctx
+                 ;; Check there is no incompatible Accept-Charset header.
+
+                 ;; A request without any Accept-Charset header field
+                 ;; implies that the user agent will accept any
+                 ;; charset in response.  Most general-purpose user
+                 ;; agents do not send Accept-Charset.
+                 ;; rfc7231.html#section-5.3.3
+
+                 (let [available-charsets
+
+                       (remove nil?
+                               (or (service/produces-charsets produces-charsets ctx)
+                                   (res/produces-charsets resource ctx)
+                                   ;;[(charset/to-charset-map (.name (java.nio.charset.Charset/defaultCharset)))]
+                                   ))
+                       accept-charset (get-in req [:headers "accept-charset"])]
+
+                   (if-let [charset (conneg/negotiate-charset accept-charset available-charsets)]
+
+                     (-> ctx
+                         (assoc-in [:response :charset] charset)
+                         ;; Update charset in ctx content-type
+                         (update-in [:response :content-type]
+                                    (fn [ct] (if (and ct
+                                                     ;; Only for text media-types
+                                                     (= (:type ct) "text")
+                                                     ;; But don't overwrite an existing charset
+                                                     (not (some-> ct :parameters (get "charset"))))
+                                              (assoc-in ct [:parameters "charset"] (first charset))
+                                              ct))))
+
+                     ;; We should support the case where a resource or
+                     ;; service declares charset parameters in the
+                     ;; content-types they declare in :produces.
+
+                     ;; If no charset (usually only if there's an
+                     ;; explicit Accept-Charset header sent, or the
+                     ;; resource really declares that it provides no
+                     ;; charsets), then send a 406, a per the
+                     ;; specification.
+
+                     (when accept-charset
+                       (d/error-deferred
+                        (ex-info ""
+                                 {:status 406
+                                  ::debug {:message "No acceptable charset"}
+                                  ::http-response true}))))))
+
+

                (link ctx
                  (when-not
@@ -401,98 +500,7 @@

-               ;; Content-type and charset negotiation - done here to throw back to the client any errors
-               (fn [ctx]
-                 (let [available-content-types
-                       (map mime/string->media-type (remove nil?
-                                                            (or (service/produces produces ctx)
-                                                                (res/produces resource ctx))))]
-
-                   ;; Check to see if the server-specified charset is
-                   ;; recognized (registered with IANA). If it isn't we
-                   ;; throw a 500, as this is a server error. (It might be
-                   ;; necessary to disable this check in future but a
-                   ;; balance should be struck between giving the
-                   ;; developer complete control to dictate charsets, and
-                   ;; error-proofing. It might be possible to disable
-                   ;; this check for advanced users if a reasonable case
-                   ;; is made.)
-                   (when-let [bad-charset
-                              (some (fn [mt] (when-let [charset (some-> mt :parameters (get "charset"))]
-                                              (when-not (charset/valid-charset? charset) charset)))
-                                    available-content-types)]
-                     (throw (ex-info (format "Resource or service declares it produces an unknown charset: %s" bad-charset) {:charset bad-charset})))
-
-
-                   ;; Negotiate the content type
-                   (if-let [content-type
-                            (conneg/negotiate-content-type
-                             ;; TODO: Check, if no Accept header, does it really default to */* ?
-                             (or (get-in req [:headers "accept"]) "*/*")
-                             available-content-types)]
-
-                     (assoc-in ctx [:response :content-type] content-type)
-
-                     ;; No content type negotiated means a 406
-                     (if (not-empty available-content-types)
-                       ;; If there is a produces specification, but not
-                       ;; matched content-type, it's a 406.
-                       (d/error-deferred
-                        (ex-info ""
-                                 {:status 406
-                                  ::debug {:message "No acceptable content-type"
-                                           :available-content-types available-content-types}
-                                  ::http-response true}))
-                       ;; Otherwise return the context unchanged
-                       ctx))))
-
-               (link ctx
-                 ;; Check there is no incompatible Accept-Charset header.
-
-                 ;; A request without any Accept-Charset header field
-                 ;; implies that the user agent will accept any
-                 ;; charset in response.  Most general-purpose user
-                 ;; agents do not send Accept-Charset.
-                 ;; rfc7231.html#section-5.3.3
-
-                 (let [available-charsets
-                       (remove nil?
-                               (or (service/produces-charsets produces-charsets ctx)
-                                   (res/produces-charsets resource ctx)
-                                   ;;[(charset/to-charset-map (.name (java.nio.charset.Charset/defaultCharset)))]
-                                   ))
-                       accept-charset (get-in req [:headers "accept-charset"])]
-
-                   (if-let [charset (conneg/negotiate-charset accept-charset available-charsets)]
-
-                     (-> ctx
-                         (assoc-in [:response :charset] charset)
-                         ;; Update charset in ctx content-type
-                         (update-in [:response :content-type]
-                                    (fn [ct] (if (and ct
-                                                     ;; Only for text media-types
-                                                     (= (:type ct) "text")
-                                                     ;; But don't overwrite an existing charset
-                                                     (not (some-> ct :parameters (get "charset"))))
-                                              (assoc-in ct [:parameters "charset"] (first charset))
-                                              ct))))
-
-                     ;; We should support the case where a resource or
-                     ;; service declares charset parameters in the
-                     ;; content-types they declare in :produces.
-
-                     ;; If no charset (usually only if there's an
-                     ;; explicit Accept-Charset header sent, or the
-                     ;; resource really declares that it provides no
-                     ;; charsets), then send a 406, a per the
-                     ;; specification.
-
-                     (when accept-charset
-                       (d/error-deferred
-                        (ex-info ""
-                                 {:status 406
-                                  ::debug {:message "No acceptable charset"}
-                                  ::http-response true}))))))
+

                ;; Do the fetch here
                ;; The pre-fetch can return a deferred result. (TODO think


extended the navigation and added dummy entries to it, formatted it to work with bootstrap v4

--- src-cljs/bitfondue/core.cljs
+++ src-cljs/bitfondue/core.cljs
@@ -20,10 +20,20 @@

 (defn header
   []
-  [:nav.navbar.navbar-default
-   [:div.container-fluid
-    [:div.navbar-header
-     [:a.navbar-brand "bitfondue"]]]])
+  [:nav.navbar.navbar-light.bg-faded
+   [:a.navbar-brand {:href "/"} "bitfondue"]
+   [:ul.nav.navbar-nav
+    [:li.nav-item
+     [:a.nav-link {:href "#"} "Features"]]
+    [:li.nav-item
+     [:a.nav-link {:href "#"} "Pricing"]]
+    [:li.nav-item
+     [:a.nav-link {:href "#"} "About"]]]
+   [:ul.nav.navbar-nav.pull-right
+    [:li.nav-item
+     [:a.nav-link {:href "#"} "Login"]]
+    [:li.nav-item
+     [:a.nav-link {:href "#"} "Register"]]]])

 (defn layout
   []


make tools shortcuts consistent with adobe's

--- src-cljs/frontend/state.cljs
+++ src-cljs/frontend/state.cljs
@@ -21,11 +21,11 @@
                                         :main-menu-learned false
                                         :chat-button-learned false
                                         :login-button-learned false}}
-   :keyboard-shortcuts {:select #{"s"}
-                        :circle #{"c"}
-                        :rect #{"r"}
-                        :line #{"l"}
-                        :pen #{"p"}
+   :keyboard-shortcuts {:select #{"v"}
+                        :circle #{"l"}
+                        :rect #{"m"}
+                        :line #{"/"}
+                        :pen #{"n"}
                         :text #{"t"}
                         :undo #{"meta+z" "ctrl+z"}
                         :shortcuts-menu #{"shift+/"}


balloon positioning

balloon positioning

--- src-cljs/jasons-game/ui.cljs
+++ src-cljs/jasons-game/ui.cljs
@@ -4,7 +4,6 @@
             [jasons-game.draw :as d]
             [jasons-game.thing :as t]
             [jasons-game.thing.person]
-            [jasons-game.speech-balloon :refer [say]]
             [jasons-game.world :as w]
             [libre.sketch :as s]))

@@ -24,16 +23,21 @@
   ; display coordinates in text box
   (d/set-text-box! [:div "x:" [:span.highlight x] ", y:" [:span.highlight y]]))

+
+;; World
+
+(def world (w/new-world))
+
 (defn say [thing speech]
   (w/add-thing world {:type :speech-balloon
                       :name :speech-balloon
-                      :location (:location thing)
+                      :location (let [[x y] (:location thing)
+                                      [x0 y0 w h] (t/bounds-in-local thing)]
+                                  [x (+ y y0)])
                       :sentence speech}))

 ;; Sketch
-
-(def world (w/new-world))

 (defn setup []
   (s/size (.-innerWidth js/window) (.-innerHeight js/window))


Implement a very rough prototype of the LMAX Disruptor based queue

Disruptor is known to beat queue performance extremely well.
Certainly this prototype doesn't involve things like back pressure,
event optimisation (GC pressure because of event instances created
every time) also memory access across the barrier and many
other possible optimisations, but it might serve as a good basis
for further discussion.

--- src/io/cyanite/engine/queue.clj
+++ src/io/cyanite/engine/queue.clj
@@ -6,6 +6,7 @@
            com.lmax.disruptor.RingBuffer
            com.lmax.disruptor.dsl.Disruptor
            com.lmax.disruptor.EventFactory
+           com.lmax.disruptor.EventTranslatorOneArg
            com.lmax.disruptor.EventHandler)
   (:require [com.stuartsierra.component :as component]
             [clojure.tools.logging      :refer [warn]]
@@ -14,7 +15,7 @@
 (defcounter cnt-queue)
 (defcounter cnt-errors)
 (defonce default-poolsize 4)
-(defonce default-capacity (int 10e2))
+(defonce default-capacity (int 1024))

 (defprotocol QueueEngine
   (consume! [this k opts f])
@@ -25,6 +26,25 @@
   (reify EventFactory
     (newInstance [this]
       (ctor))))
+
+(defprotocol WrapperEvent
+  (get-data [_])
+  (set-data [this v]))
+
+;; For sakes of prototyping, we are using the mutable
+;; wrapper. This is not very idiomatic to ring buffer,
+;; so it's better to use mutable bags of primitives.
+;; If the approach with RB proves itself, we will migrate
+;; the code to use it.
+(deftype Event [^{:volatile-mutable true} x]
+  WrapperEvent
+  (get-data [_] x)
+  (set-data [this v] (set! x v)))
+
+(defn wrapper-event-factory
+  []
+  (make-event-factory
+   (fn [] (Event. nil))))

 (defn threadpool
   [sz]
@@ -38,45 +58,50 @@
   [p & body]
   `(pool-future-call ~p (fn [] ~@body)))

-(defn ring-buffer
-  [size]
-  )
+(defn disruptor
+  [event-factory size executor]
+  (Disruptor. event-factory size executor))
+
+(defn make-translator
+  [f]
+  (reify EventTranslatorOneArg
+    (translateTo [this event sequence arg0]
+      (f event arg0))))
+
 (defn linked-queue
   [sz]
   (java.util.concurrent.ArrayBlockingQueue.
    (int sz)))

-(defrecord BlockingMemoryQueue [state pool defaults]
+(defrecord BlockingMemoryQueue [state defaults]
   component/Lifecycle
   (start [this]
+    (assoc this
+           :state (atom {})
+           ))
+  (stop [this]
+    (doseq [[_ {:keys [[pool disruptor]]}] @state]
+      (.shutdown disruptor)
+      (.shutdown pool))
+    (assoc this :state nil))
+  QueueEngine
+  (consume! [this k opts f]
     (let [sz   (or (:pool-size opts)
                    (get-in defaults [k :pool-size])
-                   default-poolsize)]
-      (assoc this
-             :state (atom {})
-             pool (threadpool sz))))
-  (stop [this]
-    (.shutdown (:pool @state))
-    (assoc this :state nil))
-  QueueEngine
-  (consume! [this k opts event-ctor f]
-    (let [cap  (or (:queue-capacity opts)
-                   (get-in defaults [k :queue-capacity])
-                   default-capacity)
-          rb    (ring-buffer (event-factory event-ctor) cap pool)]
-      (swap! state assoc k {:ring-buffer rb})
-      (.handleEventsWith rb
-                         (reify EventHandler
-                           (onEvent [this event sequence eob]
-                             (f event))))
-      (.start rb)))
+                   default-poolsize)
+          pool (threadpool sz)
+          cap       (or (:queue-capacity opts)
+                        (get-in defaults [k :queue-capacity])
+                        default-capacity)
+          disruptor (disruptor (wrapper-event-factory) cap pool)]
+      (swap! state assoc k {:disruptor  disruptor
+                            :translator (make-translator (fn [e v]  (set-data e v)))})
+      (.handleEventsWith disruptor
+                         (into-array [(reify EventHandler
+                                         (onEvent [this event sequence eob]
+                                           (f (get-data event))))]))
+      (.start disruptor)))
   (add! [this k e]
-    (if-let [q (get-in @state [k :queue])]
-      (do (inc! cnt-queue)
-          (try
-            (.add q e)
-            (catch IllegalStateException e
-              ;; Queue is full
-              (inc! cnt-errors)
-              (warn "queue is full"))))
-      (throw (ex-info "cannot find queue" {:queue-name k})))))
+    ;; TODO: dereferencing is an expensive operation going through the atomic memory barrier
+    (let [{:keys [disruptor translator]} (get @state k)]
+      (.publishEvent disruptor translator e))))


Make rendering faster by avoiding apply in more places

--- src/reagent/impl/component.cljs
+++ src/reagent/impl/component.cljs
@@ -142,9 +142,6 @@
         res)
       (ratom/run rat))))

-(defn reactive-render [C]
-  (run-reactively C #(do-render C) #(queue-render C)))
-

 ;;; Function wrapping

@@ -154,42 +151,48 @@
     (assert false "getDefaultProps not supported yet")

     :getInitialState
-    (fn [C]
-      (when f
-        (aset C cljs-state (merge (state C) (f C)))))
+    (fn []
+      (this-as C
+               (when f
+                 (aset C cljs-state (merge (state C) (f C))))))

     :componentWillReceiveProps
-    (fn [C props]
-      (when f (f C (aget props cljs-argv))))
+    (fn [props]
+      (this-as C
+               (when f (f C (aget props cljs-argv)))))

     :shouldComponentUpdate
-    (fn [C nextprops nextstate]
-      ;; Don't care about nextstate here, we use forceUpdate
-      ;; when only when state has changed anyway.
-      (let [inprops (js-props C)
-            old-argv (aget inprops cljs-argv)
-            new-argv (aget nextprops cljs-argv)]
-        (if (nil? f)
-          (not (util/equal-args old-argv new-argv))
-          (f C old-argv new-argv))))
+    (fn [nextprops nextstate]
+      (this-as C
+               ;; Don't care about nextstate here, we use forceUpdate
+               ;; when only when state has changed anyway.
+               (let [inprops (js-props C)
+                     old-argv (aget inprops cljs-argv)
+                     new-argv (aget nextprops cljs-argv)]
+                 (if (nil? f)
+                   (not (util/equal-args old-argv new-argv))
+                   (f C old-argv new-argv)))))

     :componentWillUpdate
-    (fn [C nextprops]
-      (let [next-argv (aget nextprops cljs-argv)]
-        (f C next-argv)))
+    (fn [nextprops]
+      (this-as C
+               (let [next-argv (aget nextprops cljs-argv)]
+                 (f C next-argv))))

     :componentDidUpdate
-    (fn [C oldprops]
-      (let [old-argv (aget oldprops cljs-argv)]
-        (f C old-argv)))
+    (fn [oldprops]
+      (this-as C
+               (let [old-argv (aget oldprops cljs-argv)]
+                 (f C old-argv))))

     :componentWillUnmount
-    (fn [C]
-      (let [ratom (.-cljsRatom C)]
-        (if-not (nil? ratom)
-          (ratom/dispose! ratom)))
-      (set! (.-cljsIsDirty C) false)
-      (when f (f C)))
+    (fn []
+      (this-as C
+               (let [ratom (.-cljsRatom C)]
+                 (if-not (nil? ratom)
+                   (ratom/dispose! ratom)))
+               (set! (.-cljsIsDirty C) false)
+               (when f (f C))))

     nil))

@@ -199,7 +202,7 @@
       (this-as C (apply f C args)))
     f))

-(def dont-wrap #{:cljsRender})
+(def dont-wrap #{:cljsRender :render})

 (defn get-wrapper [key f name]
   (if (dont-wrap key)
@@ -209,7 +212,7 @@
       (when (and wrap f)
         (assert (fn? f)
                 (str "Expected function in " name key " but got " f)))
-      (default-wrapper (or wrap f)))))
+      (or wrap (default-wrapper f)))))

 (def obligatory {:shouldComponentUpdate nil
                  :componentWillUnmount nil})
@@ -224,7 +227,10 @@
 (defn add-render [fun-map render-f]
   (assoc fun-map
     :cljsRender render-f
-    :render reactive-render))
+    :render (fn []
+              (this-as C
+                       (run-reactively
+                        C #(do-render C) #(queue-render C))))))

 (defn wrap-funs [fun-map]
   (let [render-fun (or (:componentFunction fun-map)


A pair generator is just a tuple

A pair generator is just a tuple

Makes sure that pairs keep their count at two during shrinking.

--- src/simple_check/generators.clj
+++ src/simple_check/generators.clj
@@ -159,7 +159,9 @@
 ;; Generic generators and helpers
 ;; ---------------------------------------------------------------------------

-(defn pair
+(declare tuple)
+
+(def pair
   "Create a generator that generates two-vectors that generate a value
   from `a` and `b`.

@@ -167,10 +169,7 @@

       (pair gen/int gen/int)
   "
-  [a b]
-  [:gen (fn [rand-seed size]
-    [(call-gen a rand-seed size)
-     (call-gen b rand-seed size)])])
+  tuple)

 (defn shrink-index
   [coll index]


Releasing bootstrap 0.1.0

Releasing bootstrap 0.1.0

--- modules/bootstrap/project.clj
+++ modules/bootstrap/project.clj
@@ -1,6 +1,6 @@
 ;; Copyright © 2014 JUXT LTD.

-(defproject juxt.modular/bootstrap "0.1.0-SNAPSHOT"
+(defproject juxt.modular/bootstrap "0.1.0"
   :description "A modular extension that HTML rendering of components with the Twitter Bootstrap library."
   :url "https://github.com/juxt/modular/tree/master/modules/bootstrap"
   :license {:name "The MIT License"
@@ -11,5 +11,5 @@
                  [prismatic/plumbing "0.2.2"]
                  [hiccup "1.0.5"]
                  [garden "1.1.5"]
-                 [juxt.modular/web-template "0.5.0"]
-                 [juxt.modular/bidi "0.4.0"]])
+                 [juxt.modular/web-template "0.5.1"]
+                 [juxt.modular/bidi "0.5.2"]])


show uers

show uers

--- src/frontend/renderer.cljs
+++ src/frontend/renderer.cljs
@@ -116,6 +116,20 @@
         (dom/div #js {:id "uploads-queue"}
           (om/build-all upload-view (:uploads data)))))))

+(defn user-view [data owner]
+  (reify
+    om/IRender
+    (render [_]
+      (dom/div nil
+        (data "username")))))
+
+(defn users-list-view [data owner]
+  (reify
+    om/IRender
+    (render [_]
+      (dom/div nil
+        (om/build-all user-view (vals data))))))
+
 (defn chat-view [data owner]
   (reify
     om/IRenderState
@@ -123,7 +137,9 @@
       (let [width (:width state)]
         (dom/div #js {:id "center-left"
                       :style #js {:width width}}
-          (om/build messages-window nil))))))
+          (list
+            (om/build messages-window nil)
+            (om/build users-list-view (:users data))))))))

 (defn center-area [data owner]
   (reify
@@ -141,7 +157,7 @@
                         (om/set-state! owner
                                        :dimensions
                                        {:chat-width (str left-width "px")
-                                        :track-queue-width (str right-width "px")}))))
+                                        :track-queue-width (str right-width "px")})))
       ((om/get-state owner :handle-resize))
       (dommy/listen! js/window :resize (om/get-state owner :handle-resize)))
     om/IWillUnmount
@@ -150,10 +166,10 @@
     om/IRenderState
     (render-state [_ state]
       (dom/div #js {:id "center-area"}
-        (list
-          (let [dimensions {:dimensions state}]
+        (let [dimensions (:dimensions state)]
+          (list
             (om/build chat-view data {:state {:width (:chat-width dimensions)}})
-            (om/build track-queue-view data {:state {:width (:track-queue-width dimensions)}}))))))
+            (om/build track-queue-view data {:state {:width (:track-queue-width dimensions)}})))))))

 (defn volume-control [data owner]
   (reify


forgot to import schema.core

forgot to import schema.core

--- src/gangway/validation.clj
+++ src/gangway/validation.clj
@@ -1,6 +1,7 @@
 (ns gangway.validation
   (:require [clojure.data.json :as json]
             [hatch]
+            [schema.core :as s]
             [navigator.validation :as nav-val]
             [oarlock.validation :as oar-val]))


Rolled dependencies

Rolled dependencies

--- src/leiningen/amp/run_jetty.clj
+++ src/leiningen/amp/run_jetty.clj
@@ -54,7 +54,7 @@
   (let [war (install/locate-war project args)
         xml (temp-jetty-xml project)]
     (Runner/main (into-array String
-                             ["--lib" (lib "/.m2/repository/com/h2database/h2/1.3.174")
+                             ["--lib" (lib "/.m2/repository/com/h2database/h2/1.4.181")
                               "--lib" (lib "/.m2/repository/tk/skuro/alfresco/h2-support/1.6")
                               "--config" (str xml)
                               (str war)]))))


more elegant handling of missing value in timeseries.

--- src/clj/forma/hadoop/jobs/load_tseries.clj
+++ src/clj/forma/hadoop/jobs/load_tseries.clj
@@ -33,25 +33,25 @@
          (apply map tupleize)
          (map-indexed cons))))

-;; TODO: Make sure that this is really the right missing val. Probably not!
-(def
-  ^{:doc "Predicate macro aggregator that generates a timeseries, given
-  `?chunk`, `?temporal-resolution` and `?date`. Currently only
-  functions when `?chunk` is an instance of `forma.schema.DoubleArray`."}
-  form-tseries
+(defn form-tseries
+  "Returns a predicate macro aggregator that generates a timeseries,
+  given `?chunk`, `?temporal-resolution` and `?date`. Currently only
+  functions when `?chunk` is an instance of
+  `forma.schema.DoubleArray`."
+  [missing-val]
   (<- [?temporal-res ?date ?chunk :> ?pix-idx ?t-start ?t-end ?tseries]
       (datetime->period ?temporal-res ?date :> ?tperiod)
       (:sort ?tperiod)
-      (timeseries [-9999] ?tperiod ?chunk :> ?pix-idx ?t-start ?t-end ?tseries)))
+      (timeseries [missing-val] ?tperiod ?chunk :> ?pix-idx ?t-start ?t-end ?tseries)))

-;; TODO: Get count-vals working for int arrays
 (defn extract-tseries
-  [chunk-source]
-  (<- [?dataset ?s-res ?t-res ?tilestring ?chunk-size
-       ?chunkid ?pix-idx ?t-start ?t-end ?tseries]
-      (chunk-source ?dataset ?s-res ?t-res ?tilestring ?date ?chunkid ?chunk)
-      (io/count-vals ?chunk :> ?chunk-size)
-      (form-tseries ?t-res ?date ?chunk :> ?pix-idx ?t-start ?t-end ?tseries)))
+  [chunk-source missing-val]
+  (let [mk-tseries (form-tseries missing-val)]
+    (<- [?dataset ?s-res ?t-res ?tilestring ?chunk-size
+         ?chunkid ?pix-idx ?t-start ?t-end ?tseries]
+        (chunk-source ?dataset ?s-res ?t-res ?tilestring ?date ?chunkid ?chunk)
+        (io/count-vals ?chunk :> ?chunk-size)
+        (mk-tseries ?t-res ?date ?chunk :> ?pix-idx ?t-start ?t-end ?tseries))))

 (defn process-tseries
   "Given a source of timeseries, this subquery extracts the proper
@@ -63,11 +63,14 @@
       (tilestring->hv ?tilestring :> ?tile-h ?tile-v)
       (tile-position ?s-res ?chunk-size ?chunkid ?pix-idx :> ?sample ?line)))

+;; TODO: this needs to go.
+(def *missing-val* -9999)
+
 (defn -main
   [in-path output-path]
   (?- (hfs-seqfile output-path)
       (-> (hfs-seqfile in-path)
-          extract-tseries
+          (extract-tseries *missing-val*)
           process-tseries)))

 ;; This is the old one, that allows for the pieces. We'll reinstitute


% tooltip in pie chart (nodes)

% tooltip in pie chart (nodes)

--- src/cljs/swarmpit/component/node/list.cljs
+++ src/cljs/swarmpit/component/node/list.cljs
@@ -14,10 +14,17 @@
             [sablono.core :refer-macros [html]]
             [rum.core :as rum]
             [goog.string.format]
+            [goog.string :as gstring]
             [clojure.contrib.inflect :as inflect]
             [clojure.contrib.humanize :as humanize]))

 (enable-console-print!)
+
+(defn- render-percentage
+  [val]
+  (if (some? val)
+    (str (gstring/format "%.2f" val) "%")
+    "-"))

 (defn- node-item-state [value]
   (case value
@@ -36,19 +43,19 @@

 (defn node-used [stat]
   (cond
-    (< stat 75) {:name  "actual"
+    (< stat 75) {:name  "used"
                  :value stat
                  :color "#43a047"}
-    (> stat 90) {:name  "actual"
+    (> stat 90) {:name  "used"
                  :value stat
                  :color "#d32f2f"}
-    :else {:name  "actual"
+    :else {:name  "used"
            :value stat
            :color "#ffa000"}))

-(rum/defc node-graph [stat label id]
+(rum/defc node-graph < rum/static [stat label id]
   (let [data [(node-used stat)
-              {:name  "rest"
+              {:name  "free"
                :value (- 100 stat)
                :color "#ccc"}]]
     (chart/pie
@@ -56,10 +63,10 @@
       label
       "Swarmpit-node-stat-graph"
       id
-      nil)))
+      {:formatter (fn [value name props]
+                    (render-percentage value))})))

-(defn- node-item
-  [item index]
+(rum/defc node-item < rum/static [item index]
   (let [cpu (-> item :resources :cpu (int))
         memory-bytes (-> item :resources :memory (* 1024 1024))
         disk-bytes (-> item :stats :disk :total)]


Fixed typo.

Fixed typo.

--- src/cljs/wombats_web_client/utils/url.cljs
+++ src/cljs/wombats_web_client/utils/url.cljs
@@ -1,6 +1,6 @@
 (ns wombats-web-client.utils.url
   (:require [pushy.core :as pushy]
-            [wombats-web-client.routes :refer [history]][wombats-web-client.routes :refer [history]]))
+            [wombats-web-client.routes :refer [history]]))

 (defn strip-access-token
   "removes access token from query"


Fix the triple-ID initiate check in server

bit-twiddling/bytes= needs byte-arrays because (so far) it can't handle
ByteBuf instances.

--- src/clojure/frereth_cp/server/initiate.clj
+++ src/clojure/frereth_cp/server/initiate.clj
@@ -9,7 +9,7 @@
             [frereth-cp.shared.crypto :as crypto]
             [frereth-cp.util :as util])
   (:import clojure.lang.ExceptionInfo
-           io.netty.buffer.Unpooled))
+           [io.netty.buffer ByteBuf Unpooled]))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Named Constants
@@ -288,7 +288,6 @@

 (s/fdef verify-client-public-key-triad
         :args (s/cat :state ::state/state
-                     :client-long-key ::shared/long-pk
                      :supplied-client-short-key ::shared/short-pk
                      ;; TODO: Come up with a ByteBuf spec
                      ::client-message-box any?)
@@ -313,7 +312,9 @@
 * impose policy limitations on clients: known, maxconn
 * for known clients, retrieve shared secret from cache
 "
-  [state supplied-client-short-key client-message-box]
+  [state
+   ^ByteBuf supplied-client-short-key
+   client-message-box]
   (let [client-long-buffer (::K/long-term-public-key client-message-box)
         client-long-key (byte-array K/key-length)]
     (.getBytes client-long-buffer 0 client-long-key)
@@ -322,15 +323,6 @@
                                             my-long-secret)]
       (log/info (str "Getting ready to decrypt the inner-most hidden public key\n"
                      "Supplied client long-term key:\n"
-                     ;; This next should match:
-                     #_[0x26 0x9f 0x81 0x8d
-                        0x4a 0xfc 0x55 0x04
-                        0xad 0x01 0x34 0xfd
-                        0xb0 0xa4 0xf4 0x12
-                        0xe3 0x64 0x96 0xae
-                        0x8c 0xe7 0x14 0xb5
-                        0x70 0x76 0x62 0xb2
-                        0x64 0xb8 0x3f 0x19]
                      (b-t/->string client-long-key)
                      "which arrived in: "
                      client-long-buffer
@@ -339,24 +331,17 @@
                      "My long-term public key:\n"
                      (b-t/->string (.getPublicKey (get-in state [::shared/my-keys ::shared/long-pair])))
                      "Shared:\n"
-                     ;; Client's version:
-                     #_[0xc5 0x91 0x62 0xcd
-                        0xfe 0xc1 0x33 0x89
-                        0xa3 0xff 0x82 0x3d
-                        0x26 0x2d 0x09 0x03
-                        0x09 0xbc 0x9e 0xdd
-                        0x35 0x87 0x1b 0x1c
-                        0x81 0xb5 0xff 0x2a
-                        0xa9 0xe1 0x6b 0x58]
                      (b-t/->string shared-secret)))
-      ;; Failing here.
-      ;; The shared secret doesn't match what the client used to encrypt the box.
-      (when-let [inner-pk (crypto/open-crypto-box
-                           K/vouch-nonce-prefix
-                           (::K/inner-i-nonce client-message-box)
-                           (::K/hidden-client-short-pk client-message-box)
-                           shared-secret)]
-        (b-t/bytes= supplied-client-short-key inner-pk)))))
+      (when-let [^ByteBuf inner-pk-buf (crypto/open-crypto-box
+                                        K/vouch-nonce-prefix
+                                        (::K/inner-i-nonce client-message-box)
+                                        (::K/hidden-client-short-pk client-message-box)
+                                        shared-secret)]
+        (let [inner-pk (byte-array K/key-length)
+              short-pk (byte-array K/key-length)]
+          (.getBytes inner-pk-buf 0 inner-pk)
+          (.getBytes supplied-client-short-key 0 short-pk)
+          (b-t/bytes= short-pk inner-pk))))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Public


Addressed review comments.

Addressed review comments.

--- src/cmr/search/services/health_service.clj
+++ src/cmr/search/services/health_service.clj
@@ -15,5 +15,5 @@
         ok? (every? :ok? [echo-rest-health metadata-db-health index-set-health])]
     {:ok? ok?
      :dependencies {:echo echo-rest-health
-                    :metadata-db metadata-db-health
+                    :internal-metadata-db metadata-db-health
                     :index-set index-set-health}}))


modified hello world header

modified hello world header

--- examples/helloworld.clj
+++ examples/helloworld.clj
@@ -1,3 +1,3 @@
-":"; mkdir -p ~/.dj; if [ ! -e "$HOME/.dj/run" ]; then cd $HOME/.dj; curl -O 'https://raw.githubusercontent.com/bmillare/dj3/master/bin/run'; cd -; fi; exec sh ~/.dj/run $0 $@
+":"; if [ ! -e "$HOME/.rundj" ]; then curl 'https://raw.githubusercontent.com/bmillare/dj3/master/bin/run' > $HOME/.rundj ; fi; exec sh ~/.rundj $0 $@
 (prn "clojure runs baybe" *command-line-args*)
 (println (System/getProperty "user.dir"))


Tidy up namespace definition

Tidy up namespace definition

--- src/tabular/grafter/tabular.clj
+++ src/tabular/grafter/tabular.clj
@@ -1,16 +1,16 @@
-(ns grafter.tabular
+(ns ^{:doc "Functions for processing tabular data."}
+  grafter.tabular
   "Functions for processing tabular data."
-  (:require [clojure.set :as set]
-            [clojure.string :as str]
-            [grafter.pipeline :refer [graft-form->Pipeline]]
-            [grafter.tabular.common :refer [lift->vector map-keys] :as tabc]
-            [grafter.tabular.csv]
-            [grafter.tabular.excel]
-            [grafter.tabular.melt]
-            [clojure.tools.logging :refer [spy]]
+  (:require [clojure
+             [set :as set]
+             [string :as str]]
+            [grafter
+             [common :refer [build-defgraft-docstring]]
+             [pipeline :refer [graft-form->Pipeline]]]
+            [grafter.tabular.common :as tabc :refer [lift->vector map-keys]]
             [incanter.core :as inc]
             [potemkin.namespaces :refer [import-vars]]
-            [grafter.common :refer [build-defgraft-docstring]]))
+            [grafter.tabular.melt]))

 (import-vars
  [grafter.tabular.common


If device is alredy registered don't show the error

--- src/mambobox_mobile/events.cljs
+++ src/mambobox_mobile/events.cljs
@@ -38,13 +38,21 @@
 ;;;;;;;;;;;;;;;;;;;;

 (reg-event-fx
+ :device-register-error
+ []
+ (fn [_ [_ {:keys [status] :as error}]]
+   ;; if the device is already registered don't show any errors
+   (when (not= status 409)
+     {:dispatch [:error error]})))
+
+(reg-event-fx
   :initialize-app
   [validate-spec-mw debug (inject-cofx :device-info)]
   (fn [cofxs _]
     (let [{:keys [uniq-id locale country]} (:device-info cofxs)]
      {:db app-db
       :http-xhrio (assoc (services/register-device-http-fx uniq-id locale country)
-                         :on-failure [:error]
+                         :on-failure [:device-register-error]
                          :on-success [:initialize-success])
       ;; TODO Remove this hack, it's only until we call register if it wasn't registered
       :dispatch [:initialize-success]})))


allow http(s) on elb loadbalancer

allow http(s) on elb loadbalancer

--- src/terraboot/elasticsearch.clj
+++ src/terraboot/elasticsearch.clj
@@ -96,6 +96,7 @@
                                      :subnets (mapv #(id-of "aws_subnet" (stringify  vpc_name "-public-" %)) azs)
                                      :instances [(id-of "aws_instance" (vpc-unique "kibana"))]
                                      :sgs ["allow_outbound"
+                                           "allow_external_http_https"
                                            (vpc-unique "elb-kibana")
                                            ]})


Implemented a Clojure datastore query parser.

--- src/appengine_magic/services/datastore.clj
+++ src/appengine_magic/services/datastore.clj
@@ -1,12 +1,30 @@
 (ns appengine-magic.services.datastore
   (:import [com.google.appengine.api.datastore DatastoreService DatastoreServiceFactory
             Key KeyFactory KeyRange
-            Entity]))
+            Entity
+            Query Query$FilterOperator Query$SortDirection]))

 (defonce *datastore-service* (atom nil))
-
 (defonce *current-transaction* nil)
+
+
+(defonce *filter-operator-map*
+  {:eq Query$FilterOperator/EQUAL
+   :gt Query$FilterOperator/GREATER_THAN
+   :ge Query$FilterOperator/GREATER_THAN_OR_EQUAL
+   :in Query$FilterOperator/IN
+   :lt Query$FilterOperator/LESS_THAN
+   :le Query$FilterOperator/LESS_THAN_OR_EQUAL
+   :ne Query$FilterOperator/NOT_EQUAL})
+
+
+(defonce *sort-direction-map*
+  {:ascending Query$SortDirection/ASCENDING
+   :asc Query$SortDirection/ASCENDING
+   :descending Query$SortDirection/DESCENDING
+   :dsc Query$SortDirection/DESCENDING
+   :desc Query$SortDirection/DESCENDING})

 (defn get-datastore-service []
@@ -156,3 +174,54 @@
        (catch Throwable err#
          (do (.rollback *current-transaction*)
              (throw err#))))))
+
+
+(defn query [& {:keys [kind ancestor filter sort keys-only]
+                :or {keys-only false, filter [[]], sort [[]]}}]
+  (let [kind (cond (nil? kind) kind
+                   (string? kind) kind
+                   (extends? EntityProtocol kind) (unqualified-name kind)
+                   :else (throw (RuntimeException. "invalid kind specified in query")))
+        ancestor-key-object (cond (instance? Key ancestor) ancestor
+                                  (extends? EntityProtocol ancestor) (get-key-object ancestor)
+                                  :else nil)
+        query-object (cond (and (nil? kind) (nil? ancestor-key-object)) (Query.)
+                           (nil? kind) (Query. ancestor-key-object)
+                           (nil? ancestor-key-object) (Query. kind)
+                           :else (Query. kind ancestor-key-object))
+        ;; normalize filter criteria into a vector (even if there's just one)
+        filter (if (every? sequential? filter) filter (vector filter))
+        ;; normalize sort criteria into a vector (even if there's just one)]
+        sort (if (every? sequential? sort) sort (vector sort))]
+    (when keys-only
+      (.setKeysOnly query-object))
+    (doseq [[filter-operator filter-property-kw filter-value] filter]
+      (cond
+       ;; valid filter provided
+       (and (not (nil? filter-operator))
+            (not (nil? filter-property-kw))
+            (not (nil? filter-value))
+            (keyword? filter-property-kw))
+       (let [op-object (get *filter-operator-map* filter-operator)
+             filter-property (.substring (str filter-property-kw) 1)]
+         (.addFilter query-object filter-property op-object filter-value))
+       ;; no filter definition
+       (and (nil? filter-operator) (nil? filter-property-kw) (nil? filter-value))
+       nil
+       ;; invalid filter
+       :else (throw (RuntimeException. "invalid filter specified in query"))))
+    (doseq [[sort-property-kw sort-direction] sort]
+      (cond
+       ;; valid sort provided
+       (and (not (nil? sort-property-kw))
+            (not (nil? sort-direction))
+            (keyword? sort-property-kw))
+       (let [sort-property (.substring (str sort-property-kw) 1)
+             sort-direction-object (get *sort-direction-map* sort-direction)]
+         (.addSort query-object sort-property sort-direction-object))
+       ;; no sort definition
+       (and (nil? sort-property-kw) (nil? sort-direction))
+       nil
+       ;; invalid sort
+       :else (throw (RuntimeException. "invalid sort specified in query"))))
+    query-object))


Formatting long lines

Formatting long lines

--- src/braid/client/ui/views/threads.cljs
+++ src/braid/client/ui/views/threads.cljs
@@ -10,24 +10,26 @@
         this-elt (r/atom nil)
         reset-threads! (fn [new-threads]
                          (reset! threads (vec new-threads)))
-        update-threads! (fn [new-threads]
-                          (swap! threads
-                                 (fn [old-threads]
-                                   (let [old-thread-ids (set (map :id old-threads))
-                                         new-thread-ids (set (map :id new-threads))
-                                         to-remove (difference old-thread-ids new-thread-ids)
-                                         to-add (difference new-thread-ids old-thread-ids)
-                                         ordered-ids (concat (remove to-remove old-thread-ids)
-                                                             (filter to-add new-thread-ids))]
-                                     (mapv (comp first (group-by :id new-threads)) ordered-ids)))))
-        scroll-horizontally (fn [e]
-                              (let [target-classes (.. e -target -classList)]
-                                ; TODO: check if threads-div needs to scroll?
-                                (when (and (or (.contains target-classes "thread")
-                                               (.contains target-classes "threads"))
-                                        (= 0 (.-deltaX e) (.-deltaZ e)))
-                                  (set! (.-scrollLeft @this-elt)
-                                        (- (.-scrollLeft @this-elt) (.-deltaY e))))))]
+        update-threads!
+        (fn [new-threads]
+          (swap! threads
+                 (fn [old-threads]
+                   (let [old-thread-ids (set (map :id old-threads))
+                         new-thread-ids (set (map :id new-threads))
+                         to-remove (difference old-thread-ids new-thread-ids)
+                         to-add (difference new-thread-ids old-thread-ids)
+                         ordered-ids (concat (remove to-remove old-thread-ids)
+                                             (filter to-add new-thread-ids))]
+                     (mapv (comp first (group-by :id new-threads)) ordered-ids)))))
+        scroll-horizontally
+        (fn [e]
+          (let [target-classes (.. e -target -classList)]
+            ; TODO: check if threads-div needs to scroll?
+            (when (and (or (.contains target-classes "thread")
+                           (.contains target-classes "threads"))
+                    (= 0 (.-deltaX e) (.-deltaZ e)))
+              (set! (.-scrollLeft @this-elt)
+                    (- (.-scrollLeft @this-elt) (.-deltaY e))))))]
     (r/create-class
       {:display-name "threads-view"


do batched hydration for annotation.creator

--- src/metabase/api/annotation.clj
+++ src/metabase/api/annotation.clj
@@ -7,7 +7,8 @@
             [metabase.db :refer :all]
             [metabase.models.hydrate :refer :all]
             (metabase.models [annotation :refer [Annotation annotation-general annotation-description]]
-                             [org :refer [Org]])
+                             [org :refer [Org]]
+                             [user :refer [User]])
             [metabase.util :as util]))

@@ -34,7 +35,7 @@
         (sel :many Annotation :organization_id org :object_type_id object_model :object_id object_id (korma/order :start :DESC))
         ;; default is to return all annotations
         (sel :many Annotation :organization_id org (korma/order :start :DESC)))
-      (hydrate :author)))
+      (simple-batched-hydrate User :author_id :author)))

 (defendpoint POST "/" [:as {{:keys [organization start end title body annotation_type object_model object_id]