Implement Utopia, Hades, Eden Shard.

Implement Utopia, Hades, Eden Shard.

--- src/clj/game/cards-resources.clj
+++ src/clj/game/cards-resources.clj
@@ -110,7 +110,12 @@

    "Eden Shard"
    {:abilities [{:effect (effect (trash card {:cause :ability-cost}) (draw :corp 2))
-                 :msg "force the Corp to draw 2 cards"}]}
+                 :msg "force the Corp to draw 2 cards"}]
+    :install-cost-bonus (req (if (and run (= (:server run) [:rd]) (= 0 (:position run)))
+                               [:credit -7 :click -1] nil))
+    :effect (req (when (and run (= (:server run) [:rd]) (= 0 (:position run)))
+                   (swap! state update-in [:runner :prompt] rest)
+                   (handle-end-run state side)))}

    "Enhanced Vision"
    {:events {:successful-run {:msg (msg "force the Corp to reveal " (:title (first (shuffle (:hand corp)))))
@@ -169,7 +174,12 @@

    "Hades Shard"
    {:abilities [{:msg "access all cards in Archives"
-                 :effect (effect (trash card {:cause :ability-cost}) (handle-access (access state side [:archives])))}]}
+                 :effect (effect (trash card {:cause :ability-cost}) (handle-access (access state side [:archives])))}]
+    :install-cost-bonus (req (if (and run (= (:server run) [:archives]) (= 0 (:position run)))
+                               [:credit -7 :click -1] nil))
+    :effect (req (when (and run (= (:server run) [:archives]) (= 0 (:position run)))
+                   (swap! state update-in [:runner :prompt] rest)
+                   (handle-end-run state side)))}

    "Hard at Work"
    {:events {:runner-turn-begins {:msg "gain 2 [Credits] and lose [Click]"
@@ -476,7 +486,7 @@
                                        (:hosted card)))
                  :msg (msg "install " (:title target) " lowering its install cost by 1 [Credits]")
                  :effect (effect
-                           (install-cost-bonus -1) (runner-install (dissoc target :facedown))
+                           (install-cost-bonus [:credit -1]) (runner-install (dissoc target :facedown))
                            (trash (update-in card [:hosted]
                                              (fn [coll]
                                                (remove-once #(not= (:cid %) (:cid target)) coll)))
@@ -572,7 +582,12 @@
    "Utopia Shard"
    {:abilities [{:effect (effect (trash-cards :corp (take 2 (shuffle (:hand corp))))
                                  (trash card {:cause :ability-cost}))
-                 :msg "force the Corp to discard 2 cards from HQ at random"}]}
+                 :msg "force the Corp to discard 2 cards from HQ at random"}]
+    :install-cost-bonus (req (if (and run (= (:server run) [:hq]) (= 0 (:position run)))
+                               [:credit -7 :click -1] nil))
+    :effect (req (when (and run (= (:server run) [:hq]) (= 0 (:position run)))
+                   (swap! state update-in [:runner :prompt] rest)
+                   (handle-end-run state side)))}

    "Virus Breeding Ground"
    {:data {:counter-type "Virus"}


Define the type of library_signature more strictly

--- src/clj/mdr2/production/spec.clj
+++ src/clj/mdr2/production/spec.clj
@@ -2,10 +2,9 @@
   (:require [spec-tools.data-spec :as spec]
             [clojure.spec.alpha :as s]))

-(s/def ::state (s/and string? #{"new" "archived" "cataloged"
-                                "deleted" "encoded" "failed"
-                                "pending-split" "recorded" "split" "structured"}))
+(s/def ::state (s/and string? #{"new" "archived" "cataloged" "deleted" "encoded" "failed" "pending-split" "recorded" "split" "structured"}))
 (s/def ::production_type (s/and string? #{"book" "periodical" "other"}))
+(s/def ::library_signature (s/and string? #(re-matches #"^ds\d{5,}$" %)))
 (s/def ::date #(instance? java.time.LocalDate %))

 (def production
@@ -43,6 +42,6 @@
    (spec/opt :production_type) ::production_type
    (spec/opt :periodical_number) string?
    (spec/opt :library_number) string?
-   (spec/opt :library_signature) string?
+   (spec/opt :library_signature) ::library_signature
    (spec/opt :library_record_id) int?
    })


extra constant

extra constant

--- src/cljc/scrabble/constants.cljc
+++ src/cljc/scrabble/constants.cljc
@@ -1,4 +1,8 @@
 (ns scrabble.constants)
+
+(def ^:const ALPHA-LOWER
+  "All possible characters"
+  (map char (range (int \a) (inc (int \z)))))

 (def ^:const JOLLY-CHAR
   "Symbol to use for the jolly letter"


Only do move if the note is found where it should be

--- src/cljs/retroboard/actions.cljs
+++ src/cljs/retroboard/actions.cljs
@@ -32,7 +32,7 @@

   (move-note
    [id column-id new-column-id state]
-   (let [note (get-in state [column-id :notes id])]
+   (if-let [note (get-in state [column-id :notes id])]
      (-> state
          (update-in [column-id :notes] dissoc id)
          (assoc-in [new-column-id :notes id] note)))))


fixed issue with anti-aliased text returning the wrong color on the colormap

--- src/cljs/zee3/draw/colormap.cljs
+++ src/cljs/zee3/draw/colormap.cljs
@@ -25,6 +25,10 @@
   (let [ hex (.toString s 16)]
     (str (.substr "00" 0, (- 2 (.-length hex))) hex)))

+(defn from-hex [s]
+  (let [r (subs s 1 3) g (subs s 3 5) b (subs s 5 7)]
+    [(js/parseInt r 16) (js/parseInt g 16) (js/parseInt b 16)]))
+
 (defn color-hash []
    (let [r (atom 1) g (atom 0) b (atom 0)]
       (fn []
@@ -37,20 +41,72 @@

 (def color-generator (color-hash))

+(defn create-canvas [config stage-id]
+    (let [ {:keys [id width height]} config e (.createElement js/document "canvas")]
+      (set! (.-id e) stage-id)
+      (set! (.-width e) width)
+      (set! (.-height e) height)
+      e))
+
 (defn draw-stage [config]
-  (let [ {:keys [id width height]} config e (.createElement js/document "canvas") hit-stage-id (build-name id)]
-    (set! (.-id e) hit-stage-id)
-    (set! (.-width e) width)
-    (set! (.-height e) height)
+  (let [ {:keys [id width height]} config
+         hit-stage-id (build-name id)
+         e (create-canvas config hit-stage-id) ]
+
     (let [ctx (.getContext e "2d")]
       (swap! shape/entities conj (assoc config :type "stage" :ref e :context ctx :id hit-stage-id :parent id)))))
+
+(defn render-text
+  "Custom text renderer for color map"
+  [ctx config]
+  (let [{:keys [x y text font textBaseline]} config]
+    (shape/draw-base ctx config (fn []
+      (set! (.-fillStyle ctx) "#050505")
+      (set! (.-font ctx) font)
+      (set! (.-textBaseline ctx) textBaseline)
+      (.fillText ctx text x y)))))
+
+(defn transpose-text
+  "transfers the text without anti-alias to the color map context"
+  [d1 d2 rgb]
+  (let [len (.-length d1)]
+    (dotimes [n (/ len 4)]
+      (let [i (* n 4)
+            r (aget d1 i)
+            g (aget d1 (+ i 1))
+            b (aget d1 (+ i 2))]
+        (cond (and (= r 5) (= g 5) (= b 5))
+              (do
+                (aset d2 i (rgb 0))
+                (aset d2 (+ i 1) (rgb 1))
+                (aset d2 (+ i 2) (rgb 2))
+                (aset d2 (+ i 3) 255)
+                (.log js/console (str "index:" (* n 4))))))))
+    d2)
+
+(defn draw-text [ctx config]
+  (let [hit-stage (.-id (.-canvas ctx))
+        ctx-config (get-by-id hit-stage)
+        tmp-ctx (.getContext (create-canvas ctx-config "tmp") "2d")]
+    (render-text tmp-ctx config)
+    (let [d1 (.-data (.getImageData tmp-ctx 0 0 (.-width (.-canvas tmp-ctx)) (.-height (.-canvas tmp-ctx))))
+          imgData2 (.getImageData ctx 0 0 (.-width (.-canvas ctx)) (.-height (.-canvas ctx)))
+          d2 (.-data imgData2)
+          len (.-length d1)
+          color (:fillStyle config)
+          rgb (from-hex color)]
+      (transpose-text d1 d2 rgb)
+        (.putImageData ctx imgData2 0 0))))

 (defn render-shape [ctx config]
    (let [color (color-generator)
           hit-config (assoc config :strokeStyle color :fillStyle color)
          hit-context (get-hit-context config)]
       (swap! color-map assoc color config)
-      ((:renderer config) hit-context hit-config)))
+     (cond (= "text" (:type config))
+           (draw-text hit-context hit-config)
+           :else
+          ((:renderer config) hit-context hit-config))))

 (defn intersects
   "Tests for intersection using the colormap"
@@ -88,9 +144,11 @@
         hit-ctx (:context (get-by-id hit-stage))
         color (pixel-color hit-ctx x y)
         color-map-config (get @color-map color)]
-    (cond (= event-type :mousemove)
+    (cond (= event-type :mouseup)
           (do (.log js/console (str ":mousemove"))
-            (.log js/console (str "color:" color))))
+            (.log js/console (str "color:" color))
+            (.log js/console (str "alpha:" (.-globalAlpha hit-ctx)))
+            (.log js/console (str "x:" x " y:" y))))
     (cond (not(nil? color-map-config))
           (let [f (get color-map-config event-type)]
             (cond (not (nil? f))


remove unused code

remove unused code

--- src/clojure_fabric/chaincode.clj
+++ src/clojure_fabric/chaincode.clj
@@ -201,12 +201,6 @@
                                                  :extension extension)
                       :signature-header (proto/make-signature-header :creator identity :nonce nonce))))

-(defn make-config-update-envelope
-  [channel-name user orderer config signatures]
-  (let [header (make-header channel-name user {:channel-header-type :config-update})
-        payload ]))
-
-
 (defn make-chaincode-proposal
   [chaincode-key channel-name user {:keys [args] :as opts}]
   (let [{:keys [chaincode-id header-extension proposal-payload]}
@@ -271,9 +265,9 @@
                         (Exception. "Verification failed!")
                         (if ->response
                           (let [response (.getResponse ^ProposalResponsePackage$ProposalResponse raw-response)]
-                            (->> (.getPayload ^ProposalResponsePackage$Response response)
-                                 (->response)
-                                 (proto/proto->clj)))
+                            (-> (.getPayload ^ProposalResponsePackage$Response response)
+                                (->response)
+                                (proto/proto->clj nil)))
                           raw-response)))))))))

 ;; Responses -


Improve default :visualize behavior

Improve default :visualize behavior

--- src/clojush/pushgp/visualize.clj
+++ src/clojush/pushgp/visualize.clj
@@ -2,31 +2,44 @@
   (:use [clojush.globals])
   (:require [quil.core :as q]))

-;; The initial value of viz-data-atom is set in clojush.pushgp.report/initial-report,
-;; and updates are made in other functions in that namespace.
+(def viz-width 1000)
+(def viz-height 1000)
+(def viz-border 50)
+
+;; The initial value of viz-data-atom is set set below, in start-visualization.
+
+;; Updates should be made in clojush.pushgp.report/report-and-check-for-success.

 (defn visualize []
-  (let [scale-x 10
-        scale-y 2]
-    (q/background 255)
-    (q/fill 0)
-    (q/text "Evolution!" 100 100)
-    (let [gen (:generation @viz-data-atom)]
-      (q/line (* (inc gen) scale-x) 0 (* (inc gen) scale-x) 1000))
-    (doseq [[gen err]
-            (map vector
-                 (iterate inc 0)
-                 (map (partial * scale-y)
-                      (map (partial apply +)
-                           (:history-of-errors-of-best @viz-data-atom))))]
-      (q/fill 0)
-      (q/rect (* gen scale-x) (- 1000 (* err scale-y) scale-y) scale-x scale-y))))
+  (let [data @viz-data-atom
+        gen (:generation data)]
+    (when (> gen 0)
+      (let [bests (:history-of-errors-of-best data)
+            num-errors (count (first bests))
+            scale-x (/ (- viz-width (* 2 viz-border))
+                       (max 1 gen))
+            scale-y (/ (- viz-height (* 2 viz-border))
+                       (max 1 (apply max (flatten bests))))]
+        (q/color-mode :rgb 255)
+        (q/background 255)
+        ;(q/fill 0)
+        ;(q/text (str "Generation: " gen) 10 20)
+        (q/color-mode :hsb)
+        (doseq [[g errs] (map vector (iterate inc 0) bests)]
+          (doseq [[i e] (map vector (iterate inc 0) errs)]
+            (q/no-stroke)
+            (q/fill (* i (/ 255 num-errors)) 255 255 64)
+            (q/ellipse (+ viz-border (* g scale-x))
+                       (- viz-height viz-border (* e scale-y))
+                       20
+                       20)))))))

 (defn start-visualization []
+  ;; Initialize viz-data-atom here, with whatever keys you want to track.
   (reset! viz-data-atom {:generation 0
                          :history-of-errors-of-best []})
   (q/sketch
-    :size [1000 1000]
+    :size [viz-width viz-height]
     :draw visualize))

 (start-visualization)


