Fix the git clone race condition

Fix the git clone race condition

--- src/circle/backend/git.clj
+++ src/circle/backend/git.clj
@@ -5,9 +5,23 @@
   (:use [circle.util.except :only (throw-if-not)])
   (:use [clojure.tools.logging :only (infof)])
   (:use [arohner.utils :only (inspect)])
+  (:use [circle.util.args :only (require-args)])
+  (:require fs)
   (:require [circle.sh :as sh]))

 (def repo-root "repos")  ;; Root directory where we will check out repos
+
+(defn locking-repo*
+  "Takes a repo path, and a fn of no args. Calls f while locking the repo"
+  [repo f]
+  (throw-if-not (instance? String repo))
+  (locking (.intern repo)
+    (f)))
+
+(defmacro with-repo-lock [repo & body]
+  `(locking-repo* ~repo
+                  (fn []
+                    ~@body)))

 (defn project-name
   "Infer the project name from the URL"
@@ -24,9 +38,7 @@

 (defn default-repo-path [url]
   {:pre [url]}
-  ;;TECHNICAL_DEBT stick thread-id into the repo path to avoid a race
-  ;;condition when a customer triggers multiple builds
-  (fs/join repo-root (str "thread-" (-> (Thread/currentThread) (.getId))) (project-name url)))
+  (fs/join repo-root (project-name url)))

 (defmacro with-temp-ssh-key-file
   "Writes the ssh-key to a temp file, executes body. f is the name of the variable that will hold the File for the ssh-key. Deletes the temp key file when done"
@@ -47,12 +59,14 @@
 (defn git-fn*
   "Takes a seq of stevedore code. Executes it locally, with GIT_SSH and GIT_SSH_KEY set up."
   [steve & {:keys [ssh-key repo]}]
+  (require-args steve repo)
   (with-temp-ssh-key-file [f ssh-key]
-    (let [result (sh/sh steve
-                        :environment (when ssh-key
-                                       {"GIT_SSH" git-ssh-path
-                                        "GIT_SSH_KEY" f})
-                        :pwd repo)]
+    (let [result (with-repo-lock repo
+                   (sh/sh steve
+                          :environment (when ssh-key
+                                         {"GIT_SSH" git-ssh-path
+                                          "GIT_SSH_KEY" f})
+                          :pwd repo))]
       (throw-if-not (zero? (-> result :exit)) "git command %s returned %s: %s" (first steve) (-> result :exit) (-> result :err))
       result)))

@@ -60,11 +74,14 @@
   "Clone a git repo at url, writing the directory to path"
   [url & {:keys [path ssh-key]}]
   (let [path (or path (default-repo-path url))]
+
     (infof "git clone %s %s" url path)
+    (fs/mkdirs path)
     (git-fn* (sh/q
               (git clone ~url ~path))
              :ssh-key
-             ssh-key)))
+             ssh-key
+             :repo path)))

 (defn checkout
   "git checkout cmd"


move code without changing anything

move code without changing anything


New message

New message


Change :move-attack to :move-attack-once

--- src/cljs/zetawar/data.cljs
+++ src/cljs/zetawar/data.cljs
@@ -110,7 +110,7 @@
                      :base-type true}}

     :unit-state-maps
-    {:move-attack
+    {:move-attack-once
      {:start-state :start
       :built-state :done
       :states


CMR-3228: Fixing grammar in comment.

CMR-3228: Fixing grammar in comment.

--- system-int-test/test/cmr/system_int_test/search/granule_counts_search_test.clj
+++ system-int-test/test/cmr/system_int_test/search/granule_counts_search_test.clj
@@ -202,8 +202,7 @@
             (gran-counts/granule-counts-match? :xml expected-counts refs))
           1 6 {coll2 0 coll3 3 coll4 3 coll5 3 coll6 3}

-          ;; coll3 not returned here because it has no granules that cover the time range even though
-          ;; it's temporal matches the range.
+          ;; coll3 not returned here because it has no granules that cover the time range
           5 6 {coll4 1 coll5 2 coll6 1}

           2 3 {coll2 0 coll3 2 coll4 1 coll6 1}))


Add copyright banner

Add copyright banner

--- src/tick/ical.clj
+++ src/tick/ical.clj
@@ -1,3 +1,5 @@
+;; Copyright © 2016-2018, JUXT LTD.
+
 (ns tick.ical
   (:require
    [clojure.set :as set]


Make *transaction-connection* public

Make *transaction-connection* public

Fixes https://github.com/metabase/toucan/issues/42

--- src/toucan/db.clj
+++ src/toucan/db.clj
@@ -109,7 +109,7 @@
 ;;;                                         TRANSACTION & CONNECTION UTIL FNS
 ;;; ==================================================================================================================

-(def ^:private ^:dynamic *transaction-connection*
+(def ^:dynamic *transaction-connection*
   "Transaction connection to the application DB. Used internally by `transaction`."
   nil)


using ip function

using ip function

--- src/openstack/provider.clj
+++ src/openstack/provider.clj
@@ -103,8 +103,8 @@
            (let [ip (allocate-floating (floating-ips tenant) pool)]
              (assoc-floating (floating-ips tenant) server ip)
              (update-floating spec ip))))
-       (debug "waiting for ssh to be available at" (.remote this))
-       (wait-for-ssh (.remote this) (get-in spec [:machine :user]) [5 :minute])
+       (debug "waiting for ssh to be available at" (.ip this))
+       (wait-for-ssh (.ip this) (get-in spec [:machine :user]) [5 :minute])
        (when-let [volumes (get-in spec [:openstack :volumes])]
          (doseq [{:keys [device] :as v} volumes :let [vid (v/create spec v tenant)]]
            (v/attach instance-id vid device tenant)))
@@ -116,7 +116,7 @@
          (debug "starting" instance-id )
          (.action (servers tenant) instance-id Action/START)
          (wait-for-start this [5 :minute] ::openstack:start-failed)
-         (wait-for-ssh (.remote this) (get-in spec [:machine :user]) [5 :minute]))))
+         (wait-for-ssh (.ip this) (get-in spec [:machine :user]) [5 :minute]))))

   (delete [this]
      (with-instance-id


For transitions, when name matches, take union of the bounds only.

--- src/pamela/inheritance.clj
+++ src/pamela/inheritance.clj
@@ -99,13 +99,41 @@
                                  {} clist)]
     (methods-from-signature-map m-with-signature)))

+(defn merge-bounds
+  "Return new bounds with min and max values of either a or b"
+  [a b]
+  (let [la (first a)
+        lb (first b)
+        ua (second a)
+        ub (second b)]
+    [(apply min (remove nil? [la lb]))
+     (apply max (remove nil? [ua ub]))]))
+
+(defn merge-transition
+  "More specific transition overrides specific transition.
+  However, if they have :temporal-constraints, they are merged such that the
+  new constraints have min and max of the two transitions."
+  [specific more-specific]
+  (let [has-tc? (or (:temporal-constraints specific) (:temporal-constraints more-specific))
+        trans (or more-specific specific)]
+    (if has-tc?
+      (conj trans {:temporal-constraints [{:type :bounds :value (merge-bounds (-> specific :temporal-constraints first :value)
+                                                                              (-> more-specific :temporal-constraints first :value))}]
+                   })
+      trans)))
+
 (defn merge-transitions
   "Returns a map of transitions-signature -> transition
   Note: Currently, transitions signature is assumed to be name of the transitions."
   [clist ir]
   (reduce (fn [result clas]
-            ; result always holds the value from the class itself or the closes parent
-            (merge (get-in ir [clas :transitions]) result)) {} clist))
+            (let [bounds-updated (reduce (fn [inner-result [name trans]]
+                                           (merge inner-result {name (merge-transition trans (name inner-result))}))
+                                         result (get-in ir [clas :transitions]))]
+              ; Note bounds-updated has transition from more specific class
+              ; and union of the bounds
+              (merge result bounds-updated)))
+          {} clist))

 (defn merge-modes
   "Returns a map of modes-signature -> mode"


CMR-2100 Removes unused functions.

CMR-2100 Removes unused functions.

--- umm-spec-lib/src/cmr/umm_spec/util.clj
+++ umm-spec-lib/src/cmr/umm_spec/util.clj
@@ -63,15 +63,3 @@
   "Returns a 5 character random id to use as an ISO id"
   []
   (str "d" (java.util.UUID/randomUUID)))
-
-(defn short-name-part
-  "Returns the short name part of an EntryId string."
-  [entry-id version]
-  (str/replace entry-id (str "_" version) ""))
-
-(defn make-entry-id
-  "Returns an EntryId string from ShortName and Version values."
-  [short-name version]
-  (if version
-    (str short-name "_" version)
-    short-name))


New function: insert-repository

New function: insert-repository

--- src/arachnida/db_interface.clj
+++ src/arachnida/db_interface.clj
@@ -25,6 +25,11 @@
 (defn insert-product
     [db product-name]
     (jdbc/insert! db "products" {:name product-name}))
+
+(defn insert-repository
+    [db product-name repository-name repository-url]
+    (let [product-id (first (jdbc/query db ["select id from products where name=?;" product-name]))]
+        (jdbc/insert! db "repos" {:product (:id product-id) :name repository-name :url repository-url})))

 (defn insert-changed-file
     [db commit-id changed-file]


Split into tests of different schedulers.

--- test/onyx/log/generative_peer_join.clj
+++ test/onyx/log/generative_peer_join.clj
@@ -21,7 +21,8 @@
 (def peer-config (assoc (:peer-config config)
                         :onyx/id onyx-id
                         :onyx.messaging/impl :dummy-messenger
-                        :onyx.peer/job-scheduler :onyx.job-scheduler/round-robin))
+                        ;:onyx.peer/job-scheduler :onyx.job-scheduler/round-robin
+                        ))

 (def messenger (->DummyMessenger))

@@ -79,15 +80,15 @@
                                  :joiner id}}])
                peer-ids)))

-(deftest joins
+(deftest greedy-allocation
   (checking
-    "Checking joins"
-    10000
+    "Checking greedy allocation causes all peers to be allocated to one of two jobs"
+    100
     [{:keys [replica log peer-choices]}
      (log-gen/apply-entries-gen
        (gen/return
-         {:replica {:job-scheduler (:onyx.peer/job-scheduler peer-config)
-                    :messaging peer-config}
+         {:replica {:job-scheduler :onyx.job-scheduler/greedy
+                    :messaging {:onyx.messaging/impl :dummy-messenger}}
           :message-id 0
           :entries (assoc
                      (generate-join-entries [:a :b :c :d :e :f :g :h])
@@ -101,10 +102,58 @@
                                                           (planning/discover-tasks (:catalog job-2) (:workflow job-2)))])
           :log []
           :peer-choices []}))]
+
+    (let [allocs (vector (apply + (map count (vals (get (:allocations replica) job-1-id))))
+                         (apply + (map count (vals (get (:allocations replica) job-2-id)))))]
+      (is
+        (or (= allocs [0 8])
+            (= allocs [8 0]))))))
+
+(deftest greedy-allocation-reallocated
+  (checking
+    "Checking peers reallocated to other job when killed"
+    100
+    [{:keys [replica log peer-choices]}
+     (log-gen/apply-entries-gen
+       (gen/return
+         {:replica {:job-scheduler :onyx.job-scheduler/greedy
+                    :messaging {:onyx.messaging/impl :dummy-messenger}}
+          :message-id 0
+          :entries (assoc (generate-join-entries [:a :b :c :d :e :f :g :h])
+                          :job-1 [(api/create-submit-job-entry job-1-id
+                                                               peer-config
+                                                               job-1
+                                                               (planning/discover-tasks (:catalog job-1) (:workflow job-1)))]
+                          :job-2 [(api/create-submit-job-entry job-2-id
+                                                               peer-config
+                                                               job-2
+                                                               (planning/discover-tasks (:catalog job-2) (:workflow job-2)))
+                                  {:fn :kill-job :args {:job job-2-id}}])
+          :log []
+          :peer-choices []}))]
+    (is (= (apply + (map count (vals (get (:allocations replica) job-1-id)))) 8))
+    (is (= (apply + (map count (vals (get (:allocations replica) job-2-id)))) 0))))
+
+(deftest round-robin-allocations
+  (checking
+    "Checking round robin allocation causes peers to be evenly split"
+    100000
+    [{:keys [replica log peer-choices]}
+     (log-gen/apply-entries-gen
+       (gen/return
+         {:replica {:job-scheduler :onyx.job-scheduler/round-robin
+                    :messaging {:onyx.messaging/impl :dummy-messenger}}
+          :message-id 0
+          :entries (assoc (generate-join-entries [:a :b :c :d :e :f :g :h])
+                          :job-1 [(api/create-submit-job-entry job-1-id
+                                                               peer-config
+                                                               job-1
+                                                               (planning/discover-tasks (:catalog job-1) (:workflow job-1)))]
+                          :job-2 [(api/create-submit-job-entry job-2-id
+                                                               peer-config
+                                                               job-2
+                                                               (planning/discover-tasks (:catalog job-2) (:workflow job-2)))])
+          :log []
+          :peer-choices []}))]
     (is (= (apply + (map count (vals (get (:allocations replica) job-1-id)))) 4))
-    (is (= (apply + (map count (vals (get (:allocations replica) job-2-id)))) 4))
-    (is (= (:prepared replica) {}))
-    (is (= (:accepted replica) {}))
-    (is (= (set (keys (:pairs replica)))
-           (set (vals (:pairs replica)))))
-    (is (= (count (:peers replica)) 8))))
+    (is (= (apply + (map count (vals (get (:allocations replica) job-2-id)))) 4))))


Invert check for comment url.

Invert check for comment url.

--- src/oc/email/content.clj
+++ src/oc/email/content.clj
@@ -857,8 +857,8 @@
                       :team-id (:team-id org)} ;; Let's read the team-id from the org to avoid problems on multiple org users
         id-token (jwt/generate-id-token token-claims config/passphrase)
         base-url (if (seq interaction-id)
-                   (s/join "/" [origin-url org-slug board-slug "post" uuid])
-                   (s/join "/" [origin-url org-slug board-slug "post" uuid "comment" interaction-id]))
+                   (s/join "/" [origin-url org-slug board-slug "post" uuid "comment" interaction-id])
+                   (s/join "/" [origin-url org-slug board-slug "post" uuid]))
         entry-url (str base-url "?id=" id-token)
         button-cta (if (or (not mention?) interaction-id)
                     "view_comment"


remove CHEESE

remove CHEESE

--- src/overtone/sc/node.clj
+++ src/overtone/sc/node.clj
@@ -492,31 +492,27 @@
          (with-meta (parse-node-tree tree)
            {:type ::node-tree})))))

-(defonce _CHEESE_
-  (do
-
-
-    (extend SynthGroup
-      ISynthGroup
-      {:group-prepend-node group-prepend-node*
-       :group-append-node  group-append-node*
-       :group-clear        group-clear*
-       :group-deep-clear   group-deep-clear*
-       :group-post-tree    group-post-tree*
-       :group-node-tree    group-node-tree*}
-
-      IKillable
-      {:kill* group-deep-clear*})
-
-
-    (extend java.lang.Long
-      ISynthGroup
-      {:group-prepend-node group-prepend-node*
-       :group-append-node  group-append-node*
-       :group-clear        group-clear*
-       :group-deep-clear   group-deep-clear*
-       :group-post-tree    group-post-tree*
-       :group-node-tree    group-node-tree*})))
+(extend SynthGroup
+  ISynthGroup
+  {:group-prepend-node group-prepend-node*
+   :group-append-node  group-append-node*
+   :group-clear        group-clear*
+   :group-deep-clear   group-deep-clear*
+   :group-post-tree    group-post-tree*
+   :group-node-tree    group-node-tree*}
+
+  IKillable
+  {:kill* group-deep-clear*})
+
+
+(extend java.lang.Long
+  ISynthGroup
+  {:group-prepend-node group-prepend-node*
+   :group-append-node  group-append-node*
+   :group-clear        group-clear*
+   :group-deep-clear   group-deep-clear*
+   :group-post-tree    group-post-tree*
+   :group-node-tree    group-node-tree*})

 (defn node-tree
   "Returns a data representation of the synth node tree starting at


Replaced ByteBuffer with simple array creation.

--- src/pandect/checksum.clj
+++ src/pandect/checksum.clj
@@ -2,11 +2,22 @@
       :author "Yannick Scherer"}
   pandect.checksum
   (:use pandect.hashable)
-  (:import [java.util.zip Adler32 CRC32]
-           [java.nio ByteBuffer]))
+  (:import [java.util.zip Adler32 CRC32]))

 (set! *warn-on-reflection* true)
 (set! *unchecked-math* true)
+
+;; ## Long to 4 Bytes
+
+(defmacro ^:private long->4-bytes
+  "Convert an unsigned 32-bit integer (given as long) to a 4-byte array."
+  [v]
+  `(let [v# (long ~v)]
+     (doto (byte-array 4)
+      (aset 0 (byte (bit-and (bit-shift-right v# 24) 0xFF)))
+      (aset 1 (byte (bit-and (bit-shift-right v# 16) 0xFF)))
+      (aset 2 (byte (bit-and (bit-shift-right v# 8) 0xFF)))
+      (aset 3 (byte (bit-and v# 0xFF))))))

 ;; ## Adler32

@@ -21,10 +32,7 @@
   (update-digest! [this data offset length]
     (.update this ^"[B" data offset length))
   (read-digest! [this]
-    (let [v (int (.getValue this))]
-      (-> (ByteBuffer/allocate 4)
-        (.putInt v)
-        (.array))))
+    (long->4-bytes (.getValue this)))
   (byte-digest [this data]
     (doto this
       (reset-digest!)
@@ -44,10 +52,7 @@
   (update-digest! [this data offset length]
     (.update this ^"[B" data offset length))
   (read-digest! [this]
-    (let [v (int (.getValue this))]
-      (-> (ByteBuffer/allocate 4)
-        (.putInt v)
-        (.array))))
+    (long->4-bytes (.getValue this)))
   (byte-digest [this data]
     (doto this
       (reset-digest!)


Tweak layout of report results

Tweak layout of report results

--- src/pinpointer/core.cljc
+++ src/pinpointer/core.cljc
@@ -105,14 +105,14 @@
     (println (str " (" (inc i) "/" total ")\n"))
     (println "     Input:" line)
     (doseq [line lines]
-      (println "          :" line))
+      (println "           " line))
     (let [[line & lines] (as-> (:pred problem) it
                            (simplify-spec it)
                            (with-out-str (fipp/pprint it))
                            (str/split it #"\n"))]
       (println "  Expected:" line)
       (doseq [line lines]
-        (println "          :" line)))
+        (println "           " line)))
     (when-let [reason (:reason problem)]
       (println "    Reason:" reason))))


Fix cli! based on new semantics

Fix cli! based on new semantics

Apparently, there were some changes introduced in 0.2.2 of
`org.clojure/tools.logging` that affected some of the behavior
of the cli validation that we were doing in our `utils` namespace.

PuppetDB is patching this here:

https://github.com/puppetlabs/puppetdb/pull/751/files

This commit simply brings that same change over to kitchensink,
since it'll be needed when we submit the PR to move PuppetDB
over to kitchensink.

--- src/puppetlabs/utils.clj
+++ src/puppetlabs/utils.clj
@@ -470,13 +470,12 @@
     (when (:help options)
       (println banner)
       (System/exit 0))
-    (let [required-pairs (select-keys options required-args)]
-      (when-let [missing-field (some #(if (nil? (val %)) (key %)) required-pairs)]
-        (println)
-        (println (format "Missing required argument '--%s'!" (name missing-field)))
-        (println)
-        (println banner)
-        (System/exit 1)))
+    (when-let [missing-field (some #(if (not (contains? options %)) %) required-args)]
+      (println)
+      (println (format "Missing required argument '--%s'!" (name missing-field)))
+      (println)
+      (println banner)
+      (System/exit 1))
     [options extras]))


Handle fetching fail

Handle fetching fail

--- src/showkr/browsing.cljs
+++ src/showkr/browsing.cljs
@@ -31,7 +31,11 @@
         (d/h1 nil
           "Sets of "
           (d/a {:href (str "https://flickr.com/photos/" username)} username)))
-      (when (= :fetched (-> user :sets meta :state))
+      (condp = (-> user :sets meta :state)
+        :fetched
         (for [set (-> user :sets :photoset)]
-          (Set set))))
+          (Set set))
+
+        [(d/div nil
+           "Seems user does not exist")]))
     :onMount #(data/fetch-user username)))


add hooks for PRIVMSG, JOIN, PART & QUIT

--- src/subrosa/commands.clj
+++ src/subrosa/commands.clj
@@ -85,6 +85,7 @@
                                            (format ":%s QUIT :Client Quit"
                                                    (format-client channel)))]
     (await chan-future-agent)
+    (run-hook 'quit-hook channel quit-msg)
     (when-let [chan-future @chan-future-agent]
       (.addListener chan-future (ChannelFutureListener/CLOSE)))))

@@ -102,7 +103,8 @@
                                              (format-client channel)
                                              room-name))
              (dispatch-message (format "TOPIC %s" room-name) channel)
-             (dispatch-message (format "NAMES %s" room-name) channel))))
+             (dispatch-message (format "NAMES %s" room-name) channel)
+             (run-hook 'join-hook channel room-name))))
         (raise {:type :client-error
                 :code 461
                 :msg "JOIN :Not enough parameters"}))
@@ -156,9 +158,15 @@
     (if (not (empty? recipient))
       (if (not (nil? received-msg))
         (if (room-for-name recipient)
-          (send-to-room-except recipient msg channel)
+          (do
+            (send-to-room-except recipient msg channel)
+            (run-hook 'privmsg-room-hook
+                      channel recipient (subs received-msg 1)))
           (if-let [channel (channel-for-nick recipient)]
-            (send-to-client* channel msg)
+            (do
+              (send-to-client* channel msg)
+              (run-hook 'privmsg-nick-hook
+                        channel recipient (subs received-msg 1)))
             (raise {:type :client-error
                     :code 401
                     :msg (format "%s :No such nick/channel" recipient)})))
@@ -225,7 +233,8 @@
                                         (format-client channel)
                                         room
                                         (or part-message nick)))
-             (remove-nick-from-room! nick room))
+             (remove-nick-from-room! nick room)
+             (run-hook 'part-hook channel room))
             (raise {:type :client-error
                     :code 442
                     :msg (format "%s :You're not on that channel" room)}))


WIP - support customizable serializers.

WIP - support customizable serializers.

--- src/taoensso/faraday.clj
+++ src/taoensso/faraday.clj
@@ -181,7 +181,7 @@
     (BigDecimal. s)
     (bigint (BigInteger. s))))

-(defn- db-val->clj-val "Returns the Clojure value of given AttributeValue object."
+(defn default-deserializer "Returns the Clojure value of given AttributeValue object."
   [^AttributeValue x]
   (or (.getS x)
       (some->> (.getN  x) ddb-num-str->num)
@@ -190,7 +190,35 @@
       (some->> (.getNS x) (mapv ddb-num-str->num) (into #{}))
       (some->> (.getBS x) (mapv nt-thaw)          (into #{}))))

-(defn- clj-val->db-val "Returns an AttributeValue object for given Clojure value."
+(defn rotary-deserializer "Returns the Clojure value of given
+AttributeValue object as persisted by rotary."
+  [^AttributeValue x]
+  (or (.getS x)
+      (some->> (.getN  x) Long.)
+      (some->> (.getB  x) .array)
+      (some->> (.getSS x) (into #{}))
+      (some->> (.getNS x) (mapv (fn [^String s] (Long. s))) (into #{}))
+      (some->> (.getBS x) (mapv (fn [^java.nio.ByteBuffer b] (.array b))) (into #{}))
+      ))
+
+(defn- set-of [f s]
+  (and (set? s) (every? f s)))
+
+(defn rotary-serializer
+  "Convert a value into an AttributeValue object."
+  ^AttributeValue [x]
+  (cond
+   (string? x) (doto (AttributeValue.) (.setS x))
+   (number? x) (doto (AttributeValue.) (.setN (str x)))
+   (set-of string? x) (doto (AttributeValue.) (.setSS x))
+   (set-of number? x) (doto (AttributeValue.) (.setNS (map str x)))
+   (set? x) (throw (Exception. "Set must be all numbers or all strings"))
+   :else (doto (AttributeValue.) (.setB (java.nio.ByteBuffer/wrap x)))
+;      :else (throw (Exception. (str "Unknown value type: " (type
+;      x))))
+   ))
+
+(defn default-serializer "Returns an AttributeValue object for given Clojure value."
   ^AttributeValue [x]
   (cond
    (stringy? x)
@@ -214,7 +242,9 @@

    (instance? AttributeValue x) x
    :else (throw (Exception. (str "Unknown DynamoDB value type: " (type x) "."
-                                 " See `freeze` for serialization.")))))
+                                 " See `freeze` for serialization." x)))))
+
+

 (comment
   (mapv clj-val->db-val [  "a"    1 3.14    (.getBytes "a")    (freeze :a)
@@ -222,113 +252,114 @@

 ;;;; Coercion - objects

-(def db-item->clj-item (partial utils/keyword-map db-val->clj-val))
-(def clj-item->db-item (partial utils/name-map    clj-val->db-val))
+(defn- db-item->clj-item [deserializer] (partial utils/keyword-map deserializer))
+(defn- clj-item->db-item [serializer] (partial utils/name-map serializer))

 (defn- cc-units [^ConsumedCapacity cc] (some-> cc (.getCapacityUnits)))

-(defprotocol AsMap (as-map [x]))
-
-(defmacro ^:private am-item-result [result get-form]
+(defprotocol AsMap (as-map [x deserializer]))
+
+(defmacro ^:private am-item-result [result deserializer get-form]
   `(when-let [get-form# ~get-form]
-     (with-meta (db-item->clj-item get-form#)
+     (with-meta ((db-item->clj-item ~deserializer) get-form#)
        {:cc-units (cc-units (.getConsumedCapacity ~result))})))

-(defmacro ^:private am-query|scan-result [result & [meta]]
-  `(let [result# ~result]
-     (merge {:items (mapv db-item->clj-item (.getItems result#))
+(defmacro ^:private am-query|scan-result [result deserializer & [meta]]
+  `(let [result# ~result
+         deserializer# ~deserializer]
+     (merge {:items (mapv (db-item->clj-item deserializer#) (.getItems result#))
              :count (.getCount result#)
              :cc-units (cc-units (.getConsumedCapacity result#))
-             :last-prim-kvs (as-map (.getLastEvaluatedKey result#))}
+             :last-prim-kvs (as-map (.getLastEvaluatedKey result#) deserializer#)}
             ~meta)))

 (extend-protocol AsMap
-  nil                 (as-map [_] nil)
-  java.util.ArrayList (as-map [a] (mapv as-map a))
-  java.util.HashMap   (as-map [m] (utils/keyword-map as-map m))
-
-  AttributeValue      (as-map [v] (db-val->clj-val v))
-  AttributeDefinition (as-map [d] {:name (keyword       (.getAttributeName d))
-                                   :type (utils/un-enum (.getAttributeType d))})
-  KeySchemaElement    (as-map [e] {:name (keyword (.getAttributeName e))
-                                   :type (utils/un-enum (.getKeyType e))})
+  nil                 (as-map [_ deserializer] nil)
+  java.util.ArrayList (as-map [a deserializer] (mapv #(as-map % deserializer) a))
+  java.util.HashMap   (as-map [m deserializer] (utils/keyword-map #(as-map % deserializer) m))
+
+  AttributeValue      (as-map [v deserializer] (deserializer v))
+  AttributeDefinition (as-map [d deserializer] {:name (keyword       (.getAttributeName d))
+                                        :type (utils/un-enum (.getAttributeType d))})
+  KeySchemaElement    (as-map [e deserializer] {:name (keyword (.getAttributeName e))
+                                        :type (utils/un-enum (.getKeyType e))})
   KeysAndAttributes
-  (as-map [x]
+  (as-map [x deserializer]
     (merge
      (when-let [a (.getAttributesToGet x)] {:attrs (mapv keyword a)})
      (when-let [c (.getConsistentRead  x)] {:consistent? c})
-     (when-let [k (.getKeys            x)] {:keys (mapv db-item->clj-item k)})))
-
-  GetItemResult       (as-map [r] (am-item-result r (.getItem r)))
-  PutItemResult       (as-map [r] (am-item-result r (.getAttributes r)))
-  UpdateItemResult    (as-map [r] (am-item-result r (.getAttributes r)))
-  DeleteItemResult    (as-map [r] (am-item-result r (.getAttributes r)))
-
-  QueryResult         (as-map [r] (am-query|scan-result r))
-  ScanResult          (as-map [r] (am-query|scan-result r
-                                    {:scanned-count (.getScannedCount r)}))
+     (when-let [k (.getKeys            x)] {:keys (mapv (db-item->clj-item deserializer) k)})))
+
+  GetItemResult       (as-map [r deserializer] (am-item-result r deserializer (.getItem r)))
+  PutItemResult       (as-map [r deserializer] (am-item-result r deserializer (.getAttributes r)))
+  UpdateItemResult    (as-map [r deserializer] (am-item-result r deserializer (.getAttributes r)))
+  DeleteItemResult    (as-map [r deserializer] (am-item-result r deserializer (.getAttributes r)))
+
+  QueryResult         (as-map [r deserializer] (am-query|scan-result r deserializer))
+  ScanResult          (as-map [r deserializer] (am-query|scan-result r deserializer
+                                                             {:scanned-count (.getScannedCount r)}))

   BatchGetItemResult
-  (as-map [r]
-    {:items       (utils/keyword-map as-map (.getResponses r))
+  (as-map [r deserializer]
+    {:items       (utils/keyword-map #(as-map % deserializer) (.getResponses r))
      :unprocessed (.getUnprocessedKeys r)
      :cc-units    (cc-units (.getConsumedCapacity r))})

   BatchWriteItemResult
-  (as-map [r]
+  (as-map [r deserializer]
     {:unprocessed (.getUnprocessedItems r)
      :cc-units    (cc-units (.getConsumedCapacity r))})

   TableDescription
-  (as-map [d]
+  (as-map [d deserializer]
     {:name          (keyword (.getTableName d))
      :creation-date (.getCreationDateTime d)
      :item-count    (.getItemCount d)
      :size          (.getTableSizeBytes d)
-     :throughput    (as-map (.getProvisionedThroughput  d))
-     :indexes       (as-map (.getLocalSecondaryIndexes  d)) ; DEPRECATED
-     :lsindexes     (as-map (.getLocalSecondaryIndexes  d))
-     :gsindexes     (as-map (.getGlobalSecondaryIndexes d))
+     :throughput    (as-map (.getProvisionedThroughput  d) deserializer)
+     :indexes       (as-map (.getLocalSecondaryIndexes  d) deserializer) ; DEPRECATED
+     :lsindexes     (as-map (.getLocalSecondaryIndexes  d) deserializer)
+     :gsindexes     (as-map (.getGlobalSecondaryIndexes d) deserializer)
      :status        (utils/un-enum (.getTableStatus d))
      :prim-keys
-     (let [schema (as-map (.getKeySchema d))
-           defs   (as-map (.getAttributeDefinitions d))]
+     (let [schema (as-map (.getKeySchema d) deserializer)
+           defs   (as-map (.getAttributeDefinitions d) deserializer)]
        (merge-with merge
          (reduce-kv (fn [m k v] (assoc m (:name v) {:key-type  (:type v)}))
                     {} schema)
          (reduce-kv (fn [m k v] (assoc m (:name v) {:data-type (:type v)}))
                     {} defs)))})

-  DescribeTableResult (as-map [r] (as-map (.getTable r)))
-  CreateTableResult   (as-map [r] (as-map (.getTableDescription r)))
-  UpdateTableResult   (as-map [r] (as-map (.getTableDescription r)))
-  DeleteTableResult   (as-map [r] (as-map (.getTableDescription r)))
+  DescribeTableResult (as-map [r deserializer] (as-map (.getTable r) deserializer))
+  CreateTableResult   (as-map [r deserializer] (as-map (.getTableDescription r) deserializer))
+  UpdateTableResult   (as-map [r deserializer] (as-map (.getTableDescription r) deserializer))
+  DeleteTableResult   (as-map [r deserializer] (as-map (.getTableDescription r) deserializer))

   Projection
-  (as-map [p] {:projection-type    (.getProjectionType p)
-               :non-key-attributes (.getNonKeyAttributes p)})
+  (as-map [p deserializer] {:projection-type    (.getProjectionType p)
+                    :non-key-attributes (.getNonKeyAttributes p)})

   LocalSecondaryIndexDescription
-  (as-map [d] {:name       (keyword (.getIndexName d))
-               :size       (.getIndexSizeBytes d)
-               :item-count (.getItemCount d)
-               :key-schema (as-map (.getKeySchema d))
-               :projection (as-map (.getProjection d))})
+  (as-map [d deserializer] {:name       (keyword (.getIndexName d))
+                    :size       (.getIndexSizeBytes d)
+                    :item-count (.getItemCount d)
+                    :key-schema (as-map (.getKeySchema d) deserializer)
+                    :projection (as-map (.getProjection d) deserializer)})

   GlobalSecondaryIndexDescription
-  (as-map [d] {:name       (keyword (.getIndexName d))
-               :size       (.getIndexSizeBytes d)
-               :item-count (.getItemCount d)
-               :key-schema (as-map (.getKeySchema d))
-               :projection (as-map (.getProjection d))
-               :throughput (as-map (.getProvisionedThroughput d))})
+  (as-map [d deserializer] {:name       (keyword (.getIndexName d))
+                    :size       (.getIndexSizeBytes d)
+                    :item-count (.getItemCount d)
+                    :key-schema (as-map (.getKeySchema d) deserializer)
+                    :projection (as-map (.getProjection d) deserializer)
+                    :throughput (as-map (.getProvisionedThroughput d) deserializer)})

   ProvisionedThroughputDescription
-  (as-map [d] {:read                (.getReadCapacityUnits d)
-               :write               (.getWriteCapacityUnits d)
-               :last-decrease       (.getLastDecreaseDateTime d)
-               :last-increase       (.getLastIncreaseDateTime d)
-               :num-decreases-today (.getNumberOfDecreasesToday d)}))
+  (as-map [d deserializer] {:read                (.getReadCapacityUnits d)
+                    :write               (.getWriteCapacityUnits d)
+                    :last-decrease       (.getLastDecreaseDateTime d)
+                    :last-increase       (.getLastIncreaseDateTime d)
+                    :num-decreases-today (.getNumberOfDecreasesToday d)}))

 ;;;; API - tables

@@ -340,7 +371,7 @@
   "Returns a map describing a table, or nil if the table doesn't exist."
   [client-opts table]
   (try (as-map (.describeTable (db-client client-opts)
-                (doto (DescribeTableRequest.) (.setTableName (name table)))))
+                (doto (DescribeTableRequest.) (.setTableName (name table)))) nil)
        (catch ResourceNotFoundException _ nil)))

 (defn table-status-watch
@@ -480,7 +511,7 @@
              lsindexes (.setLocalSecondaryIndexes
                         (local-2nd-indexes hash-keydef lsindexes))
              gsindexes (.setGlobalSecondaryIndexes
-                        (global-2nd-indexes gsindexes)))))]
+                        (global-2nd-indexes gsindexes)))) nil)]
     (if-not block? result @(table-status-watch client-opts table-name :creating))))

 (comment (time (create-table mc "delete-me7" [:id :s] {:block? true})))
@@ -538,7 +569,7 @@
                        (doto (UpdateTableRequest.)
                          (.setTableName (name table))
                          (.setProvisionedThroughput (provisioned-throughput
-                                                     {:read r' :write w'})))))
+                                                     {:read r' :write w'})))) nil)
                     ;; Returns _new_ descr when ready:
                     @(table-status-watch client-opts table :updating))]

@@ -553,7 +584,7 @@

 (defn delete-table "Deletes a table, go figure."
   [client-opts table]
-  (as-map (.deleteTable (db-client client-opts) (DeleteTableRequest. (name table)))))
+  (as-map (.deleteTable (db-client client-opts) (DeleteTableRequest. (name table))) nil))

 ;;;; API - items

@@ -567,19 +598,20 @@
    (.getItem (db-client client-opts)
     (doto-cond [g (GetItemRequest.)]
       :always     (.setTableName       (name table))
-      :always     (.setKey             (clj-item->db-item prim-kvs))
+      :always     (.setKey             ((clj-item->db-item (or (:serializer client-opts) default-serializer)) prim-kvs))
       consistent? (.setConsistentRead  g)
       attrs       (.setAttributesToGet (mapv name g))
-      return-cc?  (.setReturnConsumedCapacity (utils/enum :total))))))
+      return-cc?  (.setReturnConsumedCapacity (utils/enum :total))))
+   (or (:deserializer client-opts) default-deserializer)))

 (defn- expected-values
   "{<attr> <cond> ...} -> {<attr> ExpectedAttributeValue ...}"
-  [expected-map]
+  [expected-map serializer]
   (when (seq expected-map)
     (utils/name-map
      #(if (= false %)
         (ExpectedAttributeValue. false)
-        (ExpectedAttributeValue. (clj-val->db-val %)))
+        (ExpectedAttributeValue. (serializer %)))
      expected-map)))

 (defn put-item
@@ -595,17 +627,18 @@
    (.putItem (db-client client-opts)
      (doto-cond [g (PutItemRequest.)]
        :always  (.setTableName    (name table))
-       :always  (.setItem         (clj-item->db-item item))
-       expected (.setExpected     (expected-values g))
+       :always  (.setItem         ((clj-item->db-item (or (:serializer client-opts) default-serializer)) item))
+       expected (.setExpected     (expected-values g (or (:serializer client-opts) default-serializer)))
        return   (.setReturnValues (utils/enum g))
-       return-cc? (.setReturnConsumedCapacity (utils/enum :total))))))
+       return-cc? (.setReturnConsumedCapacity (utils/enum :total))))
+   (or (:deserializer client-opts) default-deserializer)))

 (defn- attribute-updates
   "{<attr> [<action> <value>] ...} -> {<attr> AttributeValueUpdate ...}"
-  [update-map]
+  [update-map serializer]
   (when (seq update-map)
     (utils/name-map
-     (fn [[action val]] (AttributeValueUpdate. (when val (clj-val->db-val val))
+     (fn [[action val]] (AttributeValueUpdate. (when val (serializer val))
                                               (utils/enum action)))
      update-map)))

@@ -621,11 +654,12 @@
    (.updateItem (db-client client-opts)
      (doto-cond [g (UpdateItemRequest.)]
        :always  (.setTableName        (name table))
-       :always  (.setKey              (clj-item->db-item prim-kvs))
-       :always  (.setAttributeUpdates (attribute-updates update-map))
-       expected (.setExpected         (expected-values g))
+       :always  (.setKey              ((clj-item->db-item (or (:serializer client-opts) default-serializer)) prim-kvs))
+       :always  (.setAttributeUpdates (attribute-updates update-map (or (:serializer client-opts) default-serializer)))
+       expected (.setExpected         (expected-values g (or (:serializer client-opts) default-serializer)))
        return   (.setReturnValues     (utils/enum g))
-       return-cc? (.setReturnConsumedCapacity (utils/enum :total))))))
+       return-cc? (.setReturnConsumedCapacity (utils/enum :total))))
+   (or (:deserializer client-opts) default-deserializer)))

 (defn delete-item
   "Deletes an item from a table by its primary key.
@@ -636,16 +670,17 @@
    (.deleteItem (db-client client-opts)
      (doto-cond [g (DeleteItemRequest.)]
        :always  (.setTableName    (name table))
-       :always  (.setKey          (clj-item->db-item prim-kvs))
-       expected (.setExpected     (expected-values g))
+       :always  (.setKey          ((clj-item->db-item (or (:serializer client-opts) default-serializer)) prim-kvs))
+       expected (.setExpected     (expected-values g (or (:serializer client-opts) default-serializer)))
        return   (.setReturnValues (utils/enum g))
-       return-cc? (.setReturnConsumedCapacity (utils/enum :total))))))
+       return-cc? (.setReturnConsumedCapacity (utils/enum :total))))
+   nil))

 ;;;; API - batch ops

 (defn- attr-multi-vs
   "[{<attr> <v-or-vs*> ...} ...]* -> [{<attr> <v> ...} ...] (* => optional vec)"
-  [attr-multi-vs-map]
+  [attr-multi-vs-map serializer]
   (let [ensure-coll (fn [x] (if (coll?* x) x [x]))]
     (reduce (fn [r attr-multi-vs]
               (let [attrs (keys attr-multi-vs)
@@ -653,7 +688,7 @@
                 (when (> (count (filter next vs)) 1)
                   (-> (Exception. "Can range over only a single attr's values")
                       (throw)))
-                (into r (mapv (comp clj-item->db-item (partial zipmap attrs))
+                (into r (mapv (comp (clj-item->db-item serializer) (partial zipmap attrs))
                               (apply utils/cartesian-product vs)))))
             [] (ensure-coll attr-multi-vs-map))))

@@ -662,13 +697,13 @@

 (defn- batch-request-items
   "{<table> <request> ...} -> {<table> KeysAndAttributes> ...}"
-  [requests]
+  [requests serializer]
   (utils/name-map
    (fn [{:keys [prim-kvs attrs consistent?]}]
      (doto-cond [g (KeysAndAttributes.)]
        attrs       (.setAttributesToGet (mapv name g))
        consistent? (.setConsistentRead  g)
-       :always     (.setKeys (attr-multi-vs prim-kvs))))
+       :always     (.setKeys (attr-multi-vs prim-kvs serializer))))
    requests))

 (comment (batch-request-items {:my-table {:prim-kvs [{:my-hash  ["a" "b"]
@@ -713,8 +748,9 @@
              (.batchGetItem (db-client client-opts)
                (doto-cond [g (BatchGetItemRequest.)] ; {table-str KeysAndAttributes}
                  :always    (.setRequestItems raw-req)
-                 return-cc? (.setReturnConsumedCapacity (utils/enum :total))))))]
-    (merge-more run1 span-reqs (run1 (batch-request-items requests)))))
+                 return-cc? (.setReturnConsumedCapacity (utils/enum :total))))
+             (or (:deserializer client-opts) default-deserializer)))]
+    (merge-more run1 span-reqs (run1 (batch-request-items requests (or (:serializer client-opts) default-serializer))))))

 (comment
   (def bigval (.getBytes (apply str (range 14000))))
@@ -737,7 +773,6 @@
      {:users {:put    [{:user-id 1 :username \"sally\"}
                        {:user-id 2 :username \"jane\"}]
               :delete [{:user-id [3 4 5]}]}})
-
   :span-reqs - {:max _ :throttle-ms _} allows a number of requests to
   automatically be stitched together (to exceed throughput limits, for example)."
   [client-opts requests & [{:keys [return-cc? span-reqs] :as opts
@@ -747,7 +782,8 @@
              (.batchWriteItem (db-client client-opts)
                (doto-cond [g (BatchWriteItemRequest.)]
                  :always    (.setRequestItems raw-req)
-                 return-cc? (.setReturnConsumedCapacity (utils/enum :total))))))]
+                 return-cc? (.setReturnConsumedCapacity (utils/enum :total))))
+             (or (:deserializer client-opts) default-deserializer)))]
     (merge-more run1 span-reqs
       (run1
        (utils/name-map
@@ -755,7 +791,7 @@
         (fn [table-request]
           (reduce into []
             (for [action (keys table-request)
-                  :let [items (attr-multi-vs (table-request action))]]
+                  :let [items (attr-multi-vs (table-request action) (or (:serializer client-opts) default-serializer))]]
               (mapv (partial write-request action) items))))
         requests)))))

@@ -767,7 +803,7 @@

 (defn- query|scan-conditions
   "{<attr> [operator <val-or-vals>] ...} -> {<attr> Condition ...}"
-  [conditions]
+  [conditions serializer]
   (when (seq conditions)
     (utils/name-map
      (fn [[operator val-or-vals & more :as condition]]
@@ -775,7 +811,7 @@
        (let [vals (if (coll?* val-or-vals) val-or-vals [val-or-vals])]
          (doto (Condition.)
            (.setComparisonOperator (enum-op operator))
-           (.setAttributeValueList (mapv clj-val->db-val vals)))))
+           (.setAttributeValueList (mapv serializer vals)))))
      conditions)))

 (defn query
@@ -816,17 +852,18 @@
              (.query (db-client client-opts)
                (doto-cond [g (QueryRequest.)]
                  :always (.setTableName        (name table))
-                 :always (.setKeyConditions    (query|scan-conditions prim-key-conds))
+                 :always (.setKeyConditions    (query|scan-conditions prim-key-conds (or (:serializer client-opts) default-serializer)))
                  :always (.setScanIndexForward (case order :asc true :desc false))
                  last-prim-kvs   (.setExclusiveStartKey
-                                  (clj-item->db-item last-prim-kvs))
+                                  ((clj-item->db-item (or (:serializer client-opts) default-serializer)) last-prim-kvs))
                  limit           (.setLimit     (int g))
                  index           (.setIndexName      g)
                  consistent?     (.setConsistentRead g)
                  (coll?* return) (.setAttributesToGet (mapv name return))
                  return-cc? (.setReturnConsumedCapacity (utils/enum :total))
                  (and return (not (coll?* return)))
-                 (.setSelect (utils/enum return))))))]
+                 (.setSelect (utils/enum return))))
+             (or (:deserializer client-opts) default-deserializer)))]
     (merge-more run1 span-reqs (run1 last-prim-kvs))))

 (defn scan
@@ -866,16 +903,17 @@
              (.scan (db-client client-opts)
                (doto-cond [g (ScanRequest.)]
                  :always (.setTableName (name table))
-                 attr-conds      (.setScanFilter        (query|scan-conditions g))
+                 attr-conds      (.setScanFilter        (query|scan-conditions g (or (:serializer client-opts) default-serializer)))
                  last-prim-kvs   (.setExclusiveStartKey
-                                  (clj-item->db-item last-prim-kvs))
+                                  ((clj-item->db-item (or (:serializer client-opts) default-serializer)) last-prim-kvs))
                  limit           (.setLimit             (int g))
                  total-segments  (.setTotalSegments     (int g))
                  segment         (.setSegment           (int g))
                  (coll?* return) (.setAttributesToGet (mapv name return))
                  return-cc? (.setReturnConsumedCapacity (utils/enum :total))
                  (and return (not (coll?* return)))
-                 (.setSelect (utils/enum return))))))]
+                 (.setSelect (utils/enum return))))
+             (or (:deserializer client-opts) default-deserializer)))]
     (merge-more run1 span-reqs (run1 last-prim-kvs))))

 (defn scan-parallel


Octave jump should be 8 notes

Octave jump should be 8 notes

--- src/tenor/constructs.clj
+++ src/tenor/constructs.clj
@@ -94,10 +94,10 @@

 (defn up-step [degree] (inc degree))
 (defn down-step [degree] (dec degree))
-(defn up-leap [degree] (+ (rand-nth [2 3 4 5]) degree))
-(defn down-leap [degree] (- (rand-nth [2 3 4 5]) degree))
-(defn up-octave [degree] (+ 7 degree))
-(defn down-octave [degree] (- 7 degree))
+(defn up-leap [degree] (+ (rand-nth [2 3 4 5 6 7]) degree))
+(defn down-leap [degree] (- (rand-nth [2 3 4 5 6 7]) degree))
+(defn up-octave [degree] (+ 8 degree))
+(defn down-octave [degree] (- 8 degree))

 (defn make-move [scale degree]
   "Generate an interval jump from the current note


Add `resize-dim` function to geom helpers.

A helper for resize by width and height with
initial support for rect, icon and circle.

--- src/uxbox/main/geom.cljs
+++ src/uxbox/main/geom.cljs
@@ -277,6 +277,52 @@
   (let [{:keys [width height]} (size shape)]
     (assoc shape :proportion (/ width height))))

+;; --- Resize (Dimentsions)
+
+(declare resize-dim-rect)
+(declare resize-dim-circle)
+
+(defn resize-dim
+  "Resize using calculated dimensions (eg, `width` and `height`)
+  instead of absolute positions."
+  [shape opts]
+  (case (:type shape)
+    :rect (resize-dim-rect shape opts)
+    :icon (resize-dim-rect shape opts)
+    :circle (resize-dim-circle shape opts)))
+
+(defn- resize-dim-rect
+  [{:keys [proportion proportion-lock x1 y1] :as shape}
+   {:keys [width height]}]
+  {:pre [(not (and width height))]}
+  (if-not proportion-lock
+    (if width
+      (assoc shape :x2 (+ x1 width))
+      (assoc shape :y2 (+ y1 height)))
+    (if width
+      (-> shape
+          (assoc :x2 (+ x1 width))
+          (assoc :y2 (+ y1 (/ width proportion))))
+      (-> shape
+          (assoc :y2 (+ y1 height))
+          (assoc :x2 (+ x1 (* height proportion)))))))
+
+(defn- resize-dim-circle
+  [{:keys [proportion proportion-lock] :as shape}
+   {:keys [rx ry]}]
+  {:pre [(not (and rx ry))]}
+  (if-not proportion-lock
+    (if rx
+      (assoc shape :rx rx)
+      (assoc shape :ry ry))
+    (if rx
+      (-> shape
+          (assoc :rx rx)
+          (assoc :ry (/ rx proportion)))
+      (-> shape
+          (assoc :ry ry)
+          (assoc :rx (* ry proportion))))))
+
 ;; --- Resize (Absolute)

 (declare resize-rect)


Added default clauses to users-href and remember-me-href

--- src/zg/html_renderer.clj
+++ src/zg/html_renderer.clj
@@ -91,7 +91,8 @@
     (condp = mode
         :whitelist    (str url-prefix "users-whitelist")
         :blacklist    (str url-prefix "users-blacklist")
-        :atomic-typos (str url-prefix "users-atomic-typos")))
+        :atomic-typos (str url-prefix "users-atomic-typos")
+                      nil))

 (defn remember-me-href
     "Generator for URL used by 'remember me' button."
@@ -99,7 +100,8 @@
     (condp = mode
         :whitelist    (str url-prefix "whitelist")
         :blacklist    (str url-prefix "blacklist")
-        :atomic-typos (str url-prefix "atomic-typos")))
+        :atomic-typos (str url-prefix "atomic-typos")
+                      nil))

 (defn render-navigation-bar-section
     "Renders whole navigation bar."


Record /multi traffic in new-relic

Record /multi traffic in new-relic

--- src/poky/protocol/http.clj
+++ src/poky/protocol/http.clj
@@ -224,7 +224,9 @@
                                            (new-relic/wrap-transaction-name
                                              :category "kv"
                                              :tx-name-fn #(str "/" (name (:request-method %))))))
-                     (context "/multi" [] (multi-routes kvstore))
+                     (context "/multi" [] (-> (multi-routes kvstore)
+                                              (new-relic/wrap-transaction-name
+                                                :tx-name-fn #(str "/multi/" (name (:request-method %))))))
                      (context "/status" [] status-routes)
                      (context "*" [] fall-back-routes))]
     (-> (handler/api api-routes)


Refactoring

Refactoring

--- src/cljs/klang/core.cljs
+++ src/cljs/klang/core.cljs
@@ -319,7 +319,7 @@
                 :margin "0em"
                 :line-height "1.06em"}}
    ;; Create the rendered log message
-   (for [lg (rseq logs) #_(take 30 logs)]
+   (for [lg (rseq logs) #_(subvec logs 30)]
      ^{:key (:uuid lg)} [render-msg lg])])

 (defn render-tab-item
@@ -479,6 +479,10 @@
    (contains? log-ev :msg) ;; can be anything (even nil!), but must exist
    ))

+(defn cache-render
+  [lg-ev]
+  (assoc lg-ev ::cached-render (render-msg lg-ev)))
+
 (defn log+rules
   "Adds some data to the log message (such as date and uuid) if it's not already
   there"
@@ -487,7 +491,8 @@
   (-> log-ev
       ensure-uuid
       ensure-msg-vec
-      ensure-timed))
+      ensure-timed
+      cache-render))

 (defn single-transduce
   "Takes a transducer (xform) and an item and applies the transducer to the
@@ -508,23 +513,21 @@
   ;; be filling up.
   ;; Problem: Can't put the transducer into the chan argument since it's empty
   ;; when called in the beginning
-  ;; TODO: Rewrite with mix & toggle
+  ;; TODO: Rewrite with mix & toggle. Then remix everytime the transducers
+  ;; change?
   (let [lg-ch (tap (:log-sub-ch @db) (chan (sliding-buffer (:freeze-buffer @db))))
         freeze-ch (:freeze-ch @db)]
     (go-loop [is-frozen false]
-      ;; l-chans: What ch to listen
+      ;; l-chans: What chnnels to listen to
       (let [l-chans (if is-frozen [freeze-ch] [freeze-ch lg-ch])
             ;; The transducers that do the global transducing such as rendering
             ;; Might change over time so they're re-evaluated here
-            transd (apply comp
-                          (vals (:transducers @db)))
+            transd (apply comp (vals (:transducers @db)))
             [v ch] (alts! l-chans)]
         (when (= ch lg-ch)
           ;; Put the log event into the db
           (action! db :new-log
-                   (log+rules
-                    ;; TODO: apply the transducer in a channel?
-                    db (single-transduce transd v))))
+                   (log+rules db (single-transduce transd v))))
         (recur (and (= ch freeze-ch) v))))))

@@ -633,20 +636,19 @@
 (defmethod handle-action :new-log
   [db {:keys [data]}]
   {:pre [(valid-log? data)]}
-  (let [data (assoc data ::cached-render (render-msg data))]
-    ;; First put it in the global log message vector:
-    (swap! db update-in [:logs] conj data)
-    ;; Then also put it into all tabs :logs vectors
-    (doseq [tab (keys (:tabs @db))]
-      (let [td (apply comp
-                      (search-transducer db tab)
-                      (get-in @db [:tabs tab :transducers]))
-            ;; A hack: Run a transducer on a single element and pick out the elem
-            data-td (single-transduce td data)
-            kork [:tabs tab :logs]]
-        ;; Don't swap if it's empty. Doh
-        (when-not (empty? data-td)
-          (swap! db update-in kork conj data-td))))))
+  ;; First put it in the global log message vector:
+  (swap! db update-in [:logs] conj data)
+  ;; Then also put it into all tabs :logs vectors
+  (doseq [tab (keys (:tabs @db))]
+    (let [td (apply comp
+                    (search-transducer db tab)
+                    (get-in @db [:tabs tab :transducers]))
+          ;; A hack: Run a transducer on a single element and pick out the elem
+          data-td (single-transduce td data)
+          kork [:tabs tab :logs]]
+      ;; Don't swap if it's empty. Doh
+      (when-not (empty? data-td)
+        (swap! db update-in kork conj data-td)))))

 ;; Invalidades the cached log vector in a certain tab. This is needed when the
 ;; search term is changed or new tab-transduceres were added


change path to comment json to online version

--- src/codeitlater/core.clj
+++ src/codeitlater/core.clj
@@ -7,7 +7,7 @@

 (defn read-json
   ([]
-   (json/read-str (slurp "./src/codeitlater/comments.json")))
+   (json/read-str (slurp "https://raw.githubusercontent.com/ccqpein/codeitlater/master/src/codeitlater/comments.json")))
   ([path]
    (json/read-str (slurp (str path "/comments.json")))))


Add threading to time things. Lets time things out, shall we? Ticks every 15 minutes, selecting a random  follower and creating a model for them.

--- markov-clj/src/markov_clj/twitter.clj
+++ markov-clj/src/markov_clj/twitter.clj
@@ -9,7 +9,8 @@
    [twitter.api.streaming]
    [clojure.data.json :as json ]
    [markov-clj.markov :as markov]
-   [clojure.set :as set])
+   [clojure.set :as set]
+   )
   (:require
    [http.async.client :as ac])
   (:import
@@ -58,7 +59,6 @@
     (loop [candidate (first candidate-tweets)
            others (rest candidate-tweets)]
       (let [final-tweet (str candidate suffix)]
-        (println (count final-tweet) "*****\n" final-tweet)
         (if (< (count final-tweet) 140)
           final-tweet
           (if (empty? others)
@@ -67,7 +67,6 @@

 (defn create-and-send-tweet [[screen-name tweets]]
-  (println screen-name tweets)
   (->> (make-valid-tweet screen-name tweets)
        println
        ;; tweet-the-twitter
@@ -93,8 +92,16 @@
        store-and-reply-to-followers
        ))

-(def ktweets (slurp "resources/koleman_tweets.txt"))
+;; (def ktweets (slurp "resources/koleman_tweets.txt"))

-(defn -main [] (process-followers))
+(defn start-markov-thread []
+  (loop []
+    (Thread/sleep (* 60 15000))
+    (process-followers)
+    (recur)))

-(process-followers)
+(defn -main [] (start-markov-thread))
+
+;; (markov-clj.util/tick-now 500 #(println "Hey there!"))
+
+;; (process-followers)


Update genetic-algorithm.clj

Update genetic-algorithm.clj

--- src/machine_learning/genetic-algorithm.clj
+++ src/machine_learning/genetic-algorithm.clj
@@ -1,4 +1,4 @@
-(ns machine-learning.core
+(ns genetic-algorithm.core
   (:require [clojure.core.matrix :as mat]))

 ;; Aufgabe 3 Genetischer Algorithmus ohne Gray


Use matching verison of cider.

Use matching verison of cider.

--- lein/.lein/profiles.clj
+++ lein/.lein/profiles.clj
@@ -1,8 +1,7 @@
-{:repl {:plugins [[cider/cider-nrepl "0.18.0"]
+{:repl {:plugins [[cider/cider-nrepl "0.18.0-SNAPSHOT"]
                   [refactor-nrepl "2.4.0-SNAPSHOT"]]
         :dependencies
-        [[acyclic/squiggly-clojure "0.1.9-SNAPSHOT"
-          :exclusions [org.clojure/tools.reader]]
+        [[acyclic/squiggly-clojure "0.1.9-SNAPSHOT" :exclusions [org.clojure/tools.reader]]
          [compliment "0.3.5"]]}
  :env {:squiggly
        "{:checkers [:eastwood]


remove :pred from reflexive pronoun "ourselves"

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -1390,8 +1390,7 @@
               :agr {:person :1st
                     :number :plur
                     :gender :fem}
-              :sem {:human true
-                    :pred :noi}
+              :sem {:human true}
               :subcat '()}}

     {:english {:note "♂"}
@@ -1402,8 +1401,7 @@
               :agr {:person :1st
                     :number :plur
                     :gender :masc}
-              :sem {:human true
-                    :pred :noi}
+              :sem {:human true}
               :subcat '()}}]

    "paint"  {:synsem {:cat :verb


add 2 senses of party: could be either a place, or an event

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -1333,10 +1333,12 @@
    "participate"  {:synsem {:cat :verb
                             :sem {:pred :participate}}}

-   "party" {:synsem {:cat :noun
-                     :sem {:pred :party
-                           :place true
-                           :event true}}}
+   "party" [{:synsem {:cat :noun
+                      :sem {:pred :party
+                            :place true}}}
+            {:synsem {:cat :noun
+                      :sem {:pred :party
+                           :event true}}}]

    ;; TODO: 3sing present exception used below to avoid "playies" is not an exception: it's a rule: y->ys.
    ;; the exceptional case is when "ys" is not used (e.g. "tries").


add TODO

add TODO

--- src/babel/italiano/grammar.clj
+++ src/babel/italiano/grammar.clj
@@ -387,6 +387,7 @@
        (filter #(not (fail? %))
                grammar)))

+;; TODO: move to italiano/morphology
 (defn morph-walk-tree [tree]
   (log/debug (str "morph-walk-tree: " (fo tree)))
   (merge


whitespace

whitespace

--- src/babel/italiano/lexicon.clj
+++ src/babel/italiano/lexicon.clj
@@ -11,7 +11,6 @@
                    :person :3rd
                    :gender :fem}
              :propernoun true}}
-
    "Antonio"
    {:synsem {:agr {:number :sing
                    :person :3rd
@@ -19,7 +18,6 @@
              :sem {:pred :antonio
                    :human true}
              :propernoun true}}
-
    "a"
    [(let [location (ref {:place true})]
       {:synsem {:cat :prep
@@ -51,8 +49,7 @@
                            :sem {:pred :abandon}}}

    "abbassare"  {:synsem {:cat :verb
-                                        :sem {:pred :lower}}}
-
+                          :sem {:pred :lower}}}
    "abbracciare"
     {:synsem {:cat :verb
               :essere false
@@ -101,13 +98,11 @@

    "aggiungere" {:synsem {:cat :verb
                           :sem {:pred :add}}}
-
    "aiutare"
     {:synsem {:essere false
               :sem {:pred :aiutare
                     :activity true
                     :obj {:human true}}}}
-
    "alto"
    [;; non-comparative:
     (let [subject-sem (ref {:human true}) ;; only humans can be tall.
@@ -159,7 +154,6 @@
                     :activity false
                     :discrete false
                     :subj {:human true}}}}
-
    "amico"
    (unify agreement-noun
           common-noun
@@ -168,10 +162,8 @@
           {:synsem {:sem {:pred :amico
                           :human true
                           :child false}}})
-
    "ammirare" {:synsem {:cat :verb
                         :sem {:pred :admire}}}
-
    "andare"
     {:italiano {:italiano "andare"
                 :essere true
@@ -187,8 +179,7 @@
               :essere true
               :sem {:subj {:animate true}
                     :pred :andare}}}
-
-
+
 ;   (map (fn [each]
 ;          (unify
 ;           each
@@ -237,7 +228,7 @@

    "approfittare"  {:synsem {:cat :verb
                              :sem {:pred :take-advantage-of}}}
-
+
    "approvare" {:synsem {:cat :verb
                          :sem {:pred :approve}}}

@@ -254,7 +245,6 @@

    "aumentare"   {:synsem {:cat :verb
                            :sem {:pred :increase}}}
-
    "avere"
    (let [avere-common {:synsem {:essere false
                                 :cat :verb}
@@ -811,7 +801,6 @@
                                             :pronoun true
                                             :reflexive true
                                             :sem subject-semantics}}}})
-
       "domani"
       (unify sentential-adverb
              {:synsem {:cat :sent-modifier


ex35 fix

ex35 fix

--- examples/ex35_mandelbrot_julia.clj
+++ examples/ex35_mandelbrot_julia.clj
@@ -147,18 +147,9 @@
   ([[a b]]
    (complex-matrix a b)))

-(defn complex-matrix1
-  "True Complex representation"
-  ([^double a ^double b]
-   (Vec4. a (- b a) (+ a b) (m/sinh a)))
-  ([[a b]]
-   (complex-matrix a b)))
-
-(check-matrix-def complex-matrix1)
-
 ;; window, context and events

-(def matrix-maker (atom complex-matrix1))
+(def matrix-maker (atom complex-matrix))

 (def canvas (make-canvas w w))
 (def window (show-window canvas "Mandelbrot"))


Update maintainer.clj (#1393)

Update maintainer.clj (#1393)

fixes detection of expired instances in instance-tracking

--- waiter/src/waiter/state/maintainer.clj
+++ waiter/src/waiter/state/maintainer.clj
@@ -665,7 +665,7 @@
                                          (let [curr-exp-instance-ids (instances->ids expired-instances)
                                                prev-exp-instances (get service-id->expired-instances service-id)
                                                prev-exp-instance-ids (instances->ids prev-exp-instances)]
-                                           (when-not (not= prev-exp-instance-ids curr-exp-instance-ids)
+                                           (when (not= prev-exp-instance-ids curr-exp-instance-ids)
                                              (let [new-expired-instance-ids (set/difference curr-exp-instance-ids prev-exp-instance-ids)]
                                                (doseq [new-expired-instance (select-instances expired-instances new-expired-instance-ids)]
                                                  (scheduler/log-service-instance new-expired-instance :expire :info)))))


Added error code 301 and 302

Added error code 301 and 302

--- src/clinvar_submitter/form.clj
+++ src/clinvar_submitter/form.clj
@@ -155,36 +155,36 @@
   "Returns clinvar condition name based on available content.
   May log warnings if available content does not conform to
   clinvar specifcations."
-  [t c]
+  [t c r]
   (if (not (nil? c))
   (let [name (get c "name")]
-    (csv-colval (if (nil? name) "" name) "ERROR-condition-name"))
-  (log/error (str "ERROR-condition-name: condition name not found"))))
+    (csv-colval (if (nil? name) "" name) "*E-301"))
+  (report/append-to-report r "\n\n*E-301: Condition disease code or name not provided.")))

 (defn condition-idtype
   ;TODO modify to deal with phenotypes and multi-values for satisfying clinvar specs.
-  [t c]
+  [t c r]
   (if (not (nil? c))
   (let [disease-coding (ld-> t c "disease" "coding")]
     (let [disease-code (get disease-coding "code")]
-      (csv-colval (if (nil? disease-code) "" (get (re-find #"(.*)\_(.*)" disease-code) 1)) "ERROR-condition-idtype")))
-  (log/error (str "ERROR-condition-idtype: condition idt type not found"))))
+      (csv-colval (if (nil? disease-code) "" (get (re-find #"(.*)\_(.*)" disease-code) 1)) "*E-301")))
+  (report/append-to-report r "\n\n*E-301: Condition disease code or name not provided.")))

 (defn condition-idvals
 ;TODO modify to deal with phenotypes and multi-values for satisfying clinvar specs.
-[t c]
+[t c r]
 (if (not (nil? c))
 (let [disease-coding (ld-> t c "disease" "coding")]
 (let [disease-code (get disease-coding "code")]
-(csv-colval (if (nil? disease-code) "" (get (re-find #"(.*)\_(.*)" disease-code) 2)) "ERROR-condition-idvals")))
-(log/error (str "Exception in function condition-idvals: condition id not found"))))
+(csv-colval (if (nil? disease-code) "" (get (re-find #"(.*)\_(.*)" disease-code) 2)) "*E-301")))
+(report/append-to-report r "\n\n*E-301: Condition disease code or name not provided.")))

 (defn condition-moi
-  [t c]
-  (if (not (nil? c)) (csv-colval (if (nil? (ld-> t c "modeOfInheritance" "display")) "" (ld-> t c "modeOfInheritance" "display")) "ERROR-condition-moi")
-  (log/error (str "Exception in function condition-moi: condition moi not found"))))
+  [t c r]
+  (if (not (nil? c)) (csv-colval (if (nil? (ld-> t c "modeOfInheritance" "display")) "" (ld-> t c "modeOfInheritance" "display")) "*E-302")
+  (report/append-to-report r "\n\n*E-302: Mode of Inheritance display value not provided.")))

 (defn get-condition
   "Processes the condition element to derive the ClinVar sanctioned fields:
@@ -211,10 +211,10 @@
   [t i r]
   (let [c (ld-> t i "condition")]
      (if (nil? c) (log/debug (str "Exception in function get-condition: condition not found")))
-     {:name (if (nil? c) "" (condition-name t c)),
-      :idtype (if (nil? c) "" (condition-idtype t c)),
-      :idvalue (if (nil? c) "" (condition-idvals t c)),
-      :moi (if (nil? c) "" (condition-moi t c))}))
+     {:name (if (nil? c) "" (condition-name t c r)),
+      :idtype (if (nil? c) "" (condition-idtype t c r)),
+      :idvalue (if (nil? c) "" (condition-idvals t c r)),
+      :moi (if (nil? c) "" (condition-moi t c r))}))

   (defn evidence-rule-strength
     "Returns the translated strength based on the clingen/acmg recommended


games > rounds

games > rounds

--- src/clj/battlebots/handler.clj
+++ src/clj/battlebots/handler.clj
@@ -34,7 +34,7 @@
   (not-found "Not Found")

   ;; list games
-  (GET "/games" [] (dao/get-games))
+  (GET "/rounds" [] (dao/get-rounds))
   )

 (def app (wrap-middleware #'routes))


Extract a read-file function

Extract a read-file function

--- src/clj/comic_reader/sites.clj
+++ src/clj/comic_reader/sites.clj
@@ -214,13 +214,17 @@
        (filter (complement (memfn isDirectory)))
        (map base-name)))

+(defn read-file [file]
+  (when-let [r1 (some-> file
+                        io/reader
+                        java.io.PushbackReader.)]
+    (with-open [r r1]
+      (read r))))
+
 (defn read-site-options [site-name]
   (if-let [file (-> (str "sites/" site-name ".clj")
                     io/resource)]
-    (with-open [r (-> file
-                      io/reader
-                      java.io.PushbackReader.)]
-      (read r))
+    (read-file file)
     (throw (IllegalArgumentException.
             (str "`sites/" site-name "' "
                  "was not found in the resources.")))))


Don't need parens when using keyword with -> macro

--- src/clj/elephantdb/service.clj
+++ src/clj/elephantdb/service.clj
@@ -65,6 +65,7 @@
         local-dir (:local-dir local-config)
         local-domain-root (str (path local-dir domain))
         remote-path (-> global-config (:domains) (get domain))
+        remote-path (-> global-config :domains (get domain))
         remote-vs (DomainStore. fs remote-path)
         local-vs (DomainStore. lfs local-domain-root (.getSpec remote-vs))]
     (if (domain-needs-update? local-vs remote-vs)


Puppies and kittens

Puppies and kittens

--- src/clj/mokkameister/train.clj
+++ src/clj/mokkameister/train.clj
@@ -43,6 +43,7 @@
    (train ":coffee:" ":timwendelboe:")
    (train ":coffee:" ":jan-richter:")
    (train ":syringe:" ":hocho:")
+   (train ":coffee:" ":heavy_heart_exclamation_mark_ornament:")
    ":steam_locomotive::coffee::coffee::running::running::running::dash:"
    "All aboard the coffee train\n:steam_locomotive::coffee::coffee::running::running::running::dash:"
    "Det er kaffi å få på kjøken!"


Adds the storing of history in app state

--- src/cljs/chess/components.cljs
+++ src/cljs/chess/components.cljs
@@ -33,7 +33,7 @@
     (display-name [_]
       "square")))

-(defn board [{:keys [game] :as app-state} owner]
+(defn board [{:keys [game hist] :as app-state} owner]
   (reify
     om/IInitState
     (init-state [_]
@@ -58,8 +58,10 @@
                        old-selection (om/get-state owner :selected)]
                    (if old-selection
                      (do
-                       (om/transact! app-state :game (fn [b]
-                                            (move b old-selection new-selection)))
+                       (om/transact! app-state
+                                     (fn [{:keys [game hist]}]
+                                       {:game (move game old-selection new-selection)
+                                        :hist (vec (conj (seq hist) game))}))
                        (om/set-state! owner :selected nil))
                      (if (in (deref game) new-selection)
                        (om/set-state! owner :selected new-selection))))


Added database object and its re-rendering

Mithril has to be manually told to
redraw, since update happens outside its purview.

Events and network ops should make redraw happen
automatically.

--- src/cljs/modern_cljs/core.cljs
+++ src/cljs/modern_cljs/core.cljs
@@ -2,13 +2,19 @@
 (ns modern-cljs.core
   (:require [foo.bar] [m]))

+(def db
+  (js-obj "var" (str "tosi: " (rand-int 10))))
+
 (defn ^:export ctrl []
-  (println "Calling major Tom")
-  (js-obj "var" (str "tosi: " (rand-int 10))))
+  (println "Calling major Tom"))
 (defn ^:export viewer [arg]
   (println "Seeing things")
-  (js/m "div" (.-var arg)))
+  (js/m "div" (.-var db)))
 (def app (js-obj "controller" ctrl "view" viewer))
+
+(defn ^:export updatedb [arg]
+  (set! (.-var db) arg)
+  (.redraw js/m true))

 (enable-console-print!)
 (println "Hello All!!!")


[n.threading] Deprecate post* and post-delayed*

Redundant, they are exact copies of respective Java methods.

--- src/clojure/neko/threading.clj
+++ src/clojure/neko/threading.clj
@@ -42,7 +42,7 @@
   [& body]
   `(on-ui* (fn [] ~@body)))

-(defn post*
+(defn ^{:deprecated "3.1.0"} post*
   "Causes the function to be added to the message queue.  The function will
   execute on the UI thread.  Returns true if successfully placed in the message
   queue."
@@ -55,7 +55,7 @@
   [view & body]
   `(post* ~view (fn [] ~@body)))

-(defn post-delayed*
+(defn ^{:deprecated "3.1.0"} post-delayed*
   "Causes the function to be added to the message queue, to be run after the
   specified amount of time elapses.  The function will execute on the UI
   thread.  Returns true if successfully placed in the message


Prepend all acquisition engine logging with [AE]

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

--- acqEngine/src/org/micromanager/mm.clj
+++ acqEngine/src/org/micromanager/mm.clj
@@ -90,7 +90,7 @@
       (clojure.pprint/pprint x))))

 (defn send-to-debug-log [s]
-    (.logMessage mmc s true))
+    (.logMessage mmc (str "[AE] " s) true))

 (defn cleanup-multiline
   "Take a string, remove empty lines and redundant newline-like characters, and


changed return format for the extractors

--- src/crawler/rich_extractor.clj
+++ src/crawler/rich_extractor.clj
@@ -154,12 +154,14 @@
                                       (sort-by second xpaths-scored)))

                                         ; links at the chosen XPaths
-               decision-links       (flatten
+               decision-links       (into
+                                     {}
                                      (map
                                       (fn [[a-decision score]]
-                                        (map
-                                         #(-> % :href)
-                                         (in-host-xpaths-hrefs a-decision)))
+                                        [a-decision
+                                         (map
+                                          #(-> % :href)
+                                          (in-host-xpaths-hrefs a-decision))])
                                       decision))

                                         ; this guy is computing the score products of the decisions alone
@@ -172,17 +174,17 @@
           (do
             (println :url url)
             (println :decision decision)
-            {:links decision-links
-             :action-score decision-scores
-             :xpaths (map first decision)}))
+            {:decision decision-links
+             :score decision-scores}))

          (let [decision (-> url-ds :content-xpaths)
-               decision-links (flatten
-                               (map
-                                (fn [a-decision]
-                                  (map
-                                   #(-> % :href)
-                                   (in-host-xpaths-hrefs a-decision)))
+               decision-links (into
+                               {} (map
+                                   (fn [a-decision]
+                                     [a-decision
+                                      (map
+                                       #(-> % :href)
+                                       (in-host-xpaths-hrefs a-decision))])
                                 decision))
                decision-scores (/ (reduce
                                    (fn [acc a-decision]
@@ -194,9 +196,8 @@
              (println :url url)
              (println :decision decision)
              (println "PAGINATED")
-             {:links decision-links
-              :action-score decision-scores
-              :xpaths decision}))))))
+             {:decision decision-links
+              :score decision-scores}))))))

 (defn pagination?
   "Args:


Moar refactoring

Moar refactoring

--- src/degasolv/resolver_core.clj
+++ src/degasolv/resolver_core.clj
@@ -209,19 +209,19 @@
       result)))

 ;; If transformed value passes test,
-;; return a singleton list of those;
-;; otherwise, return the full list of transformed stuffs.
+;; return the it; otherwise, return an aggregated version of the
+;; values that don't pass the test.
 ;; This is because lazy seqs in clojure aren't exactly lazy;
 ;; they're "chunked" lazy, which is sad. Sad panda :'(
 (defn- first-found
-  [f pred coll]
+  [f aggregate pred coll]
   (reduce
     (fn find-first
       [c v]
       (let [new-v (f v)]
         (if (pred new-v)
           (reduced [new-v])
-          (conj c new-v))))
+          (aggregate c new-v))))
     []
     coll))

@@ -339,6 +339,21 @@
           [:successful
            filtered-query-results])))))

