Moar.

Moar.

--- src/clojurecraft/core.clj
+++ src/clojurecraft/core.clj
@@ -26,6 +26,8 @@
   0x11 :usebed
   0x12 :animation
   0x13 :entityaction
+  0x14 :namedentityspawn
+  0x15 :pickupspawn
 })
 (def packet-ids (apply assoc {} (mapcat reverse packet-types)))

@@ -191,6 +193,20 @@

   (-write-int conn eid)
   (-write-byte conn action))
+
+(defn write-packet-pickupspawn [conn {eid :eid item :item count :count damagedata :damagedata x :x y :y z :z rotation :rotation pitch :pitch roll :roll}]
+  (-write-byte conn (:pickupspawn packet-ids))
+
+  (-write-int conn eid)
+  (-write-short conn item)
+  (-write-byte conn count)
+  (-write-short conn damagedata)
+  (-write-int conn x)
+  (-write-int conn y)
+  (-write-int conn x)
+  (-write-byte conn rotation)
+  (-write-byte int conn pitch)
+  (-write-byte int conn roll))

 ; Writing Wrappers -----------------------------------------------------------------
@@ -214,6 +230,7 @@
     (= packet-type :usebed)               (write-packet-usebed conn payload)
     (= packet-type :animation)            (write-packet-animation conn payload)
     (= packet-type :entityaction)         (write-packet-entityaction conn payload)
+    (= packet-type :pickupspawn)          (write-packet-pickupspawn conn payload)
     )
   (flushc conn))

@@ -352,6 +369,30 @@
   (-> {}
     (assoc :eid (-read-int conn))
     (assoc :action (-read-byte conn))))
+
+(defn read-packet-namedentityspawn [conn]
+  (-> {}
+    (assoc :eid (-read-int conn))
+    (assoc :playername (-read-string16 conn))
+    (assoc :x (-read-int conn))
+    (assoc :y (-read-int conn))
+    (assoc :z (-read-int conn))
+    (assoc :rotation (-read-byte conn))
+    (assoc :pitch (-read-byte conn))
+    (assoc :currentitem (-read-short conn))))
+
+(defn read-packet-pickupspawn [conn]
+  (-> {}
+    (assoc :eid (-read-int conn))
+    (assoc :item (-read-short conn))
+    (assoc :count (-read-byte conn))
+    (assoc :damagedata(-read-short conn))
+    (assoc :x (-read-int conn))
+    (assoc :y (-read-int conn))
+    (assoc :z (-read-int conn))
+    (assoc :rotation (-read-byte conn))
+    (assoc :pitch (-read-byte conn))
+    (assoc :roll (-read-byte conn))))

 ; Reading Wrappers -----------------------------------------------------------------
@@ -378,6 +419,8 @@
         (= packet-type :usebed)               (read-packet-usebed conn)
         (= packet-type :animate)              (read-packet-animate conn)
         (= packet-type :entityaction)         (read-packet-entityaction conn)
+        (= packet-type :namedentityspawn)     (read-packet-namedentityspawn conn)
+        (= packet-type :pickupspawn)          (read-packet-pickupspawn conn)
         :else (str "UNKNOWN PACKET TYPE: " packet-id)
         ))
     (println "\n\n\n")))


Fixing the way points are output so copying from test.check failures will evaluate it.

--- src/cmr/spatial/point.clj
+++ src/cmr/spatial/point.clj
@@ -128,7 +128,7 @@
 (defn print-point
   "Prints the point in a way that it can be copy and pasted for testing"
   [^Point p ^java.io.Writer writer]
-  (.write writer (str (apply list (into ['cmr.spatial.point/point]
+  (.write writer (str "#=" (apply list (into ['cmr.spatial.point/point]
                                         [(.lon p) (.lat p)])))))

 ;; These define Clojure built in multimethods for point so it can be printed easily


Six tests for the get-exception function

--- test/zg/utils_test.clj
+++ test/zg/utils_test.clj
@@ -68,3 +68,61 @@
     (testing "if the zg.utils/get-exception-message definition exists."
         (is (callable? 'zg.utils/get-exception-message))))

+;
+; Tests for behaviour of all functions
+;
+
+(deftest test-get-exception-message-1
+    "Check the function zg.utils/get-exception-message."
+    (testing "the function zg.utils/get-exception-message."
+        (try
+            (throw (new java.lang.Exception "Message text"))
+            (is nil "Exception not thrown as expected!")
+            (catch Exception e
+                (is (= "Message text" (get-exception-message e)))))))
+
+(deftest test-get-exception-message-2
+    "Check the function zg.utils/get-exception-message."
+    (testing "the function zg.utils/get-exception-message."
+        (try
+            (/ 1 0)
+            (is nil "Exception not thrown as expected!")
+            (catch Exception e
+                (is (= "Divide by zero" (get-exception-message e)))))))
+
+(deftest test-get-exception-message-3
+    "Check the function zg.utils/get-exception-message."
+    (testing "the function zg.utils/get-exception-message."
+        (try
+            (Integer/parseInt "unparseable")
+            (is nil "Exception not thrown as expected!")
+            (catch Exception e
+                (is (.startsWith (get-exception-message e) "For input string:"))))))
+
+(deftest test-get-exception-message-4
+    "Check the function zg.utils/get-exception-message."
+    (testing "the function zg.utils/get-exception-message."
+        (try
+            (throw (new java.lang.Exception ""))
+            (is nil "Exception not thrown as expected!")
+            (catch Exception e
+                (is (= "" (get-exception-message e)))))))
+
+(deftest test-get-exception-message-5
+    "Check the function zg.utils/get-exception-message."
+    (testing "the function zg.utils/get-exception-message."
+        (try
+            (throw (new java.lang.Exception))
+            (is nil "Exception not thrown as expected!")
+            (catch Exception e
+                (is (nil? (get-exception-message e)))))))
+
+(deftest test-get-exception-message-6
+    "Check the function zg.utils/get-exception-message."
+    (testing "the function zg.utils/get-exception-message."
+        (try
+            (println (nth [] 10)) ; realize the sequence and getter
+            (is nil "Exception not thrown as expected!")
+            (catch Exception e
+                (is (nil? (get-exception-message e)))))))
+


reader: fix indexing-push-back-reader

reader: fix indexing-push-back-reader

--- src/main/clojure/clojure/tools/reader.clj
+++ src/main/clojure/clojure/tools/reader.clj
@@ -940,13 +940,10 @@
 (defn indexing-push-back-reader
   "Creates an IndexingPushbackReader from a given string or Reader"
   ([s-or-rdr]
-     (IndexingPushbackReader.
-      ((if (string? s-or-rdr) string-push-back-reader input-stream-push-back-reader)
-       s-or-rdr) 0 1 true nil))
+     (indexing-push-back-reader s-or-rdr 1))
   ([s-or-rdr buf-len]
      (IndexingPushbackReader.
-      ((if (string? s-or-rdr) string-push-back-reader input-stream-push-back-reader)
-       s-or-rdr buf-len) 0 1 true nil)))
+      (if (string? s-or-rdr) (string-push-back-reader s-or-rdr buf-len) s-or-rdr) 0 1 true nil)))

 (defn read
   "Reads the first object from an IPushbackReader or a java.io.PushbackReader.


can now send messages with mentions

can now send messages with mentions

--- src/clj_discord/core.clj
+++ src/clj_discord/core.clj
@@ -64,9 +64,10 @@
                          (Thread/sleep (get @the-ready "heartbeat_interval"))))))))

-(defn post-message [channel_id message]
+(defn post-message-with-mentions [channel_id message mentions]
   (client/post (str "https://discordapp.com/api/channels/" channel_id "/messages")
                {:body (json/write-str {:content message
+                                       :mentions mentions
                                        :nonce (str (System/currentTimeMillis))
                                        :tts false})
                 :headers {:authorization @the-token}
@@ -74,4 +75,13 @@
                 :accept :json}))

+(defn post-message [channel_id message]
+  (post-message-with-mentions channel_id message '()))

+
+(defn post-message-with-mention [channel_id message user_id]
+  (post-message-with-mentions channel_id (str "<@" user_id "> " message) (list user_id)))
+
+
+
+


Specify default value for query-params.

Specify default value for query-params.

--- src/clj_spotify/core.clj
+++ src/clj_spotify/core.clj
@@ -90,7 +90,7 @@

 (defn spotify-api-call
   "Returns a function that takes a map m and an optional oauth-token t as arguments."
-  [method endpoint & {:keys [query-params]}]
+  [method endpoint & {:keys [query-params] :or {query-params []}}]
   (fn f
     ([m] (f m nil))
     ([m t]


fix that port

fix that port

--- src/cljs/ceres/core.cljs
+++ src/cljs/ceres/core.cljs
@@ -82,7 +82,7 @@
                                (if ssl?  "wss://" "ws://")
                                (.getDomain uri)
                                ":"
-                               8082 #_(.getPort uri)
+                               (.getPort uri)
                                "/tweets/ws")))]
             (om/set-state! owner :ws-in (:in connection))
             (om/set-state! owner :ws-out (:out connection))


Move all user-editable form stuff into data hashmap

--- src/cljs/htmly/core.cljs
+++ src/cljs/htmly/core.cljs
@@ -113,16 +113,18 @@
                                                      [["One"] ["http://www.youtube.com"]]
                                                      [["Two"] ["http://www.google.com"]]
                                                      [["Three"] ["http://www.kika.de"]]]}