Docstring for error-handler-plugin

Docstring for error-handler-plugin

--- src/com/wsscode/pathom/core.cljc
+++ src/com/wsscode/pathom/core.cljc
@@ -973,6 +973,11 @@
           (seq @errors) (assoc ::errors @errors))))))

 (def error-handler-plugin
+  "Wrap reads with try-catch and put any errors under `::p/errors` (including the path),
+   setting the value of the errored node to `::p/reader-error`.
+
+  You can customize how the error is exported into the `::p/errors` map by setting the key
+  `::p/process-error` in your environment to a function of [env, err] -> data."
   {::wrap-read   wrap-handle-exception
    ::wrap-parser wrap-parser-exception
    ::wrap-mutate wrap-mutate-handle-exception})


Plugin to wrap trace

Plugin to wrap trace

--- src/com/wsscode/pathom/core.cljc
+++ src/com/wsscode/pathom/core.cljc
@@ -728,6 +728,17 @@
    ::wrap-parser wrap-parser-exception
    ::wrap-mutate wrap-mutate-handle-exception})

+(defn wrap-parser-trace [parser]
+  (fn wrap-parser-trace-internal [env tx]
+    (if (some #{:com.wsscode.pathom/trace} tx)
+      (let [trace* (pt/live-trace! (atom []))]
+        (let-chan [res (parser (assoc env ::pt/trace* trace*) tx)]
+          (assoc res :com.wsscode.pathom/trace @trace*)))
+      (parser env tx))))
+
+(def trace-plugin
+  {::wrap-parser wrap-parser-trace})
+
 (defn collapse-error-path [m path]
   "Reduces the error path to the last available nesting on the map m."
   (vec


CMR-738: Added support for cartesian polygons in atom responses.

--- src/cmr/search/results_handlers/atom_spatial_results_handler.clj
+++ src/cmr/search/results_handlers/atom_spatial_results_handler.clj
@@ -5,6 +5,7 @@
             [cmr.spatial.point :as p]
             [cmr.spatial.mbr :as m]
             [cmr.spatial.geodetic-ring :as gr]
+            [cmr.spatial.cartesian-ring :as cr]
             [cmr.spatial.line-string :as l]
             [clojure.string :as str]))

@@ -65,6 +66,17 @@
                (x/element :gml:posList {}
                           (shape->string ring))))

+  cmr.spatial.cartesian_ring.CartesianRing
+  (shape->string
+    [ring]
+    (points-map->points-str ring))
+
+  (shape->xml-element
+    [ring]
+    (x/element :gml:LinearRing {}
+               (x/element :gml:posList {}
+                          (shape->string ring))))
+
   cmr.spatial.polygon.Polygon
   (shape->xml-element
     [{:keys [rings]}]


Fixed add-new-object bug...

Fixed add-new-object bug...

--- src/conexp/contrib/gui/editors/context_editor/context_editor.clj
+++ src/conexp/contrib/gui/editors/context_editor/context_editor.clj
@@ -62,7 +62,7 @@

 (defn-context-changer add-new-object
   "Adds a new object."
-  (make-context (conj (objects context)
+  (make-context (conj (objects ctx)
                       (req-unique-string (objects ctx) "new object"))
                 (attributes ctx)
                 (incidence ctx)))


Test for unknown environment handling

Test for unknown environment handling

--- test/emender_jenkins/results_test.clj
+++ test/emender_jenkins/results_test.clj
@@ -278,3 +278,12 @@
             :prod (job-name->environment "test-Red_Hat_Enterprise_Linux-6.2-Book_Name_1-en-US (prod)" "(preview)" "(stage)" "(prod)")
             :prod (job-name->environment "test-Red_Hat_Enterprise_Linux-7-Book_Name_1-en-US (prod)" "(preview)" "(stage)" "(prod)"))))

+(deftest test-job-name->environment-unknown
+    "Check the emender-jenkins.results/job-name->environment function."
+    (testing "the emender-jenkins.results/job-name->environment function."
+        (are [x y] (= x y)
+            nil (job-name->environment "test-Product-1-Book1-en-US (unknown)" "(preview)" "(stage)" "(prod)")
+            nil (job-name->environment "test-Product_Name-1-Book1-en-US (unknown)" "(preview)" "(stage)" "(prod)")
+            nil (job-name->environment "test-Red_Hat_Enterprise_Linux-6.2-Book_Name_1-en-US (unknown)" "(preview)" "(stage)" "(prod)")
+            nil (job-name->environment "test-Red_Hat_Enterprise_Linux-7-Book_Name_1-en-US (unknown)" "(preview)" "(stage)" "(prod)"))))
+


updated title of category pages

updated title of category pages

--- src/distillery/view/category.clj
+++ src/distillery/view/category.clj
@@ -64,7 +64,7 @@
   "Renders the main page for a category."
   [{:keys [job-name category] :as args}]
   [:base-path "../../"
-   :title job-name
+   :title (str job-name " - " "Kategorie")
    :secondary-menu [["Übersicht" (jshref "innerpage('overview')")]
                     ["Wortwolke" (jshref "innerpage('cloud')")]
                     ["Videos" (jshref "innerpage('videos')")]


Refactoring and using event timers for simulation and rendering cycles.

--- ClojureScript/hello.cljs
+++ ClojureScript/hello.cljs
@@ -6,40 +6,54 @@
         [goog.events :only [listen]]
         [goog.events.EventType :only [CLICK]]
         [goog.graphics :only [createGraphics Stroke SolidFill]]
+        [goog :only [Timer]]
         ))