+(defn make-error
+  [present-packages found-packages absent-specs clause reason &
+   {:keys [] :as additional}]
+  (let [base-problem
+        {:term clause
+         :found-packages found-packages
+         :present-packages present-packages
+         :absent-specs absent-specs
+         :reason reason}
+        problem
+        (into base-problem additional)]
+    [:unsuccessful
+     {:problems
+      [problem]}]))
+
 (defn make-resolve-deps
   [conflict-strat
    concat-reqs
@@ -358,15 +373,14 @@
       (let [fclause (first clauses)
             rclauses (rest clauses)
             {:keys [clause parent]}
-            fclause]
+            fclause
+            mkerror (partial make-error
+                             present-packages
+                             found-packages
+                             absent-specs
+                             clause)]
         (if (empty? clause)
-          [:unsuccessful
-           {:problems
-            [{:term clause
-              :found-packages found-packages
-              :present-packages present-packages
-              :absent-specs absent-specs
-              :reason :empty-alternative-set}]}]
+          (mkerror :empty-alternative-set)
           (let [clause-result
                 (first-found
                   (fn try-alternative
@@ -419,8 +433,10 @@
                                (not (nil? found-id-packages))
                                (not (nil? present-id-packages)))
                              (not (= conflict-strat :inclusive)))
-                        [:unsuccessful
-                         {:suggestions
+                        (mkerror
+                          :present-package-conflict
+                          :alternative alternative
+                          :suggestions
                           ;; pass suggestions up the chain
                           (when (and
                                   (nil? present-id-packages)
@@ -433,16 +449,7 @@
                                            absent-specs
                                            id
                                            spec))]
-                              {id pkgs}))
-                          :problems
-                          [
-                           {:term clause
-                            :found-packages found-packages
-                            :present-packages present-packages
-                            :absent-specs absent-specs
-                            :reason :present-package-conflict
-                            :alternative alternative
-                            :package-id id}]}]
+                              {id pkgs})))
                         (= status :absent)
                         (resolve-deps
                           repo
@@ -496,6 +503,7 @@
                                                       (do [%2])
                                                       (conj %1 %2))
                                                    candidate)))