+
                                           {:function :form
-                                           :title ["Quiz"]
-                                           :intro ["Rate mal, was mein Lieblingstier ist"]
-                                           :data [
-                                                     ["Elefant"]
-                                                     ["Giraffe"]
-                                                     ["Tiger"]
-                                                     ["Schlange"]
-                                                     ["Hai"]]
-                                           :button ["Raten"]}]]})))
+                                           :data {:title ["Quiz"]
+                                                  :intro ["Rate mal, was mein Lieblingstier ist"]
+                                                  :items [
+                                                          ["Elefant"]
+                                                          ["Giraffe"]
+                                                          ["Tiger"]
+                                                          ["Schlange"]
+                                                          ["Hai"]]
+                                                  :answer 1
+                                                  :button ["Raten"]}}]]})))

 (defn edit-title-and-intro [details]
@@ -530,31 +532,31 @@
   (reify
     om/IRenderState
     (render-state [this state]
-      (let [indexed-details (map-indexed (fn [idx itm] [idx itm]) (:data details))]
+      (let [indexed-details (map-indexed (fn [idx itm] [idx itm]) (-> details :data :items))]
         (if (:help state)
           (dom/div nil
                    (raw-html form-text-1)
                    (source-code
-                    (edit-title-and-intro details)
-                    (form-help details))
+                    (edit-title-and-intro (details :data))
+                    (form-help (details :data)))

                    (raw-html form-text-2)
                    (dom/div #js {:className "form-group"}
                             (dom/label #js {:className "control-label"} "Die Lösung:")
                             (apply
                              dom/select #js {:className "form-control"
-                                             :value (:answer details)
-                                             :onChange (fn [e] (om/transact! details :answer (fn [_] (.. e -target -value))))}
+                                             :value (-> details :data :answer)
+                                             :onChange (fn [e] (om/transact! details :data :answer (fn [_] (.. e -target -value))))}
                              (om/build-all option-tag indexed-details)))
                    (raw-html form-text-3))
           (dom/form #js {:onSubmit js/runQuiz}
-                    (dom/h3 nil (-> details :title first))
-                    (dom/p nil (-> details :intro first))
-                    (dom/input #js {:type "hidden" :name "quiz-answer" :value (:answer details)})
+                    (dom/h3 nil (-> details :data :title first))
+                    (dom/p nil (-> details :data :intro first))
+                    (dom/input #js {:type "hidden" :name "quiz-answer" :value (-> details :data :answer)})
                     (apply
                      dom/fieldset nil
                      (om/build-all checkbox indexed-details))
-                    (dom/button #js {:type "submit" :className "btn btn-default"} (first (:button details)))))))))
+                    (dom/button #js {:type "submit" :className "btn btn-default"} (-> details :data :button first))))))))

 (def step-lookup
   {:background background


dead code

dead code

--- src/spec_tools/impl.cljc
+++ src/spec_tools/impl.cljc
@@ -79,8 +79,7 @@
                (if (symbol? x)
                  (or (some->> x res ->sym) x)
                  x)))
-            (unfn cljs?)
-            #_(walk/postwalk clojure-core-symbol-or-any)))))
+            (unfn cljs?)))))

 (defn extract-pred-and-info [x]
   (if (map? x)


Add step* impl for s/keys

Add step* impl for s/keys

--- src/spectrace/trace.cljc
+++ src/spectrace/trace.cljc
@@ -108,6 +108,41 @@
 (defmethod step* `s/every-kv [state succ fail]
   (step-for-every-kv state succ fail))

+(defn- possible-keys [{:keys [args]}]
+  (letfn [(walk [ret [kind arg]]
+            (case kind
+              :key (conj ret arg)
+              (:and :or) (collect-keys ret (:keys arg))))
+          (collect-keys [ret keys]
+            (reduce walk ret keys))]
+    (-> {}
+        (into (map (fn [k] [k k]))
+              (collect-keys (set (:opt args)) (:req args)))
+        (into (map (fn [k] [(keyword (name k)) k]))
+              (collect-keys (set (:opt-un args)) (:req-un args))))))
+
+(defn- step-for-keys [{:keys [spec path val in]} succ fail val-fn]
+  (with-cont succ fail
+    (let [[segment & path] path
+          [key & in] in
+          keys (possible-keys spec)]
+      (when (and (contains? keys segment)
+                 (map? val)
+                 (contains? val key))
+        {:spec (get keys segment)
+         :path path
+         :val (val-fn val key)
+         :in in}))))
+
+(defmethod step* `s/keys [state succ fail]
+  (step-for-keys state succ fail get))
+
+;; Add this after CLJ-2143 is fixed
+#_(defmethod step* `s/keys* [state succ fail]
+  (letfn [(get-key [[& {:as keys}] key]
+            (get keys key))]
+    (step-for-keys state succ fail get-key)))
+
 (defmethod step* `s/cat [state succ fail]
   (step-by-key state succ fail :val-fn nth))

@@ -166,10 +201,9 @@
             (if (empty? path)
               ret
               (step state
-                    (fn [{:keys [skip?] :as state'} fail]
-                      (let [state' (-> state'
-                                       (update :spec second)
-                                       normalize)
+                    (fn [{:keys [spec skip?] :as state'} fail]
+                      (let [spec (if (keyword? spec) spec (second spec))
+                            state' (normalize (assoc state' :spec spec))
                             ret' (if skip? ret (conj ret state'))]
                         #(rec state' fail ret')))
                     (fn [] fail))))]


Add `as-bool`, `parse-bool` fns

Add `as-bool`, `parse-bool` fns

--- src/taoensso/carmine.clj
+++ src/taoensso/carmine.clj
@@ -64,8 +64,13 @@
 ;;; versions that auto-serialized simple number types
 (defn as-long   [x] (when x (if (number? x) (long   x) (Long/parseLong     x))))
 (defn as-double [x] (when x (if (number? x) (double x) (Double/parseDouble x))))
+(defn as-bool   [x] (cond (or (true? x) (false? x))    x
+                          (or (= x "false") (= x "0")) false
+                          (or (= x "true")  (= x "1")) true
+                          :else nil))
 (defmacro parse-long    [& body] `(with-parser as-long   ~@body))
 (defmacro parse-double  [& body] `(with-parser as-double ~@body))
+(defmacro parse-bool    [& body] `(with-parser as-bool   ~@body))
 (defmacro parse-keyword [& body] `(with-parser #(keyword %) ~@body))

 (defn make-keyfn


Housekeeping, add support for Binary values

--- src/taoensso/faraday.clj
+++ src/taoensso/faraday.clj
@@ -39,7 +39,8 @@
              WriteRequest]
             com.amazonaws.ClientConfiguration
             com.amazonaws.auth.BasicAWSCredentials
-            com.amazonaws.services.dynamodb.AmazonDynamoDBClient))
+            com.amazonaws.services.dynamodb.AmazonDynamoDBClient
+            java.nio.ByteBuffer))

 ;;;; TODO Rotary PRs
 ;; * Feature/can update dynamo items (mrgordon)
@@ -76,13 +77,16 @@
 (def db-client (memoize db-client*))

 (defn- coerce-num [x] (if (.contains x ".") (Double. x) (Long. x)))
+(defn- coerce-ba  [^ByteBuffer bb] (.array bb))

 (defn- get-value "Returns the value of an AttributeValue object."
   [attr-value]
   (or (.getS attr-value)
-      (some->> (.getN attr-value)  coerce-num)
+      (some->> (.getN  attr-value) coerce-num)
+      (some->> (.getB  attr-value) coerce-ba)
+      (some->> (.getSS attr-value) (into #{}))
       (some->> (.getNS attr-value) (map coerce-num) (into #{}))
-      (some->> (.getSS attr-value) (into #{}))))
+      (some->> (.getBS attr-value) (map coerce-ba)  (into #{}))))

 (defn- key-schema-element "Returns a new KeySchemaElement object."
   [{key-name :name key-type :type}]
@@ -102,6 +106,29 @@
   (doto (ProvisionedThroughput.)
     (.setReadCapacityUnits  (long read-units))
     (.setWriteCapacityUnits (long write-units))))
+
+(defn- set-of [pred s] (and (set? s) (every? pred s)))
+(def ^:private ^:const ba-class (Class/forName "[B"))
+(defn- ba? [x] (instance? ba-class x))
+(defn- ba-buffer [^bytes ba] (ByteBuffer/wrap ba))
+
+(defn- to-attr-value
+  "Returns an AttributeValue object for given Clojure value."
+  ;; TODO Nippy support
+  ;; TODO More efficient set-type dispatch
+  [x]
+  (cond
+   (string? x)        (doto (AttributeValue.) (.setS x))
+   (number? x)        (doto (AttributeValue.) (.setN (str x)))
+   (ba?     x)        (doto (AttributeValue.) (.setB (ba-buffer x)))
+   (set-of string? x) (doto (AttributeValue.) (.setSS x))
+   (set-of number? x) (doto (AttributeValue.) (.setNS (map str x)))
+   (set-of ba?     x) (doto (AttributeValue.) (.setBS (map ba-buffer x)))
+   (set? x)           (throw (Exception. "Set must contain values of the same type."))
+   :else              (throw (Exception. (str "Unknown value type: " (type x))))))
+
+(comment (map to-attr-value ["foo" 10 3.14 (.getBytes "foo")
+                             #{"a" "b" "c"} #{1 2 3.14} #{(.getBytes "foo")}]))

 ;;;; TODO Dev

@@ -229,20 +256,6 @@
       .listTables
       .getTableNames
       seq))
-
-(defn- set-of [f s]
-  (and (set? s) (every? f s)))
-
-(defn- to-attr-value
-  "Convert a value into an AttributeValue object."
-  [value]
-  (cond
-   (string? value)        (doto (AttributeValue.) (.setS value))
-   (number? value)        (doto (AttributeValue.) (.setN (str value)))
-   (set-of string? value) (doto (AttributeValue.) (.setSS value))
-   (set-of number? value) (doto (AttributeValue.) (.setNS (map str value)))
-   (set? value)    (throw (Exception. "Set must be all numbers or all strings"))
-   :else           (throw (Exception. (str "Unknown value type: " (type value))))))

 (defn- item-map
   "Turn a item in DynamoDB into a Clojure map."


More async fixes.

More async fixes.

--- src/datascript/query.cljs
+++ src/datascript/query.cljs
@@ -417,14 +417,14 @@
 (defn -resolve-clause [context clause callback]
   (condp looks-like? clause
     '[[*]] ;; predicate [(pred ?a ?b ?c)]
-      (callback (filter-by-pred context clause))
+      (callback (filter-by-pred @context clause))

     '[[*] _] ;; function [(fn ?a ?b) ?res]
-      (callback (bind-by-fn context clause))
+      (callback (bind-by-fn @context clause))

     '[*] ;; pattern
-      (lookup-pattern context clause (fn [datoms]
-        (callback (update-in context [:rels] collapse-rels datoms))))))
+      (lookup-pattern @context clause (fn [datoms]
+        (callback (update-in @context [:rels] collapse-rels datoms))))))

 ;TODO not really sure it is valid to replace all these context's with @context's, but it seems to work
 (defn resolve-clause [context clause callback]
@@ -435,7 +435,7 @@
           source (get-in @context [:sources source])]
       (solve-rule (assoc @context :sources {'$ source}) rule (fn [rel]
         (callback (update-in @context [:rels] collapse-rels rel)))))
-    (-resolve-clause @context clause callback)))
+    (-resolve-clause context clause callback)))

 (defn -q [context clauses callback]
   (async-reduce resolve-clause context clauses callback))


rewrote path filling to be much more concise

--- src/duffel/tree/paths.clj
+++ src/duffel/tree/paths.clj
@@ -1,9 +1,8 @@
 (ns duffel.tree.paths
   "Functions for filling out duffel trees with necessary information and pruning
   them of unecessary dirs/files/information"
-  (:require [duffel.tree.core :refer [tree-dir-mapreduce
-                                      tree-file-map
-                                      tree-assoc]]))
+  (:require [duffel.tree.core :refer [tree-map tree-contents-map
+                                      tree-get tree-assoc]]))

 (defn- try-append-slash
   "Given a string representing a directory, appends a slash to the string if
@@ -11,40 +10,30 @@
   [dir]
   (if-not (= (last dir) \/) (str dir "/") dir))

+(defn- set-path
+  [el path-type root]
+  (if (sequential? el)
+    (tree-assoc el path-type (str root (tree-get el :real-name) "/"))
+    (tree-assoc el path-type (str root (tree-get el :real-name)))))
+
 (defn fill-relpaths
   "Goes through a duffel tree and fills all relative paths for both dir-maps and
   file-maps"
   [dtree]
-  (->> dtree
-    (tree-dir-mapreduce
-      (fn [dir-map acc _]
-        (let [rel-path (str acc (dir-map :real-name) "/")]
-          [ (assoc dir-map :rel-path rel-path)
-            rel-path ]))
-      "")
-    (tree-file-map
-      (fn [dir-map file-map]
-        (assoc file-map
-          :rel-path (str (dir-map :rel-path) (file-map :real-name)))))))
+  (tree-map
+    (fn [dt]
+      (tree-contents-map #(set-path % :rel-path (tree-get dt :rel-path)) dt))
+    (set-path dtree :rel-path "")))

 (defn fill-abspaths
   "Goes through a duffel tree and fills all absolute paths for both dir-maps and
   file-maps. The absolute paths are chrooted such that the root of the tree's
   abs-path is the given chroot, and all children follow from that"
   [dtree root]
-  (let [real-root (try-append-slash root)
-        rooted-dtree (tree-assoc dtree :abs-path real-root)]
-    (->> rooted-dtree
-      (tree-dir-mapreduce
-        (fn [dir-map acc _]
-          (let [new-root (or (dir-map :abs-path)
-                             (str acc (dir-map :real-name) "/"))]
-            [ (assoc dir-map :abs-path new-root) new-root ]))
-        "")
-      (tree-file-map
-        (fn [dir-map file-map]
-          (assoc file-map
-            :abs-path (str (dir-map :abs-path) (file-map :real-name))))))))
+  (tree-map
+    (fn [dt]
+      (tree-contents-map #(set-path % :abs-path (tree-get dt :abs-path)) dt))
+    (tree-assoc dtree :abs-path (try-append-slash root))))

 (defn fill-paths
   "Goes through a duffel tree and fills all rel and abs paths using


comment ES datetime edge cases

comment ES datetime edge cases

--- resources/duckling/corpus/es.time.clj
+++ resources/duckling/corpus/es.time.clj
@@ -236,11 +236,11 @@
   "mañana a 11"
   (datetime 2013 2 13 11 :hour 11)

-  "viernes a las doce"
-  (datetime 2013 2 15 12 :hour 12 :day-of-week 5)
-
-  "viernes a las 12:00 horas"
-  (datetime 2013 2 15 12 0 :hour 12 :day-of-week 5 :minute 0)
+  ;"viernes a las doce"
+  ;(datetime 2013 2 15 12 :hour 12 :day-of-week 5)
+
+  ;"viernes a las 12:00 horas"
+  ;(datetime 2013 2 15 12 0 :hour 12 :day-of-week 5 :minute 0)

   "viernes, el 12 de septiembre de 2014"
   (datetime 2014 9 12 :day-of-week 5 :day 12 :month 9 :year 2014)


[scamp] turn old demo code into regression/unit tests

--- modules/scamp/test/world/main_test.clj
+++ modules/scamp/test/world/main_test.clj
@@ -1,5 +1,6 @@
 (ns world.main-test
-  (:require [clojure.test :refer :all]
+  (:require [clojure.data :as cd]
+            [clojure.test :refer :all]
             [schema.core :as s]
             [world.main :as main]
             [scamp.core :as scamp]
@@ -150,43 +151,65 @@
      ;; TODO: which log is this supposed to be?
      (Math/log n)))

-(defn demo-unsubscription [output-filename-base]
+(defn demo-unsubscription []
   (scamp-test/scamp-test
    #(let [world (-> main/world-base
                     (assoc-in [:config :connection-redundancy] -1)
                     (main/world-add-new-node (assoc (scamp/node-contact-address->node "node-id0")
                                                     :upstream #{"node-id2"}
-                                                    :downstream #{"node-id1"}))
+                                                    :downstream #{"node-id1"}
+                                                    :clock (scamp-test/test-clock)))
                     (main/world-add-new-node (assoc (scamp/node-contact-address->node "node-id1")
                                                     :upstream #{"node-id0"}
-                                                    :downstream #{"node-id3" "node-id4"}))
+                                                    :downstream #{"node-id3" "node-id4"}
+                                                    :clock (scamp-test/test-clock)))
                     (main/world-add-new-node (assoc (scamp/node-contact-address->node "node-id2")
                                                     :upstream #{"node-id4"}
-                                                    :downstream #{"node-id0"}))
+                                                    :downstream #{"node-id0"}
+                                                    :clock (scamp-test/test-clock)))
                     (main/world-add-new-node (assoc (scamp/node-contact-address->node "node-id3")
                                                     :upstream #{"node-id1"}
-                                                    :downstream #{"node-id4"}))
+                                                    :downstream #{"node-id4"}
+                                                    :clock (scamp-test/test-clock)))
                     (main/world-add-new-node (assoc (scamp/node-contact-address->node "node-id4")
                                                     :upstream #{"node-id1" "node-id3"}
-                                                    :downstream #{"node-id2"})))
+                                                    :downstream #{"node-id2"}
+                                                    :clock (scamp-test/test-clock))))
           world-2 (-> world
                       (main/world-instruct-node-to-unsubscribe "node-id4")
-                      (main/world-do-all-comms {:verbose? true}))
-          ]
-      (spit (str output-filename-base "-01.dot") (main/world->dot world))
-      (spit (str output-filename-base "-02.dot") (main/world->dot world-2))
-      )))
-
-(defn demo-unsubscription2 [output-filename-base]
+                      (main/world-do-all-comms {:verbose? true}))]
+      {:world world
+       :world-2 world-2})))
+
+(deftest test-demo-unsubscription
+  (let [{:keys [world world-2]} (demo-unsubscription)
+        [_in-a in-b _in-both] (cd/diff world world-2)]
+    (is (get-in in-b [:network "node-id4" :removed?]) "node-id4 has been removed")))
+
+(defn demo-unsubscription->dot [output-filename-base]
+  (let [{:keys [world world-2]} (demo-unsubscription)]
+    (spit (str output-filename-base "-01.dot") (main/world->dot world))
+    (spit (str output-filename-base "-02.dot") (main/world->dot world-2))))
+
+(defn demo-unsubscription2 [& [output-filename-base]]
   (scamp-test/scamp-test
    #(let [world (world-with-subs 6)
           world-2 (-> world
                       (main/world-instruct-node-to-unsubscribe "node-id4")
                       (main/world-do-all-comms {:verbose? true}))
           ]
-      (spit (str output-filename-base "-01.dot") (main/world->dot world))
-      (spit (str output-filename-base "-02.dot") (main/world->dot world-2))
-      )))
+      {:world world
+       :world-2 world-2})))
+
+(deftest test-demo-unsubscription2
+  (let [{:keys [world world-2]} (demo-unsubscription2)
+        [_in-a in-b _in-both] (cd/diff world world-2)]
+    (is (get-in in-b [:network "node-id4" :removed?]) "node-id4 has been removed")))
+
+(defn demo-unsubscription2->dot [& [output-filename-base]]
+  (let [{:keys [world world-2]} (demo-unsubscription2)]
+    (spit (str output-filename-base "-01.dot") (main/world->dot world))
+    (spit (str output-filename-base "-02.dot") (main/world->dot world-2))))

 (defn pprint-cluster [world]
   (->> world


v 0.7.10

v 0.7.10

--- src/useful/exception.clj
+++ src/useful/exception.clj
@@ -1,4 +1,6 @@
-(ns useful.exception)
+(ns useful.exception
+  (:use [clojure.stacktrace :only [print-cause-trace]]
+        [clojure.string :only [split-lines trim]]))

 (defmacro rescue
   "Evaluate form, returning error-form on any Exception."


Fix typo breaking uberjar.

Fix typo breaking uberjar.

--- src/leiningen/uberjar.clj
+++ src/leiningen/uberjar.clj
@@ -67,6 +67,6 @@
          (let [deps (->> (.listFiles (file (:library-path project)))
                          (filter #(.endsWith (.getName %) ".jar"))
                          (cons (file (get-jar-filename project))))]
-           (write-components project out)))
+           (write-components deps out)))
        (println "Created" standalone-filename)))
   ([project] (uberjar project (get-default-uberjar-name project))))


URL prefix should be used everywhere :)

URL prefix should be used everywhere :)

--- src/zg/html_renderer.clj
+++ src/zg/html_renderer.clj
@@ -6,16 +6,16 @@

 (defn render-html-header
     "Renders part of HTML page - the header."
-    [package]
+    [word url-prefix]
     [:head
-        [:title "zg" package]
+        [:title "zg " word]
         [:meta {:name "Author"    :content "Pavel Tisnovsky"}]
         [:meta {:name "Generator" :content "Clojure"}]
         [:meta {:http-equiv "Content-type" :content "text/html; charset=utf-8"}]
         ;(page/include-css "http://torment.usersys.redhat.com/openjdk/style.css")]
-        (page/include-css "bootstrap.min.css")
-        (page/include-css "smearch.css")
-        (page/include-js  "bootstrap.min.js")
+        (page/include-css (str url-prefix "bootstrap.min.css"))
+        (page/include-css (str url-prefix "smearch.css"))
+        (page/include-js  (str url-prefix "bootstrap.min.js"))
     ] ; head
 )

@@ -26,8 +26,8 @@

 (defn render-search-field
     "Renders search box on the top side of HTML page."
-    [word]
-    (form/form-to {:class "navbar-form navbar-left" :role "search"} [:get "/" ]
+    [word url-prefix]
+    (form/form-to {:class "navbar-form navbar-left" :role "search"} [:get url-prefix ]
         [:div {:class "input-group"}
             [:span {:class "input-group-addon"} "Search"]
             (form/text-field {:size "40" :class "form-control" :placeholder "Search for word"} "word" (str word))
@@ -36,8 +36,8 @@

 (defn render-name-field
     "Renders box for typing user name on the top side of HTML page."
-    [user-name]
-    (form/form-to {:class "navbar-form navbar-left" :role "search"} [:get "/" ]
+    [user-name url-prefix]
+    (form/form-to {:class "navbar-form navbar-left" :role "search"} [:get url-prefix ]
         [:div {:class "input-group"}
             ;[:span {:class "input-group-addon"} "Name"]
             (form/text-field {:size "10" :class "form-control" :placeholder "User name"} "user-name" (str user-name))
@@ -46,35 +46,35 @@

 (defn render-navigation-bar-section
     "Renders whole navigation bar."
-    [word user-name]
+    [word user-name url-prefix]
     [:nav {:class "navbar navbar-inverse navbar-fixed-top" :role "navigation"}
         [:div {:class "container-fluid"}
             [:div {:class "row"}
                 [:div {:class "col-md-1"}
                     [:div {:class "navbar-header"}
-                        [:a {:href "/" :class "navbar-brand"} "zg"]
+                        [:a {:href url-prefix :class "navbar-brand"} "zg"]
                     ] ; ./navbar-header
                 ] ; col ends
                 [:div {:class "col-md-3"}
-                    (render-search-field word)
+                    (render-search-field word url-prefix)
                 ] ; col ends
                 [:div {:class "col-md-3"}
                     [:div {:class "navbar-header"}
-                        [:a {:href "/all-words" :class "navbar-brand"} "All words"]
-                    ] ; ./navbar-header
-                    [:div {:class "navbar-header"}
-                        [:a {:href "/active-words" :class "navbar-brand"} "Active words"]
-                    ] ; ./navbar-header
-                    [:div {:class "navbar-header"}
-                        [:a {:href "/deleted-words" :class "navbar-brand"} "Deleted words"]
+                        [:a {:href (str url-prefix "all-words") :class "navbar-brand"} "All words"]
+                    ] ; ./navbar-header
+                    [:div {:class "navbar-header"}
+                        [:a {:href (str url-prefix "active-words") :class "navbar-brand"} "Active words"]
+                    ] ; ./navbar-header
+                    [:div {:class "navbar-header"}
+                        [:a {:href (str url-prefix "deleted-words") :class "navbar-brand"} "Deleted words"]
                     ] ; ./navbar-header
                 ] ; col ends
                 [:div {:class "col-md-3"}
-                    (render-name-field user-name)
+                    (render-name-field user-name url-prefix)
                 ]
                 [:div {:class "col-md-1"}
                     [:div {:class "navbar-header"}
-                        [:a {:href "/users" :class "navbar-brand"} "Users"]
+                        [:a {:href (str url-prefix "users") :class "navbar-brand"} "Users"]
                     ] ; ./navbar-header
                 ] ; col ends
             ] ; row ends
@@ -83,12 +83,12 @@

 (defn render-error-page
     "Render error page with a 'back' button."
-    [word user-name message]
-    (page/xhtml
-        (render-html-header "")
-        [:body
-            [:div {:class "container"}
-                (render-navigation-bar-section word user-name)
+    [word user-name message url-prefix]
+    (page/xhtml
+        (render-html-header "" url-prefix)
+        [:body
+            [:div {:class "container"}
+                (render-navigation-bar-section word user-name url-prefix)
                 [:div {:class "col-md-10"}
                     [:h2 "Sorry, error occured in zg"]
                     [:p message]
@@ -103,10 +103,10 @@
 (defn render-front-page
     [word user-name search-results message url-prefix]
     (page/xhtml
-        (render-html-header word)
-        [:body
-            [:div {:class "container"}
-                (render-navigation-bar-section word user-name)
+        (render-html-header word url-prefix)
+        [:body
+            [:div {:class "container"}
+                (render-navigation-bar-section word user-name url-prefix)

                 (form/form-to [:post "/add-words"]
                         [:div {:class "label label-primary"} "New words"]
@@ -150,10 +150,10 @@
 (defn render-users
     [user-name statistic changes url-prefix]
     (page/xhtml
-        (render-html-header nil)
-        [:body
-            [:div {:class "container"}
-                (render-navigation-bar-section nil user-name)
+        (render-html-header nil url-prefix)
+        [:body
+            [:div {:class "container"}
+                (render-navigation-bar-section nil user-name url-prefix)

                 [:table {:class "table table-stripped table-hover" :style "width:auto"}
                     [:tr [:th "User name"]
@@ -181,10 +181,10 @@
 (defn render-user-info
     [user-name changes url-prefix]
     (page/xhtml
-        (render-html-header nil)
-        [:body
-            [:div {:class "container"}
-                (render-navigation-bar-section nil user-name)
+        (render-html-header nil url-prefix)
+        [:body
+            [:div {:class "container"}
+                (render-navigation-bar-section nil user-name url-prefix)
                 [:h1 (str "Changes made by " user-name)]

                 [:br]


Fix editor for advanced optimization mode

--- frontend/src-editor/editor/views/editor.cljs
+++ frontend/src-editor/editor/views/editor.cljs
@@ -54,8 +54,8 @@
 (defn is-not-in-sync? [editor]
   (let [old-path (stringify-path *path*)
         new-path (stringify-path (:editor-path editor))
+        new-value (:editor-content editor)
         old-value (or (codemirror-value) new-value)
-        new-value (:editor-content editor)
         unsaved? (has-unsaved-data?)]
     (and unsaved? (= old-path new-path) (not (= old-value new-value)))))

@@ -128,20 +128,21 @@
                         :foldGutter        true
                         :gutters           #js ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
                         :viewportMargin:   Infinity})
-          charWidth (.defaultCharWidth editor)
-          basePadding 4]
-      (.on editor "renderLine" (fn [cm, line, elt]
-                                 ; following code implements fancy indentation for wrapping text of json values
-                                 ; see https://codemirror.net/demo/indentwrap.html
-                                 (let [re-length (fn [re s]
-                                                   (let [re (js/RegExp. re "g")]
-                                                     (if-let [m (.exec re s)]
-                                                       (count (aget m 0))
-                                                       0)))
-                                       text (.-text line)
-                                       base-off (* (.countColumn js/CodeMirror text nil (.getOption cm "tabSize")) charWidth)
-                                       val-open-quote-pos (re-length "\".*\"\\: \"" text)
-                                       val-open-quote-offset (+ base-off (* val-open-quote-pos charWidth))]
-                                   (aset elt "style" "textIndent" (str "-" val-open-quote-offset "px"))
-                                   (aset elt "style" "paddingLeft" (str (+ basePadding val-open-quote-offset) "px")))))
+          char-width (.call (aget editor "defaultCharWidth") editor)
+          base-padding 4]
+      (.call (aget editor "on") editor "renderLine" (fn [cm, line, elt]
+                                                      ; following code implements fancy indentation for wrapping text of json values
+                                                      ; see https://codemirror.net/demo/indentwrap.html
+                                                      (let [re-length (fn [re s]
+                                                                        (let [re (js/RegExp. re "g")]
+                                                                          (if-let [m (.exec re s)]
+                                                                            (count (aget m 0))
+                                                                            0)))
+                                                            text (aget line "text")
+                                                            tab-size (.call (aget cm "getOption") cm "tabSize")
+                                                            base-off (* (.call (aget js/CodeMirror "countColumn") js/CodeMirror text nil tab-size) char-width)
+                                                            val-open-quote-pos (re-length "\".*\"\\: \"" text)
+                                                            val-open-quote-offset (+ base-off (* val-open-quote-pos char-width))]
+                                                        (aset elt "style" "textIndent" (str "-" val-open-quote-offset "px"))
+                                                        (aset elt "style" "paddingLeft" (str (+ base-padding val-open-quote-offset) "px")))))
       (set! *codemirror* editor))))


Don't trigger an airbrake when testing straight-jacket.

--- test/circle/util/test_straight_jacket.clj
+++ test/circle/util/test_straight_jacket.clj
@@ -1,11 +1,12 @@
 (ns circle.util.test-straight-jacket
   (:use midje.sweet)
-  (:use circle.util.straight-jacket))
-
+  (:use circle.util.straight-jacket)
+  (:require [circle.airbrake :as airbrake]))

 (fact "straight-jacket catches exceptions"
   (straight-jacket (throw (Exception. "test"))) => nil
   (provided
+    (airbrake/airbrake) => nil
     (circle.env/env) => :production))

@@ -21,9 +22,12 @@
     (circle.env/env) => :development))

-(fact "code still works in a straigth-jacket"
+(fact "code still works in a straight-jacket"
   (straight-jacket (+ 4 5)) => 9)

 (fact "straight-jacket catches assertions"
-  (straight-jacket (assert false)) => nil)+  (straight-jacket (assert false)) => nil
+  (provided
+    (airbrake/airbrake) => nil
+    (circle.env/env) => :production))


more tests

more tests

--- test/cljs/lisp_interpreter/core-test.cljs
+++ test/cljs/lisp_interpreter/core-test.cljs
@@ -233,3 +233,13 @@
     (is (= 4 (aget foo "a")))
     (is (= 5 (aget foo "b" "c")))
     (is (= 25 (aget foo "b" "x" "q")))))
+
+(deftest advanced-eval
+  (let [_(l/my-eval '(define my-inc (fn (x) (+ x 1))) atom-env)
+        _ (l/my-eval '(define my-dec (fn (x) (- x 1))) atom-env)
+        _ (l/my-eval '(define fun (fn (x) (my-dec (my-inc x)))) atom-env)
+        _ (l/my-eval '(define sum (fn(x y) (+ x y))) atom-env)]
+    (is (= 76 (l/my-eval '(fun 76) atom-env)))
+    (is (= 3 (l/my-eval '(my-inc 2) atom-env)))
+    (is (= 87 (l/my-eval '(my-dec 88) atom-env)))
+    (is (= 7 (l/my-eval '(sum 3 4) atom-env)))))


(PDB-4257) Test processing of unusual certnames after a restart

Now that we've fixed the metadata serialization and parsing
issues, add a test to try to make sure they stay fixed.

--- test/puppetlabs/puppetdb/command_test.clj
+++ test/puppetlabs/puppetdb/command_test.clj
@@ -47,7 +47,8 @@
             [slingshot.test]
             [puppetlabs.puppetdb.utils :as utils]
             [puppetlabs.puppetdb.time :as pt]
-            [puppetlabs.trapperkeeper.app :refer [get-service app-context]]
+            [puppetlabs.trapperkeeper.app  :as tk-app
+             :refer [get-service app-context]]
             [clojure.core.async :as async]
             [puppetlabs.kitchensink.core :as ks]
             [clojure.string :as str]
@@ -1653,6 +1654,50 @@
             (is (= (+ 3 (:total start-global)) (:total global)))
             (is (= (+ 3 (or (:total start-cmd) 0)) (:total cmd)))))))))

+(deftest handling-commands-producing-unusual-queue-names-across-restart
+  ;; Should also apply to a full server stop/start
+  (let [producer-ts (to-string (now))]
+    (svc-utils/with-puppetdb-instance
+      (let [dispatcher (get-service *server* :PuppetDBCommandDispatcher)
+            enqueue-command (partial enqueue-command dispatcher)
+            mod-cert "underscores_must_be_altered_for_the_queue"
+            long-cert (apply str (repeat (inc queue/max-metadata-utf8-bytes) "z"))
+            enqueue #(enqueue-command (command-names :replace-facts) 4 %
+                                      nil
+                                      (tqueue/coerce-to-stream
+                                       {:environment "DEV" :certname %
+                                        :values {:foo "foo"}
+                                        :producer_timestamp producer-ts})
+                                      "")]
+        (with-redefs [process-command-and-respond! (fn [& _]
+                                                     (throw (Exception. "prevent processing")))]
+          (enqueue mod-cert)
+          (enqueue long-cert)))
+      ;; Now start back up with a functional processor and make sure the commands
+      ;; can be found and processed.
+      (let [orig-process process-command-and-respond!
+            continue-processing? (promise)]
+        (with-redefs [process-command-and-respond! #(do
+                                                      @continue-processing?
+                                                      (apply orig-process %&))]
+          (tk-app/restart *server*)  ; have to restart -- stop/start doesn't work
+          (let [dispatcher (get-service *server* :PuppetDBCommandDispatcher)
+                response-mult (response-mult dispatcher)
+                response-watch-ch (async/chan 10)
+                _ (async/tap response-mult response-watch-ch)]
+            (deliver continue-processing? true)
+            (let [[val _] (async/alts!! [(async/into
+                                          #{} (async/take 2 response-watch-ch))
+                                         (async/timeout tu/default-timeout-ms)])]
+              (when-not val
+                (throw (Exception. "timed out waiting for response-chan")))
+              (is (= 2 (count val)))
+              (let [expected #{{:command "replace facts" :version 4
+                                 :producer-timestamp producer-ts :delete? nil}}]
+                (is (= expected
+                       (->> val
+                            (map #(select-keys % [:command :version :producer-timestamp :delete?]))
+                            set)))))))))))

 ;; Test mitigation of
 ;; https://bugs.openjdk.java.net/browse/JDK-8176254 i.e. handling of


Testing another set of points for spline

--- desktop/src-common/ds3/splines.clj
+++ desktop/src-common/ds3/splines.clj
@@ -26,11 +26,14 @@
         x1 (if x-left hook-near-x hook-width-near-x)
         x2 (if x-left hook-width-near-x hook-near-x)
         x3 (if x-left 0 (c/screen-to-world c/game-width))
+        x4 (if x-left (c/screen-to-world c/game-width) 0)
         ty (- y hook-near-x)
         dy (/ (- ty bottom-y) 5)
         points [[x y][x y][x (+ y hook-near-x)][(x-fn x hook-near-x) (+ y hook-near-x)][(x-fn x hook-near-x) ty]
                 [x1 (- ty dy)][x1 (- ty (* 2 dy))][x2 (- ty (* 3 dy))][x2 (- ty (* 4 dy))][x1 bottom-y][x3 (- hook-far-x)][x3 (- hook-far-x)]]
-        points-vec (points-to-vector-2 points)
+        points2 [[x y][x y][x (+ y hook-near-x)][(x-fn x hook-near-x) (+ y hook-near-x)][(x-fn x hook-near-x) ty]
+                [x1 (- ty dy)][x1 (- ty (* 3 dy))][x2 (- ty (* 4 dy))][x4 (- hook-far-x)][x4 (- hook-far-x)]]
+        points-vec (points-to-vector-2 points2)
         spline (b-spline points-vec 3 false)]
     spline))


added comment

added comment

--- sidecar/src/figwheel_sidecar/core.clj
+++ sidecar/src/figwheel_sidecar/core.clj
@@ -416,6 +416,7 @@
       (file-changed? state df)))
   (:file-md5-atom state))

+;; remove resource paths here
 (defn create-initial-state [{:keys [root name version resource-paths
                                     css-dirs ring-handler http-server-root
                                     server-port output-dir output-to


Update nightcode

Update nightcode

--- desktop/project.clj
+++ desktop/project.clj
@@ -6,7 +6,7 @@
                  [com.badlogicgames.gdx/gdx-platform "0.9.9"
                   :classifier "natives-desktop"]
                  [com.cemerick/pomegranate "0.3.0"]
-                 [nightcode "0.3.0"
+                 [nightcode "0.3.1"
                   :exclusions [leiningen
                                lein-ancient
                                lein-cljsbuild


fix db-pre-migration not running on postgres

--- src/metabase/db.clj
+++ src/metabase/db.clj
@@ -212,11 +212,12 @@

    see https://github.com/metabase/metabase/issues/3715"
   [conn]
-  (let [fresh-install? (jdbc/with-db-metadata [meta (jdbc-details)] ;; don't migrate on fresh install
-                         (empty? (jdbc/metadata-query (.getTables meta nil nil "DATABASECHANGELOG" (into-array String ["TABLE"])))))
-        query (if (= (db-type) :h2)
-                "UPDATE DATABASECHANGELOG SET FILENAME = ?"
-                "UPDATE databasechangelog SET filename = ?")]
+  (let [liquibases-table-name (if (= (db-type) :h2)
+                                "DATABASECHANGELOG"
+                                "databasechangelog")
+        fresh-install? (jdbc/with-db-metadata [meta (jdbc-details)] ;; don't migrate on fresh install
+                         (empty? (jdbc/metadata-query (.getTables meta nil nil liquibases-table-name (into-array String ["TABLE"])))))
+        query (format "UPDATE %s SET FILENAME = ?" liquibases-table-name)]
     (when-not fresh-install?
       (jdbc/execute! conn [query "migrations/000_migrations.yaml"]))))


cleaning macros (thx @DomKM)

cleaning macros (thx @DomKM)

removing reader conditionals from defstate, since this part of the macro is compiled by clojure (not cljs)

adding ":require-macros [mount.core :refer [defstate]]" to itself (mount.core) to obviate a need for mount clients to do ":require-macros"

--- src/mount/core.cljc
+++ src/mount/core.cljc
@@ -2,7 +2,8 @@
   #?(:clj (:require [mount.tools.macro :refer [on-error throw-runtime] :as macro])
      :cljs (:require [mount.tools.macro :as macro]
                      [mount.tools.cljs :as cljs]))
-  #?(:cljs (:require-macros [mount.tools.macro :refer [on-error throw-runtime]])))
+  #?(:cljs (:require-macros [mount.tools.macro :refer [on-error throw-runtime]]
+                            [mount.core :refer [defstate]])))

 (defonce ^:private -args (atom :no-args))                  ;; mostly for command line args and external files
 (defonce ^:private state-seq (atom 0))
@@ -130,8 +131,7 @@
 (defmacro defstate [state & body]
   (let [[state params] (macro/name-with-attributes state body)
         {:keys [start stop suspend resume] :as lifecycle} (apply hash-map params)
-        state-name (with-ns #?(:clj *ns*
-                               :cljs (cljs/this-ns)) state)      ;; on cljs side (cljs.analyzer/*cljs-ns*) may do it, but still might not be good for :advanced
+        state-name (with-ns *ns* state)
         order (make-state-seq state-name)
         sym (str state)]
     (validate lifecycle)


Added :height to scroller

Added :height to scroller

--- src/re_com/box.cljs
+++ src/re_com/box.cljs
@@ -415,6 +415,7 @@
    {:name :h-scroll        :required false                   :type "keyword"  :description "see :scroll. Overrides that setting."}
    {:name :v-scroll        :required false                   :type "keyword"  :description "see :scroll. Overrides that setting."}
    {:name :width           :required false                   :type "string"   :description "Initial width."}
+   {:name :height          :required false                   :type "string"   :description "Initial height."}
    {:name :min-width       :required false                   :type "string"   :description "a CSS width style. The minimum width to which the box can shrink."}
    {:name :min-height      :required false                   :type "string"   :description "a CSS height style. The minimum height to which the box can shrink."}
    {:name :justify         :required false :default :start   :type "keyword"  :description "one of :start, :end, :center, :between and :around."}


Add schema annotations to nodes.

Add schema annotations to nodes.

--- src/shale/nodes.clj
+++ src/shale/nodes.clj
@@ -43,12 +43,9 @@
 (defn node-tags-key [id]
   (format node-tags-key-template id))

-(defn node-ids []
-  (with-car* (car/smembers node-set-key)))
-
 (defn uuid [] (str (java.util.UUID/randomUUID)))

-(defn node-ids []
+(s/defn node-ids :- [s/Str] []
   (with-car* (car/smembers node-set-key)))

 (def NodeInRedis
@@ -62,7 +59,8 @@
    (s/optional-key :url)   s/Str
    (s/optional-key :tags) [s/Str]})

-(defn view-model [id]
+(s/defn view-model :- NodeView
+  [id :- s/Str]
   (let [node-key (node-key id)
         node-tags-key (node-tags-key id)
         [contents tags] (with-car*
@@ -71,16 +69,17 @@
     (keywordize-keys
       (assoc (apply hash-map contents) :tags (or tags []) :id id))))

-(defn view-models []
-  (s/validate [NodeView] (map view-model (node-ids))))
+(s/defn view-models :- [NodeView] []
+  (map view-model (node-ids)))

-(defn view-model-from-url [url]
-  (s/validate s/Str url)
-  (s/validate NodeView (first (filter #(= (% :url) url) (view-models)))))
+(s/defn view-model-from-url :- NodeView
+  [url :- s/Str]
+  (first (filter #(= (% :url) url) (view-models))))

-(defn modify-node [id {:keys [url tags]
-                       :or {:url nil
-                            :tags nil}}]
+(s/defn modify-node :- NodeView
+  [id {:keys [url tags]
+       :or {:url nil
+            :tags nil}}]
   (last
     (with-car*
       (let [node-key (node-key id)
@@ -89,9 +88,10 @@
         (if tags (sset-all node-tags-key tags))
         (car/return (view-model id))))))

-(defn create-node [{:keys [url
-                           tags]
-                    :or {:tags []}}]
+(s/defn create-node :- NodeView
+  [{:keys [url
+           tags]
+    :or {:tags []}}]
   (last
     (with-car*
       (let [id (uuid)
@@ -100,8 +100,7 @@
         (modify-node id {:url url :tags tags})
         (car/return (view-model id))))))

-(defn destroy-node [id]
-  (s/validate s/Str id)
+(s/defn destroy-node [id :- s/Str]
   (with-car*
     (car/watch node-set-key)
     (try
@@ -130,11 +129,12 @@
              (difference registered-nodes nodes)))))
   true)

-(defn get-node [{:keys [url
-                        tags]
-                 :or {:url nil
-                      :tags []}
-                 :as requirements}]
+(s/defn get-node :- (s/maybe NodeView)
+  [{:keys [url
+           tags]
+    :or {:url nil
+         :tags []}
+    :as requirements}]
   (let [matches-requirements (fn [model]
                                (apply clojure.set/subset?
                                       (map #(select-keys % [:url :tags])


CMR-1843: Removed an unnecessary comment.

--- umm-spec-lib/src/cmr/umm_spec/test/umm_generators.clj
+++ umm-spec-lib/src/cmr/umm_spec/test/umm_generators.clj
@@ -59,9 +59,7 @@
                 ;; Generate a hash map containing the properties
                 prop-map (apply gen/hash-map (flatten (seq selected-prop-gens)))]
                ;; Construct a record from the hash map
-               ; (when (seq (util/remove-nil-keys prop-map))
-                 (constructor-fn prop-map))))
-; )
+               (constructor-fn prop-map))))

 (defn- assert-field-not-present-with-one-of
   [schema-type k]


See what pushing visit-recent back does

See what pushing visit-recent back does

--- src/mars_ogler/routes.clj
+++ src/mars_ogler/routes.clj
@@ -51,7 +51,8 @@
         visit-start (if (nil? visit-start) now (Long/parseLong visit-start))
         visit-recent (if (nil? visit-recent) now (Long/parseLong visit-recent))]
     (if (> (- now visit-recent) (* 10 60 1000))
-      [visit-recent now now]
+      ;; curiositymsl.com updates every 15 minutes, and we scrape every minute
+      [(- visit-recent (* 16 60 1000)) now now]
       [visit-last visit-start now])))

 (defn set-expires


removed unnecessary public vars

removed unnecessary public vars

--- src/midje/util/report.clj
+++ src/midje/util/report.clj
@@ -23,15 +23,16 @@
 (defn note-failure-in-fact
   ([] (note-failure-in-fact true))
   ([val] (alter-var-root #'*failure-in-fact* (constantly val))))
-(defn fact-begins []
-  (note-failure-in-fact false))
-(defn fact-checks-out? [] (not *failure-in-fact*))
-

 (defn form-providing-friendly-return-value [test-form]
-  `(do (fact-begins)
+  `(letfn [(fact-begins# []
+            (note-failure-in-fact false))
+           (fact-checks-out?# []
+             (not *failure-in-fact*))]
+     (do
+       (fact-begins#)
        ~test-form
-       (fact-checks-out?)))
+       (fact-checks-out?#))))

 (defn midje-position-string [[filename line-num]]
   (format "(%s:%s)" filename line-num))


Fix empty stage case.

Fix empty stage case.

--- src/topiq/core.cljs
+++ src/topiq/core.cljs
@@ -6,6 +6,7 @@
             [replikativ.stage :as s]
             [replikativ.crdt.cdvcs.realize :refer [commit-history-values trans-apply summarize-conflict]]
             [replikativ.crdt.cdvcs.stage :as sc]
+            [replikativ.crdt.materialize :refer [key->crdt]]
             [replikativ.peer :refer [client-peer]]
             [replikativ.crdt :refer [map->CDVCS]]
             [konserve.memory :refer [new-mem-store]]
@@ -182,8 +183,9 @@
       ;; HACK for single commit ops to work with commit-history-values by setting commit as root
       (when-not (applied new-heads)
         (let [cg (if (= 1 (count cg)) (assoc cg (first new-heads) []) cg)
-              cdvcs (get-in @stage [(get-in @stage [:config :user])
-                                    #uuid "26558dfe-59bb-4de4-95c3-4028c56eb5b5" :state])
+              cdvcs (or (get-in @stage [(get-in @stage [:config :user])
+                                        #uuid "26558dfe-59bb-4de4-95c3-4028c56eb5b5" :state])
+                        (key->crdt :cdvcs))
               heads (:heads (-downstream cdvcs pub))]
           (cond (= 1 (count heads))
                 (let [txs (mapcat :transactions (<! (commit-history-values store cg (first new-heads))))]


Refactor blob-store initialization in tool.clj.

--- src/mvxcvi/vault/tool.clj
+++ src/mvxcvi/vault/tool.clj
@@ -20,29 +20,39 @@
                      "/.config/vault/blob-stores.edn")})

+(def ^:private config-readers
+  "Map of EDN readers for supported types in config files."
+  {'vault/file-store (partial apply file-store)})

-;; BLOB STORES
+
+
+;; BLOB STORAGE
+
+(defn- select-blob-store
+  [stores selection]
+  (->> (or selection :default)
+       (iterate stores)
+       (drop-while keyword?)
+       first))
+

 (defn- initialize-blob-stores
   [opts]
   (try
     (let [config (slurp (:blob-stores config-paths))
-          edn-readers {'vault/file-store (partial apply file-store)}
-          stores (edn/read-string {:readers edn-readers} config)]
-      (assoc opts :blob-stores stores))
+          stores (edn/read-string {:readers config-readers} config)
+          store (select-blob-store stores (:store opts :default))]
+      (assoc opts :blob-stores stores :store store))
     (catch java.io.FileNotFoundException e
       (assoc opts :blob-stores {}))))

-(defn- get-blob-store
-  "Returns the selected blob-store (as opposed to its keyword nickname)."
+(defn- require-blob-store
   [opts]
-  (let [blob-stores (:blob-stores opts)
-        nickname (:store opts :default)]
-    (loop [store (blob-stores nickname)]
-      (if (keyword? store)
-        (recur (blob-stores store))
-        store))))
+  (when-not (:store opts)
+    (println "No blob-store initialized.")
+    (System/exit 1))
+  opts)

 (defn- list-blob-stores
@@ -63,6 +73,8 @@
   (command "vault [global opts] <command> [command args]"
     "Command-line tool for the vault data store."

+    ["--store" "Select blob store to use."
+     :parse-fn keyword]
     ["-v" "--verbose" "Show extra debugging messages."
      :flag true :default false]
     ["-h" "--help" "Show usage information."
@@ -80,14 +92,7 @@
     (command "blob <action> [args]"
       "Blob storage command."

-      ["--store" "Select blob store to use."]
-
-      (init [opts]
-        (let [store (get-blob-store opts)]
-          (when-not store
-            (println "No blob-store initialized.")
-            (System/exit 1))
-          (assoc opts :store store)))
+      (init require-blob-store)

       (command "list [opts]"
         "Enumerate the stored blobs."


Do not re-use constructors

Do not re-use constructors

According to the docs, the Yaml and by extension the constructor objects are not
thread-safe. We should avoid sharing them.

See [docs](https://bitbucket.org/asomov/snakeyaml/wiki/Documentation#markdown-header-threading)

--- src/yaml/reader.clj
+++ src/yaml/reader.clj
@@ -7,12 +7,12 @@
           [org.yaml.snakeyaml.composer ComposerException]))

 (def ^:dynamic *keywordize* true)
-(def ^:dynamic *constructor* (Constructor.))
+(def ^:dynamic *constructor* (fn [] (Constructor.)))
 (def passthrough-constructor
   "Custom constructor that will not barf on unknown YAML tags. This constructor
   will treat YAML objects with unknown tags with the underlying type (i.e. map,
   sequence, scalar) "
-  (PassthroughConstructor.))
+  (fn [] (PassthroughConstructor.)))

 (defprotocol YAMLReader
   (decode [data]))
@@ -52,7 +52,7 @@
    docs and return a vector containing each document"
   [^String yaml-documents]
   (mapv decode
-    (.loadAll (Yaml. *constructor*) yaml-documents)))
+    (.loadAll (Yaml. (*constructor*)) yaml-documents)))

 (defn parse-string
   "Parse a yaml input string. If multiple documents are found it will return a vector of documents
@@ -60,13 +60,14 @@
   When keywords is a true (default), map keys are converted to keywords. When
   keywords is a function, invokes the function on the map keys.

-  When a custom :constructor is provided, it's used to construct objects.
+  When a custom :constructor is provided, it's used to construct objects. Should
+  be a 0-arity function that returns a constructor.
   "
   [^String string & {:keys [keywords constructor]
                      :or   {keywords    *keywordize*
                             constructor *constructor*}}]
   (binding [*keywordize* keywords]
     (try
-      (decode (.load (Yaml. constructor) string))
+      (decode (.load (Yaml. (constructor)) string))
       (catch ComposerException e
         (parse-documents string)))))


stop live mode before starting acquisition

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

--- acqEngine/src/org/micromanager/acq_engine.clj
+++ acqEngine/src/org/micromanager/acq_engine.clj
@@ -497,7 +497,8 @@
       ;(proxy [TaggedImageAnalyzer] []
         ;(analyze [img] (log "pretending to analyze"))))
     (when-not (:stop @(.state this))
-      (. gui enableLiveMode false)
+      (if (. gui isLiveModeOn)
+        (. gui enableLiveMode false))
       (.start acq-thread)
       (swap! (.state this) assoc :display display)
       (.start display))))


fix bug that only appeared on spinning disk

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

--- acqEngine/src/org/micromanager/acq_engine.clj
+++ acqEngine/src/org/micromanager/acq_engine.clj
@@ -473,7 +473,7 @@

 (defn z-stage-needs-adjustment [stage-name]
   (or (not (@state :init-continuous-focus))
-      ;(not (core isContinuousFocusEnabled))
+      (not (core isContinuousFocusEnabled))
       (core isContinuousFocusDrive stage-name)))

 (defn update-z-positions [msp-index]


don't re-set position if it isn't changing

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

--- acqEngine/src/org/micromanager/acq_engine.clj
+++ acqEngine/src/org/micromanager/acq_engine.clj
@@ -227,19 +227,23 @@
       (zipmap devs (repeatedly (count devs) #(agent nil))))))

 (defn get-z-stage-position [stage]
-  (if (pos? (count stage)) (core getPosition stage) 0))
+  (when-not (empty? stage) (core getPosition stage) 0))

 (defn set-z-stage-position [stage pos]
   (when (core isContinuousFocusEnabled)
     (core enableContinuousFocus false))
-  (when (pos? (count stage)) (core setPosition stage pos)))
+  (when-not (empty? stage) (core setPosition stage pos)))

 (defn set-stage-position
-  ([stage-dev z] (log "setting z position to " z)
-     (set-z-stage-position stage-dev z)
-     (state-assoc! :last-z-position z))
-  ([stage-dev x y] (log "setting x,y position to " x "," y)
-                   (when (and x y) (core setXYPosition stage-dev x y))))
+  ([stage-dev z]
+    (when (not= z (:last-z-position @state))
+      (set-z-stage-position stage-dev z)
+      (state-assoc! :last-z-position z)))
+  ([stage-dev x y]
+    (when (and x y
+               (not= [x y] (:last-xy-position @state)))
+      (core setXYPosition stage-dev x y)
+      (state-assoc! :last-xy-position [x y]))))

 (defn set-property
   ([prop] (core setProperty (prop 0) (prop 1) (prop 2))))
@@ -391,7 +395,8 @@
       :running true
       :finished false
       :last-wake-time (clock-ms)
-      :last-z-position z
+      :last-z-position nil
+      :last-xy-position nil
       :reference-z-position z
       :start-time (clock-ms)
       :init-auto-shutter (core getAutoShutter)


cleanup

cleanup


Indentation fix

Indentation fix


Make run-row commit sha clickable

Make run-row commit sha clickable

--- src-cljs/frontend/components/pages/workflow.cljs
+++ src-cljs/frontend/components/pages/workflow.cljs
@@ -6,6 +6,7 @@
             [frontend.components.pieces.icon :as icon]
             [frontend.components.templates.main :as main-template]
             [frontend.datetime :as datetime]
+            [frontend.models.build :as build-model]
             [frontend.routes :as routes]
             [frontend.utils :refer-macros [component element html]]
             [frontend.utils.github :as gh-utils]
@@ -38,6 +39,18 @@
          [:a {:href url}
           "#"
           (gh-utils/pull-request-number url)]))])))
+
+(defn- commit-link
+  "Om Next compatible version of `frontend.components.builds-table/commits`."
+  [sha]
+  (html
+   (when sha
+     (let [pretty-sha (build-model/github-revision {:vcs_revision sha})]
+       [:span.metadata-item.revision
+        [:i.octicon.octicon-git-commit]
+        [:a {:title pretty-sha
+             :href (build-model/commit-url {:vcs_revision sha})}
+         pretty-sha]]))))

 ;; TODO: Move this to pieces.*, as it's used on the run page as well.
 (defui ^:once RunRow
@@ -118,10 +131,7 @@
                   "-")]]
               [:div.metadata-row.pull-revision
                (run-prs pull-requests)
-               [:span.metadata-item.revision
-                [:i.octicon.octicon-git-commit]
-                (when commit-sha
-                 [:a (subs commit-sha 0 7)])]]]
+               (commit-link commit-sha)]]
              [:div.actions
               (button/icon {:label "Stop this workflow"
                             :disabled? true}


view entities of a single type in the workspace data tab (temporary solution)

--- src/cljs/org/broadinstitute/firecloud_ui/page/workspaces.cljs
+++ src/cljs/org/broadinstitute/firecloud_ui/page/workspaces.cljs
@@ -121,6 +121,33 @@
                           "Me"])
                     filtered-workspaces)})])]))})

+(react/defc EntitiesList
+  {:render
+   (fn [{:keys [props]}]
+     [:div {:style {:padding "0 4em"}}
+      (if (zero? (count (:entities props)))
+        [:div {:style {:textAlign "center" :backgroundColor (:background-gray style/colors)
+                       :padding "1em 0" :borderRadius 8}}
+         "No entities to display."]
+        [table/Table
+         (let [cell-style {:flexBasis "8ex" :flexGrow 1 :whiteSpace "nowrap" :overflow "hidden"
+                           :borderLeft (str "1px solid " (:line-gray style/colors))}
+               header-label (fn [text & [padding]]
+                              [:span {:style {:paddingLeft (or padding "1em")}}
+                               [:span {:style {:fontSize "90%"}} text]])]
+           {:columns [{:label (header-label "Entity Type")
+                       :style (merge cell-style {:borderLeft "none"})}
+                      {:label (header-label "Entity Name")
+                       :style cell-style
+                       :header-style {:borderLeft "none"}}
+                      {:label (header-label "Attributes")
+                       :style (merge cell-style {:flexBasis "30ex"})
+                       :header-style {:borderLeft "none"}}]
+            :data (map (fn [m]
+                         [(m "entityType") ;;properly map to entities after
+                          (m "name")
+                          (m "attributes")])
+                       (:entities props))})])])})

 (react/defc FilterButtons
   (let [Button
@@ -153,6 +180,43 @@
           [Button {:text (build-text "Exception" :exception) :state state :filter :exception}]
           [:div {:style {:clear "both"}}]]))}))

+(react/defc EntityFilterButtons
+            (let [Button
+                  (react/create-class
+                    {:render
+                     (fn [{:keys [props]}]
+                       [:div {:style {:float "left"
+                                      :backgroundColor (if (:active? props)
+                                                         (:button-blue style/colors)
+                                                         (:background-gray style/colors))
+                                      :color (when (:active? props) "white")
+                                      :marginLeft "1em" :padding "1ex" :width "16ex"
+                                      :border (str "1px solid " (:line-gray style/colors))
+                                      :borderRadius "2em"
+                                      :cursor "pointer"}}
+                        (:text props)])})]
+              {:render
+               (fn []
+                 [:div {:style {:display "inline-block" :marginLeft "-1em"}}
+                  [Button {:text "sample" :active? true}]
+                  [Button {:text "aliquot"}]
+                  [Button {:text "all"}]
+                  [:div {:style {:clear "both"}}]])}))
+
+(defn- contains-text [text fields]
+  (fn [entity]
+    (some #(not= -1 (.indexOf (entity %) text)) fields)))
+
+(defn- filter-entities [entities fields text]
+  (filter (contains-text text fields) entities))
+
+(defn- create-mock-entities []
+  (map
+    (fn [i]
+      {:entityType (rand-nth ["sample"])
+       :name (str "entity" (inc i))
+       :attributes (str "entity" (inc i) " has no attributes")})
+    (range (rand-int 20))))

 (defn- modal-background [state]
   {:backgroundColor "rgba(82, 129, 197, 0.4)"
@@ -282,12 +346,17 @@
     (create-paragraph [:em {} "Billing account not available yet"])]
    [:div {:style {:clear "both"}}]])

-(defn- render-selected-workspace [workspace]
+(defn- render-workspace-data [entities]
+  [:div {:style {:padding "2em 0" :textAlign "center"}}
+   [EntityFilterButtons]
+  [:div {:style {:padding "2em 0"}} [EntitiesList {:entities entities}]]])
+
+(defn- render-selected-workspace [workspace entities]
   [:div {}
    (if workspace
      [comps/TabBar {:key "selected"
                     :items [{:text "Summary" :component (render-workspace-summary workspace)}
-                            {:text "Data"}
+                            {:text "Data" :component (render-workspace-data entities)}
                             {:text "Methods"}
                             {:text "Monitor"}
                             {:text "Files"}]}]
@@ -358,7 +427,7 @@
             :onClick #(swap! state assoc :overlay-shown? true)}]]
          [:span {:style {:fontSize "180%"}} (if selected-ws-name selected-ws-name "Workspaces")]]
         (cond
-          selected-ws-name (render-selected-workspace selected-ws)
+          selected-ws-name (render-selected-workspace selected-ws (:entities @state))
           (:workspaces-loaded? @state) (render-workspaces-list state nav-context)
           (:error @state) (style/create-server-error-message (get-in @state [:error :message]))
           :else [comps/Spinner {:text "Loading workspaces..."}])]))
@@ -376,4 +445,15 @@
                      (swap! state assoc
                             :error {:message (.-statusText xhr)})))
         :canned-response {:responseText (utils/->json-string (create-mock-workspaces))
-                          :status 200 :delay-ms (rand-int 2000)}}))})
+                          :status 200 :delay-ms (rand-int 2000)}})
+     (utils/ajax-orch
+       "/workspaces/broad-dsde-dev/testws/entities/sample"
+       {:on-done (fn [{:keys [success? xhr]}]
+                   (if success?
+                     (let [entities (utils/parse-json-string (.-responseText xhr))]
+                       (swap! state assoc :entities-loaded? true
+                              :entities entities))
+                     (swap! state assoc :error-message (.-statusText xhr))))
+        :canned-response {:responseText (utils/->json-string (create-mock-entities))
+                          :status 200
+                          :delay-ms (rand-int 2000)}}))})


Make pagination links actual links.

Make pagination links actual links.

--- src/cljs/clj_templates/pages/templates/page.cljs
+++ src/cljs/clj_templates/pages/templates/page.cljs
@@ -21,8 +21,8 @@

 (defn pagination-link [page current-page-index]
   (let [page-active? (= page current-page-index)]
-    [:div.pagination-link {:class    (when page-active? "current-page")
-                           :on-click (when-not page-active? #(dispatch [:templates/page-change page]))}
+    [:a.pagination-link {:class    (when page-active? "current-page")
+                         :on-click (when-not page-active? #(dispatch [:templates/page-change page]))}
      page]))

 (defn pagination [page-count]


Add some controls to tunes mode.

Add some controls to tunes mode.

--- src/clojure/playasophy/wonderdome/mode/tunes.clj
+++ src/clojure/playasophy/wonderdome/mode/tunes.clj
@@ -129,11 +129,29 @@
              :bands (mapv #(update-energy %1 %2 smoothing)
                           bands (:spectrum event)))

-      [:button/press :A]
+      [:button/press :L]
       (do (reset! log-next? true)
           this)

-      ; TODO: add controls for adjusting gain, decay, rotation-rate, shift-rate
+      [:button/press :A]
+      (update this :decay #(ctl/bound [0.1 10.0] (* 1.1 %)))
+
+      [:button/press :B]
+      (update this :decay #(ctl/bound [0.1 10.0] (* 0.9 %)))
+
+      [:axis/direction :x-axis]
+      (update this :rotation-rate
+              ctl/adjust event
+              :rate 0.2
+              :min-val -2.0
+              :max-val 2.0)
+
+      [:axis/direction :y-axis]
+      (update this :shift-rate
+              ctl/adjust event
+              :rate 0.2
+              :min-val -5.0
+              :max-val 5.0)

       ; default
       this))


Add clickable lines.

Add clickable lines.

--- src/constraint/core.cljs
+++ src/constraint/core.cljs
@@ -9,8 +9,8 @@
     :viewBox "0 0 10 10"
     :refX "1"
     :refY "5"
-    :markerWidth "6"
-    :markerHeight "6"
+    :markerWidth "3"
+    :markerHeight "3"
     :orient "auto"}
    [:svg:path {:d "M0,0 L 10,5 L0,10 z"}]]
   )
@@ -23,9 +23,10 @@

 (defn line [from to color]
   [:svg:path
-   {:d (make-line-dirs from to)
+   {:id "clickthis"
+    :d (make-line-dirs from to)
     :stroke color
-    :stroke-width "4px"
+    :stroke-width "10px"
     :fill "none"
     :marker-mid "url(#Triangle)"}])

@@ -42,14 +43,21 @@
                                          :cx 50 :cy 50
                                          :r 50}]]))

+(defn e->tid [e]
+  (-> e
+      (js->clj)
+      (.-target)
+      (.-id)))
+
 (defn click-handler [e]
+  (.log js/console (e->tid e))
   (js/alert "123"))

-(dommy.core/listen! (dommy.core/sel1 :circle) :click click-handler)
+(map #(dommy.core/listen! % :click click-handler) (dommy.core/sel :#clickthis))

-(dommy.core/append (dommy.core/parent (dommy.core/sel1 :circle))
-                   (crate/html
-                     [:svg:line]))
+; (dommy.core/append (dommy.core/parent (dommy.core/sel1 :circle))
+;                    (crate/html
+;                      [:svg:line]))


remove planck reference

remove planck reference

--- ClojureScript/replete/src/replete/repl.cljs
+++ ClojureScript/replete/src/replete/repl.cljs
@@ -430,8 +430,7 @@
     (let [file-source (js/REPLETE_LOAD filepath)]
       (or file-source
           (js/REPLETE_LOAD (s/replace filepath #"^out/" ""))
-          (js/REPLETE_LOAD (s/replace filepath #"^src/" ""))
-        (js/REPLETE_LOAD (s/replace filepath #"^/.*/planck-cljs/src/" ""))))))
+          (js/REPLETE_LOAD (s/replace filepath #"^src/" ""))))))

 (defn- fetch-source
   [var]


jobs/genhtml.clj: use jobconf for system properties

--- src/org/altlaw/jobs/genhtml.clj
+++ src/org/altlaw/jobs/genhtml.clj
@@ -3,6 +3,11 @@
             [org.altlaw.www.case-pages :as cases]))

 (hadoop/setup-mapreduce)
+
+(defn mapper-configure [this jobconf]
+  (alter-var-root #'org.altlaw.util.context/get-property
+                  (fn [_] (fn [name] (or (.get jobconf name)
+                                         (throw (Exception. (str "Missing property " name))))))))

 (defn mapper-map [this wkey wvalue output reporter]
   (let [docid (.get wkey)


Renamed

Renamed

--- src/demo/xa.clj
+++ src/demo/xa.clj
@@ -38,7 +38,7 @@
 (defn attempt-transaction [name & [f]]
   (try
     (xa/transaction
-     (write-thing-to-db name)
+     (write-thing name)
      (msg/publish "/queue/xa" name)
      (cache/put cache :name name)
      (tx/not-supported


core text

core text

--- src/selectscript/core.clj
+++ src/selectscript/core.clj
@@ -52,13 +52,39 @@
    ;; A boolean option defaulting to nil
    ["-h" "--help"]])

+
+
+;     _          _                    _                _
+;    | |        | |           _      | |              (_)      _
+;    \ \   ____| | ____ ____| |_     \ \   ____  ____ _ ____ | |_
+;     \ \ / _   |/ _   ___  _     \ \ / ___/ ___ |  _ \|  _]]
+;  _____) | (/ /| ( (/ ( (___| |__ _____) | (___| |   | | | | | |__
+;(______/ \____)_|\________\___|______/ \_____|   |_| ||_/ \___
+;                                                      |_|]])
+
+
+; __   ___       ___  __  ___  __   __   __     __  ___
+;/__` |__  |    |__  /  `  |  /__` /  ` |__  | |__)  |
+;.__/ |___ |___ |___ \__,  |  .__/ \__, |  \ | |     |
+
+
+;"  __,      _          __,                     "
+;" (        //      _/_(           o     _/_  "
+;"  `.  _  // _  _, /   `.  _, _  , ,_   /    "
+;"(___)(/_(/_(/_(__(__(___)(__/ _(_/|_)_(__   "
+;"                                    |         "
+
+
+
+
 (defn -main [& args]
-  (println "  ███████╗███████╗██╗     ███████╗ ██████╗████████╗███████╗ ██████╗██████╗ ██╗██████╗ ████████╗")
-  (println "  ██╔════╝██╔════╝██║     ██╔════╝██╔════╝╚══██╔══╝██╔════╝██╔════╝██╔══██╗██║██╔══██╗╚══██╔══╝")
-  (println "  ███████╗█████╗  ██║     █████╗  ██║        ██║   ███████╗██║     ██████╔╝██║██████╔╝   ██║   ")
-  (println "  ╚════██║██╔══╝  ██║     ██╔══╝  ██║        ██║   ╚════██║██║     ██╔══██╗██║██╔═══╝    ██║   ")
-  (println "  ███████║███████╗███████╗███████╗╚██████╗   ██║   ███████║╚██████╗██║  ██║██║██║        ██║   ")
-  (println "  ╚══════╝╚══════╝╚══════╝╚══════╝ ╚═════╝   ╚═╝   ╚══════╝ ╚═════╝╚═╝  ╚═╝╚═╝╚═╝        ╚═╝   ")
+  (println " o-o      o           o   o-o                   o ")
+  (println "|         |           |  |              o       | ")
+  (println " o-o  o-o | o-o  o-o -o-  o-o   o-o o-o   o-o  -o-")
+  (println "    | |-' | |-' |     |      | |    |   | |  |  | ")
+  (println "o--o  o-o o o-o  o-o  o  o--o   o-o o   | O-o   o ")
+  (println "                                          |       ")
+  (println "                                          o       ")
   (println)

   (let [{:keys [options arguments errors summary]} (parse-opts args cli-options)]


comp q3

comp q3

--- q3.clj
+++ q3.clj
@@ -1,8 +1,19 @@
 (def N 100)
+(def start-num 2)
 (def cards (for [x (range 1 (inc N)) y [false]] [x y]))

-(defn reverse-cars [cards num]
+(defn reverse-cards [cards num]
   (map #(if (= 0 (mod (first %) num))
             [(first %) (not (second %))]
             %)
        cards))
+
+(defn reverse [cards num]
+  (if (= num N)
+      (reverse-cards cards num)
+      (reverse (reverse-cards cards num) (inc num))))
+
+(defn get-answer []
+  (map #(first %)
+      (filter #(not (second %))
+              (reverse cards start-num))))


separate interactive stroke from interactive fill

--- src-cljs/frontend/components/canvas.cljs
+++ src-cljs/frontend/components/canvas.cljs
@@ -121,7 +121,10 @@
                                                                   :onMouseUp (when (and (= :text tool)
                                                                                (= :layer.type/text (:layer/type layer)))
                                                                                #(.stopPropagation %))
-                                                                  :className (when (= :text tool) "editable")
+                                                                  :className (str (when (= :text tool) "editable ")
+                                                                                (and (when (= :select tool))
+                                                                                (:layer/ui-target layer)
+                                                                                "interactive-stroke"))
                                                                   :key (:db/id layer)))
                                      (when (= :select tool)
                                        (svg-element selected-eids
@@ -200,7 +203,7 @@
                                                                          :canvas-size (let [size (goog.style/getSize (sel1 "#svg-canvas"))]
                                                                                {:width (.-width size)
                                                                                :height (.-height size)})})))
-                                                :className (str "action interactive-layer "
+                                                :className (str "action interactive-fill "
                                                                 (when (and (< 1 (count selected-eids))
                                                                            (contains? selected-eids (:db/id layer)))
                                                                   "selected-group ")


update instead of assoc

update instead of assoc

--- src-cljs/frontend/controllers/controls.cljs
+++ src-cljs/frontend/controllers/controls.cljs
@@ -424,9 +424,8 @@

 (defmethod control-event :overlay-info-toggled
   [target message _ state]
-  (let [overlay-info-open? (not (get-in state state/overlay-info-opened-path))]
-    (-> state
-        (assoc-in state/overlay-info-opened-path overlay-info-open?))))
+  (-> state
+      (update-in state/overlay-info-opened-path not)))

 (defmethod post-control-event! :application-shutdown
   [target message _ previous-state current-state]


fix inc-ing ui-target when layers are duplicated

--- src-cljs/frontend/controllers/controls.cljs
+++ src-cljs/frontend/controllers/controls.cljs
@@ -336,19 +336,6 @@
                         0 ids)]
     (str base "(" (+ 1 offset max-num) ")")))

-
-(defn inc-str-target [db str-target & {:keys [offset]
-                                       :or {offset 0}}]
-  (let [[_ base _] (re-find str-id-regex str-target)
-        base (or base (str str-target " "))
-        ids (remove nil? (map first (d/q '[:find ?id :where [_ :layer/ui-target ?id]] db)))
-        max-num (reduce (fn [acc str-target]
-                          (if-let [[match num] (re-find (re-pattern (str base "\\((\\d+\\))$")) str-target)]
-                            (max acc (js/parseInt num))
-                            acc))
-                        0 ids)]
-    (str base "(" (+ 1 offset max-num) ")")))
-
 (defmethod control-event :layer-duplicated
   [browser-state message {:keys [layer x y]} state]
   (let [[rx ry] (cameras/screen->point (:camera state) x y)
@@ -368,7 +355,7 @@
                                            :layer/ui-id (when (:layer/ui-id layer)
                                                           (inc-str-id @(:db state) (:layer/ui-id layer)))
                                            :layer/ui-target (when (:layer/ui-target layer)
-                                                              (inc-str-target @(:db state) (:layer/ui-target layer))))])
+                                                              (:layer/ui-target layer)))])
       (assoc-in [:drawing :moving?] true)
       (assoc-in [:drawing :starting-mouse-position] [rx ry]))))


Don't return team records for all star games

The records returned from the NHL API are not updated for the all star
teams.

--- src/nhl_score_api/fetchers/mlbam/game_scores.clj
+++ src/nhl_score_api/fetchers/mlbam/game_scores.clj
@@ -3,6 +3,14 @@

 (defn- regular-season-game? [api-game]
   (= "R" (:game-type api-game)))
+
+(defn- all-star-game? [api-game]
+  (= "A" (:game-type api-game)))
+
+(defn- non-playoff-game? [api-game]
+  (or
+    (regular-season-game? api-game)
+    (all-star-game? api-game)))

 (defn- parse-goal-team [scoring-play team-details]
   (let [team-id (:id (:team scoring-play))
@@ -11,7 +19,7 @@

 (defn- parse-goal-period [api-game scoring-play]
   (let [period-number (str (:period (:about scoring-play)))]
-    (if (regular-season-game? api-game)
+    (if (non-playoff-game? api-game)
       (case (:period-type (:about scoring-play))
         "REGULAR" period-number
         "OVERTIME" "OT"
@@ -157,7 +165,7 @@
   (let [current-records (parse-current-records team-details)]
     (reduce-current-game-from-records current-records teams scores)))

-  (defn- parse-current-playoff-series-wins [api-game teams]
+(defn- parse-current-playoff-series-wins [api-game teams]
   (let [away-team (:away teams)
         home-team (:home teams)
         series-summary-description (:series-status-short (:series-summary api-game))
@@ -195,8 +203,13 @@
         wins-before-game (reduce-current-game-from-playoff-series-wins current-wins game-details)]
     {:wins wins-before-game}))

+(defn- add-team-records [api-game game-details team-details teams scores]
+  (if (all-star-game? api-game)
+    game-details
+    (assoc game-details :records (parse-records team-details teams scores))))
+
 (defn- add-playoff-series-information [api-game game-details]
-  (if (regular-season-game? api-game)
+  (if (non-playoff-game? api-game)
     game-details
     (assoc game-details :playoff-series (parse-playoff-series-information api-game game-details))))

@@ -204,11 +217,11 @@
   (let [team-details (parse-game-team-details api-game)
         scores (parse-scores api-game team-details)
         teams (get-team-abbreviations team-details)
-        game-details {:state (parse-game-state api-game)
-                      :goals (parse-goals api-game team-details)
-                      :scores scores
-                      :teams teams
-                      :records (parse-records team-details teams scores)}]
+        common-game-details {:state (parse-game-state api-game)
+                             :goals (parse-goals api-game team-details)
+                             :scores scores
+                             :teams teams}
+        game-details (add-team-records api-game common-game-details team-details teams scores)]
     (add-playoff-series-information api-game game-details)))

 (defn parse-game-scores [date-and-api-games]


Aeron: improve connection handling, info logging

--- src/onyx/messaging/aeron/publication_manager.clj
+++ src/onyx/messaging/aeron/publication_manager.clj
@@ -34,8 +34,8 @@
       (fatal "Writing to closed publication." e)
       (stop publication-manager))
     (catch Throwable t
-      ;; TODO, handle this outcome better. Should reset connection?
-      (fatal "Aeron write from buffer error: " t))))
+      (fatal "Aeron write from buffer error: " t)
+      (stop publication-manager))))

 (defrecord PublicationManager [channel stream-id send-idle-strategy connection publication pending-ch write-fut cleanup-fn]
   PPublicationManager
@@ -48,6 +48,7 @@
     (>!! pending-ch (->Message buf start end)))

   (stop [this]
+    (info (format "Stopped publication manager at: %s, stream-id: %s" channel stream-id))
     (cleanup-fn)
     (future-cancel (:write-fut this))
     (close! pending-ch)
@@ -65,6 +66,7 @@
                             (taoensso.timbre/warn "Aeron messaging publication error:" x)))
           conn (Aeron/connect (.errorHandler (Aeron$Context.) error-handler))
           pub (.addPublication conn channel stream-id)]
+      (info (format "Connected via publication on: %s, stream-id: %s" channel stream-id))
       (assoc this :publication pub :connection conn))))

 (defn new-publication-manager [channel stream-id send-idle-strategy write-buffer-size cleanup-fn]


use interop for Path

use interop for Path

--- examples/war/build.clj
+++ examples/war/build.clj
@@ -6,8 +6,8 @@
         classpath  (for [dir ["/src" "/lib*"]] (str root dir))]
     ;; (println classpath)
     (cake.ant/ant org.apache.tools.ant.taskdefs.Javac {:destdir (java.io.File. root "classes")
-                :fork true
-                :classpath (org.apache.tools.ant.types.Path. @cake.ant/ant-project (apply str (interpose ":" classpath)))
-                :srcdir (org.apache.tools.ant.types.Path. @cake.ant/ant-project (java.io.File. root "src"))
-                :includes "*.clj"})))
+                                                       :fork true
+                                                       :classpath (org.apache.tools.ant.types.Path. @cake.ant/ant-project (apply str (interpose ":" classpath)))
+                                                       :srcdir (org.apache.tools.ant.types.Path. @cake.ant/ant-project (java.io.File. root "src"))
+                                                       :includes "*.clj"} false)))