-(def pos (atom 0))
+; State (AAAAHAHAHG, don't touch it!)
+(def pos (atom [0 100]))
 (def keys-pressed (atom (set)))
+
 (def my-code-url "https://github.com/pauldoo/scratch/blob/master/ClojureScript/hello.cljs")

 (defn print-to-log [v]
     (.log js/console v))

-(defn foobar [t canvas-element y event] (do
-    (print-to-log "hello")
+(defn input-event [event]
     (cond
-        (= t :up)
+        (= (.type event) goog.events.EventType/KEYUP)
             (swap! keys-pressed disj (.keyCode event))
-        (= t :down)
+        (= (.type event) goog.events.EventType/KEYDOWN)
             (swap! keys-pressed conj (.keyCode event))
         :else
-            nil)
-    (let [x (swap! pos inc)
+            nil))
+
+(defn tick []
+    (swap! pos (fn [[x y]] [(inc x) (* (count (deref keys-pressed)) 50)])))
+
+(defn rerender [canvas-element]
+    (let [[x y] (deref pos)
         graphics (goog.graphics/createGraphics 400 300)]
         (do
             (.drawCircle graphics x y 30 (Stroke. 2 "green") (SolidFill. "yellow"))
             (goog.dom/removeChildren canvas-element)
             (.render graphics canvas-element)
-            ))))
+            )))

 (defn ^:export main []
     (let [
         canvas (goog.dom/createDom "div" {} "")
-        button (goog.dom/createDom "button" {} "Click!")]
+        button (goog.dom/createDom "button" {} "Click!")
+        tick-timer (Timer. 100)
+        render-timer (Timer. 100)
+        ]
         (do
-            (goog.events/listen button goog.events.EventType/CLICK (partial foobar :click canvas 100))
-            (goog.events/listen document.body goog.events.EventType/KEYDOWN (partial foobar :down canvas 50) true)
-            (goog.events/listen document.body goog.events.EventType/KEYUP (partial foobar :up canvas 150) true)
+            (. tick-timer (start))
+            (. render-timer (start))
+            (goog.events/listen button goog.events.EventType/CLICK input-event)
+            (goog.events/listen document.body goog.events.EventType/KEYDOWN input-event true)
+            (goog.events/listen document.body goog.events.EventType/KEYUP input-event true)
+            (goog.events/listen tick-timer goog.Timer/TICK tick)
+            (goog.events/listen render-timer goog.Timer/TICK #(rerender canvas))
             (goog.dom/appendChild document.body (goog.dom/createDom "div" {}
                 (goog.dom/createDom "h1" {} "Work in progress..")
                 (goog.dom/createDom "div" {} "Try clicking the button, or pressing keys.")


1.3-ifying experimental.nimrod-row1

1.3-ifying experimental.nimrod-row1

--- src/experimental/nimrod_row1.clj
+++ src/experimental/nimrod_row1.clj
@@ -4,7 +4,7 @@
 ;; Lee Spector, lspector@hampshire.edu, 2012

 (ns experimental.nimrod_row1
-  (:use [clojush] [clojure.contrib.math]))
+  (:use [clojush] [clojure.math.numeric-tower]))

 ;;;;;;;;;;;;
 ;; Integer symbolic regression for row r=1 of the r vs p graph for nimrod


Introduce a defmulti to dispatch on the complex expression

--- src/clj/algorithms_clj/derivative.clj
+++ src/clj/algorithms_clj/derivative.clj
@@ -48,11 +48,22 @@

 (declare derivative)

+(defmulti derivate-expr
+  (fn [operand terms var] operand))
+
+(defmethod derivate-expr +
+  [_ terms var]
+  (make-sum (map #(derivative % var) terms)))
+
 (defn derivative-prod
   [terms var]
   (for [r (utils/rotations terms)]
     (make-product (conj (rest r) (derivative (first r) var)))
     ))
+
+(defmethod derivate-expr *
+  [_ terms var]
+  (make-sum (derivative-prod terms var)))

 (defn derivative
   "Compute the partial derivative of the provided expression"
@@ -61,7 +72,6 @@
     (number? expr) 0
     (symbol? expr) (if (= expr var) 1 0)
     (keyword? expr) (if (= expr var) 1 0)
-    (sum? expr) (make-sum (map  #(derivative % var) (rest expr)))
-    (prod? expr) (make-sum (derivative-prod (rest expr) var))
+    :else (derivate-expr (first expr) (rest expr) var)
     ))


wip hybrid-cache

wip hybrid-cache

--- src/cljc/commos/delta/compscribe.cljc
+++ src/cljc/commos/delta/compscribe.cljc
@@ -343,7 +343,7 @@
       #_(println "unsubscribing" (::identifier (meta unsubs-fn)))
       (unsubs-fn))))

-(def ^:private sum-xf
+(def ^:private sum-and-delta
   "Transducer that sums deltas and passes on [sum delta] for each
   delta."
   (fn [rf]
@@ -354,14 +354,24 @@
         ([result input]
          (rf result [(vswap! sum delta/add input) input]))))))

-(defn- hybrid-cache
-  "Caches on endpoints.  Sends the current sum to a new subscriber,
-  continues with deltas."
-  [service]
+(def ^:private sum-then-deltas
+  (fn [rf]
+    (let [done (volatile! false)]
+      (fn
+        ([] (rf))
+        ([result] (rf result))
+        ([result input]
+         (if @done
+           (rf result (second input))
+           (do (vreset! done true)
+               (rf result (first input)))))))))
+
+(defn- cached-service
+  [service source-xf target-xf]
   (let [subscribe-ch (chan)
         cancel-ch (chan)]
     (go-loop [subs {}
-              ch->identifier {}]
+              chs {}]
       (let [[msg port] (alts! [subscribe-ch
                                cancel-ch])]
         (case port
@@ -369,38 +379,46 @@
           (let [[this identifier target] msg
                 [m :as cache]
                 (or (get subs identifier)
-                    (let [ch-in (chan)
+                    (let [ch-in (chan 1 source-xf)
                           m (mult ch-in)]
-                      (subscribe (assoc service :cached-service this)
+                      (subscribe (caching service this)
                                  identifier
                                  ch-in)
-                      [m #{} ch-in]))]
-            (tap m target)
+                      [m #{} ch-in]))
+                target-step (chan 1 target-xf)]
+            (pipe target-step target)
+            (tap m target-step)
             (recur (assoc subs identifier (update cache 1 conj target))
-                   (assoc ch->identifier target identifier)))
+                   (assoc chs target [identifier target-step])))
           cancel-ch
           (let [[this target] msg]
-            (if-let [identifier (get ch->identifier target)]
-              (let [[m chs ch-in :as cache] (get subs identifier)
-                    chs (disj chs target)
-                    ch->identifier (dissoc ch->identifier target)]
-                (untap m target)
-                (close! target)
-                (if (empty? chs)
+            (if-let [[identifier target-step] (get chs target)]
+              (let [[m m-chs ch-in :as cache] (get subs identifier)
+                    m-chs (disj m-chs target)
+                    chs (dissoc chs target)]
+                (untap m target-step)
+                (close! target-step)
+                (if (empty? m-chs)
                   (do
                     (cancel service ch-in)
                     (recur (dissoc subs identifier)
-                           ch->identifier))
-                  (recur (assoc subs identifier (assoc cache 1 chs))
-                         ch->identifier)))
+                           chs))
+                  (recur (assoc subs identifier (assoc cache 1 m-chs))
+                         chs)))
               (recur subs
-                     ch->identifier))))))
+                     chs))))))
     (reify
       IStream
       (subscribe [this identifier target]
         (put! subscribe-ch [this identifier target]))
       (cancel [this target]
         (put! cancel-ch [this target])))))
+
+(defn- hybrid-cache
+  "Caches on endpoints.  Sends the current sum to a new subscriber,
+  continues with deltas."
+  [service]
+  (cached-service service sum-and-delta sum-then-deltas))

 (defn compscriber
   [service]


wrap-on-close helper

wrap-on-close helper

--- src/cljc/commos/delta/compscribe.cljc
+++ src/cljc/commos/delta/compscribe.cljc
@@ -295,6 +295,11 @@
     (pipe source watch-ch)
     (pipe watch-ch target)))

+(defn- wrap-on-close
+  [target on-close]
+  (doto (chan)
+    (wrap-on-close target on-close)))
+

 (defn compscribe


optimize halo resize

optimize halo resize

--- src/cljs/cljs_morphic/morph/halo.cljs
+++ src/cljs/cljs_morphic/morph/halo.cljs
@@ -1,13 +1,14 @@
 (ns cljs-morphic.morph.halo
   (:require [cljs-morphic.morph :refer [rectangle image ellipse find-morph
-                                        set-prop position-in-world]]
-            [cljs-morphic.helper :refer-macros [morph-fn] :refer [add-points]]))
+                                        set-prop position-in-world $morph redefine properties]]
+            [cljs-morphic.helper :refer-macros [morph-fn] :refer [add-points]]
+            [fresnel.lenses :refer [fetch]]))

 (declare resize-button inspect-button close-button)

 (defn halo [world-state id]
   "Render a halo element for morph with id"
-  (let [[_ {ext :extent pos :position} _] (find-morph world-state id)]
+  (let [[_ {ext :extent pos :position} _] (fetch world-state ($morph id))]
     (conj world-state
           (-> (rectangle {:id "halo" :border-color "red" :border-width 1
                           :layout (fn [self props submorphs]
@@ -21,6 +22,12 @@
             (close-button)
             (inspect-button)))))

+(defn align-buttons [world-state]
+  (redefine world-state ($morph "halo")
+            (fn [halo props buttons]
+              (-> (halo props buttons)
+                (set-prop "infoButton" :position (add-points {:x ((props :extent) :x) :y 0} {:x 5 :y -15}))))))
+
 (morph-fn resize-button [halo props submorphs target-id]
           (halo props
                 submorphs
@@ -29,14 +36,17 @@
                           :id "resizeButton"
                           :position (add-points (props :extent) {:x 0 :y 0})
                           :draggable? true
-                          :on-drag (fn [world id]
-                                     (let [global-pos (position-in-world world id)
-                                           target-pos (position-in-world world target-id)
-                                           new-extent (add-points global-pos {:x (- (- 5) (target-pos :x))
-                                                                              :y (- (- 5) (target-pos :y))})]
-                                       (-> world
-                                         (set-prop target-id :extent new-extent)
-                                         (set-prop "halo" :extent new-extent))))}
+                          :on-drag (fn [world id {dx :x dy :y}]
+                                     (-> world
+                                         (redefine ($morph target-id)
+                                                   (fn [target props submorphs]
+                                                     (target (assoc props :extent (add-points (:extent props) {:x (- dx) :y (- dy)})) submorphs)))
+                                        (redefine ($morph "halo")
+                                                  (fn [halo props buttons]
+                                                    (let [new-extent (add-points (:extent props) {:x (- dx) :y (- dy)})]
+                                                      (-> (halo (assoc props :extent new-extent) buttons)
+                                                        (set-prop "infoButton" :position (add-points {:x (:x new-extent) :y 0} {:x 5 :y -15}))))))
+                                       ))}
                          (image {:id "resizeImage"
                                  :position {:x -5 :y -5}
                                  :url "http://lively-web.org/core/media/halos/resize.svg"
@@ -45,15 +55,23 @@
 (morph-fn close-button [halo props submorphs]
           (halo props
                 submorphs
-                (-> (image {:position {:x -15 :y -15}
-                            :url "http://lively-web.org/core/media/halos/close.svg"
-                            :extent {:x 15 :y 15}
-                            :id "closeButton"}))))
+                (ellipse {:fill "rgba(255,255,255,0.4)"
+                          :extent {:x 25 :y 25}
+                          :id "closeButton"
+                          :position {:x -25 :y -25}}
+                         (image {:id "closeImage"
+                                 :position {:x -5 :y -5}
+                                 :url "http://lively-web.org/core/media/halos/close.svg"
+                                 :extent {:x 15 :y 15}}))))

 (morph-fn inspect-button [halo props submorphs]
           (halo props
                 submorphs
-                (-> (image {:position (add-points {:x ((props :extent) :x) :y 0} {:x 5 :y -15})
-                            :url "http://lively-web.org/core/media/halos/info.svg"
-                            :extent {:x 15 :y 15}
-                            :id "infoButton"}))))+                (ellipse {:fill "rgba(255,255,255,0.4)"
+                          :extent {:x 25 :y 25}
+                          :id "infoButton"
+                          :position (add-points {:x ((props :extent) :x) :y 0} {:x 5 :y -15})}
+                         (image {:id "infoImage"
+                                 :position {:x -5 :y -5}
+                                 :url "http://lively-web.org/core/media/halos/info.svg"
+                                 :extent {:x 15 :y 15}}))))


add stepping, remove cemerick.test ref

add stepping, remove cemerick.test ref

--- src/cljs/cljs_morphic/playground.cljs
+++ src/cljs/cljs_morphic/playground.cljs
@@ -2,11 +2,10 @@
   (:require-macros [cljs.core.async.macros :refer [go go-loop]])
   (:require [cljs-morphic.morph :refer [rectangle ellipse image
                                         rerender redefine move-morph morph-under-me
-                                        without get-description $morph
+                                        without get-description $morph it submorphs ast-type
                                         world-state set-prop add-morphs-to
                                         evolve redefinitions compile-props default-meta
-                                        read-morph description properties text]]
-            [fipp.edn :refer [pprint]]
+                                        morphic-read description properties text]]
             [fresnel.lenses :refer [fetch putback]]
             [cljs-morphic.morph.editor :refer [ace-editor set-editor-value]]
             [cljs-morphic.morph.window :refer [window]]
@@ -14,11 +13,11 @@
             [cljs-morphic.event :refer [signals]]
             [cljs-morphic.helper :refer [eucl-distance add-points morph?] :refer-macros [morph-fn]]
             [cljs-morphic.test :as t]
-            [cljs.core.async :as async :refer [<! chan close!]]
+		      	[cljs.pprint :refer [pprint]]
+            [cljs.core.async :as async :refer [>! <! chan close!]]
             [cljs.reader :refer [read-string]]
             [cljs.core.match :refer-macros [match]]
-            [rksm.cloxp-com.net :as net]
-            [cemerick.cljs.test :refer-macros [deftest testing is run-tests]]))
+            [cljs.test :refer-macros [deftest testing is run-tests]]))

 ; EVENT HANDLING

@@ -44,6 +43,16 @@
            :args {:pos pos}}] [(-> world-state
                                  (set-prop "handMorph" :position pos))
                                hand]
+         [{:type :mouse-enter
+           :target-props props
+           :args {:callback mouse-enter-cb}}] [(if mouse-enter-cb
+                                                 (mouse-enter-cb world-state ($morph (:id props)))
+                                                 world-state) hand]
+         [{:type :mouse-leave
+           :target-props props
+           :args {:callback mouse-leave-cb}}] [(if mouse-leave-cb
+                                                 (mouse-leave-cb world-state ($morph (:id props)))
+                                                 world-state) hand]
          :else :zero))

 ; GRABBING
@@ -125,7 +134,7 @@
          [:mouse-move focus-id]
            (if (< 10 (eucl-distance pos new-pos))
              [world-state (partial dragging-in-progress pos focus-id
-                                   (fetch world-state [($morph focus-id) properties :on-drag]))]
+                                   (-> (fetch world-state ($morph focus-id)) meta :compiled-props :on-drag))]
              [world-state (partial attempt-drag-from pos focus-id)])
          [:mouse-up-left _]
              [world-state (either grabbing dragging)]
@@ -188,9 +197,7 @@
               (add-morphs-to "world" editor)
               (focus-editor-on editor-id focused-morph-id)))
           (partial inspection-protected focused-morph-id)]
-         [:io _ _] [(do
-                      (pprint (args :value))
-                      world-state)
+         [:io _ _] [world-state
                     (partial inspection-protected focused-morph-id)]
          ; redefine the morph the editor is editing by compiling the new description and hot swapping it
          [:mouse-down-left _ "closeButton"] [(-> world-state
@@ -206,11 +213,11 @@
                                {id :id inspectable? :inspectable? target :target} :target-props
                                args :args}]
   (match [evt-type inspectable?]
-         [:mouse-down-right true] [(-> world-state
-                                     (halo id)) (partial inspection-active id)]
+         [:mouse-down-right true] [(morphic-read (-> world-state
+                                                   (halo id))) (partial inspection-active id)]
          [:io _] [(do
                     (redefine world-state ($morph target) (fn [_ _ _]
-                                               (read-string (args :value)))))
+                                                            (morphic-read (read-string (args :value))))))
                   (partial inspecting)]
          :else :zero))

@@ -247,21 +254,59 @@
                                      world))) world-state observers) observing]
          :else :zero))

+(defmulti step (fn [lens world-state]
+                 (prn lens "and" world-state)
+                 (ast-type (fetch world-state lens))))
+
+(defmethod step :vector [morphs-ref world-state]
+  (reduce (fn [world-state idx]
+            (step (conj morphs-ref idx) world-state))
+          world-state
+          (range (count (fetch world-state morphs-ref)))))
+
+(defmethod step :expr [expr-ref world-state]
+  (step (conj expr-ref submorphs) world-state))
+
+(defmethod step :morph [morph-ref world-state]
+  (let [morph (fetch world-state morph-ref)
+        world-state (if-let [step-fn (-> morph meta :compiled-props :step)]
+                      (if (fn? step-fn)
+                        (do
+                          (prn step-fn)
+                          (step-fn world-state morph-ref))
+                        (do
+                          (prn "Errornous step function: " step-fn)
+                          world-state))
+                      world-state)
+        [_ _ & submorphs] morph]
+    (if submorphs
+      (step (conj morph-ref cljs-morphic.morph/submorphs) world-state)
+      world-state)))
+
+; (js/setInterval
+;   #(go (>! signals {:type :step}))
+;   1000)
+
+(defn stepping [world-state {evt-type :type}]
+  (match [evt-type]
+         [:step] [(step [it] world-state) stepping]
+         :else :zero))
+
 (def lively
   "A lively set of transitions. Enables, morphs to be grabbable, draggable, observable
    and inspectable. This provides live and direct interaction with morphic objects."
   [(either grabbing dragging)
+   stepping
    inspecting
    observing
    hand])

 (def default-world-state
   [(rectangle {:id "world"
-                  :extent {:x 1000 :y 1000}
-                  :position {:x 500 :y 0}
+                  :extent {:x 1500 :y 1000}
+                  :position {:x 0 :y 0}
                   :fill "darkgrey"})
-   (rectangle {:id "handMorph" :fill "red" :extent {:x 2 :y 2}})
-   (ace-editor "Welcome to cljs-morphic!" {:x 0 :y 0} {:x 500 :y 1000} "world-editor")])
+   (rectangle {:id "handMorph" :fill "red" :extent {:x 2 :y 2}})])

 (defn tree [stem-pos]
   (rectangle
@@ -334,6 +379,7 @@
 (defn create-minute-pointer [radius]
   (rectangle {:id "MinutePointer"
               :position {:x 0 :y -2}
+              :fill "darkblue"
               :stroke-width 2
               :extent {:x (* .7 radius) :y 4}}))

@@ -368,7 +414,7 @@
               :grabbable? true
               :inspectable? true
               :fps 1
-              :step '(fn [world id]
+              :step '(fn [world self-ref]
                        (let [{:keys [hours minutes seconds]} (get-current-time)
                              minutes (+ minutes (/ seconds 60))
                              hours (+ hours (/ minutes 60))]
@@ -403,6 +449,7 @@
               :id "eli"}))))
    (image {:url "http://www.daniellaondesign.com/uploads/7/3/9/7/7397659/464698_orig.jpg"
            :extent {:x 300 :y 500}
+           :position {:x 50 :y 50}
            :grabbable? true
            :inspectable? true
            :id "kyoto"})


