fixed uploading while stopped

fixed uploading while stopped

--- src/frontend/uploads.cljs
+++ src/frontend/uploads.cljs
@@ -118,8 +118,8 @@
         stream (.createStream js/ss)
         blob-stream (.createBlobReadStream js/ss file)
         upload-watch-fn! (fn [_ _ old-state new-state]
-                           (println "COUNT:" (count (:active-uploads @app-state/app-state)))
-                           (let [action (get-action old-state new-state upload-id)]
+                           (let [action (get-action old-state new-state upload-id)
+                                 upload (get (:uploads @app-state/app-state) upload-id)]
                              (if-not (nil? action)
                                (do
                                  (println "ACTION:" action)
@@ -127,11 +127,13 @@
                                  (cond
                                    (= action :paused)
                                      (.unpipe blob-stream)
-                                   (= action :unpaused)
+                                   (and (= action :unpaused)
+                                        (:started? upload))
                                      (.pipe blob-stream stream)
                                    (= action :stopped)
                                      (.unpipe blob-stream)
-                                   (= action :started)
+                                   (and (= action :started)
+                                        (not (:paused? upload)))
                                      (.pipe blob-stream stream))))))]
     (.on blob-stream "end"
       (fn []


whitespace

whitespace

--- test/babel/test/it.cljc
+++ test/babel/test/it.cljc
@@ -837,13 +837,16 @@

 (deftest present-progressive-reflexive
-  (is (= "loro si stanno addormentando" (morph (generate {:synsem {:cat :verb
-                                                                   :subcat []
-                                                                   :sem {:tense :present
-                                                                         :aspect :progressive
-                                                                         :subj {:pred :loro}}}
-                                                          :modified false
-                                                          :root {:italiano {:italiano "addormentarsi"}}})))))
+  (is (= "loro si stanno addormentando"
+         (-> {:synsem {:cat :verb
+                       :subcat []
+                       :sem {:tense :present
+                             :aspect :progressive
+                             :subj {:pred :loro}}}
+              :modified false
+              :root {:italiano {:italiano "addormentarsi"}}}
+             morph
+             generate))))

 (defn generate-speed-test [spec & [times]]
   (btest/generate-speed-test spec model times))


s/def/defn/

s/def/defn/

--- test/babel/test/la.cljc
+++ test/babel/test/la.cljc
@@ -41,7 +41,7 @@
          (conjugate "ardēre"
                     {:synsem {:sem {:subj {:pred :noi}}}}))))