replace title attribute with itemprop

replace title attribute with itemprop

--- frontend/components/landing_b.cljs
+++ frontend/components/landing_b.cljs
@@ -239,14 +239,14 @@
                 [:div.home-cover]
                 [:div.home-top-shelf]
                 [:div.home-slogans
-                 [:h1.slogan.proverb {:title "Ship better code, faster."
-                                      :alt   "Let's just authorize first."}
+                 [:h1.slogan.proverb {:item-prop "Ship better code, faster."
+                                      :alt       "Let's just authorize first."}
                   "Ship better code, faster."]
-                 [:h3.slogan.context {:title "You have a product to focus on, let Circle handle your"
-                                      :alt   "Signing up using your GitHub login lets us start really fast."}
+                 [:h3.slogan.context {:item-prop "You have a product to focus on, let Circle handle your"
+                                      :alt       "Signing up using your GitHub login lets us start really fast."}
                   "You have a product to focus on, let Circle handle your"]
-                 [:h3.slogan.context {:title "Continuous Integration & Deployment."
-                                      :alt   "Currently, we must request permissions in bulk."}
+                 [:h3.slogan.context {:item-prop "Continuous Integration & Deployment."
+                                      :alt       "Currently, we must request permissions in bulk."}
                   "Continuous Integration & Deployment."]]
                 [:div.home-avatars
                  [:div.avatars
@@ -382,14 +382,14 @@
                 [:div.home-cover]
                 [:div.home-top-shelf]
                 [:div.home-slogans
-                 [:h1.slogan.proverb {:title "So, ready to ship faster?"
-                                      :alt   "Let's just authorize first."}
+                 [:h1.slogan.proverb {:item-prop "So, ready to ship faster?"
+                                      :alt       "Let's just authorize first."}
                   "So, ready to ship faster?"]
-                 [:h3.slogan.context {:title "Next you'll just need to sign in using your GitHub account."
-                                      :alt   "Signing up using your GitHub login lets us start really fast."}
+                 [:h3.slogan.context {:item-prop "Next you'll just need to sign in using your GitHub account."
+                                      :alt       "Signing up using your GitHub login lets us start really fast."}
                   "Next you'll just need to sign in using your GitHub account."]
-                 [:h3.slogan.context {:title "Still not convinced yet? Try taking the full tour."
-                                      :alt   "Currently, we must request permissions in bulk."}
+                 [:h3.slogan.context {:item-prop "Still not convinced yet? Try taking the full tour."
+                                      :alt       "Currently, we must request permissions in bulk."}
                   "Still not convinced yet? Try taking the "
                   [:a {:href "#"} "full tour"]
                   "."]]


change EC2-NAT Instance to "Tenancy: default"

--- src/aws_overlord/tasks/networking.clj
+++ src/aws_overlord/tasks/networking.clj
@@ -182,7 +182,7 @@
                  "SecurityGroupIds" [{"Ref" "NatSecurityGroup"}]
                  "SourceDestCheck" false
                  "SubnetId" {"Ref" subnet-id}
-                 "Tenancy" "dedicated"
+                 "Tenancy" "default"
                  "Tags" [{"Key" "Name"
                           "Value" "NAT"}]}
    })


Add a SiteScraper protocol

Add a SiteScraper protocol

And implement its first function, list-sites

--- src/clj/comic_reader/site_scraper.clj
+++ src/clj/comic_reader/site_scraper.clj
@@ -290,7 +290,15 @@

 (def sites (dissoc (get-sites) "test-site"))

+(defprotocol ISiteScraper
+  (list-sites [this] "Return the list of sites this scraper supports."))
+
 (defrecord SiteScraper [sites]
+  ISiteScraper
+
+  (list-sites [this]
+    (keys sites))
+
   component/Lifecycle

   (start [component]


home page needs anti-forgery token

home page needs anti-forgery token

--- src/clj/conference_rating/handler.clj
+++ src/clj/conference_rating/handler.clj
@@ -32,7 +32,7 @@
      (include-css "css/reagent-forms.css")
      (include-css "css/site.css")
      [:link {:rel "icon" :type "image/png" :href "img/favicon.png"}]
-     [:script (str "_anti_forgery_token=\"" *anti-forgery-token*"\"")]]
+     [:script (str "_anti_forgery_token=\"" *anti-forgery-token* "\"")]]
     [:body {:class "bg-body"}
      [:div#app
       [:h3 "ClojureScript has not been compiled!"]
@@ -96,26 +96,26 @@
     handler
     (wrap-anti-forgery handler)))

-(defn api-routes [db]
+(defn anti-forgery-routes [db]
   (with-anti-forgery
     (routes
-      (GET "/conferences" [] (response (get-conferences db)))
-      (GET "/conferences/:id" [id] (response (get-conference id db)))
-      (GET "/conferences/:id/ratings" [id] (get-conference-ratings id db))
-      (POST "/conferences/:id/ratings" [id :as request] (add-rating id (:body request) db))
-      (POST "/conferences/" request (add-conference (:body request) db))
-      (GET "/series/suggestions" {params :params} (response (series-suggestions  db (:q params)))))))
+      (GET "/api/conferences" [] (response (get-conferences db)))
+      (GET "/api/conferences/:id" [id] (response (get-conference id db)))
+      (GET "/api/conferences/:id/ratings" [id] (get-conference-ratings id db))
+      (POST "/api/conferences/:id/ratings" [id :as request] (add-rating id (:body request) db))
+      (POST "/api/conferences/" request (add-conference (:body request) db))
+      (GET "/api/series/suggestions" {params :params} (response (series-suggestions  db (:q params))))
+      (GET "/" [] (home-page)))))

 (defn create-routes [db]
   (routes
-    (context "/api" [] (api-routes db))
+    (context "" [] (anti-forgery-routes db))
     (resources "/")
     (GET "/css/reagent-forms.css" [] (response (-> "reagent-forms.css"
                                                    clojure.java.io/resource
                                                    slurp)))
     okta/okta-routes
     (GET "/login" [] (redirect "/"))
-    (GET "/" [] (home-page))
     (not-found "Not Found")))

 (defn ring-settings [ssl-redirect-disabled]


missed an encode thus back link for therapy? was broken

--- src/cljs/cljspazzer/client/pages.cljs
+++ src/cljs/cljspazzer/client/pages.cljs
@@ -103,7 +103,7 @@
                                     (utils/encode artist)
                                     (utils/encode album-name))
         tracks (album "tracks")
-        artist-url (utils/format "#/artists/%s" artist)
+        artist-url (utils/format "#/artists/%s" (utils/encode artist))
         play-album (fn [e] (put! track-list tracks))
         compilation? (album "compilation")]
     (if (and (not (nil? artist)) (not (nil? album)))


Fetch all productions if the search string is empty

--- src/cljs/mdr2/productions/search.cljs
+++ src/cljs/mdr2/productions/search.cljs
@@ -10,15 +10,16 @@
 (rf/reg-event-fx
    ::set-search
    (fn [{:keys [db]} [_ id new-search-value handler]]
-     (cond-> {:db (assoc-in db [:search id] new-search-value)}
-       (> (count new-search-value) 2)
-       ;; if the string has more than 2 characters fetch the productions
-       ;; from the server
-       (assoc :dispatch-n
-              (list
-               ;; when searching for a new production reset the pagination
-               [::pagination/reset id]
-               [handler])))))
+     (let [length (count new-search-value)]
+       (cond-> {:db (assoc-in db [:search id] new-search-value)}
+         (or (= length 0) (> length 2))
+         ;; do not fetch the productions from the server for very small strings,
+         ;; unless the string has been reset to the empty string
+         (assoc :dispatch-n
+                (list
+                 ;; when searching for a new production reset the pagination
+                 [::pagination/reset id]
+                 [handler]))))))

 (defn productions-search [id handler]
   (let [get-value (fn [e] (-> e .-target .-value))