minor tidy

minor tidy

--- src/grafter/rdf4j/repository.clj
+++ src/grafter/rdf4j/repository.clj
@@ -443,13 +443,13 @@

   RepositoryConnection
   (prepare-query* [repo sparql-string restriction]
-    (let [conn (->connection repo)]
-      (let [pq (.prepareQuery conn
-                              QueryLanguage/SPARQL
-                              sparql-string)]
-
-        (when restriction (.setDataset pq restriction))
-        pq))))
+    (let [conn (->connection repo)
+          pq (.prepareQuery conn
+                            QueryLanguage/SPARQL
+                            sparql-string)]
+
+      (when restriction (.setDataset pq restriction))
+      pq)))

 (defn prepare-query
   "Low level function to prepare (parse, but not process) a sesame RDF
@@ -497,7 +497,6 @@
       (.execute prepared-query)))

   pr/ITripleDeleteable
-
   (pr/delete-statement
     ([this statement]
        {:pre [(instance? IStatement statement)]}


Fill out page layout.

Fill out page layout.

--- src/incise/layouts/impl/page.clj
+++ src/incise/layouts/impl/page.clj
@@ -2,20 +2,60 @@
   (:require [incise.layouts.core :refer [register]]
             [incise.parsers.core]
             [dieter.core :refer [link-to-asset]]
-            (hiccup [page :refer :all]
+            (hiccup [def :refer :all]
+                    [page :refer :all]
+                    [element :refer :all]
                     [core :refer :all])))
+
+(defhtml header
+  [{:keys [site-title] :as site-options} parse]
+  [:header
+   [:h1#site-title (link-to "/" site-title)]])
+
+(defmulti contact (fn [x & _] x))
+(defmethod contact :default
+  [end-point handle]
+  (link-to (str "https://" (name end-point) ".com/" handle)
+           (str \@ handle)))
+(defmethod contact :email
+  [_ email]
+  (mail-to email))
+
+(defhtml contact-spec [[end-point handle]]
+  [:div.contact
+   [:span.end-point end-point]
+   (contact end-point handle)])
+
+(defhtml footer
+  [{:keys [contacts author] :as site-options} parse]
+  [:hr]
+  [:footer
+   [:div.row
+    [:div#cc.col-md-8
+     (link-to {:rel "license"} "http://creativecommons.org/licenses/by-sa/3.0/deed.en_US"
+              (image "http://i.creativecommons.org/l/by-sa/3.0/88x31.png" "Creative Commons License"))
+     [:p "Content on this website is licensed under a "
+      (link-to {:rel "license"} "http://creativecommons.org/licenses/by-sa/3.0/deed.en_US"
+               "Creative Commons Attribution-ShareAlike 3.0 Unported License")
+      " by " author "."]]
+    [:div#contacts.col-md-4 (map contact-spec contacts)]]
+    [:p "This website is " (link-to "https://github.com/RyanMcG/incise" "incise") "d."]])

 (defn page
   "The default page/post layout."
-  [{:keys [site-title]}
-   ^incise.parsers.core.Parse {:keys [title content]}]
+  [{:keys [site-title] :as site-options}
+   ^incise.parsers.core.Parse {:keys [title content] :as parse}]
   (html5
     [:head
      [:title (str site-title (when title (str " - " title)))]
      [:meta {:name "viewport"
              :content "width=device-width, initial-scale=1.0"}]
      (include-css (link-to-asset "stylesheets/app.css.dieter"))]
-    [:body#page content
+    [:body#page
+     [:div.container
+      (header site-options parse)
+      [:div#content content]
+      (footer site-options parse)]
      (include-js "http://code.jquery.com/jquery-2.0.3.min.js"
                  (link-to-asset "javascripts/app.js.dieter"))]))


Show basic blocks on startup

Show basic blocks on startup

Show basic blocks on startup

--- idecode/myappshare/mainapp.cljs
+++ idecode/myappshare/mainapp.cljs
@@ -402,6 +402,9 @@
   {:on-mount
    (do  (go
           (js/initBlockly)
+          (show-blocks  "Basic"  basic-blocks)
+
+
           ))

    }
@@ -456,7 +459,8 @@
             )

-    (div {:style {
+    (div {
+           :style {
                    :display (if (or (= (get-in @app-state [:ui :editor :mode]) "blockly")
                                     (= (get-in @app-state [:ui :editor :mode]) nil))
                               "inline-block"


require list

require list

--- test/celestial/integration/jobs.clj
+++ test/celestial/integration/jobs.clj
@@ -1,6 +1,6 @@
 (ns celestial.integration.jobs
   (:require
-    [celestial.fixtures.core :refer [with-conf]]
+    [celestial.fixtures.core :refer (with-conf)]
     [celestial.jobs :as jobs :refer (initialize-workers workers)])
   (:use midje.sweet))


remove debugging

remove debugging

--- test/github_authors/github_test.clj
+++ test/github_authors/github_test.clj
@@ -22,8 +22,7 @@
 (defn verify-args-called-for [f & expected-args]
   (doseq [[expected actual] (map vector expected-args (->> f bond/calls (map :args)))]
     (if (instance? java.util.regex.Pattern (last expected))
-      (is (and (= (butlast expected) (butlast actual)) (re-find (last expected) (last actual)))
-          (str "Expected: " (last expected)))
+      (is (and (= (butlast expected) (butlast actual)) (re-find (last expected) (last actual))))
       (is (= expected actual)))))

 (deftest stream-repositories-receives-403-from-github


Added conj to PersistentHashMap

Added conj to PersistentHashMap

--- src/main/cljs/lean_map/core.cljs
+++ src/main/cljs/lean_map/core.cljs
@@ -197,6 +197,20 @@
   IMeta
   (-meta [coll] meta)

+  ICollection
+  (-conj [coll entry]
+    (if (vector? entry)
+      (-assoc coll (-nth entry 0) (-nth entry 1))
+      (loop [ret coll es (seq entry)]
+        (if (nil? es)
+          ret
+          (let [e (first es)]
+            (if (vector? e)
+              (recur (-assoc ret (-nth e 0) (-nth e 1))
+                     (next es))
+              (throw (js/Error. "conj on a map takes map entries or seqables of map entries"))))))))
+
+
   IEmptyableCollection
   (-empty [coll] (-with-meta (.-EMPTY PersistentHashMap) meta))


removing useless statements from test. no idea how in-parallel got into the steps for testing itself but now they are gone...

--- test/lambdacd/control_flow_test.clj
+++ test/lambdacd/control_flow_test.clj
@@ -39,7 +39,7 @@
   (testing "that one failing step fails the pipeline"
     (is (= {:outputs { [1 0 0] {:status :success} [2 0 0] {:status :failure}} :status :failure} ((in-parallel some-successful-step some-failing-step) {} [0 0]))))
   (testing "that it executes things faster than it would serially"
-    (is (close? 3 10 (my-time ((in-parallel some-step-taking-10ms in-parallel some-step-taking-10ms in-parallel some-step-taking-10ms) {} [0 0]))))))
+    (is (close? 3 10 (my-time ((in-parallel some-step-taking-10ms some-step-taking-10ms some-step-taking-10ms) {} [0 0]))))))

 (deftest in-cwd-test
   (testing "that it collects all the outputs together correctly and passes cwd to steps"


Moved System/exit call outside of usageError.

--- src/app/core.clj
+++ src/app/core.clj
@@ -15,8 +15,7 @@
   (when (:errors opts)
     (doseq [e (:errors opts)]
       (println " * " e)))
-  (println banner)
-  (System/exit 1))
+  (println banner))

 (defn info [msg]
   (println " [info] " msg))
@@ -37,9 +36,11 @@

 (defn treat-possible-errors [opts banner]
   (when (:errors opts)
-    (usageError banner opts ""))
+    (usageError banner opts "")
+    (System/exit 1))
   (when (conflicting-options? opts)
-    (usageError banner opts self-exclusive-modes-error)))
+    (usageError banner opts self-exclusive-modes-error)
+    (System/exit 1)))

 (defn run-linter-mode [opts]
   (when-not (:dir opts)
@@ -66,7 +67,8 @@
       (name2operation (:query opts))
       (nil? (:errors opts)))
     (run opts)
-    (usageError banner opts "")))
+    (do (usageError banner opts "")
+        (System/exit 1))))

 (defn -main
   [& args]


Perf: update-in is slower and update is not part of clojure 1.6

Partial + comp is also slower than a form

--- src/onyx/peer/task_lifecycle.clj
+++ src/onyx/peer/task_lifecycle.clj
@@ -216,13 +216,12 @@
     (let [peers (get (:ackers @replica) job-id)
           _ (validate-ackable! peers event)
           candidates (operation/select-n-peers id peers max-acker-links)]
-      (update-in
-        event
-        [:onyx.core/batch]
-        (fn [batch]
-          (map (comp (partial add-completion-id id)
-                     (partial add-acker-id candidates))
-               batch))))
+      (assoc event
+             :onyx.core/batch
+             (map (fn [segment]
+                    (add-acker-id candidates
+                                  (add-completion-id id segment)))
+                  (:onyx.core/batch event))))
     event))

 (defn add-messages-to-timeout-pool [task-type state event]


Use clojure native hash rather than hand roll

--- src/onyx/peer/task_lifecycle.clj
+++ src/onyx/peer/task_lifecycle.clj
@@ -93,16 +93,12 @@
     (choose-output-paths event compiled-ex-fcs result leaf serialized-task downstream)
     (choose-output-paths event compiled-norm-fcs result leaf serialized-task downstream)))

-(defn hash-value [x]
-  (let [md5 (MessageDigest/getInstance "MD5")]
-    (apply str (.digest md5 (.getBytes (pr-str x) "UTF-8")))))
-
 (defn group-message [segment catalog task]
   (let [t (find-task-fast catalog task)]
     (if-let [k (:onyx/group-by-key t)]
-      (hash-value (get segment k))
+      (hash (get segment k))
       (when-let [f (:onyx/group-by-fn t)]
-        (hash-value ((operation/resolve-fn {:onyx/fn f}) segment))))))
+        (hash ((operation/resolve-fn {:onyx/fn f}) segment))))))

 (defn group-segments [leaf next-tasks catalog event]
   (let [post-transformation (:post-transformation (:routes leaf))


Make setup-checkpoint-watch! log using onyx.core/log-prefix.

--- src/onyx/peer/task_lifecycle.clj
+++ src/onyx/peer/task_lifecycle.clj
@@ -775,7 +775,7 @@
         (db/export-reader state-store)]))

 (defn setup-checkpoint-watch!
-  [{:keys [onyx.core/log onyx.core/tenancy-id onyx.core/job-id
+  [{:keys [onyx.core/log onyx.core/tenancy-id onyx.core/job-id onyx.core/log-prefix
            onyx.core/group-ch onyx.core/job-id onyx.core/id onyx.core/task-kill-flag
            onyx.core/kill-flag] :as event}
    track-checkpointed]
@@ -794,8 +794,8 @@
                                      (when (and (not @task-kill-flag)
                                                 (not @kill-flag))
                                        (setup-checkpoint-watch! event track-checkpointed))))
-   (catch Throwable t
-     (warn "Error setting checkpoint watch. Restarting peer." t)
+   (catch Exception e
+     (warn log-prefix "Error setting checkpoint watch. Restarting peer." e)
      (>!! group-ch [:restart-vpeer id]))))

 (deftype TaskStateMachine


Fixes broken ns.

Fixes broken ns.

--- src/onyx/peer/task_lifecycle.clj
+++ src/onyx/peer/task_lifecycle.clj
@@ -184,7 +184,7 @@
             (>!! (:onyx.core/complete-ch event) true))))
       (recur))))