+                                    conj
                                     successful?
                                     filtered-query-results)]
                               (or
@@ -543,6 +551,7 @@
                                     :reason :seek-package-logic-error
                                     :package-id id}]}]))
                             )))))
+conj
 successful?
 ;; Hoisting
 (hoist (cull-alternatives


Add corpses

Add corpses

--- src/dungeon_crusade/update.clj
+++ src/dungeon_crusade/update.clj
@@ -34,8 +34,12 @@
             (fn [npcs]
               (vec (concat (subvec npcs 0 npc-idx)
                            (subvec npcs (inc npc-idx) (count npcs))))))
-          ;; TODO add corpse
-          )
+          ;; maybe add corpse
+          (update-in [:world :places current-place-id y x :items]
+                     (fn [items]
+                       (if (= (rand-int 3) 0)
+                         (conj items {:type :food :name (format "%s corpse" (name (npc :type))) :hunger 10})
+                         items))))
       ;; player dead?
       (not (pos? (- player-hp player-dmg)))
         ;; add dead status


CMR-5081: Add common-app-lib dependency.

--- collection-renderer-lib/project.clj
+++ collection-renderer-lib/project.clj
@@ -27,6 +27,7 @@
     [commons-io]]
   :dependencies [
     [commons-io "2.6"]
+    [nasa-cmr/cmr-common-app-lib "0.1.0-SNAPSHOT"]
     [nasa-cmr/cmr-common-lib "0.1.1-SNAPSHOT"]
     [nasa-cmr/cmr-umm-spec-lib "0.1.0-SNAPSHOT"]
     [org.clojure/clojure "1.8.0"]


Add exemplars for URIs

Add exemplars for URIs

--- test/exemplar.clj
+++ test/exemplar.clj
@@ -4,17 +4,18 @@
 (ns exemplar
   (:require [transit.read :as r]
             [transit.write :as w]
-            [clojure.java.io :as io]))
+            [clojure.java.io :as io])
+  (:import [java.net URI]))

 ;; Generate a set of increasingly complex transit files.
 ;; Output checked into the transit repo under simple-examples.

 (import [java.io File FileOutputStream ByteArrayInputStream ByteArrayOutputStream OutputStreamWriter])