-(def model (-> ((-> models target-language)) deref))
+(defn model [] (-> ((-> models target-language)) deref))

 (deftest generate-present
   (is (= "ardetis"
@@ -71,7 +71,7 @@
               {:root "ardēre"
                :synsem {:sem {:subj {:pred :voi}
                               :tense :present}}}
-              model)))))
+              (model))))))

 (deftest reader1
   (let [spec {:synsem {:sem {:subj {:pred :lui}
@@ -100,7 +100,7 @@
         result (read-one {:root "ardēre"
                           :synsem {:sem {:tense :past
                                          :aspect :progressive}}}
-                         model source-model)
+                         (model) source-model)
         ;; for specific literal strings in the result.
         subj (get-in result [:semantics :subj :pred])
         possible-answer (first (get result :targets))]


sprinkle a little spec back in

sprinkle a little spec back in

--- src/mccarthy_animation/character.cljc
+++ src/mccarthy_animation/character.cljc
@@ -3,11 +3,16 @@
             [quil.core :as quil :include-macros true]
             [mccarthy-animation.config :as config]))

-(spec/def ::x        int?) ; check overflows elsewhere
-(spec/def ::y        int?) ; check overflows elsewhere
-(spec/def ::position (spec/keys :req [::x ::y]))
+(defonce image-keys   [:stand1 :blink1 :tap1 :moveL1 :moveL2 :moveR1 :moveR2])

-(defonce image-keys   [:stand1 :blink1 :tap1 :moveL1 :moveL2 :moveR1 :moveR2])
+;; define what it is to be a hero
+(spec/def ::x        int?)
+(spec/def ::y        int?)
+(spec/def ::position (spec/keys :req-un [::x ::y]))
+(spec/def ::size     (spec/keys :req-un [::x ::y]))
+(spec/def ::id       string?)
+(spec/def ::name     string?)
+(spec/def ::hero     (spec/keys :req-un [::name ::position ::size])) ;; TODO why does id fail?

 ;; {:stand 1 :move 4}
 (defonce image-counts (frequencies (map #(keyword (apply str (take (- (count (name %)) 1) (name %)))) image-keys)))
@@ -65,20 +70,22 @@

 (defn create
   ([name images initial-x initial-y size-x size-y]
-   {:id (gensym "char-")
-    :name name
-    :images images
-    :animation :stand
-    :position {:x initial-x :y initial-y}
-    :size {:x size-x :y size-y}
-    :speed 2
+   {:id         (gensym "char-")
+    :name       name
+    :images     images
+    :animation  :stand
+    :position   {:x initial-x :y initial-y}
+    :size       {:x size-x    :y size-y}
+    :speed      2
     :halo-angle (rand-int 360)
     })
   ([name initial-x initial-y]
    (create name (load-images) initial-x initial-y (:x config/hero-size) (:y config/hero-size))))

 (defn- move-to? [screen-size sprite-size new-position]
-  ;;{:pre [(spec/valid? ::position new-position)]} ; throw on bogus input
+  {:pre [(spec/valid? ::position screen-size)  ; throw on bogus input
+         (spec/valid? ::position sprite-size)
+         (spec/valid? ::position new-position)]}
   (cond
     (> (:x new-position) (- (:x screen-size) (:x sprite-size))) false
     (> (:y new-position) (- (:y screen-size) (:y sprite-size))) false
@@ -87,6 +94,7 @@
     :else true))

 (defn proposed-position [hero direction]
+  {:pre [(spec/valid? ::hero hero)]}
   (let [speed   (:speed hero)
         x-delta (cond (= :right direction)       speed
                       (= :left  direction) (* -1 speed)
@@ -98,6 +106,7 @@
      :y (+ (:y (:position hero)) y-delta)} ))

 (defn ensure-screen-position [hero direction]
+  {:pre [(spec/valid? ::hero hero)]}
   ;; keep the hero on-screen
   (let [new-pos (proposed-position hero direction)]
     (if (move-to? config/screen-size (:size hero) new-pos)


Fixes conpath bug

Fixes conpath bug

--- src/org/zalando/stups/friboo/ring.clj
+++ src/org/zalando/stups/friboo/ring.clj
@@ -29,15 +29,27 @@
     (not-found {})
     (response (first results))))

+(defmacro xor
+  [a b]
+  `(or (and ~a (not ~b))
+       (and (not ~a) ~b)))
+
 (defn conpath
   "Concatenates path elements to an URL."
   [url & path]
   (let [[x & xs] path]
     (if x
-      (let [url (if (or
-                      (.endsWith url "/")
-                      (.startsWith x "/"))
+      (let [first-with-slash (.endsWith url "/")
+            last-with-slash  (.startsWith x "/")
+            url (if (xor first-with-slash
+                         last-with-slash)
+                  ; concat if exactly one of them has a /
                   (str url x)
-                  (str url "/" x))]
+                  (if (and first-with-slash
+                           last-with-slash)
+                    ; if both have a /, remove one
+                    (str url (s/replace-first x #"/" ""))
+                    ; if none have a /, add one
+                    (str url "/" x)))]
         (recur url xs))
       url)))


(PE-2368) get-in-config can now recieve a default if the requested key is missing

--- src/puppetlabs/trapperkeeper/core.clj
+++ src/puppetlabs/trapperkeeper/core.clj
@@ -46,7 +46,7 @@
   ((services/service :config-service
     {:depends  []
      :provides [get-in-config get-config]}
-    {:get-in-config (fn [ks] (get-in config ks))
+    {:get-in-config (partial get-in config)
      :get-config    (fn [] config)})))

 (defn- parse-config-file


abstracting layers and loss functions

abstracting layers and loss functions

--- src/thinktopic/cortex/autoencoder.clj
+++ src/thinktopic/cortex/autoencoder.clj
@@ -7,14 +7,121 @@

 (mat/set-current-implementation :vectorz)

-;; Primary Protocols
+;; Neural Protocols
+
 (defprotocol NeuralLayer
   (forward [this input] "Pass data into the layer and return its output.")
   (backward [this input output-gradient] "Back propagate error gradients through the layer."))

-(defprotocol CostFn
-  (cost [this activation target])
-  (delta [this activation z target]))
+(defprotocol LossFn
+  (loss [this v target])
+  (delta [this v target]))
+
+;; Helpers
+(defn exp
+  [a]
+  (mat/emap #(Math/exp %) a))
+
+(defn exp!
+  [a]
+  (mat/emap! #(Math/exp %) a))
+
+(defn log
+  [a]
+  (mat/emap #(Math/log %) a))
+
+(defn log!
+  [a]
+  (mat/emap! #(Math/log %) a))
+
+(defn rand-vector
+  "Produce a vector with guassian random elements having mean of 0.0 and std of 1.0."
+  [n]
+  (let [rgen (Random.)]
+    (mat/array (repeatedly n #(.nextGaussian rgen)))))
+
+(defn rand-matrix
+  [m n]
+  (let [rgen (Random.)]
+    (mat/array (repeatedly m (fn [] (repeatedly n #(.nextGaussian rgen)))))))
+
+(defn weight-matrix
+  [m n]
+  (let [stdev (/ 1.0 n)]
+    (mat/emap #(* stdev %) (rand-matrix m n))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Activation Functions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; NOTE: This form of computing a sigmoid over a matrix is faster than mapping
+; over each individual element.  Using the mutable versions of most functions
+; saves .
+(defn sigmoid
+  "y =  1 / (1 + e^(-z))
+  Produces an output between 0 and 1."
+  [z]
+  (mat/div! (mat/add! (exp! (mat/negate z)) 1.0)))
+
+(defn sigmoid!
+  "y =  1 / (1 + e^(-z))
+  Produces an output between 0 and 1."
+  [z]
+  (mat/div! (mat/add! (exp! (mat/negate! z)) 1.0)))
+
+(defn sigmoid'
+  [z]
+  (let [sz (sigmoid z)]
+    (mat/emul sz (mat/sub 1.0 sz))))
+
+(defrecord SigmoidActivation [output]
+  NeuralLayer
+  (forward [this input]
+    (mat/assign! output input)
+    (sigmoid! output))
+
+  ; z = dot(weights, input) + b
+  ; activation = sigmoid(z)
+  (backward [this input output-gradient]
+    (mat/emul output-gradient (sigmoid' input))))
+
+(defn sigmoid-activation
+  [shape]
+  (map->SigmoidActivation {:output (mat/zero-array shape)}))
+
+(defn softmax
+  "Used for multinomial classification (choose 1 of n classes), where the output
+  layer can be interpreted as class probabilities."
+  [z]
+  (mat/div z (mat/esum z)))
+
+(defrecord LinearLayer [weights biases weight-gradients bias-gradients outputs]
+  NeuralLayer
+  (forward [this input]
+    (mat/assign! outputs biases)
+    (mat/add! outputs (mat/mmul weights input)))
+
+  (backward [this input output-gradient]
+    (mat/fill! weight-gradients 0.0)
+    (mat/assign! bias-gradients output-gradient)
+
+    ; Compute the error gradients with respect to the input data by multiplying the
+    ; output errors backwards through the weights, and then compute the error
+    ; with respect to the weights by multiplying the input error times the
+    ; output error.
+    (let [input-grad (mat/mmul (mat/transpose weights) output-gradient)]
+      (mat/assign! weight-gradients (mat/outer-product output-gradient input-grad)))))
+
+(defn linear-layer
+  [n-inputs n-outputs]
+  (let [weights (weight-matrix n-outputs n-inputs)
+        biases (rand-matrix 1 n-outputs)]
+    (map->LinearLayer
+      {:weights weights
+       :biases biases
+       :weight-gradients (mat/zero-array (mat/shape weights))
+       :bias-gradients (mat/zero-array (mat/shape biases))
+       :outputs (mat/zero-array (mat/shape biases))})))

 (defrecord SequentialNetwork [layers config]
   NeuralLayer
@@ -24,118 +131,45 @@
             input layers))

   (backward [this input output-gradient]
-    ))
-
-(defn network
-  [layers & opts]
-  {:n-layers (count layers)
-   :biases (map rand-vector (next layer-sizes))
-   :weights (map weight-matrix (rest layer-sizes) (drop-last layer-sizes))
-   :cost-fn (get opts :cost-fn (QuadraticCost.))})
-
-(defrecord LinearLayer [weights biases]
-  NeuralLayer
-  (forward [this input]
-    (assoc this :output (mat/add (mat/mmul weights input) biases)))
-
-  (backward [this input output-gradient]
-    ))
-
-(reduce
-  (fn [[activations zs] [layer-biases layer-weights]]
-    )
-  [[input] []] ; initialize zs to nil so it's the same shape as activations
-  (map vector biases weights))
-
-(defn feed-forward
-  [{:keys [biases weights] :as net} input]
-  (when (and biases weights)
-    (loop [biases biases
-           weights weights
-           activation input]
-      (if biases
-        (let [z (mat/add (mat/mmul (first weights) activation)
-                         (first biases))
-              activation (sigmoid z)]
-          (recur (next biases) (next weights) activation))
-        activation))))
-;; Helpers
-(defn exp
-  [a]
-  (mat/emap #(Math/exp %) a))
-
-(defn log
-  [a]
-  (mat/emap #(Math/log %) a))
-
-(defn rand-vector
-  "Produce a vector with guassian random elements having mean of 0.0 and std of 1.0."
-  [n]
-  (let [rgen (Random.)]
-    (mat/array (repeatedly n #(.nextGaussian rgen)))))
-
-(defn rand-matrix
-  [m n]
-  (let [rgen (Random.)]
-    (mat/array (repeatedly m (fn [] (repeatedly n #(.nextGaussian rgen)))))))
-
-(defn weight-matrix
-  [m n]
-  (let [stdev (/ 1.0 n)]
-    (mat/emap #(* stdev %) (rand-matrix m n))))
+    (reduce (fn [out-grad [prev-layer layer]]
+              (backward layer (:output prev-layer) out-grad))
+            output-gradient
+            (map vector (reverse layers)
+                 (concat (next (reverse layers)) [{:output input}])))))
+
+(defn sgd-optimizer
+  [net loss-fn {:keys [learning-rate batch-size] :as opts}]
+  (fn [input label]
+    (let [output (forward net input)
+          loss (loss loss-fn output label)
+          error (delta loss-fn output label)])))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Activation Functions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defn sigmoid
-  [z]
-  (mat/div 1.0 (mat/add 1.0 (exp (mat/negate z)))))
-
-(defn sigmoid'
-  [z]
-  (mat/emul (sigmoid z) (mat/sub 1.0 (sigmoid z))))
-
-(deftype SigmoidActivation []
-  NeuralLayer
-  (forward [this input]
-    (sigmoid input))
-
-  (backward [this input output-gradient]
-    nil))
-
-(defn softmax
-  "Used for multinomial classification (choose 1 of n classes), where the output
-  layer can be interpreted as class probabilities."
-  [z]
-  (mat/div z (mat/esum z)))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Cost Functions
+;; Loss Functions
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defn mean-squared-error
   [activation target]
   (mat/div (mat/esum (mat/pow (mat/sub activation target) 2))
            (mat/ecount activation)))

-(deftype QuadraticCost []
-  CostFn
-  (cost [this activation target]
+(deftype QuadraticLoss []
+  LossFn
+  ; L = sum(0.5 * (output - label)^2)
+  (loss [this v target]
     ; NOTE: linear/norm is different for matrices and vectors so this row-matrix
     ; conversion is important for correctness.
-    (let [diff (mat/sub activation target)
+    (let [diff (mat/sub v target)
           diff (if (mat/vec? diff) (mat/row-matrix diff) diff)]
       (mat/mul 0.5 (mat/pow (linear/norm diff) 2))))

-  (delta [this activation z target]
-    (mat/emul (mat/sub activation target) (sigmoid' z))))
+  (delta [this v z target]
+    (mat/emul (mat/sub v target) (sigmoid' z))))

 (def SMALL-NUM 1e-30)

-(deftype CrossEntropyCost []
-  CostFn
-  (cost [this activation target]
+(deftype CrossEntropyLoss []
+  LossFn
+  (loss [this activation target]
     (let [a (mat/mul (mat/negate target) (log (mat/add SMALL-NUM activation)))
           b (mat/mul (mat/sub 1.0 target) (log (mat/sub (+ 1.0 SMALL-NUM) a)))
           c (mat/esum (mat/sub a b))]
@@ -144,14 +178,14 @@
   (delta [this activation z target]
     (mat/sub activation target)))

-(defn costs
+(defn losses
   []
   (let [a [0.2, 0.3, 0.1, 0.9]
         b [0.0, 0.0, 0.0, 1.0]
-        qc (QuadraticCost.)
-        ce (CrossEntropyCost.)]
-    (println "QuadraticCost: " (cost qc a b))
-    (println "CrossEntropyCost: " (cost ce a b))))
+        qc (QuadraticLoss.)
+        ce (CrossEntropyLoss.)]
+    (println "QuadraticLoss: " (loss qc a b))
+    (println "CrossEntropyLoss: " (loss ce a b))))

 ;; K-sparse autoencoder
 ;0) setup
@@ -209,7 +243,7 @@
 ;; 4) update weights
 ;;  * multiply gradient by the learning-rate to smooth out jitter in updates.
 (defn backprop
-  [{:keys [biases weights cost-fn n-layers] :as net} input expected-output]
+  [{:keys [biases weights loss-fn n-layers] :as net} input expected-output]
   (let [bias-gradients (map #(mat/zero-array (mat/shape %)) biases)
         weight-gradients (map #(mat/zero-array (mat/shape %)) weights)
         [activations zs] (reduce
@@ -322,6 +356,13 @@
           ;(println (format "sample score: %5.2f" (float (/ sample-score sample-size))))
           (recur new-net (inc epoch)))))))

+(defn network
+  [layer-sizes & opts]
+  {:n-layers (count layer-sizes)
+   :biases (map rand-vector (next layer-sizes))
+   :weights (map weight-matrix (rest layer-sizes) (drop-last layer-sizes))
+   :loss-fn (get opts :loss-fn (QuadraticLoss.))})
+
 (def trained* (atom nil))

 (defn mnist-labels


Remove game namespace before creating it

--- desktop/src/nightmod/core/desktop_launcher.clj
+++ desktop/src/nightmod/core/desktop_launcher.clj
@@ -56,6 +56,7 @@
 (defn load-game!
   "Loads game into the canvas and runs it in a sandbox."
   [path]
+  (remove-ns 'nightmod.game)
   (binding [*ns* (create-ns 'nightmod.game)]
     (clojure.core/refer 'clojure.core)
     (require '[nightmod.public :refer :all]


fix tests for :path instead of :parent

fix tests for :path instead of :parent

--- test/com/billpiel/mem_tracer/core_test.clj
+++ test/com/billpiel/mem_tracer/core_test.clj
@@ -50,27 +50,26 @@
     (mt/add-trace-ns! 'com.billpiel.mem-tracer.test.ns1)
     (com.billpiel.mem-tracer.test.ns1/func1 :a)
     (let [trace (mt/deref-workspace!)
-          expected-trace {:id "root10",
-                          :depth 0,
-                          :children
-                          [{:args [:a],
-                            :children
-                            [{:args [:a],
-                              :children [],
-                              :return :a,
-                              :started-at #inst "2010-01-01T02:00:00.000-00:00",
-                              :name "com.billpiel.mem-tracer.test.ns1/func2",
-                              :id "12",
-                              :parent-id "11",
-                              :ended-at #inst "2010-01-01T03:00:00.000-00:00",
-                              :depth 2}],
-                            :return :a,
-                            :started-at #inst "2010-01-01T01:00:00.000-00:00",
-                            :name "com.billpiel.mem-tracer.test.ns1/func1",
-                            :id "11",
-                            :parent-id "root10",
-                            :ended-at #inst "2010-01-01T04:00:00.000-00:00",
-                            :depth 1}],
+          expected-trace {:children [{:args [:a]
+                                      :children [{:args [:a]
+                                                  :children []
+                                                  :depth 2
+                                                  :ended-at #inst "2010-01-01T03:00:00.000-00:00"
+                                                  :id "12"
+                                                  :name "com.billpiel.mem-tracer.test.ns1/func2"
+                                                  :path ["root10" "11"]
+                                                  :return :a
+                                                  :started-at #inst "2010-01-01T02:00:00.000-00:00"}]
+                                      :depth 1
+                                      :ended-at #inst "2010-01-01T04:00:00.000-00:00"
+                                      :id "11"
+                                      :name "com.billpiel.mem-tracer.test.ns1/func1"
+                                      :path ["root10"]
+                                      :return :a
+                                      :started-at #inst "2010-01-01T01:00:00.000-00:00"}]
+                          :depth 0
+                          :id "root10"
+                          :path []
                           :traced #{[:ns 'com.billpiel.mem-tracer.test.ns1]}}]

       (fact "log is correct"
@@ -107,6 +106,7 @@
       => {:children []
           :depth 0
           :id "root10"
+          :path []
           :traced #{[:ns 'com.billpiel.mem-tracer.test.ns1]}})

     (fact "enable-all-traces! works"
@@ -121,18 +121,19 @@
                                   :ended-at #inst "2010-01-01T03:00:00.000-00:00"
                                   :id "12"
                                   :name "com.billpiel.mem-tracer.test.ns1/func2"
-                                  :parent-id "11"
+                                  :path ["root10" "11"]
                                   :return :a
                                   :started-at #inst "2010-01-01T02:00:00.000-00:00"}]
                       :depth 1
                       :ended-at #inst "2010-01-01T04:00:00.000-00:00"
                       :id "11"
                       :name "com.billpiel.mem-tracer.test.ns1/func1"
-                      :parent-id "root10"
+                      :path ["root10"]
                       :return :a
                       :started-at #inst "2010-01-01T01:00:00.000-00:00"}]
           :depth 0
           :id "root10"
+          :path []
           :traced #{[:ns 'com.billpiel.mem-tracer.test.ns1]}})

     (mtt/untrace-ns* 'com.billpiel.mem-tracer.test.ns1)))
@@ -150,7 +151,11 @@
       (com.billpiel.mem-tracer.test.ns1/func1 :a)

       (mt/deref-workspace!)
-      => {:children [] :depth 0 :id "root10" :traced #{}})
+      => {:children []
+          :depth 0
+          :id "root10"
+          :path []
+          :traced #{}})

     (mtt/untrace-ns* 'com.billpiel.mem-tracer.test.ns1)))

@@ -375,6 +380,7 @@
         (dissoc trace :children)
         => {:depth 0
             :id "root10"
+            :path []
             :traced #{[:ns 'com.billpiel.mem-tracer.test.ns1]}})

       (fact "log is correct"
@@ -402,7 +408,7 @@
             :ended-at #inst "2010-01-01T02:00:00.000-00:00"
             :id "10"
             :name "com.billpiel.mem-tracer.test.ns1/func-throws"
-            :parent-id "root10"
+            :path ["root10"]
             :started-at #inst "2010-01-01T01:00:00.000-00:00"})

       (fact "string output is correct"


bugfix RightsStatement entity (predicate)

--- src/imago/graph/model.clj
+++ src/imago/graph/model.clj
@@ -156,7 +156,7 @@
   {:user    {:prop (:subject rdf)
              :validate [(v/uuid4)]
              :init (pick-id :user)}
-   :perm    {:prop (:subject rdf)
+   :perm    {:prop (:predicate rdf)
              :validate [(v/required)]}
    :context {:prop (:object rdf)
              :validate [(v/uuid4)]


Added split-path for clojure

Added split-path for clojure

--- clojure/cljsearch/src/cljsearch/fileutil.clj
+++ clojure/cljsearch/src/cljsearch/fileutil.clj
@@ -44,13 +44,16 @@
 (defn is-dot-dir? [name]
   (contains? #{"." ".."} name))

+(defn split-path [f]
+  (split (.getPath f) (re-pattern File/separator)))
+
 (defn hidden? [name]
   (and
     (.startsWith name ".")
     (not (is-dot-dir? name))))

 (defn hidden-dir? [d]
-  (let [elems (split (.getPath d) (re-pattern File/separator))]
+  (let [elems (split-path d)]
     (some #(hidden? %) elems)))

 (defn hidden-file? [f]


remove debug statement

remove debug statement

--- src/overtone/sc/synth.clj
+++ src/overtone/sc/synth.clj
@@ -502,7 +502,6 @@

 (defn update-tap-data
   [msg]
-  (println "hi jeffers: " msg)
   (let [[node-id label-id val] (:args msg)
         node                     (get @active-synth-nodes* node-id)
         label                    (get (:tap-labels node) label-id)


Remove origin-x/origin-y and add scale-x/scale-y to shape

--- src/play_clj/entities.clj
+++ src/play_clj/entities.clj
@@ -86,29 +86,24 @@
     (.render renderer object attributes)))

 (defrecord ShapeEntity [object] Entity
-  (draw-entity! [{:keys [^ShapeRenderer object type draw! x y width height
-                         angle origin-x origin-y]}
+  (draw-entity! [{:keys [^ShapeRenderer object type draw!
+                         x y scale-x scale-y angle]}
                  {:keys [^Camera camera]}
                  batch]
-    (when (or x y)
-      (let [^Matrix4 m (.getTransformMatrix object)
-            x (float (or x 0))
-            y (float (or y 0))]
-        (.setTranslation m x y 0)
-        (.setTransformMatrix object m)))
     (when batch
       (.end ^SpriteBatch batch))
     (when camera
       (.setProjectionMatrix object (. camera combined)))
     (.begin object type)
-    (when angle
+    (when (or x y scale-x scale-y angle)
       (let [x (float (or x 0))
             y (float (or y 0))
-            origin-x (float (or origin-x (/ (or width 0) 2)))
-            origin-y (float (or origin-y (/ (or height 0) 2)))
+            scale-x (float (or scale-x 1))
+            scale-y (float (or scale-y 1))
             angle (float (or angle 0))]
         (.identity object)
-        (.translate object (+ x origin-x) (+ y origin-y) 0)
+        (.translate object x y 0)
+        (.scale object scale-x scale-y 1)
         (.rotate object 0 0 1 angle)))
     (draw!)
     (.end object)


fix on fonts resources

fix on fonts resources

--- src/pretty/cli/figlet.clj
+++ src/pretty/cli/figlet.clj
@@ -23,7 +23,8 @@
   usaflag, wavy, weird.
   "
   ([text font]
-   (-> (str "resources/fonts/" font ".flf")
+   (-> (str "fonts/" font ".flf")
+       (io/resource)
        (io/input-stream)
        (FigletFont/convertOneLine text)))
   ([text] (figlet text "standard")))


Add typehints to suppress infer externs warnings

Fixes #591

--- src/re_frame/interop.cljs
+++ src/re_frame/interop.cljs
@@ -24,7 +24,11 @@
   (reagent.core/atom x))

 (defn ratom? [x]
-  (satisfies? reagent.ratom/IReactiveAtom x))
+  ;; ^:js suppresses externs inference warnings by forcing the compiler to
+  ;; generate proper externs. Although not strictly required as
+  ;; reagent.ratom/IReactiveAtom is not JS interop it appears to be harmless.
+  ;; See https://shadow-cljs.github.io/docs/UsersGuide.html#infer-externs
+  (satisfies? reagent.ratom/IReactiveAtom ^js x))

 (defn deref? [x]
   (satisfies? IDeref x))
@@ -53,7 +57,11 @@
   "Produces an id for reactive Reagent values
   e.g. reactions, ratoms, cursors."
   [reactive-val]
-  (when (implements? reagent.ratom/IReactiveAtom reactive-val)
+  ;; ^:js suppresses externs inference warnings by forcing the compiler to
+  ;; generate proper externs. Although not strictly required as
+  ;; reagent.ratom/IReactiveAtom is not JS interop it appears to be harmless.
+  ;; See https://shadow-cljs.github.io/docs/UsersGuide.html#infer-externs
+  (when (implements? reagent.ratom/IReactiveAtom ^js reactive-val)
     (str (condp instance? reactive-val
            reagent.ratom/RAtom "ra"
            reagent.ratom/RCursor "rc"


Restored default size to 720

Restored default size to 720

--- src/video_server/main.clj
+++ src/video_server/main.clj
@@ -86,7 +86,7 @@
     :parse-fn str/lower-case
     :validate [#{"mkv" "mp4" "m4v"} "The output format must be one of mkv, mp4 or m4v"]]
    ["-s" "--size INT" "Preferred video size when transcoding"
-    :default 1080
+    :default 720
     :parse-fn #(Integer/parseInt %)
     :validate [#{480 720 1080 2160} "The size must be 480, 720, 1080 or 2160"]]
    [nil "--log-level LEVEL" "Override the default logging level"


improve logging

improve logging

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -256,33 +256,25 @@
 (defn candidate-parents
   "find subset of _rules_ for which each member unifies successfully with _spec_"
   [rules spec]
-  (log/trace (str "candidate-parents: spec: " (strip-refs spec)))
-  (let [result
-        (filter not-fail?
-                (mapfn (fn [rule]
-                         (log/trace (str "candidate-parents: testing rule: " (:rule rule)))
-                         (if (and (not-fail? (unify (get-in rule [:synsem :cat] :top)
-                                                    (get-in spec [:synsem :cat] :top))))
-                           ;; TODO: add checks for [:synsem :subcat] valence as well as [:synsem :cat].
-                           (do
-                             (log/trace (str "candidate-parents: " (:rule rule) " is a head candidate for spec:"
-                                             (strip-refs spec)))
-                             (unify spec rule))
-                           (do
-                             (log/trace (str "candidate-parents: " (:rule rule) " is *not* a head candidate for spec:"
-                                             (strip-refs spec)))
-                             :fail)))
-                       rules))]
-    (log/trace (str "candidate-parents: "
-                    (string/join "," (map :rule result))
-                    " for spec: " (strip-refs spec)))
-    (if (empty? result)
-      (log/trace (str "candidate-parents: "
-                      "no parents found for spec: " (spec-info spec)))
-      (log/trace (str "candidate-parents: "
-                    (string/join "," (map :rule result))
-                    " for: " (spec-info spec))))
-    result))
+  (filter not-fail?
+          (mapfn (fn [rule]
+                   (log/trace (str "candidate-parents: testing rule: " (:rule rule)))
+                   (if (not-fail? (unify (get-in rule [:synsem :cat] :top)
+                                         (get-in spec [:synsem :cat] :top)))
+                     ;; TODO: add checks for [:synsem :subcat] valence as well as [:synsem :cat].
+                     (do
+                       (log/trace (str "candidate-parents: " (:rule rule) " is a cat-wise candidate for spec:"
+                                       (strip-refs spec)))
+                       (let [unified (unify spec rule)]
+                         (if (= :fail unified)
+                           (log/trace (str "candidate parent: " (:rule rule) " failed at:" (fail-path spec rule)))
+                           (log/trace (str "candidate parent: " (:rule rule) " unified successfully with spec:" (strip-refs spec))))
+                         unified))
+                     (do
+                       (log/trace (str "candidate-parents: " (:rule rule) " is *not* a head candidate for spec:"
+                                       spec))
+                       :fail)))
+                 rules)))
 (defn show-bolt [bolt language-model]
   (if (nil? bolt)
     (throw (Exception. (str "don't call show-bolt with bolt=null.")))


added WIP example

added WIP example

--- examples/hackernews/src/core.cljs
+++ examples/hackernews/src/core.cljs
@@ -4,6 +4,8 @@
             [sablono.core :as html :refer-macros [html]]
             [twigs.core :as tw]
             [om.core :as om]))
+
+;; WIP hackernews clone!!!

 (enable-console-print!)


Generate correct root element when accumulating results, log offending junit xml when rejected by buildviz

--- src/buildviz/gosync.clj
+++ src/buildviz/gosync.clj
@@ -143,7 +143,7 @@
       (:content root))))

 (defn accumulate-junit-xml-results [junit-xml-list]
-  (with-out-str (xml/emit-element {:tag :testresults
+  (with-out-str (xml/emit-element {:tag :testsuites
                                    :content (mapcat testsuite-list junit-xml-list)})))

 (defn get-all-junit-xml [job-instance]
@@ -213,7 +213,9 @@
         (put-junit-xml job-name build-no junit-xml)
         (catch Exception e
           (if-let [data (ex-data e)]
-            (log/errorf "Unable to sync testresults for %s %s (status %s): %s" job-name build-no (:status data) (:body data))
+            (do
+              (log/errorf "Unable to sync testresults for %s %s (status %s): %s" job-name build-no (:status data) (:body data))
+              (log/info "Offending XML content is:\n" junit-xml))
             (log/errorf e "Unable to sync testresults for %s %s" job-name build-no)))))))

 ;; build load start date


Properly close the nrepl server to fix [IMMUTANT-122]

--- modules/core/src/main/clojure/immutant/repl.clj
+++ modules/core/src/main/clojure/immutant/repl.clj
@@ -65,7 +65,7 @@
   "Stops the given nrepl server."
   [server]
   (log/info "Stopping nrepl for" (util/app-name))
-  (.close (:ss @server)))
+  (.close server))

 (defn start-nrepl
   "Starts an nrepl server on the given port. If an interface-address is


trigger CI

trigger CI

--- test/clojure_playground/core_test.clj
+++ test/clojure_playground/core_test.clj
@@ -3,5 +3,5 @@
             [clojure-playground.core :refer :all]))

 (deftest a-test
-  (testing "Always passes."
+  (testing "Always passes"
     (is (= 1 1))))


Update project.clj

Update project.clj

--- cljs/src/leiningen/new/quil_cljs/project.clj
+++ cljs/src/leiningen/new/quil_cljs/project.clj
@@ -15,5 +15,5 @@
              :compiler
              {:output-to "web/js/main.js"
               :externs ["externs/processing-externs.js"]
-              :optimizations :whitespace
+              :optimizations :simple
               :pretty-print true}}]})


Fix checking of :default display.

Fix checking of :default display.

--- src/clj/quil/applet.clj
+++ src/clj/quil/applet.clj
@@ -127,7 +127,7 @@
   "Checks that the size vector is exactly two elements. If not, throws
   an exception, otherwise returns the size vector unmodified."
   [size display]
-  (cond (= size :fullscreen) (if (== :default display) (display-size)
+  (cond (= size :fullscreen) (if (= :default display) (display-size)
                                (display-size display))
         (and (coll? size) (= 2 (count size))) size
         :else (throw (IllegalArgumentException.


* src/cljs/cljs/core.cljs: remove truth test from PV fromArray

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -2716,7 +2716,7 @@
 (set! cljs.core.PersistentVector/fromArray
       (fn [xs]
         (loop [xs (seq xs) out (transient cljs.core.PersistentVector/EMPTY)]
-          (if xs
+          (if (coercive-not= xs nil)
             (recur (next xs) (conj! out (first xs)))
             (persistent! out)))))


fixed hierarchic multimethods bug, refs #126

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -3383,7 +3383,7 @@
 (defn- find-and-cache-best-method
   [name dispatch-val hierarchy method-table prefer-table method-cache cached-hierarchy]
   (let [best-entry (reduce (fn [be [k _ :as e]]
-                             (when (isa? dispatch-val k)
+                             (if (isa? dispatch-val k)
                                (let [be2 (if (or (nil? be) (dominates k (first be) prefer-table))
                                            e
                                            be)]
@@ -3392,7 +3392,8 @@
                                            (str "Multiple methods in multimethod '" name
                                                 "' match dispatch value: " dispatch-val " -> " k
                                                 " and " (first be2) ", and neither is preferred"))))
-                                 be2)))
+                                 be2)
+                               be))
                            nil @method-table)]
     (when best-entry
       (if (= @cached-hierarchy @hierarchy)


fix typo in seq, ILookup -> ISeqable

fix typo in seq, ILookup -> ISeqable

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -438,7 +438,7 @@
       (when-not (zero? (alength coll))
         (IndexedSeq. coll 0))

-      (type_satisfies_ ILookup coll)
+      (type_satisfies_ ISeqable coll)
       (-seq coll)

       :else (throw (js/Error. (str coll "is not ISeqable"))))))


* src/cljs/cljs/core.cljs: declare key val

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -1179,6 +1179,8 @@

 (defn- hash-coll [coll]
   (reduce #(hash-combine %1 (hash %2)) (hash (first coll)) (next coll)))
+
+(declare key val)

 (defn- hash-imap [m]
   ;; a la clojure.lang.APersistentMap


Changed physicloud dep to 0.2.0.

Changed physicloud dep to 0.2.0.

--- src/clojure/project.clj
+++ src/clojure/project.clj
@@ -4,7 +4,7 @@
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}
   :dependencies [[org.clojure/clojure "1.6.0"]
-                 [hypower-org/physicloud "0.2.0-SNAPSHOT"]
+                 [hypower-org/physicloud "0.2.0"]
                  [hypower-org/watershed "0.1.5"]
                  [manifold "0.1.0-beta10"]
                  [jkobuki "1.1.0"]


experimental code reverted

experimental code reverted

--- flatguicore/src/flatgui/paint.clj
+++ flatguicore/src/flatgui/paint.clj
@@ -397,5 +397,5 @@
       (apply concat
              [(conj id-path (:id container))]
              (for [[_ v] (:children container)] (get-paint-all-sequence (conj id-path (:id container)) v)))
-      (throw (IllegalStateException. "No ready for paint"))))
+     []))
   ([container] (get-paint-all-sequence [] container)))


Add to repl codes

Add to repl codes

--- repl-code.clj
+++ repl-code.clj
@@ -25,6 +25,10 @@

 (def db (client/db conn))

+;;
+(d/delete-database "datomic:dev://localhost:4334/datemo")
+(d/create-database "datomic:dev://localhost:4334/datemo")
+

 ;; for datomic api
 (require '[datomic.api :as d])
@@ -35,6 +39,7 @@
 ;; for installing the schema
 ;; run lein-repl, then:
 (use 'datemo.db)
+(require '[datomic.api :as d])
 (-> (load-schema "schemas/arb.edn")
     (install-schema (get-conn)))


Uncommented code that shouldn't be commented out.

--- test/cmr/system_int_test/search/collection_periodic_temporal_search_test.clj
+++ test/cmr/system_int_test/search/collection_periodic_temporal_search_test.clj
@@ -88,27 +88,27 @@
 (use-fixtures :once wrap-setup)

 (deftest search-by-periodic-temporal
-  ; (testing "search by both start-day and end-day."
-  ;   (let [references (search/find-collection-refs
-  ;                      {"temporal[]" "2000-02-15T00:00:00Z, 2002-03-15T00:00:00Z, 32, 90"})]
-  ;     (is (= 8 (count references)))
-  ;     (some #{"Dataset2" "Dataset3" "Dataset6" "Dataset7"
-  ;             "Dataset10" "Dataset11" "Dataset16" "Dataset17"}
-  ;           (map #(:dataset-id %) references))))
-  ; (testing "search by end-day."
-  ;   (let [references (search/find-collection-refs
-  ;                      {"temporal[]" "2000-02-15T00:00:00Z, 2002-03-15T00:00:00Z, , 90"})]
-  ;     (is (= 10 (count references)))
-  ;     (some #{"Dataset2" "Dataset3" "Dataset5" "Dataset6" "Dataset7"
-  ;             "Dataset9" "Dataset10" "Dataset11" "Dataset16" "Dataset17"}
-  ;           (map #(:dataset-id %) references))))
-  ; (testing "search by start-day."
-  ;   (let [references (search/find-collection-refs
-  ;                      {"temporal[]" "2000-02-15T00:00:00Z, 2002-03-15T00:00:00Z, 32,"})]
-  ;     (is (= 11 (count references)))
-  ;     (some #{"Dataset2" "Dataset3" "Dataset4" "Dataset6" "Dataset7"
-  ;             "Dataset8" "Dataset10" "Dataset11" "Dataset16" "Dataset17" "Dataset19"}
-  ;           (map #(:dataset-id %) references))))
+  (testing "search by both start-day and end-day."
+    (let [references (search/find-collection-refs
+                       {"temporal[]" "2000-02-15T00:00:00Z, 2002-03-15T00:00:00Z, 32, 90"})]
+      (is (= 8 (count references)))
+      (some #{"Dataset2" "Dataset3" "Dataset6" "Dataset7"
+              "Dataset10" "Dataset11" "Dataset16" "Dataset17"}
+            (map #(:dataset-id %) references))))
+  (testing "search by end-day."
+    (let [references (search/find-collection-refs
+                       {"temporal[]" "2000-02-15T00:00:00Z, 2002-03-15T00:00:00Z, , 90"})]
+      (is (= 10 (count references)))
+      (some #{"Dataset2" "Dataset3" "Dataset5" "Dataset6" "Dataset7"
+              "Dataset9" "Dataset10" "Dataset11" "Dataset16" "Dataset17"}
+            (map #(:dataset-id %) references))))
+  (testing "search by start-day."
+    (let [references (search/find-collection-refs
+                       {"temporal[]" "2000-02-15T00:00:00Z, 2002-03-15T00:00:00Z, 32,"})]
+      (is (= 11 (count references)))
+      (some #{"Dataset2" "Dataset3" "Dataset4" "Dataset6" "Dataset7"
+              "Dataset8" "Dataset10" "Dataset11" "Dataset16" "Dataset17" "Dataset19"}
+            (map #(:dataset-id %) references))))
   (testing "search by start-day without end_date."
     (let [references (search/find-collection-refs
                        {"temporal[]" ["2000-02-15T00:00:00Z, , 32"]})]
@@ -117,21 +117,21 @@
               "Dataset8" "Dataset10" "Dataset11" "Dataset12" "Dataset13"
               "Dataset15" "Dataset16" "Dataset17" "Dataset18" "Dataset19"}
             (map #(:dataset-id %) references))))
-  ; (testing "search by start-day/end-day with date crossing year boundary."
-  ;   (let [references (search/find-collection-refs
-  ;                      {"temporal[]" ["2000-04-03T00:00:00Z, 2002-01-02T00:00:00Z, 93, 2"]})]
-  ;     (is (= 11 (count references)))
-  ;     (some #{"Dataset3" "Dataset4" "Dataset5" "Dataset6" "Dataset7" "Dataset8"
-  ;             "Dataset9" "Dataset10" "Dataset16" "Dataset17" "Dataset19"}
-  ;           (map #(:dataset-id %) references))))
-  ; (testing "search by multiple temporal."
-  ;   (let [references (search/find-collection-refs
-  ;                      {"temporal[]" ["1998-01-15T00:00:00Z, 1999-03-15T00:00:00Z, 60, 90"
-  ;                                     "2000-02-15T00:00:00Z, 2001-03-15T00:00:00Z, 40, 50"]})]
-  ;     (is (= 5 (count references)))
-  ;     (some #{"Dataset2" "Dataset6" "Dataset14" "Dataset16" "Dataset17"}
-  ;           (map #(:dataset-id %) references)))))
-)
+  (testing "search by start-day/end-day with date crossing year boundary."
+    (let [references (search/find-collection-refs
+                       {"temporal[]" ["2000-04-03T00:00:00Z, 2002-01-02T00:00:00Z, 93, 2"]})]
+      (is (= 11 (count references)))
+      (some #{"Dataset3" "Dataset4" "Dataset5" "Dataset6" "Dataset7" "Dataset8"
+              "Dataset9" "Dataset10" "Dataset16" "Dataset17" "Dataset19"}
+            (map #(:dataset-id %) references))))
+  (testing "search by multiple temporal."
+    (let [references (search/find-collection-refs
+                       {"temporal[]" ["1998-01-15T00:00:00Z, 1999-03-15T00:00:00Z, 60, 90"
+                                      "2000-02-15T00:00:00Z, 2001-03-15T00:00:00Z, 40, 50"]})]
+      (is (= 5 (count references)))
+      (some #{"Dataset2" "Dataset6" "Dataset14" "Dataset16" "Dataset17"}
+            (map #(:dataset-id %) references)))))
+
 ;; Just some symbolic invalid temporal testing, more complete test coverage is in unit tests
 (deftest search-temporal-error-scenarios
   (testing "search with temporal_start_day and no temporal_start is invalid."


Added test for searching with provider_id param

--- test/cmr/system_int_test/search/collection_identifier_search_test.clj
+++ test/cmr/system_int_test/search/collection_identifier_search_test.clj
@@ -68,7 +68,10 @@

            ;; Ignore case
            all-prov1-colls "pRoV1" {:ignore-case true}
-           [] "prov1" {:ignore-case false}))
+           [] "prov1" {:ignore-case false})
+
+      (testing "legacy catalog rest parameter name"
+        (is (d/refs-match? all-prov1-colls (search/find-refs :collection {:provider-id "PROV1"})))))

     (testing "short name"
       (are [items sn options]


More net modeling.

More net modeling.

--- src/cbfg/net.cljs
+++ src/cbfg/net.cljs
@@ -1,21 +1,20 @@
 (ns cbfg.net
-  (:require-macros [cbfg.ago :refer [achan ago-loop aclose aalts aput aput-close]]))
+  (:require-macros [cbfg.ago :refer [achan-buf ago-loop aclose aalts aput aput-close]]))

-(defn make-net [actx request-listen-ch request-connect-ch max-msgs-per-stream]
+(defn make-net [actx request-listen-ch request-connect-ch
+                max-msgs-per-stream delivery-delay end-point-buf-size]
   (let [clean-up #()]
     (ago-loop net actx
               [ts 0
-               request-listen-ch request-listen-ch
-               request-connect-ch request-connect-ch
-               listens {} ; Keyed by [addr port], value is accept-ch.
-               streams {} ; A conn is represented by dual streams, where streams
-                          ; is keyed by send-ch and a value of...
-                          ; {:send-addr :send-port :send-ch
-                          ;  :recv-addr :recv-port :recv-ch
-                          ;  :to-side :to-addr :to-port
-                          ;  :msgs :tot-msgs}.
-               results []]
-              (let [deliveries (mapcat (fn [send-ch stream]
+               listens {}  ; Keyed by [addr port], value is accept-ch.
+               streams {}  ; A conn is represented by dual streams, where streams
+                           ; is keyed by send-ch and a value of...
+                           ; {:send-addr :send-port :send-ch
+                           ;  :recv-addr :recv-port :recv-ch
+                           ;  :to-side :to-addr :to-port
+                           ;  :msgs [[deliver-at msg] ...]}.
+               results []] ; A result is [ch msg].
+              (let [deliverables (mapcat (fn [send-ch stream]
                                          (when-let [[deliver-at msg] (first (:msgs stream))]
                                            (when (>= ts deliver-at)
                                              [[(:recv-ch stream) (first (:msgs stream))]])))
@@ -24,57 +23,64 @@
                                        (when (< (count (:msgs stream)) max-msgs-per-stream)
                                          [(:send-ch stream)]))
                                       streams)
-                    [v ch] (aalts net (vec (concat [request-listen-ch request-connect-ch]
-                                                   deliveries sendables
-                                                   results)))]
+                    [v ch] (aalts net (-> [request-listen-ch request-connect-ch]
+                                          (into deliverables)
+                                          (into sendables)
+                                          (into results)))]
                 (cond
                  (= ch request-listen-ch)
                  (when-let [[addr port accept-ch] v]
                    (if (get listens [addr port])
-                     (recur (inc ts) request-listen-ch request-connect-ch
+                     (recur (inc ts)
                             (assoc listens [addr port] accept-ch)
-                            streams results)
+                            streams
+                            results)
                      (do (aclose net accept-ch)
-                         (recur (inc ts) request-listen-ch request-connect-ch listens
-                                streams results))))
+                         (recur (inc ts) listens streams results))))
                  (= ch request-connect-ch)
                  (when-let [[to-addr to-port from-addr result-ch] v]
+                   ; TODO: Need to model connection delay, perhaps with a generic "later".
                    (if-let [accept-ch (get listens [to-addr to-port])]
-                     (let [client-send-ch (achan net)
-                           client-recv-ch (achan net)
-                           server-send-ch (achan net)
-                           server-recv-ch (achan net)]
-                       ; TODO: Need to model connection delay and running out of ports.
+                     (let [client-send-ch (achan-buf net end-point-buf-size)
+                           client-recv-ch (achan-buf net end-point-buf-size)
+                           server-send-ch (achan-buf net end-point-buf-size)
+                           server-recv-ch (achan-buf net end-point-buf-size)]
+                       ; TODO: Need to model running out of ports.
                        ; TODO: Need to model stop accepting connections / stop listening.
-                       (recur (inc ts) request-listen-ch request-connect-ch listens
+                       (recur (inc ts)
+                              listens
                               (-> streams
                                   (assoc client-send-ch {:send-ch client-send-ch :recv-ch server-recv-ch
-                                                         :to-side :recv :to-addr to-addr :to-port to-port})
+                                                         :to-side :recv :to-addr to-addr :to-port to-port
+                                                         :msgs []})
                                   (assoc server-send-ch {:send-ch server-send-ch :recv-ch client-recv-ch
-                                                         :to-side :send :to-addr to-addr :to-port to-port}))
+                                                         :to-side :send :to-addr to-addr :to-port to-port
+                                                         :msgs []}))
                               (-> results
                                   (conj [result-ch [client-send-ch client-recv-ch]])
                                   (conj [accept-ch [server-send-ch server-recv-ch]]))))
                      (do (aclose net result-ch)
-                         (recur (inc ts) request-listen-ch request-connect-ch listens
-                                streams results))))
+                         (recur (inc ts) listens streams results))))
                  (contains? sendables ch)
                  (let [send-ch ch]
                    (if-let [stream (get streams send-ch)]
                      (let [[msg result-ch] v]
-                       (recur (inc ts) request-listen-ch request-connect-ch listens
-                              (update-in streams [send-ch :msgs] conj msg)
+                       (recur (inc ts)
+                              listens
+                              (update-in streams [send-ch :msgs] conj [(+ ts delivery-delay) msg])
                               (if result-ch
                                 (conj results [result-ch :ok])
                                 result-ch)))
-                     ; TODO: Need to remove first msg from msgs.
-                     ; TODO: Handle closing recv-ch.
-                     (recur (inc ts) request-listen-ch request-connect-ch listens
-                            (dissoc streams send-ch)
+                     (recur (inc ts)
+                            listens
+                            (dissoc streams send-ch) ; TODO: Need to model close better by draining then closing.
                             results)))
-                 :else ; Must be completed delivery (recv) or completed results aput.
+                 :else ; Must be completed deliverable (recv-ch aput'ed) or completed results aput.
                  (let [stream (first (filter #(= (:recv-ch %) ch) (vals streams)))]
-                   (recur (inc ts) request-listen-ch request-connect-ch listens
+                   ; TODO: Need to remove first msg from msgs.
+                   ; TODO: Handle closing recv-ch.
+                   (recur (inc ts)
+                          listens
                           (dissoc streams (:send-ch stream))
                           (remove #(= (first %) ch) results))))))))


Update tag to make it obvious we have a photon

--- src/eventstore/muon.clj
+++ src/eventstore/muon.clj
@@ -45,14 +45,14 @@
       (mcc/on-command this "projections" listener-projections))))

 (defn new-microservice [mq-url db]
-  (->PhotonMicroservice (mcs/muon mq-url "eventstore" ["eventstore" "helios"])
+  (->PhotonMicroservice (mcs/muon mq-url "eventstore" ["eventstore" "photon"])
                         (streams/new-async-stream db)))

 (defn start-server! [db]
   (do
     (log/info "Connecting to" (:amqp.url conf/config))
     (let [muon-url (:amqp.url conf/config)
-          ms (->PhotonMicroservice (mcs/muon muon-url "eventstore" ["eventstore" "helios"])
+          ms (->PhotonMicroservice (mcs/muon muon-url "eventstore" ["eventstore" "photon"])
                                  (streams/new-async-stream db)
                                  #_(streams/new-async-stream (riak/riak riak/s-bucket))
                                  #_(streams/async-stream (riak/riak bucket))


Serve the SPA on all sub-routes

Serve the SPA on all sub-routes

--- phonebook-app/src/edge/phonebook_app/routes.clj
+++ phonebook-app/src/edge/phonebook_app/routes.clj
@@ -12,16 +12,18 @@
 (defn- routes
   [{:edge.phonebook/keys [db]}]
   [["" (yada/resource
-          {:id ::phonebook-app
-           :methods
-           {:get
-            {:produces "text/html"
-             :response
-             (fn [ctx]
-               (selmer/render-file
-                 "phonebook-app.html"
-                 {:ctx ctx}
-                 {:custom-resource-path (io/resource "phonebook-app/templates/")}))}}})]])
+        {:id ::phonebook-app
+         :path-info? true      ; We want to serve the same content for
+                                        ; every path below here.
+         :methods
+         {:get
+          {:produces "text/html"
+           :response
+           (fn [ctx]
+             (selmer/render-file
+              "phonebook-app.html"
+              {:ctx ctx}
+              {:custom-resource-path (io/resource "phonebook-app/templates/")}))}}})]])

 (defmethod ig/init-key :edge.phonebook-app/routes [_ config]
   (routes config))


Add some more predicates and refactor others

--- src/grimoire/things.clj
+++ src/grimoire/things.clj
@@ -66,16 +66,26 @@

-(defn thing?
-  "Predicate testing whether the input exists within the \"thing\" variant of
-  Σ[Group, Artifact,Version, Platform, Namespace, Def]"
-  [t]
-  (or (group? t)
-      (artifact? t)
-      (version? t)
-      (platform? t)
-      (namespace? t)
+(defn namespaced?
+  "Predicate testing whether the input either is a namespace or has a namespace
+  as a parent."
+  [t]
+  (or (namespace? t)
       (def? t)))
+
+(defn platformed?
+  "Predicate testing whether the input either is a platform or has a platform as
+  a parent."
+  [t]
+  (or (namespaced? t)
+      (platform? t)))
+
+(defn artifacted?
+  "Predicate testing whether the input either is an artifact or has an artifact
+  as a parent."
+  [t]
+  (or (platformed? t)
+      (artifact? t)))

 (defn versioned?
   "Predicate testing whether the input exists within the subset of the \"thing\"
@@ -83,11 +93,28 @@
   Version instance and thus a version instance can be reached by upwards
   traversal."
   [t]
-  (or (version? t)
-      (artifact? t)
-      (platform? t)
-      (namespace? t)
-      (def? t)))
+  (or (platformed? t)
+      (version? t)))
+
+(defn artifacted?
+  "Predicate testing whether the input either is an artifact or has an artifact
+  as a parent."
+  [t]
+  (or (versioned? t)
+      (artifact? t)))
+
+(defn grouped?
+  "Predicate testing whether the input either is a group or has a group as a
+  parent."
+  [t]
+  (or (artifacted? t)
+      (group? t)))
+
+(defn thing?
+  "Predicate testing whether the input exists within the \"thing\" variant of
+  Σ[Group, Artifact,Version, Platform, Namespace, Def]"
+  [t]
+  (grouped? t))

 (defn thing->parent
   "Function from any object to Maybe[Thing]. If the input is a thing, returns


Make the reason for stripping escape codes clearer

--- src-cljs/frontend/models/action.cljs
+++ src-cljs/frontend/models/action.cljs
@@ -53,12 +53,18 @@
         html-escaped-message (-> output :message gstring/htmlEscape)
         stripped-message (strip-console-codes html-escaped-message)
         converter (new-converter action converter-path)
+        ;; This is a rough proxy for "if we put this string into our ansiToHtmlConverter
+        ;; it will create so many spans the browser will fall over"
+        ;; we should evetnually use a better proxy (or a better ansiToHtmlConverter)
+        max-escape-code-characters 1000

         [converted-message converter-state] (cond
                                               (:truncated-client-side? action)
                                               [html-escaped-message nil]

-                                              (> (count stripped-message) (+ 1000 (count html-escaped-message)))
+                                              (< max-escape-code-characters
+                                                 (- (count stripped-message)
+                                                    (count html-escaped-message)))
                                               [stripped-message nil]

                                               :else    ; colorize it


enable use of l, t, r, b

enable use of l, t, r, b

git-svn-id: 03a8048b5ee8463be5048a3801110fb50f378627@10078 d0ab736e-dc22-4aeb-8dc9-08def0aa14fd

--- plugins/SlideExplorer2/src/slide_explorer/canvas.clj
+++ plugins/SlideExplorer2/src/slide_explorer/canvas.clj
@@ -1,7 +1,18 @@
 (ns slide-explorer.core
-  (:import (java.awt Graphics Graphics2D RenderingHints)
-           (java.awt Color Font Polygon)
+  (:import (java.awt Color Font Graphics Graphics2D Polygon RenderingHints)
+           (java.awt.font TextAttribute)
            (javax.swing JFrame JPanel)))
+
+;; possible
+; draggable
+; clickable
+; hoverable
+; rotatable
+; resizable
+; shearable
+;
+; gradients
+; affine transforms

 (defn enable-anti-aliasing
   "Turn on (off) anti-aliasing for a graphics context."
@@ -22,30 +33,62 @@
   (doto g2d
     (.setColor (:color params))))

+(defn- -? [a b]
+  (when (and a b)
+    (- a b)))
+
+(defn- +? [a b]
+  (when (and a b)
+    (+ a b)))
+
+(defn- half? [a]
+  (when a
+    (/ a 2)))
+
+(defn- twice? [a]
+  (when a
+    (* a 2)))
+
+(defn complete-coordinates
+  [{:keys [l left t top r right b bottom
+           x y
+           w width h height]
+    :as the-map}]
+  (let [l (or l left) t (or t top) r (or r right) b (or b bottom)
+        w (or w width (-? r l) (twice? (-? x l)) (twice? (-? r x)))
+        h (or h height (-? b t) (twice? (-? y t)) (twice? (-? b y)))
+        l (or l (-? r w) (-? x (half? w)))
+        t (or t (-? b h) (-? y (half? h)))
+        r (or r (+? l w) (+? x (half? w)))
+        b (or b (+? t h) (+? y (half? h)))
+        x (or x (+? l (half? w)))
+        y (or y (+? t (half? h)))]
+    (merge the-map {:w w :h h :l l :t t :r r :b b :x x :y y})))
+
 (defmulti draw-primitive (fn [g2d shape params] shape))

 (defmethod draw-primitive :primitive-arc
-  [g2d shape {:keys [x y w h filled start-angle arc-angle]}]
-  (if filled
-    (.fillArc g2d x y w h start-angle arc-angle)
-    (.drawArc g2d x y w h start-angle arc-angle)))
+  [g2d shape {:keys [l t w h filled start-angle arc-angle]}]
+  (if filled
+    (.fillArc g2d l t w h start-angle arc-angle)
+    (.drawArc g2d l t w h start-angle arc-angle)))

 (defmethod draw-primitive :primitive-ellipse
-  [g2d shape {:keys [x y w h filled]}]
-  (if filled
-    (.fillOval g2d x y w h)
-    (.drawOval g2d x y w h)))
+  [g2d shape {:keys [l t w h filled]}]
+  (if filled
+    (.fillOval g2d l t w h)
+    (.drawOval g2d l t w h)))

 (defmethod draw-primitive :primitive-image
-  [g2d shape {:keys [image x y w h]}]
-  (.drawImage g2d
-              image x y
+  [g2d shape {:keys [image l t w h]}]
+  (.drawImage g2d image
+              l t
               (or w (.getWidth image))
               (or h (.getHeight image)) nil))

 (defmethod draw-primitive :primitive-line
-  [g2d shape {:keys [x y w h filled]}]
-  (.drawLine g2d x y (+ x w) (+ x h)))
+  [g2d shape {:keys [l t r b filled]}]
+  (.drawLine g2d l t r b))

 (defmethod draw-primitive :primitive-polygon
   [g2d shape {:keys [vertices filled closed]}]
@@ -59,24 +102,47 @@
         (.drawPolyline g2d xs ys n)))

 (defmethod draw-primitive :primitive-rect
-  [g2d shape {:keys [x y w h filled]}]
-  (if filled
-    (.fillRect g2d x y w h)
-    (.drawRect g2d x y w h)))
+  [g2d shape {:keys [l t w h filled]}]
+  (if filled
+    (.fillRect g2d l t w h)
+    (.drawRect g2d l t w h)))

 (defmethod draw-primitive :primitive-round-rect
-  [g2d shape {:keys [x y w h filled arc-width arc-height]}]
-  (if filled
-    (.fillRoundRect g2d x y w h arc-width arc-height)
-    (.drawRoundRect g2d x y w h arc-width arc-height)))
+  [g2d shape {:keys [l t w h filled arc-width arc-height]}]
+  (if filled
+    (.fillRoundRect g2d l t w h arc-width arc-height)
+    (.drawRoundRect g2d l t w h arc-width arc-height)))
+
+(defn draw-string-center
+  "Draw a string centered at position x,y."
+  [^Graphics2D graphics ^String text x y]
+  (let [context (.getFontRenderContext graphics)
+        height (.. graphics
+                   getFont (createGlyphVector context text)
+                   getVisualBounds
+                   getHeight)
+        width (.. graphics
+                  getFontMetrics
+                  (getStringBounds text graphics)
+                  getWidth)]
+    (.drawString graphics text
+                 (float (- x (/ width 2)))
+                 (float (+ y (/ height 2))))))

 (defmethod draw-primitive :primitive-text
   [g2d shape  {:keys [text x y font]}]
-  (let [{:keys [name bold italic size]} font
+  (let [{:keys [name bold italic underline strikethrough size]} font
         style (bit-or (if bold Font/BOLD 0) (if italic Font/ITALIC 0))
-        font-obj (Font. name style size)]
-    (.setFont g2d font-obj)
-    (.drawString g2d text x y)))
+        font1 (Font. name style size)
+        attributes (.getAttributes font1)]
+    (doto attributes
+      (.put TextAttribute/STRIKETHROUGH
+            (if strikethrough TextAttribute/STRIKETHROUGH_ON false))
+      (.put TextAttribute/UNDERLINE
+            (if underline TextAttribute/UNDERLINE_ON -1)))
+    (let [font2 (Font. attributes)]
+      (.setFont g2d font2)
+      (draw-string-center g2d text x y))))

 (defn draw-primitives [g2d items]
   (enable-anti-aliasing g2d)
@@ -85,7 +151,7 @@
       (let [params (merge default-primitive-params
                                         (:params item))]
       (set-style g2d params)
-      (draw-primitive g2d (:type item) params)))))
+      (draw-primitive g2d (:type item) (complete-coordinates params))))))

 (defn paint-canvas-graphics [^Graphics graphics data]
   (draw-primitives graphics data))
@@ -104,31 +170,38 @@
 (def temp-data
   [
    {:type :primitive-round-rect
-    :params {:x 20 :y 10 :w 120 :h 100
+    :params {:l 20 :t 10 :w 140 :h 140
              :arc-width 20 :arc-height 20
              :filled true :color Color/RED}}
    {:type :primitive-ellipse
-    :params {:x 25 :y 15 :w 110 :h 90
+    :params {:l 25 :t 15 :w 110 :h 90
              :arc-width 20 :arc-height 20
              :filled true :color Color/YELLOW}}
    {:type :primitive-round-rect
-    :params {:x 20 :y 10 :w 120 :h 100
+    :params {:x 90 :y 80 :r 160 :b 150
              :arc-width 20 :arc-height 20
              :filled false :color Color/BLACK}}
    {:type :primitive-polygon
     :params {:vertices [{:x 100 :y 100}
                         {:x 50 :y 150}
-                        {:x 150 :y 150}]
+                        {:x 160 :y 160}]
              :filled false
              :closed true}}
    {:type :primitive-text
-    :params {:x 80 :y 140 :text "TEST!" :color Color/BLACK
-             :font {:name "Arial"
+    :params {:x 180 :y 280 :text "TEST"
+             :color Color/BLUE
+             :font {:name "Courier New"
                     :bold true
-                    :italic true
-                    :size 16}}}
+                    :italic false
+                    :underline true
+                    :strikethrough false
+                    :size 100}}}
+   {:type :primitive-line
+    :params {:x 180 :y 280 :w 0 :h 300 :color Color/RED}}
+   {:type :primitive-line
+    :params {:x 180 :y 280 :w 10 :h 0 :color Color/RED}}
    {:type :primitive-arc
-    :params {:x 40 :y 30 :w 100 :h 100
+    :params {:l 40 :t 30 :w 100 :h 100
              :start-angle 10 :arc-angle 100 :color Color/GREEN
              :filled true}}
    ])


Allow editor/adjust-loc to specify line movement

editor/adjust-loc accepts an optional argument of value :line or :ch
to specify the axis along which to move.
For backward compatibility, adjust-loc moves along :ch by default if no
optional argument is passed.

--- src/lt/objs/editor.cljs
+++ src/lt/objs/editor.cljs
@@ -319,9 +319,12 @@
     (-> (js/CodeMirror.innerMode (.getMode (->cm-ed e)) state)
         (.-mode))))

-(defn adjust-loc [loc dir]
-  (when loc
-    (update-in loc [:ch] + dir)))
+(defn adjust-loc
+  ([loc dir]
+   (adjust-loc loc dir :ch))
+  ([loc dir axis]
+   (when loc
+     (update-in loc [axis] + dir))))

 (defn get-char [ed dir]
   (let [loc (->cursor ed)]


Refactor: Remove nested transaction [#1678]

--- backend/src/akvo/lumen/update.clj
+++ backend/src/akvo/lumen/update.clj
@@ -29,21 +29,20 @@
   pointing to the new table-name, imported-table-name and columns. We
   also delete the previous table-name and imported-table-name so we
   don't accumulate unused datasets on each update."
-  [conn* job-execution-id dataset-id table-name imported-table-name dataset-version
+  [conn job-execution-id dataset-id table-name imported-table-name dataset-version
    transformations new-columns]
-  (jdbc/with-db-transaction [conn conn*]
-    (insert-dataset-version conn {:id (str (util/squuid))
-                                  :dataset-id dataset-id
-                                  :job-execution-id job-execution-id
-                                  :table-name table-name
-                                  :imported-table-name imported-table-name
-                                  :version (inc (:version dataset-version))
-                                  :columns new-columns
-                                  :transformations (vec transformations)})
-    (touch-dataset conn {:id dataset-id})
-    (drop-table conn {:table-name (:imported-table-name dataset-version)})
-    (drop-table conn {:table-name (:table-name dataset-version)})
-    (update-successful-job-execution conn {:id job-execution-id})))
+  (insert-dataset-version conn {:id (str (util/squuid))
+                                :dataset-id dataset-id
+                                :job-execution-id job-execution-id
+                                :table-name table-name
+                                :imported-table-name imported-table-name
+                                :version (inc (:version dataset-version))
+                                :columns new-columns
+                                :transformations (vec transformations)})
+  (touch-dataset conn {:id dataset-id})
+  (drop-table conn {:table-name (:imported-table-name dataset-version)})
+  (drop-table conn {:table-name (:table-name dataset-version)})
+  (update-successful-job-execution conn {:id job-execution-id}))

 (defn failed-update [conn job-execution-id reason]
   (update-failed-job-execution conn {:id job-execution-id


Remove debugging code

Remove debugging code

--- src/braid/client/register/views.cljs
+++ src/braid/client/register/views.cljs
@@ -243,12 +243,9 @@
                                 :message "Your URL can't end with a -"}]
                          :type [{:valid? (not (blank? :type))
                                  :message "You need to select a group type"}]}
-            tee (fn [x]
-                  (println x) x)
             valid? (fn [field]
                      (->> (validations field)
                           (map :valid?)
-                          tee
                           (every? true?)))
             messages (fn [field]
                        (->> (validations field)


Cosmetic improvements on cats.applicative.validation ns.

--- src/cats/applicative/validation.cljc
+++ src/cats/applicative/validation.cljc
@@ -25,9 +25,8 @@

 (ns cats.applicative.validation
   "The Validation applicative implementation and helper functions
-  for validating values. Isomorphic to Either.
-  "
-  (:require [cats.protocols :as proto]
+  for validating values. Isomorphic to Either."
+  (:require [cats.protocols :as p]
             [cats.core :as m]
             [cats.monad.either :as either]))

@@ -38,10 +37,10 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 (deftype Ok [v]
-  proto/Context
+  p/Context
   (get-context [_] validation-applicative)

-  proto/Extract
+  p/Extract
   (extract [_] v)

   #?(:clj clojure.lang.IDeref
@@ -59,17 +58,17 @@
          (with-out-str (print [v])))])

   #?@(:cljs
-       [cljs.core/IEquiv
-        (-equiv [_ other]
-                (if (instance? Ok other)
-                  (= v (.-v other))
-                  false))]))
+      [cljs.core/IEquiv
+       (-equiv [_ other]
+         (if (instance? Ok other)
+           (= v (.-v other))
+           false))]))

 (deftype Fail [v]
-  proto/Context
+  p/Context
   (get-context [_] validation-applicative)

-  proto/Extract
+  p/Extract
   (extract [_] v)

   #?(:clj clojure.lang.IDeref
@@ -87,11 +86,11 @@
          (with-out-str (print [v])))])

   #?@(:cljs
-       [cljs.core/IEquiv
-        (-equiv [_ other]
-                (if (instance? Fail other)
-                  (= v (.-v other))
-                  false))]))
+      [cljs.core/IEquiv
+       (-equiv [_ other]
+         (if (instance? Fail other)
+           (= v (.-v other))
+           false))]))

 (alter-meta! #'->Ok assoc :private true)
 (alter-meta! #'->Fail assoc :private true)
@@ -100,7 +99,6 @@
   "An Ok type constructor."
   [v]
   (Ok. v))
-

 (defn fail
   "A Fail type constructor."
@@ -125,8 +123,8 @@
   "Return true in case of `v` is instance
   of the Validation applicative."
   [v]
-  (if (satisfies? proto/Context v)
-    (identical? (proto/get-context v) validation-applicative)
+  (if (satisfies? p/Context v)
+    (identical? (p/get-context v) validation-applicative)
     false))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -136,7 +134,7 @@
 (def ^{:no-doc true}
   validation-applicative
   (reify
-    proto/Semigroup
+    p/Semigroup
     (mappend [_ sv sv']
       (cond
         (and (fail? sv) (fail? sv')) (fail (m/mappend (m/extract sv)
@@ -144,28 +142,28 @@
         (ok? sv) sv
         :else sv'))

-    proto/Monoid
+    p/Monoid
     (mempty [_]
       (fail))

-    proto/Functor
+    p/Functor
     (fmap [_ f s]
       (if (ok? s)
         (ok (f (.-v s)))
         s))

-    proto/Foldable
+    p/Foldable
     (foldl [_ f z mv]
       (if (ok? mv)
-        (f z (proto/extract mv))
+        (f z (p/extract mv))
         z))

     (foldr [_ f z mv]
       (if (ok? mv)
-        (f (proto/extract mv) z)
+        (f (p/extract mv) z)
         z))

-    proto/Applicative
+    p/Applicative
     (pure [_ v]
       (ok v))


Need to figure out a way to test jobs without messaging, i think.

--- integration-tests/apps/jobs/test/jobs/at.clj
+++ integration-tests/apps/jobs/test/jobs/at.clj
@@ -66,7 +66,7 @@

 (deftest until-with-every-should-repeat-until-until
   (let [q (random-queue)]
-    (with-job #(msg/publish q "ping") [:until (+ 2000 (System/currentTimeMillis)) :every 500]
+    (with-job #(msg/publish q "ping") [:until (+ 1999 (System/currentTimeMillis)) :every 500]
       (is (= "ping" (msg/receive q :timeout 10000)))
       (is (= ["ping" "ping" "ping" nil] (take 4 (msg/message-seq q :timeout 550)))))))


PoC fix for ws handler added

PoC fix for ws handler added

--- src/clj/hellhound/http/websocket.clj
+++ src/clj/hellhound/http/websocket.clj
@@ -125,8 +125,9 @@
 (defn ws
   [{:keys [input output request] :as context}]
   (log/info "Accpting WS connection")
-  ;; TODO return the Ring response using a deferred value
-  non-websocket-request)
+  (accept-ws request input output)
+  (assoc context :response {:status 101}))
+  ;;non-websocket-request)

 ;; TODO: we need to return a correct response in this
 ;; interceptor


Add more information to `ModulesSelected`

on top of the lesson label. This should give us an easier time when we need to
remove the modules.

In addition, we use the `doall` function to force evaluation of
`add-module-lesson` instead of `vec`.

Signed-off-by: Pang Yan Han <22594c345857f664c61cd411f607c4d40a9d4af9@gmail.com>

--- src/cljs/cljs_nusmods/timetable.cljs
+++ src/cljs/cljs_nusmods/timetable.cljs
@@ -342,7 +342,11 @@
       (attr tdHTMLElem "colspan" slotsOcc)
       (doseq [siblingTdElem (take (- slotsOcc 1) (.nextAll tdHTMLElem))]
         (.remove siblingTdElem))
-      divElem)))
+
+      ; Returns a map containing information to make it easier to remove the
+      ; lesson
+      {:day day, :rowNum rowNum, :startTime startTime, :endTime endTime,
+       :divElem divElem})))

 (defn- add-module-lesson-group
   "Adds a lesson group of a module to the timetable."
@@ -353,17 +357,19 @@
         lessons    (get-in ModulesMap [moduleCode "lessons" lessonType
                                        lessonLabel])]
     (if (and moduleName lessons)
-        (let [lessonDivs (vec (map (fn [lesson]
-                                (add-module-lesson moduleCode
-                                                   moduleName
-                                                   lessonType
-                                                   lessonLabel
-                                                   lesson
-                                                   bgColorCssClass))
-                              lessons))]
+        (let [lessonInfoSeq (doall
+                              (map (fn [lesson]
+                                     (add-module-lesson moduleCode
+                                                        moduleName
+                                                        lessonType
+                                                        lessonLabel
+                                                        lesson
+                                                        bgColorCssClass))
+                                   lessons))]
           ; Update ModulesSelected with the lesson group
           (set! ModulesSelected
-                (assoc-in ModulesSelected [moduleCode lessonType] lessonLabel))
+                (assoc-in ModulesSelected [moduleCode lessonType]
+                          {:label lessonLabel, :info lessonInfoSeq}))

           ; Add to ModulesSelectedOrder
           (if (not-any? #{moduleCode} ModulesSelectedOrder)


fix old merge conflict

fix old merge conflict

--- src/cljs/phonecat_re_frame/core.cljs
+++ src/cljs/phonecat_re_frame/core.cljs
@@ -123,7 +123,14 @@
         [:option (mark-selected {:value "name"} @order-prop "name") "Alphabetical"]
         [:option (mark-selected {:value "age"} @order-prop "age") "Newest"]]])))

+(defn phones-component
+  []
+  (let [phones (re-frame/subscribe [:phones])]
+    (fn []
+      [:ul (doall  (map (fn [phone] ^{:key phone} [phone-component (:name phone) (:snippet phone)]) @phones))])))
+
 (defn home-page []
+  [phones-component])
   [:div {:class "container-fluid"}
    [:div {:class "row"}
     [:div {:class "col-md-2"}


Modified invalid exclude message

Modified invalid exclude message

--- src/cmr/common/services/messages.clj
+++ src/cmr/common/services/messages.clj
@@ -49,6 +49,8 @@
     (format "Pattern option setting disallowed on these parameters: %s" params)))

 (defn invalid-exclude-param-msg
-  "Creates a message saying supplied parameter is not in exclude params set."
-  [param]
-  (format "Parameter [%s] can not be used with exclude." param))
+  "Creates a message saying supplied parameter(s) are not in exclude params set."
+  ([]
+   (format "Some or all of the supplied parameters can not be used with exclude."))
+  ([param]
+   (format "Parameter [%s] can not be used with exclude." param)))


adding delay feature to upmap

adding delay feature to upmap

--- src/flax/core.clj
+++ src/flax/core.clj
@@ -27,9 +27,13 @@

 (defn upmap
-  [fn coll]
+  [fn coll & [delay]]
   (doall
-    (for [p (doall (map #(future (fn %)) coll))]
+    (for [p (doall
+              (map
+                #(do
+                   (Thread/sleep (or delay 0))
+                   (future (fn %)) coll)))]
       @p)))


Added second button besides the new-module button, for editing.

--- src/noteServer/html.clj
+++ src/noteServer/html.clj
@@ -39,7 +39,11 @@
                          "text"
                          [:p (:text data)])]))
               modules)
-         [:div.module.module-adder [:button [:object {:type "image/svg+xml" :data "img/circle-plus.svg"}]]]
+         [:div.module.module-adder
+          [:button.edit-module-btn [:object {:type "image/svg+xml" :data "img/pencil.svg"}]]
+          [:button.pre-module-btn [:object {:type "image/svg+xml" :data "img/circle-plus.svg"}]]
+          ;; TODO There should be a delete button here!
+          ]
          [:footer
           [:span.id "Id: " id]]]))
     entries))


added span to html for easier adding of modules

--- src/noteServer/html.clj
+++ src/noteServer/html.clj
@@ -8,7 +8,7 @@
 ;; TODO split this into multiple functions, so it gets readable
 (defhtml format-notes [entries]
   (println entries)
-  (map
+  (map
     (fn [note]
       (println note)
       (let [note-id (:id note)
@@ -40,6 +40,8 @@
                          [:p (:text data)])]))
               modules)

+         [:span.module-divide]
+
          [:div.footer-module {:role "module"}
           [:span.id "Id: " note-id]]]))
     entries))


incremental progress

incremental progress

--- src-cljs/frontend/components/build_timings.cljs
+++ src-cljs/frontend/components/build_timings.cljs
@@ -163,6 +163,8 @@
         (.selectAll "rect")
           (.data #(aget % "actions"))
         (.enter)
+          (.append "a")
+            (.attr "href" (partial step-href owner))
           (.append "rect")
             (.attr "class"     #(str "container-step-" (build/status-class (wrap-status (aget % "status")))))
             (.attr "width"     step-length)
@@ -173,7 +175,7 @@
                                          (highlight-selected-step! step selected)
                                          (highlight-selected-container! %)))
             (.on   "mouseout"  #(reset-selected! step))
-            (.on   "click"     (partial scroll-to-step owner))
+            ;(.on   "click"     (partial scroll-to-step owner))
           (.append "title")
             (.text #(gstring/format "%s (%s:%s) - %s"
                                     (aget % "name")


fix adding link targets

fix adding link targets

--- src-cljs/frontend/components/documentation.cljs
+++ src-cljs/frontend/components/documentation.cljs
@@ -107,20 +107,21 @@
         (om/build article-list (get-in docs [:troubleshooting :children]))]]])))

 (defn add-link-targets [node]
-  (doseq [tag ["h2" "h3" "h3" "h4" "h5" "h6"]
-          heading (utils/node-list->seqable (goog.dom/getElementsByTagNameAndClass tag "content"))]
-    (let [title (utils/text heading)
-          id (if-not (string/blank? (.-id heading))
-               (.-id heading)
-               (-> title
-                   string/lower-case
-                   string/trim
-                   (string/replace \' "")     ; heroku's -> herokus
-                   (string/replace #"[^a-z0-9]+" "-") ; dashes
-                   (string/replace #"^-" "") ; don't let first or last be dashes
-                   (string/replace #"-$" "")))]
-      (utils/set-html! heading
-                       (gstring/format "%s" id id title)))))
+  (let [content-container (goog.dom/getElementByClass "content")]
+    (doseq [tag ["h2" "h3" "h3" "h4" "h5" "h6"]
+            heading (utils/node-list->seqable (goog.dom/getElementsByTagNameAndClass tag nil content-container))]
+      (let [title (utils/text heading)
+            id (if-not (string/blank? (.-id heading))
+                 (.-id heading)
+                 (-> title
+                     string/lower-case
+                     string/trim
+                     (string/replace \' "")     ; heroku's -> herokus
+                     (string/replace #"[^a-z0-9]+" "-") ; dashes
+                     (string/replace #"^-" "") ; don't let first or last be dashes
+                     (string/replace #"-$" "")))]
+        (utils/set-html! heading
+                         (gstring/format "%s" id id title))))))

 (defrender markdown [markdown]
   (html


debug -> trace

debug -> trace

--- src/ontrail/summary.clj
+++ src/ontrail/summary.clj
@@ -59,7 +59,7 @@
   (to-summary (get-db-summary condition) sport))

 (defn get-overall-summary-cond [user condition]
-  (.debug logger (str "Getting summary: " user " condition " condition))
+  (.trace logger (str "Getting summary: " user " condition " condition))
   (let [cond-with-user (assoc condition :user user)
         all-distinct-sports (mc/distinct EXERCISE "sport" cond-with-user)
         summary-sports (sort-by :numericalDuration > (map #(get-summary (assoc cond-with-user :sport %) %) all-distinct-sports))]


Improve logging for s3 module.

Improve logging for s3 module.

--- src/onyx/storage/s3.clj
+++ src/onyx/storage/s3.clj
@@ -150,7 +150,7 @@
    task-id slot-id checkpoint-type ^bytes checkpoint-bytes]
   (let [k (checkpoint-task-key tenancy-id job-id replica-version epoch task-id
                                slot-id checkpoint-type)
-        _ (info "Writing checkpoint to s3 under key" k)
+        _ (info "Starting checkpoint to s3 under key" k)
         up ^Upload (onyx.storage.s3/upload ^TransferManager transfer-manager
                                            bucket
                                            k
@@ -158,7 +158,8 @@
                                            "application/octet-stream"
                                            :none)]
     (reset! upload up)
-    (reset! metric {:size-bytes (alength checkpoint-bytes)
+    (reset! metric {:key k
+                    :size-bytes (alength checkpoint-bytes)
                     :start-time (System/nanoTime)})
     storage))

@@ -172,6 +173,7 @@

             (= (Transfer$TransferState/Completed) state)
             (do
+             (info "Completed checkpoint to s3 under key" (:key @metric))
              (m/update-timer-ns! (:checkpoint-store-latency monitoring)
                                  (- (System/nanoTime) (:start-time @metric)))
              (.addAndGet ^AtomicLong (:checkpoint-written-bytes monitoring) (:size-bytes @metric))


Update tabs in dark toolbar example

Update tabs in dark toolbar example

--- src/css-guide/styles/components.cljs
+++ src/css-guide/styles/components.cljs
@@ -1764,7 +1764,7 @@
   This toolbar is mainly used for specific operations and navigation for the current app you are using.
   "
   (let [selected-item (or (om/get-state this :selected-item) :widgets)
-        get-class (fn [item] (str "c-tab " (if (= item selected-item) " is-active" "")))
+        get-class (fn [item] (str "c-tab c-tab--contrast " (if (= item selected-item) " is-active" "")))
         select-item (fn [item] (om/update-state! this assoc :selected-item item))
         ]
     (e/ui-iframe {:width "100%"}


increase ajax delay a bit

increase ajax delay a bit

--- src/pc/http/talaria.clj
+++ src/pc/http/talaria.clj
@@ -16,7 +16,7 @@

 (defn init [& {:keys [ws-delay ajax-delay ping-ms]
                :or {ws-delay 30
-                    ajax-delay 100
+                    ajax-delay 150
                     ping-ms (* 1000 60)}}]
   (let [recv-queue (LinkedBlockingQueue.)
         async-pool (delay/make-pool!)]


fixed comment order

fixed comment order

--- src/blog/comment/comment_sql_datastore_impl.clj
+++ src/blog/comment/comment_sql_datastore_impl.clj
@@ -60,7 +60,7 @@
   (jdbc/query db [(str "SELECT id, name, time, text "
                        "FROM comment "
                        "WHERE article = ? "
-                       "ORDER BY time DESC")
+                       "ORDER BY time ASC")
                   article-code]
               :row-fn spec/map->Comment))


Moved lambda-blog attribution to a separate template.

--- src/lambda_blog/templates/footer.clj
+++ src/lambda_blog/templates/footer.clj
@@ -2,6 +2,12 @@
   (:require [lambda-blog.templates.bits :refer [javascript row text-centered]]
             [lambda-blog.utils :refer [pathcat]]
             [s-html.tags :refer [a div hr p script] :as tags]))
+
+(defn powered-by []
+  (p "Powered by "
+     (a {:href "https://github.com/Idorobots/lambda-blog"}
+        "λ-blog")
+     "."))

 (defn footer [{:keys [footer-contents footer-scripts path-to-root]}]
   [(tags/footer
@@ -9,8 +15,5 @@
     (row
      (text-centered
       footer-contents
-      (p "Powered by "
-         (a {:href "https://github.com/Idorobots/lambda-blog"}
-            "λ-blog")
-         "."))))
+      (powered-by))))
    (map #(javascript (pathcat path-to-root %)) footer-scripts)])


Cache response

Cache response

--- src/clj_simple_chart/ssb/nettokontantstraum.clj
+++ src/clj_simple_chart/ssb/nettokontantstraum.clj
@@ -10,7 +10,7 @@
 (def qq [{:code "ContentsCode" :selection {:filter "all" :values ["*"]}}
          {:code "Tid" :selection {:filter "all" :values ["*"]}}])
 (def q {:query qq :response {:format "csv"}})
-(def response (client/post url {:form-params q :content-type :json :as :byte-array}))
+(defonce response (client/post url {:form-params q :content-type :json :as :byte-array}))
 (test/is (= "text/csv; charset=Windows-1252" (get (:headers response) "Content-Type")))

 (def resp (String. (:body response) "Windows-1252"))


What,why,how first sentence

What,why,how first sentence

--- src/prais2/content.cljc
+++ src/prais2/content.cljc
@@ -843,7 +843,7 @@
                              [:div
                               [:p "The data come from the National Congenital Heart Disease Audit ("
                                [:a (core/href "http://www.ucl.ac.uk/nicor/audits/congenital" :target "_blank") "NCHDA"] ")
-                               which is part of the National Institute of Cardiovascular Outcomes Research ("
+                               which is managed by the National Institute of Cardiovascular Outcomes Research ("
                                [:a (core/href "https://www.ucl.ac.uk/nicor") "NICOR"] "). "
                                ;" which collects national data for the " [:a (core/href "http://www.ucl.ac.uk/nicor/audits/congenital" :target "_blank") "UK National Heart Disease Audits"] "."
                                "All hospitals in the UK and Ireland performing heart


Improve logging middleware.

Improve logging middleware.

Log request and response attributes as key/value pairs. Add Request ID to log
message.

--- src/lunchlotto/common/middleware.clj
+++ src/lunchlotto/common/middleware.clj
@@ -1,9 +1,7 @@
 (ns lunchlotto.common.middleware
   (:require [clojure.string :as s]
             [clojure.tools.logging :as log]
-            [ring.util.response :as ring]
-            [clj-time.core :as time]
-            [clj-time.format :as tformat])
+            [ring.util.response :as ring])
   (:import (java.util UUID)))

 (def sim-methods {"PUT" :put "DELETE" :delete})
@@ -23,15 +21,26 @@
   [hdlr]
   (fn [req]
     (let [start (System/currentTimeMillis)
-          method (s/upper-case (name (:request-method req)))
-          url (str (:uri req)
-                   (if-let [query-string (:query-string req)]
-                     (str "?" query-string)))]
-      (log/info "Started" method (str "'" url "'") "for" (:server-name req))
+          req-id (get-in req [:headers "x-request-id"])
+          to-keypair-strings (fn [[k v]] (str (name k) "=" v))
+          req-attrs {:method (s/upper-case (name (:request-method req)))
+                     :url (str (:uri req)
+                               (if-let [query-string (:query-string req)]
+                                 (str "?" query-string)))
+                     :params (:params req)
+                     :host (:server-name req)
+                     :protocol (s/upper-case (name (:scheme req)))}]
+      (log/info (str
+                  (format "[%s] RING Starting " req-id)
+                  (s/join " " (map to-keypair-strings req-attrs))))
       (let [resp (hdlr req)
-            finish (System/currentTimeMillis)
-            total (- finish start)]
-        (log/info "Completed" (:status resp) "in" (str total "ms"))
+            resp-attrs {:status (:status resp)
+                        :duration-ms (- (System/currentTimeMillis) start)}]
+        (log/info (str
+                    (format "[%s] RING Finished " req-id)
+                    (s/join " " (map to-keypair-strings resp-attrs))
+                    (if-let [location (get-in resp [:headers "Location"])]
+                      (str " redirect-to=" location))))
         resp))))

 (defn wrap-content-type-html


Qualify type hints when parsing rules for issue #63

--- src/main/clojure/clara/rules/dsl.clj
+++ src/main/clojure/clara/rules/dsl.clj
@@ -133,12 +133,24 @@
           (symbol (str (ns-name (:ns (meta (resolve sym))))) (name sym))
           sym)))))

+(defn- qualify-meta
+  "Qualify metadata associated with the symbol."
+  [env sym]
+  (if (:tag (meta sym))
+    (vary-meta sym update-in [:tag] (fn [tag] (-> (resolve tag)
+                                                 (.getName)
+                                                 (symbol))))
+    sym))
+
 (defn- resolve-vars
   "Resolve vars used in expression. TODO: this should be narrowed to resolve only
    those that aren't in the environment, condition, or right-hand side."
   [form env]
   (walk/postwalk
-   #(maybe-qualify env %)
+   (fn [sym]
+     (->> sym
+          (maybe-qualify env)
+          (qualify-meta env)))
    form))

 (defmacro local-syms []


Border demo page improvements. See previous checkin.

--- src/re_demo/border.cljs
+++ src/re_demo/border.cljs
@@ -25,6 +25,7 @@
                                      [args-table border-args-desc]]]
                          [v-box
                           :gap      "10px"
+                          ; :size     "0 0 auto"
                           ;:align    :start
                           :children [[title2 "Demo"]
                                      [p "Here is some sample code..."]
@@ -32,12 +33,10 @@
                                       {:style {:width "40em"}}
 "[border
  :border \"1px dashed red\"
- :size   \"100px\"
- :child  [box :child \"Hello\"]]"]
+ :child  [box :height \"100px\" :child \"Hello\"]]"]

                                      [p "Here is the result..."]
                                      [border
                                       :border "1px dashed red"
-                                      :size   "100px"
-                                      :child  [box :child "Hello"]]]]]]
+                                      :child  [box :height "100px" :child "Hello"]]]]]]
               [gap :size "30px"]]])


Error message made more generic

Error message made more generic

--- src/re_frame/utils.cljs
+++ src/re_frame/utils.cljs
@@ -42,5 +42,5 @@
   [v]
   (if (vector? v)
     (first v)
-    (error "re-frame: expected a vector event, but got: " v)))
+    (error "re-frame: expected a vector, but got: " v)))


Remove extra lines

Remove extra lines

--- src/robinson/render.clj
+++ src/robinson/render.clj
@@ -10,8 +10,6 @@
             [robinson.ui.components.robinson :as ruic]
             [clojure.stacktrace :as st]))

-(set! *warn-on-reflection* true)
-
 (defn render [terminal state last-dom]
   (binding [zc/*updater* ruu/updater]
     (try
@@ -20,7 +18,6 @@
                   terminal
                   last-dom
                   ui)]
-        #_(zt/refresh! terminal)
         (assert (zc/element? ui))
         ;; update component instance states
         (zc/update-state! zc/*updater*)


Added printlns

Added printlns

--- src/live/core.clj
+++ src/live/core.clj
@@ -5,9 +5,11 @@
 (def count (atom 124))

 (defremote get-count  []
+  (println "in server's get-count")
   (identity @count))

 (defremote set-count  [n]
+  (println "in server's set-count")
   (set! count n))

 (defn -main [& args]


reduce and friends

reduce and friends

--- src/such/better_doc.clj
+++ src/such/better_doc.clj
@@ -241,3 +241,165 @@
                 false (map inc) ; not taken
                 true  (map -))
         => [-1 -2 -3]")
+
+(update-and-make-local-copy! #'clojure.core/reduce
+  "`reduce` converts a collection into a single value. Except for
+   one exception (described below), `f` must take two arguments.
+   `+` takes two arguments, so it can be used to reduce a collection
+   of numbers to their sum:
+
+        (reduce + 0 [1 2 3 4]) => 10
+
+   `+` is called four times. Here is the sequence of calls.
+
+        (+ 0 1) => 1   ; sum of first element
+        (+ 1 2) => 3   ; sum of first two elements
+        (+ 3 3) => 6   ; sum of first three elements
+        (+ 6 4) => 10  ; ...
+
+   At any point, the first argument to `f` is the \"reduction\" of all
+   the previous calls to `f`, and the second argument is the next
+   collection element to add into the reduction. When defining functions to
+   use with `reduce`, the first argument is often called `acc` (for
+   \"accumulator\") or `so-far`.
+
+   When using `+`, the distinction between the two arguments isn't
+   clear, so here's an example that returns the longest string in a
+   collection:
+
+        (reduce (fn [max-so-far elt]
+                  (if (> (count elt) max-so-far)
+                    (count elt)
+                    max-so-far))
+                0
+                [\"abc\" \"ab\" \"abcd\" \"a\"]) => 4
+
+   When you're surprised by the results of a call to `reduce`, you
+   can use [[reductions]] as an easy way to see what's going on:
+
+        (reductions + 0 [1 2 3 4])
+                  =>    (0 1 3 6 10)
+
+   `reductions` returns a collection of all the first arguments to `f`
+   plus the final result.
+
+   Reduce is lazy, so the reduction isn't done until the result is used.
+
+   The **two-argument form** can be used when `(f val (first coll))`
+   is the same as `(first coll)`. That's the case with `+`, where
+   `(+ 0 1)` is `1`. So, in the two argument form, the first call to `f`
+   uses the first argument of the collection as the starting reduction
+   and begins working with the second element:
+
+        (reduce + [1 2 3 4]) => 10
+        (reductions + [1 2 3 4]) => (1 3 6 10) ; slightly different result
+
+   **Small arrays:** `f` takes two values. What if there aren't two values
+   to give it? There's one special case
+   for the three-argument form:
+
+        (reduce + 0 []) => 0
+        (reductions + 0 []) => (0)
+
+   In this case, `val` is returned and `f` is never called.
+
+   There are two special two-argument cases. The first is when there's
+   only one element in the collection:
+
+        (reduce + [10]) => 10
+
+   The handling is really the same as the above, since the first argument in
+   the collection is treated as the starting `val`. More interesting is the
+   empty collection:
+
+        (reduce + []) => 0
+        (reductions + []) => (0)
+
+   Here, `f` *is* called, but with zero arguments. It happens that `(+)` is `0`.
+   In the longest-string example, though, the result is not so pretty:
+
+        (reduce (fn [max-so-far elt]...) [])
+        ArityException Wrong number of args (0) ...
+
+   **See also:** [[reductions]], [[reduce-kv]]
+")
+
+(update-and-make-local-copy! #'clojure.core/reductions
+   "Perform a [[reduce]] but don't return only the final reduction.
+   Return a sequence of the intermediate reductions, ending with the
+   final reduction.
+
+   Consider this reduction that produces nested vectors:
+
+        (reduce (fn [so-far elt] (vector (conj so-far elt)))
+                []
+                [1 2 3 4 5])
+        => [[[[[[1] 2] 3] 4] 5]]
+
+   Using `reductions` instead:
+
+        (reductions (fn [so-far elt] (vector (conj so-far elt)))
+                    []
+                    [1 2 3 4 5])
+        => ([]
+            [[1]]
+            [[[1] 2]]
+            [[[[1] 2] 3]]   [[[[[1] 2] 3] 4]]   [[[[[[1] 2] 3] 4] 5]])
+
+   To be more precise, the result is a sequence of the first arguments to
+   `f`, followed by the final value. Those are slightly different in the two-argument
+   and three-argument cases:
+
+        (reductions + 0 [1 2 3]) => (0 1 3 6)
+        (reductions +   [1 2 3]) => (  1 3 6)
+
+   The sequence is lazy:
+
+        (take 3 (reductions (fn [so-far elt] (vector (conj so-far elt)))
+                            []
+                            (range)))  ; infinite list here
+        => ([]  [[0]]  [[[0] 1]])
+")
+
+(update-and-make-local-copy! #'clojure.core/reduce-kv
+  "For maps, `reduce-kv` is a trivial variant on [[reduce]]. The following
+   two functions are the same:
+
+       (reduce     (fn [so-far [key val]] ...) ... {...}
+       (reduce-kvs (fn [so-far  key val ] ...) ... {...}
+
+   For vectors, `reduce-kv` is to `reduce` as [[map-indexed]] is to `map`:
+   it provides indexes as well as collection elements. The argument list
+   is `[reduction-so-far index element]`.
+
+   This example sums up the indices and values of a vector:
+
+       (reduce-kv + 0 [-1 -2 -3 -4]) => -4
+
+   It works because `+` allows three arguments. Here's an example that converts
+   a vector to a map whose keys are the vector indexes:
+
+       (reduce-kv (fn [acc i elt] (assoc acc i elt))
+                  {}
+                  [\"0\" \"2\" \"3\" \"4\"])
+       => {0 \"0\", 1 \"2\", 2 \"3\", 3 \"4\"}
+
+   If `coll` is empty, `init` is returned and `f` is not called.
+")
+
+
+(update-and-make-local-copy! #'clojure.core/map-indexed
+  "In the two-argument form, the following two are equivalent:
+
+        (map-indexed f coll)
+        (map f (range) coll)
+
+   Thus, `f` should accept two arguments: the index of an element in `coll`
+   and the element itself.
+
+        (map-indexed vector [:a :b :c]) => ([0 :a] [1 :b] [2 :c])
+
+   Like `map`, `map-indexed` is lazy.
+
+   The single argument form produces a transducer.
+")


figwheel to server public folder, and open url automatically when figwheel starts.

--- resources/leiningen/new/reagent_frontend/project.clj
+++ resources/leiningen/new/reagent_frontend/project.clj
@@ -20,7 +20,7 @@

   :resource-paths ["public"]

-  :figwheel {:http-server-root "public"
+  :figwheel {:http-server-root "."
              :nrepl-port 7002
              :nrepl-middleware ["cemerick.piggieback/wrap-cljs-repl"]
              :css-dirs ["public/css"]}
@@ -34,7 +34,9 @@
                          :asset-path   "js/out"
                          :source-map true
                          :optimizations :none
-                         :pretty-print  true}}
+                         :pretty-print  true}
+                        :figwheel
+                        {:open-urls ["http://localhost:3449/index.html"]}}
                        :release
                        {:source-paths ["src" "env/prod/cljs"]
                         :compiler