-(defrecord TaskLifeCycle [id log queue job task opts]
+(defrecord TaskLifeCycle [id log queue job task err-ch opts]
   component/Lifecycle

   (start [component]
@@ -221,18 +221,17 @@
           complete-task-dead-ch (chan)

           catalog (extensions/read-chunk log :catalog job)
-          ingress-queues (:task/ingress-queues (:task payload))
+          task (extensions/read-chunk log :task task)
+          ingress-queues (:task/ingress-queues task)

           pipeline-data {:onyx.core/id id
                          :onyx.core/task task
                          :onyx.core/catalog catalog
-                         :onyx.core/workflow (extensions/read-chunk log :workflow (:job-id payload))
+                         :onyx.core/workflow (extensions/read-chunk log :workflow job)
                          :onyx.core/task-map (find-task catalog task)
-                         :onyx.core/serialized-task (:task payload)
+                         :onyx.core/serialized-task task
                          :onyx.core/ingress-queues ingress-queues
-                         :onyx.core/egress-queues (:task/egress-queues (:task payload))
-                         :onyx.core/payload-ch payload-ch
-                         :onyx.core/complete-ch complete-ch
+                         :onyx.core/egress-queues (:task/egress-queues task)
                          :onyx.core/params (or (get (:onyx.peer/fn-params opts) task) [])
                          :onyx.core/drained-back-off (or (:onyx.peer/drained-back-off opts) 400)
                          :onyx.core/queue queue
@@ -435,7 +434,7 @@
         :pipeline-data pipeline-data)))

   (stop [component]
-    (taoensso.timbre/info (format "[%s] Stopping Task LifeCycle for %s" id (:task/name (:task payload))))
+    (taoensso.timbre/info (format "[%s] Stopping Task LifeCycle for %s" id (:task/name task)))

     (close! (:open-session-kill-ch component))
     (<!! (:open-session-dead-ch component))
@@ -498,9 +497,9 @@

     component))

-(defn task-lifecycle [id log queue job task opts]
+(defn task-lifecycle [id log queue job task err-ch opts]
   (map->TaskLifeCycle {:id id :log log :queue queue :job job
-                       :task task :opts opts}))
+                       :task task :err-ch err-ch :opts opts}))

 (dire/with-post-hook! #'munge-start-lifecycle
   (fn [{:keys [onyx.core/id onyx.core/lifecycle-id onyx.core/start-lifecycle?] :as event}]


Close! restart-ch as performed elsewhere

--- src/onyx/peer/task_lifecycle.clj
+++ src/onyx/peer/task_lifecycle.clj
@@ -371,7 +371,7 @@
       (warn (:original-exception data) "Caught exception inside task lifecycle. Rebooting the task.")
       (do (warn e "Handling uncaught exception thrown inside task lifecycle.")
           (if (restart-pred-fn e)
-            (>!! restart-ch true)
+            (close! restart-ch)
             (let [entry (entry/create-log-entry :kill-job {:job job-id})]
               (extensions/write-chunk log :exception e job-id)
               (>!! outbox-ch entry)))))))


Added a generator pipeline test.

Added a generator pipeline test.

--- test/lambda_blog/generator_test.clj
+++ test/lambda_blog/generator_test.clj
@@ -1,7 +1,10 @@
 (ns lambda-blog.generator-test
   (:refer-clojure :exclude [update])
   (:require [clojure.test :refer :all]
-            [lambda-blog.generator :refer [update update-all whenever]]))
+            [lambda-blog.fixtures :refer [generate-blog]]
+            [lambda-blog.generator :refer [update update-all whenever]]
+            [lambda-blog.utils :refer [pathcat]]
+            [me.raynes.fs :refer [directory? file?]]))

 (deftest can-update-keys
   (let [ent {:key :value}]
@@ -47,3 +50,40 @@
            {:tags #{{:id :foo}
                     {:id :bar :hello :world}
                     {:id :baz}}}))))
+
+(deftest can-generate-a-blog
+  ;; NOTE There's no worth in testing HTML templates, so this is as much
+  ;; NOTE of the generator that can be easily tested.
+  (let [{:keys [output-dir] :as b} (generate-blog)]
+    ;; Misc stuff has been prepared correctly.
+    (is (contains? b :tags))
+    ;; Layout is correct.
+    (is (directory? (pathcat output-dir)))
+    (is (directory? (pathcat output-dir "media")))
+    (is (directory? (pathcat output-dir "style")))
+    (is (directory? (pathcat output-dir "js")))
+    (is (directory? (pathcat output-dir "tags")))
+    (is (directory? (pathcat output-dir "posts")))
+    ;; Various pages were generated.
+    (is (->> b :index :path (pathcat output-dir) file?))
+    (is (->> b :rss :path (pathcat output-dir) file?))
+    (is (->> b :archives :path (pathcat output-dir) file?))
+    (is (->> b :tag-cloud :path (pathcat output-dir) file?))
+    (is (->> b
+             :static-pages
+             (map :path)
+             (map #(pathcat output-dir %))
+             (map file?)
+             (every? true?)))
+    (is (->> b
+             :entries
+             (map :path)
+             (map #(pathcat output-dir %))
+             (map file?)
+             (every? true?)))
+    (is (->> b
+             :tags
+             (map :path)
+             (map #(pathcat output-dir %))
+             (map file?)
+             (every? true?)))))


Docstrings for each endpoint.

Docstrings for each endpoint.

--- src/lib_onyx/replica_query_server.clj
+++ src/lib_onyx/replica_query_server.clj
@@ -12,71 +12,84 @@
   (UUID/fromString x))

 (def endpoints
-  {{:uri "/replica/peers"
+  {^{:doc "Lists all the peer idss."}
+   {:uri "/replica/peers"
     :request-method :get}
    (fn [request log-subscriber replica]
      (rq/peers replica))

+   ^{:doc "Lists all non-killed, non-completed job ids."}
    {:uri "/replica/jobs"
     :request-method :get}
    (fn [request log-subscriber replica]
      (rq/jobs replica))

+   ^{:doc "Lists all the job ids that have been killed."}
    {:uri "/replica/killed-jobs"
     :request-method :get}
    (fn [request log-subscriber replica]
      (rq/killed-jobs replica))

+   ^{:doc "Lists all the job ids that have been completed."}
    {:uri "/replica/completed-jobs"
     :request-method :get}
    (fn [request log-subscriber replica]
      (rq/completed-jobs replica))

+   ^{:doc "Given a job ids, returns all the task ids for this job."}
    {:uri "/replica/tasks"
     :request-method :get}
    (fn [request log-subscriber replica]
      (let [job-id (get-in request [:query-params "job-id"])]
        (rq/tasks replica (parse-uuid job-id))))

+   ^{:doc "Returns a map of job id -> task id -> peer ids, denoting which peers are assigned to which tasks."}
    {:uri "/replica/job-allocation"
     :request-method :get}
    (fn [request log-subscriber replica]
      (rq/job-allocations replica))

+   ^{:doc "Given a job id, returns a map of task id -> peer ids, denoting which peers are assigned to which tasks for this job only."}
    {:uri "/replica/task-allocation"
     :request-method :get}
    (fn [request log-subscriber replica]
      (rq/task-allocations replica))

+   ^{:doc "Given a peer id, returns the Aeron hostname and port that this peer advertises to the rest of the cluster."}
    {:uri "/replica/peer-site"
     :request-method :get}
    (fn [request log-subscriber replica]
      (let [peer-id (get-in request [:query-params "peer-id"])]
        (rq/peer-site replica (parse-uuid peer-id))))

+   ^{:doc "Given a peer id, returns its current execution state (e.g. :idle, :active, etc)."}
    {:uri "/replica/peer-state"
     :request-method :get}
    (fn [request log-subscriber replica]
      (let [peer-id (get-in request [:query-params "peer-id"])]
        (rq/peer-state replica (parse-uuid peer-id))))

+   ^{:doc "Given a peer id, returns the job id and task id that this peer is currently assigned to, if any."}
    {:uri "/replica/peer-allocation"
     :request-method :get}
    (fn [request log-subscriber replica]
      (let [peer-id (get-in request [:query-params "peer-id"])]
        (rq/peer-allocation replica (parse-uuid peer-id))))

+   ^{:doc "Returns the job scheduler for this tenancy of the cluster."}
    {:uri "/replica/job-scheduler"
     :request-method :get}
    (fn [request log-subscriber replica]
      (rq/job-scheduler replica))

+   ^{:doc "Given a job id, returns the task scheduler for this job."}
    {:uri "/replica/task-scheduler"
     :request-method :get}
    (fn [request log-subscriber replica]
      (let [job-id (get-in request [:query-params "job-id"])]
        (rq/task-scheduler replica (parse-uuid job-id))))

+   ^{:doc "Given a job id, returns workflow for this job."}
    {:uri "/job/workflow"
     :request-method :get}
    (fn [request log-subscriber replica]
@@ -84,6 +97,7 @@
                        (parse-uuid))]
        (jq/workflow log-subscriber job-id)))

+   ^{:doc "Given a job id, returns catalog for this job."}
    {:uri "/job/catalog"
     :request-method :get}
    (fn [request log-subscriber replica]
@@ -91,6 +105,7 @@
                        (parse-uuid))]
        (jq/catalog log-subscriber job-id)))

+   ^{:doc "Given a job id, returns flow conditions for this job."}
    {:uri "/job/flow-conditions"
     :request-method :get}
    (fn [request log-subscriber replica]
@@ -98,6 +113,7 @@
                        (parse-uuid))]
        (jq/flow-conditions log-subscriber job-id)))

+   ^{:doc "Given a job id, returns lifecycles for this job."}
    {:uri "/job/lifecycles"
     :request-method :get}
    (fn [request log-subscriber replica]
@@ -105,6 +121,7 @@
                        (parse-uuid))]
        (jq/lifecycles log-subscriber job-id)))

+   ^{:doc "Given a job id, returns windows for this job."}
    {:uri "/job/windows"
     :request-method :get}
    (fn [request log-subscriber replica]
@@ -112,6 +129,7 @@
                        (parse-uuid))]
        (jq/windows log-subscriber job-id)))

+   ^{:doc "Given a job id, returns triggers for this job."}
    {:uri "/job/triggers"
     :request-method :get}
    (fn [request log-subscriber replica]
@@ -119,6 +137,7 @@
                        (parse-uuid))]
        (jq/triggers log-subscriber job-id)))

+   ^{:doc "Given a job id and task id, returns catalog entry for this task."}
    {:uri "/job/task"
     :request-method :get}
    (fn [request log-subscriber replica]


Clean up fixture constructor documentation

--- src/main/clojure/lazytest/fixture.clj
+++ src/main/clojure/lazytest/fixture.clj
@@ -9,25 +9,28 @@
 (defn fixture? [x]
   (extends? Fixture (type x)))

-(deftype ConstantFixture [value]
-  Fixture
-  (setup [this] value)
-  (teardown [this] nil))
-
-(defn constant-fixture
-  "Returns a fixture whose setup method always returns value and
-  whose teardown method does nothing."
-  [value]
-  (ConstantFixture. value))
-
 (deftype FunctionFixture [f]
   Fixture
   (setup [this] (f))
   (teardown [this] nil))

 (defn function-fixture
-  "Returns a fixture whose setup method calls and returns the value of
-  f and whose teardown method does nothing."
+  "Returns a fixture whose setup method returns the result of calling
+  f. The fixture's teardown method does nothing."
   [f]
   {:pre [(fn? f)]}
   (FunctionFixture. f))
+
+(deftype MemoizedFixture [f cache]
+  Fixture
+  (setup [this]
+	 (swap! cache (fn [value]
+			(if (= ::unset value) (f) value))))
+  (teardown [this] nil))
+
+(defn memoized-fixture
+  "Returns a fixture whose setup method calls, returns, and caches the
+  value of f. The fixture's teardown method does nothing."
+  [f]
+  {:pre [(fn? f)]}
+  (MemoizedFixture. f (atom ::unset)))


Added helper function to allow easy starting of a NGServer

This allows to fire up easily a nailgun server if the system is owned
by a different application. Use cases are external Repls, servers
(during development), etc.

Refers #23

--- src/main/clojure/vimclojure/nails.clj
+++ src/main/clojure/vimclojure/nails.clj
@@ -27,7 +27,18 @@
                  [backend :as backend]))
   (:import
      java.io.BufferedReader
-     com.martiansoftware.nailgun.NGContext))
+     com.martiansoftware.nailgun.NGContext
+     com.martiansoftware.nailgun.NGServer))
+
+(defn start-server-thread
+  "Start a nailgun server in a dedicated daemon thread. host defaults
+  to 127.0.0.1, port to 2113."
+  ([]     (start-server-thread "127.0.0.1" 2113))
+  ([host] (start-server-thread host 2113))
+  ([host port]
+   (doto (Thread. #(NGServer/main (into-array [(str host ":" port)])))
+     (.setDaemon true)
+     (.start))))

 (defmacro defnail
   "Define a new Nail of the given name. The arguments is a command line


Fixes #175

Fixes #175

--- planck-cljs/src/planck/shell.cljs
+++ planck-cljs/src/planck/shell.cljs
@@ -11,7 +11,7 @@
     [cmd (merge default-opts (apply hash-map opts))]))

 (defn sh
-  "Passes the given strings to Runtime.exec() to launch a sub-process.
+  "Launches a sub-process with the supplied arguments.
   Options are
   :in      may be given followed by a string of one of the following formats:
            String conforming to URL Syntax: 'file:///tmp/test.txt'


remove :compile key from compiled interceptors

--- modules/reitit-core/src/reitit/interceptor.cljc
+++ modules/reitit-core/src/reitit/interceptor.cljc
@@ -92,7 +92,7 @@
         (if-let [interceptor (into-interceptor (compile data opts) data opts)]
           (map->Interceptor
             (merge
-              (dissoc this :create)
+              (dissoc this :compile)
               (impl/strip-nils interceptor)))))))

   nil