-(defn range-centered-on
+(defn range-centered-on
   ([n] (range-centered-on n 5))
   ([n m] (vec (range (- n m) (+ n m 1)))))
-
+
 (defn vmap [f s]
   (vec (map f s)))

@@ -28,7 +29,7 @@
     (apply
       sorted-map
       (interleave (map #(keyword (format "key%04d" %)) nums) nums))))
-
+
 (defn write-description [file-name description vals]
   (println "##" description)
   (println "* Files:" (str file-name ".edn") (str file-name ".json") (str file-name ".mp"))
@@ -65,30 +66,30 @@
   (write-exemplar "one_keyword" "A single keyword" :hello)
   (write-exemplar "one_symbol" "A single symbol" 'hello)
   (write-exemplar "one_date" "A single date" (java.util.Date. 946728000000))
-
+
   (def vector-simple  [1 2 3])
   (def vector-mixed  [0 1 2.0 true false "five" :six 'seven "~eight" nil])
   (def vector-nested [vector-simple vector-mixed])
-
+
   (write-exemplar "vector_simple" "A simple vector" vector-simple)
   (write-exemplar "vector_empty" "An empty vector" [])
   (write-exemplar "vector_mixed" "A ten element vector with mixed values" vector-mixed)
   (write-exemplar "vector_nested" "Two vectors nested inside of an outter vector" vector-nested)
-
+
   (def small-strings  ["" "a" "ab" "abc" "abcd" "abcde" "abcdef"])
-
+
   (write-exemplar "small_strings" "A vector of small strings" small-strings)
-
+
   (write-exemplar "strings_tilde" "A vector of strings starting with ~" (vmap #(str "~" %) small-strings))

   (write-exemplar "strings_hash" "A vector of strings starting with #" (vmap #(str "#" %) small-strings))

   (write-exemplar "strings_hat" "A vector of strings starting with ^" (vmap #(str "^" %) small-strings))
-
+
   (write-exemplar "small_ints" "A vector of eleven small integers" (range-centered-on 0))

   (write-exemplar "ints", "vector of ints" (vec (range 128)))
-
+
   (def powers-two
        [1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384
         32768 65536 131072 262144 524288 1048576 2097152 4194304
@@ -105,29 +106,29 @@
         2305843009213693952 4611686018427387904 9223372036854775808
         18446744073709551616 36893488147419103232])

-  (def interesting-ints
+  (def interesting-ints
     (vec (apply concat (map #(range-centered-on % 2) powers-two))))
-
-  (write-exemplar
+
+  (write-exemplar
     "ints_interesting"
     "A vector of possibly interesting positive integers"
     interesting-ints)
-
-  (write-exemplar
+
+  (write-exemplar
     "ints_interesting_neg"
     "A vector of possibly interesting negative integers"
     (vmap #(* -1 %) interesting-ints))
-
+
   (write-exemplar
     "doubles_small"
     "A vector of eleven doubles from -5.0 to 5.0"
     (vmap #(double %) (range-centered-on 0)))
-
+
   (write-exemplar
     "doubles_interesting"
     "A vector of interesting doubles"
     [-3.14159 3.14159 4E11 2.998E8 6.626E-34])
-
+
   (def uuids [#uuid "5a2cbea3-e8c6-428b-b525-21239370dd55"
               #uuid "d1dc64fa-da79-444b-9fa4-d4412f427289"
               #uuid "501a978e-3a3e-4060-b3be-1cf2bd4b1a38"
@@ -139,7 +140,15 @@
     "uuids"
     "A vector of uuids"
     uuids)
-
+
+  (def uris [(URI. "http://example.com")
+             (URI. "ftp://example.com")
+             (URI. "file:///path/to/file.txt")
+             (URI. "http://www.詹姆斯.com/")])
+
+  (write-exemplar "one_uri" "A single URI" (first uris))
+
+  (write-exemplar "uris" "A vector of URIs" uris)

   (def dates (vmap #(java.util.Date. %) [-6106017600000 0 946728000000 1396909037000]))

@@ -149,10 +158,10 @@
     dates)

   (def symbols ['a 'ab 'abc 'abcd 'abcde 'a1 'b2 'c3 'a_b])
-
+
   (write-exemplar "symbols" "A vector of symbols" symbols)
   (write-exemplar "keywords" "A vector of keywords" (vmap keyword symbols))
-
+
   (write-exemplar "list_simple" "A simple list" (apply list vector-simple))
   (write-exemplar "list_empty" "An empty list" '())
   (write-exemplar "list_mixed" "A ten element list with mixed values" (apply list vector-mixed))
@@ -164,12 +173,12 @@
   (write-exemplar "set_mixed" "A ten element set with mixed values" (set vector-mixed))
   (write-exemplar "set_mixed" "Two sets nested inside an outter set"
     (set [(set vector-simple) (set vector-mixed)]))
-
+

   (def map-simple {:a 1 :b 2 :c 3})
   (def map-mixed {:a 1 :b "a string" :c true})
   (def map-nested {:simple map-simple, :mixed map-mixed})
-
+
   (write-exemplar "map_simple" "A simple map" map-simple)
   (write-exemplar "map_mixed" "A mixed map" map-mixed)
   (write-exemplar "map_nested" "A nested map" map-nested)
@@ -177,43 +186,43 @@
   (write-exemplar "map_string_keys" "A map with string keys" {"first" 1, "second" 2, "third" 3})

   (write-exemplar "map_numeric_keys" "A map with numeric keys" {1 "one", 2 "two"})
-
+
   (write-exemplar "map_vector_keys" "A map with vector keys" {[1 1] "one", [2 2] "two"})
-
+
   (write-exemplar "map_10_items" "10 item map"  (map-of-size 10))
-
+
   (doseq [i [10 90 91 92 93 94 95]]
-    (write-exemplar
+    (write-exemplar
       (str "map_" i "_nested")
       (str "Map of two nested " i " item maps")
       {:f (map-of-size i) :s (map-of-size i)}))
-
-  (write-exemplar
+
+  (write-exemplar
     "maps_two_char_sym_keys"
     "Vector of maps with identical two char symbol keys"
     [{:aa 1 :bb 2} {:aa 3 :bb 4} {:aa 5 :bb 6}])
-
-  (write-exemplar
+
+  (write-exemplar
     "maps_three_char_sym_keys"
     "Vector of maps with identical three char symbol keys"
     [{:aaa 1 :bbb 2} {:aaa 3 :bbb 4} {:aaa 5 :bbb 6}])
-
-  (write-exemplar
+
+  (write-exemplar
     "maps_four_char_sym_keys"
     "Vector of maps with identical four char symbol keys"
     [{:aaaa 1 :bbbb 2} {:aaaa 3 :bbbb 4} {:aaaa 5 :bbbb 6}])
-
-  (write-exemplar
+
+  (write-exemplar
     "maps_two_char_string_keys"
     "Vector of maps with identical two char string keys"
     [{"aa" 1 "bb" 2} {"aa" 3 "bb" 4} {"aa" 5 "bb" 6}])
-
-  (write-exemplar
+
+  (write-exemplar
     "maps_three_char_string_keys"
     "Vector of maps with identical three char string keys"
     [{"aaa" 1 "bbb" 2} {"aaa" 3 "bbb" 4} {"aaa" 5 "bbb" 6}])
-
-  (write-exemplar
+
+  (write-exemplar
     "maps_four_char_string_keys"
     "Vector of maps with identical four char string keys"
     [{"aaaa" 1 "bbbb" 2} {"aaaa" 3 "bbbb" 4} {"aaaa" 5 "bbbb" 6}])


so cassandra compares timeuuids as always smaller than other uuids

--- src/er_cassandra/util/time.clj
+++ src/er_cassandra/util/time.clj
@@ -49,3 +49,24 @@
     (if (not= tsc 0)
       tsc
       (compare (str timeuuid-a) (str timeuuid-b)))))
+
+(defn cassandra-uuid-compare
+  "it seems cassandra always compares timeuuids as lower than
+   non-timeuuids, so that's a thing"
+  [a b]
+  (let [ts-a (uuid/get-timestamp a)
+        ts-b (uuid/get-timestamp b)]
+    (cond
+      (and ts-a ts-b)
+      (timeuuid-comparator a b)
+
+      (and (nil? ts-a) (nil? ts-b))
+      (compare (str a) (str b))
+
+      ts-a
+      -1
+
+      ts-b
+      1
+
+      :else (throw (ex-info "huh?" {:a a :b b})))))


Add auth function

Add auth function

--- frontend/src/crunsher/communication/auth.cljs
+++ frontend/src/crunsher/communication/auth.cljs
@@ -1,13 +1,9 @@
 (ns crunsher.communication.auth
   (:require [ajax.core :refer [POST]]
-            [goog.crypt.base64 :as gtfo]
             [crunsher.communication.utils :as com]
             [crunsher.config :as config]
-            [crunsher.debug :as debug]
-            [crunsher.utils.common :as lib]
             [crunsher.communication.main :as com]
-            [crunsher.communication.utils :as clib]
-            ))
+            [crunsher.communication.utils :as clib]))

 (defn success-login
   "Callback function when login was successful. Set attributes of user."
@@ -17,11 +13,12 @@

 (defn ajax-login
   "Get cleaned data and send ajax request."
-  [nickname password]
-  (let [url (str (:base config/api) "login")]
+  [email password location]
+  (let [url (:login config/api)]
     (POST (clib/make-url url)
-          {:body            (clib/clj->json {:nickname nickname
-                                            :password password})
+          {:body            (clib/clj->json {:email email
+                                             :password password
+                                             :location location})
            :handler         success-login
            :error-handler   com/error-handler
            :response-format :json
@@ -30,8 +27,9 @@

 (defn login
   "Use login form data, validate it and send ajax request."
-  [nickname password]
+  [email password location]
   (when (and
-          (pos? (count nickname))
-          (pos? (count password)))
-    (ajax-login nickname password)))+          (pos? (count email))
+          (pos? (count password))
+          (pos? (count location)))
+    (ajax-login email password location)))


skip non-k8s pools in k8s cluster (#1608)

--- scheduler/src/cook/kubernetes/compute_cluster.clj
+++ scheduler/src/cook/kubernetes/compute_cluster.clj
@@ -352,23 +352,28 @@
     (async/chan 1))

   (pending-offers [this pool-name]
-    (log/info "In" name "compute cluster, looking for offers for pool" pool-name)
-    (let [timer (timers/start (metrics/timer "cc-pending-offers-compute" name))
-          pods (add-starting-pods this @all-pods-atom)
-          nodes @current-nodes-atom
-          offers-this-pool (generate-offers this (get-name->node-for-pool @pool->node-name->node pool-name)
-                                            (->> (get-pods-in-pool this pool-name)
-                                                 (add-starting-pods this)
-                                                 (api/pods->node-name->pods)))
-          offers-this-pool-for-logging (into #{}
-                                             (map #(into {} (select-keys % [:hostname :resources]))
-                                                  offers-this-pool))]
-      (log/info "In" name "compute cluster, generated" (count offers-this-pool) "offers for pool" pool-name
-                {:num-total-nodes-in-compute-cluster (count nodes)
-                 :num-total-pods-in-compute-cluster (count pods)
-                 :offers-this-pool offers-this-pool-for-logging})
-      (timers/stop timer)
-      offers-this-pool))
+    (let [node-name->node (get @pool->node-name->node pool-name)]
+      (if-not (or (cc/autoscaling? this pool-name) node-name->node)
+        (log/info "In" name "compute cluster, not looking for offers for pool" pool-name
+                  ". Skipping pool because it is not a known Kubernetes pool.")
+        (do
+          (log/info "In" name "compute cluster, looking for offers for pool" pool-name)
+          (let [timer (timers/start (metrics/timer "cc-pending-offers-compute" name))
+                pods (add-starting-pods this @all-pods-atom)
+                nodes @current-nodes-atom
+                offers-this-pool (generate-offers this (or node-name->node {})
+                                                  (->> (get-pods-in-pool this pool-name)
+                                                       (add-starting-pods this)
+                                                       (api/pods->node-name->pods)))
+                offers-this-pool-for-logging (into #{}
+                                                   (map #(into {} (select-keys % [:hostname :resources]))
+                                                        offers-this-pool))]
+            (log/info "In" name "compute cluster, generated" (count offers-this-pool) "offers for pool" pool-name
+                      {:num-total-nodes-in-compute-cluster (count nodes)
+                       :num-total-pods-in-compute-cluster (count pods)
+                       :offers-this-pool offers-this-pool-for-logging})
+            (timers/stop timer)
+            offers-this-pool)))))

   (restore-offers [this pool-name offers])


Make the lock vector a vector, not a sequence. (#1842)

Co-authored-by: Scott Crosby <23e8f75489aff47cf2cd5a529e9a769a24e9501c@twosigma.com>

--- scheduler/src/cook/kubernetes/compute_cluster.clj
+++ scheduler/src/cook/kubernetes/compute_cluster.clj
@@ -785,7 +785,8 @@
                                                     (atom state-locked?)
                                                     dynamic-cluster-config?
                                                     compute-cluster-launch-rate-limiter cook-pool-taint-name cook-pool-taint-prefix cook-pool-label-name
-                                                    (with-meta (repeatedly lock-shard-count #(ReentrantLock.))
+                                                    ; Vector instead of seq for O(1) access.
+                                                    (with-meta (vec (repeatedly lock-shard-count #(ReentrantLock.)))
                                                         {:json-value (str "<count of " lock-shard-count " ReentrantLocks>")}))]
     (cc/register-compute-cluster! compute-cluster)
     compute-cluster))


Add a nonsense 'Leagues' link to make it clear how to opt-in to golfing

--- src/foreclojure/utils.clj
+++ src/foreclojure/utils.clj
@@ -156,7 +156,10 @@
         (when user
           [:div#lower-menu
            [:span
-             (link-to "/login/update" "Account Settings")]
+            (link-to "/login/update" "Account Settings")]
+           (when (:golfing-active config)
+             [:span ; deserves its own page, but just make it discoverable for now
+              (link-to "/login/update" "Leagues")])
            (when (approver? user)
              [:span
                (link-to "/problems/unapproved" "View Unapproved Problems")])


Fix error in bash output of lists

Fix error in bash output of lists

--- src/nml/core.clj
+++ src/nml/core.clj
@@ -10,31 +10,31 @@
 ;; formatting

 (defn- fmt-bash [m]
-  (fmt-sh m #(str "\"$(echo $" % " | tr [:upper:] [:lower:])\"")))
+  (fmt-sh m))

 (defn- fmt-json [m]
-  (with-out-str (json/pprint m)))
+  (println m)
+  "")
+;;   (with-out-str (json/pprint m)))

 (defn- fmt-ksh [m]
-  (fmt-sh m #(str "\"$(echo $" % " | tr [:upper:] [:lower:])\"")))
+  (fmt-sh m))

 (defn- fmt-namelist [m]
   (let [f0 (fn [[dataref vals]] (str "  " dataref "=" (valstr vals) "\n"))
         f1 (fn [[name nv_sequence]] (str "&" name "\n" (strmap f0 (sort nv_sequence)) "/\n"))]
     (strmap f1 (sort m))))

-(defn- fmt-sh [m lo]
-  (let [ms  (sort m)
-        n   (lo 1)
-        k   (lo 2)
-        eq #(string/replace % "\"" "\\\"")
-        f0  (fn [[dataref vals]]
-              (let [v (eq (apply str vals))]
-                (str "'" dataref "') echo \"" v "\";;")))
-        f1  (fn [[name nv_sequence]]
-              (let [x (strmap f0 nv_sequence)]
-                (str "'" name "') case " k " in " x "*) echo '';;esac;;" )))]
-    (str "nmlquery(){ case " n " in " (strmap f1 ms) "*) echo '';;esac; }\n")))
+(defn- fmt-sh [m]
+  (let [lo #(str "\"$(echo $" % " | tr [:upper:] [:lower:])\"")
+        esc-quotes #(string/replace % "\"" "\\\"")
+        f0 (fn [[dataref vals]]
+             (let [v (esc-quotes (valstr vals))]
+               (str "'" dataref "') echo \"" v "\";;")))
+        f1 (fn [[name nv_sequence]]
+             (let [x (strmap f0 nv_sequence)]
+               (str "'" name "') case " (lo 2) " in " x "*) echo '';;esac;;" )))]
+    (str "nmlquery(){ case " (lo 1) " in " (strmap f1 (sort m)) "*) echo '';;esac; }\n")))

 ;; defs