Pretty-print Clojure forms in `show` task.

--- boot/core/src/boot/task/built_in.clj
+++ boot/core/src/boot/task/built_in.clj
@@ -3,6 +3,7 @@
    [clojure.java.io      :as io]
    [clojure.set          :as set]
    [clojure.string       :as string]
+   [clojure.pprint       :as pp]
    [boot.pod             :as pod]
    [boot.git             :as git]
    [boot.file            :as file]
@@ -159,12 +160,13 @@
    U update-snapshots bool "Include snapshot versions in updates searches."
    u updates          bool "Print newer releases of outdated dependencies."]

-  (let [updates (or updates update-snapshots)]
+  (let [updates (or updates update-snapshots)
+        pretty-str #(with-out-str (pp/pprint %))]
     (core/with-pre-wrap fileset'
       (cond
         deps           (print (pod/with-call-worker (boot.aether/dep-tree ~(core/get-env))))
-        env            (println (pr-str (core/get-env)))
-        fileset        (println (pr-str fileset'))
+        env            (println (pretty-str (core/get-env)))
+        fileset        (println (pretty-str fileset'))
         classpath      (println (or (System/getProperty "boot.class.path") ""))
         fake-classpath (println (or (System/getProperty "fake.class.path") ""))
         updates        (mapv prn (pod/outdated (core/get-env) :snapshots update-snapshots))


Is this a nicer termination clause than empty?


add support for Español

add support for Español


Provide default for `print-meta`'s `content-exts` Calling `print-meta` without passing `content-exts` previously caused a NullPointerException.

--- src/io/perun.clj
+++ src/io/perun.clj
@@ -66,7 +66,8 @@
 (def ^:private +print-meta-defaults+
   {:map-fn identity
    :filterer identity
-   :extensions []})
+   :extensions []
+   :content-exts #{}})

 (deftask print-meta
   "Utility task to print perun metadata"
@@ -75,7 +76,7 @@
    e extensions   EXTENSIONS  [str]  "extensions of files to include (default: `[]`, aka, all extensions)"
    b content-exts CONTENTEXTS #{str} "print content for these extensions, default `#{}`"]
   (boot/with-pass-thru fileset
-    (let [options (merge +print-meta-defaults+ *opts*)
+    (let [{:keys [content-exts] :as options} (merge +print-meta-defaults+ *opts*)
           entries (doall (map (:map-fn options) (filter-meta-by-ext fileset options)))]
       (pod/with-call-in @print-meta-pod
         (io.perun.print-meta/print-meta ~entries ~content-exts)))))


Don't run shortcut if the widget isn't managed

--- src/net/sekao/nightcode/shortcuts.clj
+++ src/net/sekao/nightcode/shortcuts.clj
@@ -121,8 +121,8 @@
 (defn run-shortcut! [^Scene scene actions ^String text shift?]
   (when-let [id (get reverse-mappings (if shift? (.toUpperCase text) text))]
     (when-let [action (get actions id)]
-      (let [fx-id (keyword->fx-id id)]
-        (when (some-> scene (.lookup fx-id) .isDisabled not)
+      (when-let [widget (some-> scene (.lookup (keyword->fx-id id)))]
+        (when (and (not (.isDisabled widget)) (.isManaged widget))
           (Platform/runLater
             (fn []
               (action scene))))))))


Name the lifecycles for reference elsewhere.

--- src/onyx/kafka/information_model.cljc
+++ src/onyx/kafka/information_model.cljc
@@ -98,11 +98,13 @@
    :lifecycle-entry
    {:onyx.plugin.kafka/read-messages
     {:model
-     [{:lifecycle/calls :onyx.plugin.kafka/read-messages-calls}]}
+     [{:task.lifecycle/name :read-messages
+       :lifecycle/calls :onyx.plugin.kafka/read-messages-calls}]}

     :onyx.plugin.kafka/write-messages
     {:model
-     [{:lifecycle/calls :onyx.plugin.kafka/write-messages-calls}]}}
+     [{:task.lifecycle/name :write-messages
+       :lifecycle/calls :onyx.plugin.kafka/write-messages-calls}]}}

    :display-order
    {:onyx.plugin.kafka/read-messages


Perf: improve netty segment reading / writing.

--- src/onyx/messaging/protocol_netty.clj
+++ src/onyx/messaging/protocol_netty.clj
@@ -1,5 +1,6 @@
 (ns ^:no-doc onyx.messaging.protocol-netty
-    (:require [taoensso.timbre :as timbre])
+    (:require [taoensso.timbre :as timbre]
+              [onyx.types :refer [->Leaf]])
     (:import [java.util UUID]
              [io.netty.buffer ByteBuf Unpooled UnpooledByteBufAllocator
               PooledByteBufAllocator ByteBufAllocator]))
@@ -38,8 +39,8 @@
 (def ^:const ack-base-length (int 40))

 ; message length without nippy segments
-; id (uuid), acker-id (uuid), completion-id (uuid), ack-val (long), nippy-byte-count (int)
-(def ^:const message-base-length (int 60))
+; id (uuid), acker-id (uuid), completion-id (uuid), ack-val (long)
+(def ^:const message-base-length (int 56))

 ; messages with 0 messages in it
 (def ^:const messages-base-length (int 4))
@@ -97,48 +98,42 @@
   (write-uuid buf id)
   (write-uuid buf acker-id)
   (write-uuid buf completion-id)
-  (.writeLong buf ack-val)
-  ; this could probably be a short
-  (.writeInt buf (alength ^bytes message))
-  (.writeBytes buf ^bytes message))
+  (.writeLong buf ack-val))

-(defn read-message-buf [decompress-f ^ByteBuf buf]
+(defn read-message-buf [decompress-f ^ByteBuf buf message]
   (let [id (take-uuid buf)
         acker-id (take-uuid buf)
         completion-id (take-uuid buf)
-        ack-val (.readLong buf)
-        message-size (.readInt buf)
-        arr (byte-array message-size)
-        _ (.readBytes buf arr)
-        message (decompress-f arr)]
-    {:id id
-     :acker-id acker-id
-     :completion-id completion-id
-     :ack-val ack-val
-     :message message}))
+        ack-val (.readLong buf)]
+    ;;; Maybe should have a new record type for the read messages
+    (->Leaf message id acker-id completion-id ack-val nil nil nil nil)))

 (defn build-messages-msg-buf [compress-f messages]
-  (let [compressed-messages (map (fn [msg]
-                                   (update-in msg [:message] compress-f))
-                                 messages)
+  (let [message-bytes ^bytes (compress-f (map :message messages))
+        message-count (int (count messages))
         buf-size (+ type-header-length
                     (+ 4 ; message count int
-                       (* (count messages) message-base-length)
-                       ; nippy compressed segments
-                       (apply + (map (fn [m]
-                                       (alength ^bytes (:message m)))
-                                     compressed-messages))))
+                       (alength message-bytes)
+                       (* message-base-length message-count)))
         buf ^ByteBuf (byte-buffer buf-size)]
     (.writeByte buf messages-type-id) ; message type header
-    (.writeInt buf (int (count compressed-messages))) ; number of messages
-    (doseq [msg compressed-messages]
+    (.writeInt buf message-count) ; number of messages
+    (.writeInt buf (alength message-bytes)) ; nippy compressed data size
+    (.writeBytes buf message-bytes) ; nippy compressed messages
+    (doseq [msg messages]
       (write-message-msg buf msg))
     buf))

 (defn read-messages-buf [decompress-f ^ByteBuf buf]
   {:type messages-type-id
-   :messages (let [message-count (.readInt buf)]
-               (doall (repeatedly message-count #(read-message-buf decompress-f buf))))})
+   :messages (let [message-count (.readInt buf)
+                   messages-payload-size (.readInt buf)
+                   arr (byte-array messages-payload-size)
+                   _ (.readBytes buf arr)
+                   messages (decompress-f arr)]
+               (doall (map (fn [msg]
+                             (read-message-buf decompress-f buf msg))
+                           messages)))})

 (defn read-buf [decompress-f ^ByteBuf buf]
   (let [msg-type ^byte (.readByte buf)]


Updated setParameters, parameter11, parameter12, affixHop, ItoC, and accompanying auxiliary functions

--- src/research_clojure/eChild/Child.clj
+++ src/research_clojure/eChild/Child.clj
@@ -45,13 +45,13 @@

 (defn containsTopicalizable
   [sentence]
-  (def i (.indexOf sentence "S"))
-  (def j (.indexOf sentence "01"))
-  (def k (.indexOf sentence "02"))
-  (def l (.indexOf sentence "03"))
-  (def m (.indexOf sentence "Adv"))
-
-  (or (= i 0) (= j 0) (= k 0) (= l 0) (= m 0)))
+  (let [i (.indexOf sentence "S")
+        j (.indexOf sentence "01")
+        k (.indexOf sentence "02")
+        l (.indexOf sentence "03")
+        m (.indexOf sentence "Adv")]
+
+    (or (= i 0) (= j 0) (= k 0) (= l 0) (= m 0))))

 (defn outOblique
@@ -100,9 +100,9 @@
     (do (let [sentence (get infoList 2)]
           (if (and (inSentence? sentence "02") (not (inSentence? sentence "01")))
             (do (let [tempGrammar (assoc grammar 5 1)]
-                (if (= (get tempGrammar 3) 1)
-                  (assoc tempGrammar 3 0)
-                  tempGrammar)))
+                 (if (= (get tempGrammar 3) 1)
+                   (assoc tempGrammar 3 0)
+                   tempGrammar)))
             (if (containsTopicalizable sentence)
               (assoc grammar 3 1)
               grammar))))
@@ -230,18 +230,18 @@
 (defn iToC
   "11th parameter"
   [sentence currentGrammar]
-  (def g0 (get @currentGrammar 0))
-  (def g1 (get @currentGrammar 1))
-  (def g2 (get @currentGrammar 2))
-
-  (reset! currentGrammar (iToC_aux1 g0 g1 g2 sentence @currentGrammar))
-  (reset! currentGrammar (iToC_aux2 g0 g1 g2 sentence @currentGrammar))
-  (reset! currentGrammar (iToC_aux3 g0 g1 g2 sentence @currentGrammar))
-  (reset! currentGrammar (iToC_aux4 g0 g1 g2 sentence @currentGrammar))
-  (reset! currentGrammar (iToC_aux5 g0 g1 g2 sentence @currentGrammar))
-  (reset! currentGrammar (iToC_aux6 g0 g1 g2 sentence @currentGrammar))
-  (reset! currentGrammar (iToC_aux7 g0 g1 g2 sentence @currentGrammar))
-  (reset! currentGrammar (iToC_aux8 g0 g1 g2 sentence @currentGrammar)))
+
+  (let [[g0 g1 g2] (take 3 currentGrammar)]
+
+    (->> currentGrammar
+        (iToC_aux1 g0 g1 g2 sentence ,,,)
+        (iToC_aux2 g0 g1 g2 sentence ,,,)
+        (iToC_aux3 g0 g1 g2 sentence ,,,)
+        (iToC_aux4 g0 g1 g2 sentence ,,,)
+        (iToC_aux5 g0 g1 g2 sentence ,,,)
+        (iToC_aux6 g0 g1 g2 sentence ,,,)
+        (iToC_aux7 g0 g1 g2 sentence ,,,)
+        (iToC_aux8 g0 g1 g2 sentence ,,,))))

 (defn checkForNV01or01VN
@@ -275,11 +275,12 @@
 (defn affixHop
   "12th parameter"
   [infoList initGrammar]
-  (def senType (get infoList 1))
-  (def sentence (get infoList 2))
-
-  (reset! initGrammar (affixHop_aux1 senType sentence @initGrammar))
-  (reset! initGrammar (affixHop_aux2 senType sentence @initGrammar)))
+
+  (let [[senType sentence] (subvec infoList 1)]
+
+    (->> initGrammar
+         (affixHop_aux1 senType sentence ,,,)
+         (affixHop_aux2 senType sentence ,,,))))

 (defn questionInver
@@ -308,9 +309,9 @@
   (if (and (not= nil (inSentence? (get infoList 2) "03")) (not= nil (inSentence? (get infoList 2) "P")))
     (do (def first (.indexOf (get infoList 2) "03"))
         ;If 03 followed by P
-            (if (and (> first 0) (= (.indexOf (get infoList 2) "P") (+ first 1)))
-              (assoc initGrammar 1 1)
-              initGrammar))
+        (if (and (> first 0) (= (.indexOf (get infoList 2) "P") (+ first 1)))
+          (assoc initGrammar 1 1)
+          initGrammar))
     initGrammar))

@@ -402,16 +403,16 @@

 (defn parameter11
   [initGrammar infoList]
-  (if (= (get @initGrammar 10) 1)
+  (if (= (get initGrammar 10) 1)
     (iToC (get infoList 2) initGrammar)
     initGrammar))

 (defn parameter12
   [initGrammar infoList]
-  (if (= (get @initGrammar 11) 0)
+  (if (= (get initGrammar 11) 0)
     (affixHop infoList initGrammar)
-    @initGrammar))
+    initGrammar))

 (defn parameter13
@@ -446,8 +447,8 @@
         (if (empty? remainingFuncs)
           [currentGrammar, (isGrammarLearned? currentGrammar infoList)]
           (let [[func & remaining] remainingFuncs]
-            (recur (reset! currentGrammar (func infoList currentGrammar))))))))
-)
+            (recur (reset! currentGrammar (func infoList currentGrammar)))))))))
+

 (defn setParameters
@@ -456,19 +457,21 @@
   grammar based on its sentence content and structure"
   [infoList currentGrammar]

-  (reset! currentGrammar (parameter1 @currentGrammar infoList))
-  (reset! currentGrammar (parameter2 @currentGrammar infoList))
-  (reset! currentGrammar (parameter3 @currentGrammar infoList))
-  (reset! currentGrammar (parameter4 @currentGrammar infoList))
-  (reset! currentGrammar (parameter5 @currentGrammar infoList))
-  (reset! currentGrammar (parameter6 @currentGrammar infoList))
-  (reset! currentGrammar (parameter7 @currentGrammar infoList))
-  (reset! currentGrammar (parameter8 @currentGrammar infoList))
-  (reset! currentGrammar (parameter9 @currentGrammar infoList))
-  (reset! currentGrammar (parameter10 @currentGrammar infoList))
-  (reset! currentGrammar (parameter11 currentGrammar infoList))
-  (reset! currentGrammar (parameter12 currentGrammar infoList))
-  (reset! currentGrammar (parameter13 @currentGrammar infoList)))
+  (reset! currentGrammar
+      (-> @currentGrammar
+          (parameter1 ,,, infoList)
+          (parameter2 ,,, infoList)
+          (parameter3 ,,, infoList)
+          (parameter4 ,,, infoList)
+          (parameter5 ,,, infoList)
+          (parameter6 ,,, infoList)
+          (parameter7 ,,, infoList)
+          (parameter8 ,,, infoList)
+          (parameter9 ,,, infoList)
+          (parameter10 ,,, infoList)
+          (parameter11 ,,, infoList)
+          (parameter12 ,,, infoList)
+          (parameter13 ,,, infoList))))

 (defn consumeSentence


added some logging to migrations

added some logging to migrations

--- src/ruuvi_server/heroku/migration.clj
+++ src/ruuvi_server/heroku/migration.clj
@@ -5,7 +5,7 @@
   (:require (lobos [core :as core]))
   )

-(defn -main []
+(defn -main [direction]
   (do-migration (keyword direction) *database-config*)
 )


sharp-edges should be normalized; cleanup

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

--- acqEngine/src/org/micromanager/test/autofocus.clj
+++ acqEngine/src/org/micromanager/test/autofocus.clj
@@ -2,10 +2,14 @@
   "Use image stacks to test scoring methods for image-based autofocus."
   (:import (ij IJ)))

-(defn diff
-  "Compute the difference of subsequent points"
-  [data]
-  (map (fn [[a b]] (- b a)) (partition 2 1 data)))
+(defn slice-processors
+  "Returns a sequence of ImageProcessors for a given slice in a multislice
+   ImagePlus. Zero-based."
+  [imgp]
+  (for [i (range (.getNSlices imgp))]
+    (.. imgp getStack (getProcessor (inc i)))))
+
+;; scoring methods

 (defn mean
   "Compute the mean intensity of a processor."
@@ -27,27 +31,30 @@
 (defn sharp-edges
   "Compute a score based on the intensity of sharpened edges in the image."
   [processor]
-  (-> processor .duplicate (doto .sharpen .findEdges) mean))
+  (/ (-> processor .duplicate (doto .sharpen .findEdges) mean)
+     (mean processor)))

-(defn slice-processors
-  "Returns a sequence of ImageProcessors for a given slice in a multislice
-   ImagePlus. Zero-based."
-  [imgp]
-  (for [i (range (.getNSlices imgp))]
-    (.. imgp getStack (getProcessor (inc i)))))
+;; data and printout
+
+(defn diff
+  "Compute the difference of subsequent points."
+  [data]
+  (map (fn [[a b]] (- b a)) (partition 2 1 data)))

 (defn print-results
   "Prints each item in a sequence preceded by an index integer.
    If starting-index is specified, then the first item will
    have that index; otherwise the first item will be numbered 0."
   ([starting-index data]
-  (loop [i starting-index
-         data data]
-    (println i (first data))
-    (when (next data)
-      (recur (inc i) (next data)))))
+    (loop [i starting-index
+           data data]
+      (println i (first data))
+      (when (next data)
+        (recur (inc i) (next data)))))
   ([data] (print-results 0 data)))

+;; testing
+
 (defn scoring-data
   [scoring-method]
   "Returns the scores using a particular scoring method on the slices
@@ -59,4 +66,4 @@
   [scoring-method]
   (let [data (scoring-data scoring-method)
         diff-data (diff data)]
-  (print-results (map vector data (cons nil diff-data)))))+    (print-results (map vector data (cons nil diff-data)))))


found nc parse-error

found nc parse-error

--- test/src/dda/pallet/dda_serverspec_crate/infra/fact/netcat_test.clj
+++ test/src/dda/pallet/dda_serverspec_crate/infra/fact/netcat_test.clj
@@ -42,6 +42,38 @@
     netcat-yahoo
     sut/output-separator))

+(def real-script-example
+  {:in
+   "tools-watchdog-0.dep.dev.organization.de_22_8
+0
+----- dda-pallet netcat output separator -----
+tools-watchdog-1.dep.dev.organization.de_22_8
+0
+----- dda-pallet netcat output separator -----
+app-watchdog-0.dep.dev.organization.de_22_8
+0
+----- dda-pallet netcat output separator -----
+app-watchdog-1.dep.dev.organization.de_22_8
+0
+----- dda-pallet netcat output separator -----
+app-watchdog-2.dep.dev.organization.de_22_8
+0
+----- dda-pallet netcat output separator -----
+app-watchdog-0.dep.prod.organization.de_22_8
+0
+----- dda-pallet netcat output separator -----
+app-watchdog-1.dep.prod.organization.de_22_8
+0
+----- dda-pallet netcat output separator -----"
+   :out
+   {:tools-watchdog-0.dep.dev.organization.de_22_8 {:reachable? true},
+    :tools-watchdog-1.dep.dev.organization.de_22_8 {:reachable? true},
+    :app-watchdog-0.dep.dev.organization.de_22_8 {:reachable? true},
+    :app-watchdog-1.dep.dev.organization.de_22_8 {:reachable? true},
+    :app-watchdog-2.dep.dev.organization.de_22_8 {:reachable? true},
+    :app-watchdog-0.dep.prod.organization.de_22_8 {:reachable? true},
+    :app-watchdog-1.dep.prod.organization.de_22_8 {:reachable? true}}})
+
 ; ------------------------  tests  ------------------------------
 (deftest test-parse-single-results
   (testing
@@ -53,4 +85,6 @@
   (testing
    "test parsing netcat output"
     (is (= 4
-           (count (keys (sut/parse-netcat script-results)))))))
+           (count (keys (sut/parse-netcat script-results)))))
+    (is (= (:out real-script-example)
+           (sut/parse-netcat (:in real-script-example))))))


better admin login structure

better admin login structure

--- cljs-admin/tourneybot_admin/core.cljs
+++ cljs-admin/tourneybot_admin/core.cljs
@@ -4,6 +4,7 @@
     cljsjs.moment
     [clojure.data :refer [diff]]
     [clojure.string :refer [blank? lower-case replace]]
+    [goog.functions :refer [once]]
     [tourneybot.data :refer [scheduled-status in-progress-status finished-status game-statuses
                              games->results
                              ensure-tournament-state
@@ -32,10 +33,10 @@

 (def initial-page-state
   {;; login related
+   :logging-in? false
    :password ""
    :password-error? false
    :password-valid? false
-   :logging-in? false

    ;; GameTabs across the top
    :tab-id "swiss-round-1"
@@ -304,6 +305,7 @@
   (let [team-id (aget js-evt "currentTarget" "value")]
     (swap! page-state assoc-in [:games game-id team-key] team-id)))

+;; TODO: put the team record in here
 (rum/defc TeamOption < rum/static
   [[team-id team]]
   [:option {:value (name team-id)}
@@ -312,7 +314,7 @@
 (defn- compare-team-name [[teamA-id teamA] [teamB-id teamB]]
   (compare (:name teamA) (:name teamB)))

-;; TODO: use a faster component for team selection than a <select>
+;; TODO: consider using a better team input method than <select>
 (rum/defc TeamSelect < rum/static
   [teams game-id game team-key]
   (let [sorted-teams (sort compare-team-name teams)]
@@ -509,7 +511,8 @@
                           :password-valid? false))

 (defn- click-login-btn [js-evt]
-  (prevent-default js-evt)
+  (when js-evt
+    (prevent-default js-evt))
   (swap! page-state assoc :logging-in? true
                           :password-error? false
                           :password-valid? false)
@@ -602,10 +605,16 @@
 ;; Init
 ;;------------------------------------------------------------------------------

-(defn- init!
-  "Initialize the Admin page."
-  []
-  ;; trigger the initial render
-  (swap! page-state identity))
+(def init!
+  "Initialize the Admin page.
+   NOTE: this function may only be called one time."
+  (once
+    (fn []
+      ;; do they have the password in localStorage?
+      (if-not (blank? (:password @page-state))
+        ;; attempt to login
+        (click-login-btn nil)
+        ;; else trigger an initial render
+        (swap! page-state identity)))))

 (init!)


cosets.clj: use nice Partition API; prepare on-the-fly table compression

--- clojure/org/gavrog/clojure/cosets.clj
+++ clojure/org/gavrog/clojure/cosets.clj
@@ -11,8 +11,7 @@
         row-a (merge (table a) (table b))
         row-b (merge (table b) (table a))
         q (into q (for [g (keys row-a)
-                        :when (not= (pfind equiv (row-a g))
-                                    (pfind equiv (row-b g)))]
+                        :when (not= (equiv (row-a g)) (equiv (row-b g)))]
                     [(row-a g) (row-b g)]))
         table (conj table [a row-a] [b row-a])]
     [table q]))
@@ -23,11 +22,11 @@
          equiv equiv]
     (if-let [[i j] (first q)]
       (let [q (pop q)
-            a (pfind equiv i)
-            b (pfind equiv j)]
+            a (equiv i)
+            b (equiv j)]
         (if (= a b)
           (recur q table equiv)
-          (let [equiv (punion equiv a b)
+          (let [equiv (conj equiv [a b])
                 [table q] (merge-rows table equiv q a b)]
             (recur q table equiv))))
       [table equiv])))
@@ -61,14 +60,20 @@
 (defn- scan-relations [rels subgens table equiv n]
   (let [[table equiv]
         (reduce (fn [[t p] w] (scan t p w n)) [table equiv] rels)]
-    (reduce (fn [[t p] w] (scan t p w (pfind equiv 0))) [table equiv] subgens)))
+    (reduce (fn [[t p] w] (scan t p w (equiv 0))) [table equiv] subgens)))

 (defn- compressed-table [table equiv]
-  (let [reps (into #{} (filter #(= % (pfind equiv %)) (keys table)))
+  (let [reps (into #{} (filter #(= % (equiv %)) (keys table)))
         rep-to-idx (into {} (map vector reps (range)))
-        canon (comp rep-to-idx (partial pfind equiv))]
+        canon (comp rep-to-idx equiv)]
     (into {} (for [[i row] table :when (reps i)]
                [(canon i) (into {} (map (fn [[j v]] [j (canon v)]) row))]))))
+
+(defn- maybe-compressed [table equiv factor]
+  (let [nr-invalid (- (reduce + (map count equiv)) (count equiv))]
+    (if (> nr-invalid (* factor (count table)))
+      (compressed-table [table equiv])
+      [table equiv])))

 (defn coset-table [nr-gens relators subgroup-gens]
   (let [with-inverses (fn [ws] (vec (into #{} (concat ws (map inverse ws)))))
@@ -85,7 +90,7 @@
       (cond (>= i (count table))
             (compressed-table table equiv)

-            (or (>= j (count gens)) (not= i (pfind equiv i)))
+            (or (>= j (count gens)) (not= i (equiv i)))
             (recur table equiv (inc i) 0)

             ((table i) (get gens j))


Remove taxi from sas-prboelms

Remove taxi from sas-prboelms

--- src/angelic/domains/sas_problems.clj
+++ src/angelic/domains/sas_problems.clj
@@ -32,7 +32,7 @@
 (defn sas-sample-files [n]
   (into {}
     (concat
-      [["2x2-taxi"  (taxi/write-taxi-strips (taxi/make-random-taxi-env 2 2 2 1))]]
+      ;     [["2x2-taxi"  (taxi/write-taxi-strips (taxi/make-random-taxi-env 2 2 2 1))]]
       (for [domain ["elevators" "openstacks" "parcprinter" "pegsol" "scanalyzer" #_ "sokoban" "transport" "woodworking"]]
         [(str "IPC6-" domain)
          (str "/Users/jawolfe/Projects/research/IPC/ipc2008-no-cybersec/seq-opt/" domain "-strips/p"


correlation matrix attempt

correlation matrix attempt

--- statspop/src/statspop/math/basic.cljs
+++ statspop/src/statspop/math/basic.cljs
@@ -31,3 +31,44 @@
         zed-product (elementwise-vector-multiply zed-x zed-y)]
     (/ (apply + zed-product) (- (count x) 1))))

+;; (defn correlation-matrix
+;;   "not actually a matrix, this will just return a map of correlations, because correlation matrices are an unnecessarily redundant and mentally exhausting presentation of information.
+
+;;   vector of numeric vectors --> map of string-num parings
+
+;;   assumes column-wise data input.
+
+;;   TODO"
+;;   [])
+
+;; experimenting with for loop.  this produces uniques.
+
+;; (def test1 [1 2 3])
+;; (vec (set (for [i test1, j test1] (str (max i j) (min i j) "=" (+ i j)))))
+;; good news is that max and min work with strings too.
+
+;; actually though it makes more sense to just use a reduce or a recursive function. or a reduce nested in a recursive function.
+;;
+;; first iteration: map correlation with col1 across rest of matrix (using first and rest). second iteration: recur on the rest.
+;;
+
+(defn labelled-correlation
+  [x y]
+  (str x "<-->" y (corr x y)))
+
+(defn correlation-matrix
+  "not actually a matrix, this will just return a map of correlations, because correlation matrices are an unnecessarily redundant and mentally exhausting presentation of information.
+
+   vector of numeric vectors --> map of string-num parings
+
+   assumes column-wise data input."
+  [in-matrix]
+  (loop [col (first in-matrix)
+         cor-with (rest in-matrix)
+         acc []]
+    (if (> (count cor-with) 1)
+      (recur (first cor-with) (rest cor-with) (concat acc (map (partial labelled-correlation col) cor-with)))
+      (vec acc))))
+
+;; UNTESTED.
+


Fix position of threads

Fix position of threads

Broke when pages were changed to be positioned absolutely

--- src/braid/client/ui/styles/misc.cljs
+++ src/braid/client/ui/styles/misc.cljs
@@ -88,7 +88,7 @@
    ["> .threads"
     mixins/flex
     {:position "absolute"
-     :top (m/+ vars/top-bar-height vars/pad vars/pad)
+     :top vars/pad
      :right 0
      :bottom 0
      :left 0


fix update-threads form

fix update-threads form

--- src/chat/server/extensions/asana.clj
+++ src/chat/server/extensions/asana.clj
@@ -141,20 +141,20 @@
             task (fetch-asana-info (extension :id) (str "/tasks/" resource))
             issue->thread (get-in extension [:config :issue->thread] {})]
         (if-let [task-data (get task "data")]
-          (timbre/warnf "adding thread for task %s" task-data)
-          (db/with-conn
-            (db/create-message! {:thread-id thread-id
-                                 :id (db/uuid)
-                                 :content (format "New issues from %s:\n%s"
-                                                  (get-in task-data ["followers" 0])
-                                                  (get task-data "name"))
-                                 :user-id nil ; TODO: who is this?
-                                 :created-at (java.util.Date.)
-                                 :mentioned-user-ids ()
-                                 :mentioned-tag-ids ()})
-            (db/set-extension-config!
-              extension
-              :issue->thread (assoc issue->thread resource thread-id)))
+          (do (timbre/debugf "adding thread for task %s" task-data)
+              (db/with-conn
+                (db/create-message! {:thread-id thread-id
+                                     :id (db/uuid)
+                                     :content (format "New issues from %s:\n%s"
+                                                      (get-in task-data ["followers" 0])
+                                                      (get task-data "name"))
+                                     :user-id nil ; TODO: who is this?
+                                     :created-at (java.util.Date.)
+                                     :mentioned-user-ids ()
+                                     :mentioned-tag-ids ()})
+                (db/set-extension-config!
+                  extension
+                  :issue->thread (assoc issue->thread resource thread-id))))
           (timbre/warnf "No such task %s" resource))))
     ; TODO: handle changed issue to add a new message to the thread
     (doseq [{:strs [resource parent] :as story} new-comments]


ENH: chapter 5, part 4: function functions

--- src/clj_prj03/ch5_core_functions.clj
+++ src/clj_prj03/ch5_core_functions.clj
@@ -242,3 +242,73 @@
   (into target additions))

 (my-conj [0] 1 2 3)
+
+
+; -----------------------------------------
+; 4. Function Functions
+; -----------------------------------------
+
+; 4.1 apply
+
+(defn my-into
+  [target additions]
+  (apply conj target additions))
+
+(my-into [0] [1 2 3])
+(conj [0] 1 2 3)
+
+(max [0 1 2])
+(apply max [0 1 2])
+
+; 4.2 partial
+;;
+
+(def add10 (partial + 10))
+(add10 3)
+(add10 5)
+
+(def add-missing-element
+  (partial conj ["water" "earth" "air"]))
+
+(add-missing-element "unobtainium" "adamantium")
+
+;; what partial really does
+(defn my-partial
+  [partialized-fn & args]
+  (fn [& more-args]
+    (apply partialized-fn (into more-args (reverse args)))))
+
+(def add20 (my-partial + 20))
+(add20 3)
+
+(defn lousy-logger
+  [log-level message]
+  (condp = log-level
+    :warn (clojure.string/lower-case message)
+    :emergency (clojure.string/upper-case message)))
+
+(def warn (partial lousy-logger :warn))
+(warn "Red light ahead")
+
+; 4.3 complement
+;; opposite of a function
+(defn identify-humans
+  [ssns]
+  (filter #(not (vampire? %))
+    (map vampire-related-details ssns)))
+
+(def not-vampire (complement vampire?))
+(defn identify-humans2
+  [ssns]
+  (filter not-vampire?
+    (map vampire-related-details ssns)))
+
+;; manual implementation
+(defn my-complement
+  [fun]
+  (fn [& args] (not (apply fun args))))
+
+(def my-pos? (my-complement neg?))
+(my-pos? 1)
+(my-pos? -1)
+


Remove an unused ":use" statement

Remove an unused ":use" statement

--- src/com/puppetlabs/puppetdb/core.clj
+++ src/com/puppetlabs/puppetdb/core.clj
@@ -14,8 +14,7 @@
 (ns com.puppetlabs.puppetdb.core
   (:require [com.puppetlabs.utils :as utils]
             [clojure.tools.namespace :as ns])
-  (:use [clojure.string :only (split)]
-        [clojure.stacktrace :only [print-stack-trace]])
+  (:use [clojure.string :only (split)])
   (:gen-class))

 (def ns-prefix "com.puppetlabs.puppetdb.cli.")


[#2809] Adapt RQG to null responses

[#2809] Adapt RQG to null responses

--- backend/src/akvo/lumen/lib/import/flow_common.clj
+++ backend/src/akvo/lumen/lib/import/flow_common.clj
@@ -130,8 +130,8 @@
              (question-responses-base (select-keys responses (:main-ns dict)))
              {:ns "main"})]
           (mapv #(with-meta
-                   (question-responses-base {% (get responses %)})
-                   {:ns %})
+                    (or (question-responses-base {% (get responses %)}) {})
+                     {:ns %})
                 (:rqg-ns dict)))))

 (def metadata-keys #{"identifier" "instance_id" "display_name" "submitter" "submitted_at" "surveyal_time" "device_id"})


Keep working on code

Keep working on code

--- src/day8/re_frame_10x/view/code.cljs
+++ src/day8/re_frame_10x/view/code.cljs
@@ -68,23 +68,26 @@
                :style {:overflow-y "scroll"}
                :children
                (doall
-                 (map-indexed
-                   (fn [i line]
-                     (list
-                       ;; See https://github.com/reagent-project/reagent/issues/350 for why we use random-uuid here
-                       ^{:key (random-uuid)}
-                       [rc/v-box
-                        :class "code-fragment"
-                        :style {:margin-left (str (* 50 (dec (:indent-level line))) "px")}
-                        :attr {:on-mouse-enter #(do (println "Enter" (:form line))
-                                                    (rf/dispatch [:code/hover-form (:form line)])
-                                                    true)
-                               :on-mouse-leave #(do (println "Leave" (:form line))
-                                                    (rf/dispatch [:code/exit-hover-form (:form line)])
-                                                    true)}
-                        :children [[:pre (zp/zprint-str (:form line))]
-                                   ;; TODO: disable history expansion, or at least storing of it in ls.
-                                   [components/simple-render (:result line) [(:id code-execution) i]]]]
-                       ^{:key (random-uuid)}
-                       [rc/gap-f :size "5px"]))
-                   (:code code-execution)))]])]))]]))
+                 (->> (:code code-execution)
+                      ;; Remove traced function values, these are usually not very interesting in and of themselves.
+                      (remove (fn [line] (fn? (:result line))))
+                      (map-indexed
+                        (fn [i line]
+                          (list
+                            ;; See https://github.com/reagent-project/reagent/issues/350 for why we use random-uuid here
+                            ^{:key (random-uuid)}
+                            [rc/v-box
+                             :class "code-fragment"
+                             :style {:margin-left (str (* 50 (dec (:indent-level line))) "px")}
+                             :attr {:on-mouse-enter #(do (println "Enter" (:form line))
+                                                         (rf/dispatch [:code/hover-form (:form line)])
+                                                         true)
+                                    :on-mouse-leave #(do (println "Leave" (:form line))
+                                                         (rf/dispatch [:code/exit-hover-form (:form line)])
+                                                         true)}
+                             :children [[:pre (zp/zprint-str (:form line))]
+                                        ;; TODO: disable history expansion, or at least storing of it in ls.
+                                        [components/simple-render (:result line) [(:id code-execution) i]]]]
+                            ^{:key (random-uuid)}
+                            [rc/gap-f :size "5px"]))
+                        )))]])]))]]))


Fix typo

Fix typo

--- src/flatland/useful/experimental.clj
+++ src/flatland/useful/experimental.clj
@@ -230,7 +230,7 @@

 (defn lift-meta
   "Move some of the keys from m into its metadata, overriding existing values.
-   (lift-meta {:a 1 :b 2} [:a]) -> ^{:a 1} {:b 2]"
+   (lift-meta {:a 1 :b 2} [:a]) -> ^{:a 1} {:b 2}"
   [m & ks]
   (-> (apply dissoc m ks)
       (vary-meta merge (select-keys m ks))))


CMR-3672: Addressed the last, migrate-doi-down PR comment.

--- umm-spec-lib/src/cmr/umm_spec/migration/version_migration.clj
+++ umm-spec-lib/src/cmr/umm_spec/migration/version_migration.clj
@@ -187,13 +187,9 @@
   "Migrate :DOI from collection level down to CollectionCitation level."
   [c]
   (if-let [doi-obj (:DOI c)]
-    (let [updated-coll-citations (map #(assoc % :DOI doi-obj) (:CollectionCitations c))
-          ;; assign all :DOI to nil except for the first one i.e. only one DOI in not nil.
-          updated-coll-citations (if (< 1 (count updated-coll-citations))
-                                   (map #(assoc % :DOI nil) (rest updated-coll-citations))
-                                   updated-coll-citations)
-          updated-coll (dissoc c :DOI)]
-      (assoc updated-coll :CollectionCitations updated-coll-citations))
+    (-> c
+      (util/update-in-each [:CollectionCitations] assoc :DOI doi-obj)
+      (dissoc :DOI))
     c))

 (defmethod migrate-umm-version [:collection "1.8" "1.9"]