working tree-add-edge for simple case

working tree-add-edge for simple case

--- src/hackerrank/even_tree.clj
+++ src/hackerrank/even_tree.clj
@@ -15,10 +15,19 @@
 (defn make-tree []
   '())

+(defn sort-tree-fn [a b]
+  ; (println "compare" a b "number?" (number? a) "list?" (list? b))
+  (cond (and (number? a) (list? b)) -1
+        (and (list? a) (number? b)) 1
+        (and (list? a) (list? b)) (compare (first a) (first b))
+        :else 0))
+
+(println (sort sort-tree-fn '((3) 1 (2))))
+
 (defn tree-add-edge [tree a b]
   (if (empty? tree)
     (cons b (cons (cons a nil) nil))
-    (conj tree (cons a nil))))
+    (sort sort-tree-fn (conj tree (cons a nil)))))
 ; :else
 ; find [traverse tree  root with b value
 ; add to it a child
@@ -98,9 +107,13 @@
 (cons t '(a))
 (cons (first t) (cons (cons 'a nil) nil))

-; (sort [[3] 1 [2]])
+(defn sort-tree-fn [a b]
+  ; (println "compare" a b "number?" (number? a) "list?" (list? b))
+  (cond (and (number? a) (list? b)) -1
+        (and (list? a) (number? b)) 1
+        (and (list? a) (list? b)) (compare (first a) (first b))
+        :else 0))

-(sort  #(or (> (last %1) (last %2))
-             (and (= (last %1) (last %2))
-                  (< (first %1) (first %2))))
-       (shuffle '((3) 1 (2))))
+(println (sort sort-tree-fn '((3) 1 (2))))
+
+(list? '(3))


Updated record printing to match output from Clojure.

--- src/clj/cljs/core.clj
+++ src/clj/cljs/core.clj
@@ -121,7 +121,7 @@

 (defn- emit-defrecord
    "Do not use this directly - use defrecord"
-  [tagname fields impls]
+  [tagname rname fields impls]
   (let [hinted-fields fields
         fields (vec (map #(with-meta % nil) fields))
         base-fields fields
@@ -189,7 +189,7 @@
 		  `(~'-pr-seq [this# opts#]
 			      (let [pr-pair# (fn [keyval#] (pr-sequential pr-seq "" " " "" opts# keyval#))]
 				(pr-sequential
-				 pr-pair# (str "#:" ~(name tagname) "{") ", " "}" opts#
+				 pr-pair# (str "#" ~(name rname) "{") ", " "}" opts#
 				 (concat [~@(map #(list `vector (keyword %) %) base-fields)]
 					 ~'__extmap))))
 		  ])]
@@ -217,7 +217,7 @@
 (defmacro defrecord [rsym fields & impls]
   (let [r (:name (cljs.compiler/resolve-var (dissoc &env :locals) rsym))]
     `(let []
-       ~(emit-defrecord rsym fields impls)
+       ~(emit-defrecord rsym r fields impls)
        ~(build-positional-factory rsym r fields)
        ~(build-map-factory rsym r fields))))


install-cost-bonus.

install-cost-bonus.

--- src/clj/game/core.clj
+++ src/clj/game/core.clj
@@ -413,6 +413,14 @@
       (+ (or (get-in @state [:bonus :trash]) 0))
       (max 0)))

+(defn install-cost-bonus [state side n]
+  (swap! state update-in [:bonus :install-cost] (fnil #(+ % n) 0)))
+
+(defn install-cost [state side {:keys [cost] :as card}]
+  (-> cost
+      (+ (or (get-in @state [:bonus :install-cost]) 0))
+      (max 0)))
+
 (defn damage-count [state side dtype n {:keys [unpreventable unboostable] :as args}]
   (-> n
       (+ (or (when (not unboostable) (get-in @state [:damage :damage-bonus dtype])) 0))
@@ -814,23 +822,25 @@
   ([state side card] (runner-install state side card nil))
   ([state side {:keys [title type cost memoryunits uniqueness] :as card}
     {:keys [extra-cost no-cost host-card] :as params}]
-   (if-let [hosting (and (not host-card) (:hosting (card-def card)))]
-     (resolve-ability state side
-                      {:choices hosting
-                       :effect (effect (runner-install card (assoc params :host-card target)))} card nil)
-     (let [cost (if no-cost 0 cost)]
-       (when (and (or (not uniqueness) (not (in-play? state card)))
-                  (if-let [req (:req (card-def card))]
-                    (req state side card nil) true)
-                  (pay state side card :credit cost (when memoryunits [:memory memoryunits]) extra-cost))
-         (let [c (if host-card
-                   (host state side host-card card)
-                   (move state side card [:rig (to-keyword type)]))
-               installed-card (card-init state side c)]
-           (system-msg state side (str "installs " title
-                                       (when host-card (str " on " (:title host-card)))
-                                       (when no-cost " at no cost")))
-           (trigger-event state side :runner-install installed-card)))))))
+    (swap! state update-in [:bonus] dissoc :install-cost)
+    (trigger-event state side :pre-install card)
+    (if-let [hosting (and (not host-card) (:hosting (card-def card)))]
+      (resolve-ability state side
+                       {:choices hosting
+                        :effect (effect (runner-install card (assoc params :host-card target)))} card nil)
+      (let [cost (if no-cost 0 (install-cost state side card))]
+        (when (and (or (not uniqueness) (not (in-play? state card)))
+                   (if-let [req (:req (card-def card))]
+                     (req state side card nil) true)
+                   (pay state side card :credit cost (when memoryunits [:memory memoryunits]) extra-cost))
+          (let [c (if host-card
+                    (host state side host-card card)
+                    (move state side card [:rig (to-keyword type)]))
+                installed-card (card-init state side c)]
+            (system-msg state side (str "installs " title
+                                        (when host-card (str " on " (:title host-card)))
+                                        (when no-cost " at no cost")))
+            (trigger-event state side :runner-install installed-card)))))))

 (defn server-list [state card]
   (let [remotes (cons "New remote" (for [i (range (count (get-in @state [:corp :servers :remote])))]


pre-damage event trigger.

pre-damage event trigger.

--- src/clj/game/core.clj
+++ src/clj/game/core.clj
@@ -365,11 +365,20 @@
     (when-let [events (:events cdef)] (register-events state side events c))
     (get-card state c)))

+(defn damage-count [state side dtype n]
+  (max 0 (if-let [bonus (get-in @state [:special :damage-bonus dtype])]
+                 (+ n bonus) n)))
+
+(defn damage-bonus [state side dtype n]
+      ;(system-msg state side (str (+ n (get-in state [:special :damage-bonus dtype]))))
+  (swap! state update-in [:special :damage-bonus dtype] (fnil #(+ % n) 0)))
 (defn flatline [state]
   (system-msg state :runner "is flatlined"))

 (defn damage [state side type n]
-  (let [hand (get-in @state [:runner :hand])]
+  (trigger-event state side :pre-damage type)
+  (let [n (damage-count state side type n) hand (get-in @state [:runner :hand])]
+       (system-msg state side (str n " " type))
     (when (< (count hand) n)
       (flatline state))
     (when (= type :brain)
@@ -377,7 +386,8 @@
       (swap! state update-in [:runner :max-hand-size] #(- % n)))
     (doseq [c (take n (shuffle hand))]
       (trash state side c type))
-    (trigger-event state side :damage type)))
+    (trigger-event state side :damage type))
+  (swap! state update-in [:special :damage-bonus] dissoc type))

 (defn shuffle! [state side kw]
   (swap! state update-in [side kw] shuffle))


Fix some typos

Fix some typos

--- src/io/aviso/rook/client.clj
+++ src/io/aviso/rook/client.clj
@@ -220,13 +220,16 @@
   : indicate what status code(s) to respond to, and what to do with the response

   A clause can either be :pass-success, :pass-failure, or a single status code followed by vector.
-  The first elmeent in the vector is a symbol to which the response will be bound before evaluating
+  The first element in the vector is a symbol to which the response will be bound before evaluating
   the other forms in the vector. The result of the then block is the value of the last form
   in the selected block.

+  Instead of a vector, the symbol :pass means that the response simply passes though as the
+  result of the then block.
+
   then is specifically designed to work within a go block; this means that within a clause,
-  it is allowed to use the non-blocking forms <!, >!, and so forth. This would not be possible
-  if the then macro worked by relating a status code to a callback function.
+  it is allowed to use the non-blocking forms <!, >!, and so forth (this would not be possible
+  if the then macro worked by relating a status code to a callback function).

   Instead of a specific status code, you may use :success (any 2xx status code), :failure (any other
   status code), or :else (which matches regardless of status code).
@@ -236,8 +239,6 @@

   :pass-success is equvalent to :success :pass and :pass-failure is equivalent to :failure :pass.

-  In addition, you may also specify :pass instead of the vector in a clause.
-  This also passes the response through unchanged.

   Example:


version

version

--- src/ipython_clojure/core.clj
+++ src/ipython_clojure/core.clj
@@ -7,7 +7,6 @@
            [clj-time.format :as time-format]
            [com.keminglabs.zmq-async.core :refer [register-socket!]]
            [clojure.core.async :refer [sliding-buffer >! <! go chan close!]])
-  (:import [org.jeromq ZMQ])
   (:gen-class :main true))

 (defn prep-config [args]
@@ -16,53 +15,44 @@
 (defn address [config service]
   (str (:transport config) "://" (:ip config) ":" (service config)))

-(defn get-iopub-socket [addr]
-  (let [context (zmq/context 1)]
-    (doto zmq/socket context :pub) (zmq/bind addr)))
-
-(defn get-shell-socket [addr]
-  (let [context (zmq/context 2)]
-    (doto (zmq/socket context :router) (zmq/bind addr))))
-
 (defn uuid [] (str (java.util.UUID/randomUUID)))
-

 (def kernel-info-content
   {:protocol_version [4 1]
-   :ipython_version [2 0 0 "dev"]
-   :language_version [1 5 1]
-   :language "clojure"})
+   :ipython_version  [3 1 0 "dev"]
+   :language_version [1 7 0]
+   :language         "clojure"})

 (defn now []
   "Returns current ISO 8601 compliant date."
   (let [current-date-time (time/to-time-zone (time/now) (time/default-time-zone))]
     (time-format/unparse
-     (time-format/with-zone (time-format/formatters :date-time-no-ms)
-                            (.getZone current-date-time))
-     current-date-time)))
+      (time-format/with-zone (time-format/formatters :date-time-no-ms)
+                             (.getZone current-date-time))
+      current-date-time)))

 (defn kernel-info-header [message]
-  (let [header (cheshire/generate-string {:date (get-in message [:header :date])
-                                          :msg_id (uuid)
+  (let [header (cheshire/generate-string {:date     (get-in message [:header :date])
+                                          :msg_id   (uuid)
                                           :username (get-in message [:header :username])
-                                          :session (get-in message [:header :session])
+                                          :session  (get-in message [:header :session])
                                           :msg_type "kernel_info_reply"})]
     header))

 (defn send-message-piece [socket msg]
-;  (println "Sending piece " msg)
+  ;  (println "Sending piece " msg)
   (zmq/send socket (.getBytes msg) zmq/send-more))

 (defn finish-message [socket msg]
-;  (println "Sending message " msg)
+  ;  (println "Sending message " msg)
   (zmq/send socket (.getBytes msg)))

 (defn kernel-info-reply [message socket]
   (let [header (kernel-info-header message)
         parent_header (cheshire/generate-string (:header message))
         metadata (cheshire/generate-string {})
-        content  (cheshire/generate-string kernel-info-content)]
+        content (cheshire/generate-string kernel-info-content)]
     (send-message-piece socket (get-in message [:header :session]))
     (send-message-piece socket "<IDS|MSG>")
     (send-message-piece socket "")
@@ -78,16 +68,16 @@

 (defn read-until-delimiter [socket]
   (let [preamble (doall (drop-last
-                         (take-while (comp not #(= "<IDS|MSG>" %))
-                                     (repeatedly #(read-blob socket)))))]
-;    (println "PREABMLE:" preamble)
+                          (take-while (comp not #(= "<IDS|MSG>" %))
+                                      (repeatedly #(read-blob socket)))))]
+    ;    (println "PREABMLE:" preamble)
     preamble))

 (defn new-header [msg_type session-id]
-  {:date (now)
-   :msg_id (uuid)
+  {:date     (now)
+   :msg_id   (uuid)
    :username "kernel"
-   :session session-id
+   :session  session-id
    :msg_type msg_type})

 (defn status-content [status]
@@ -95,12 +85,12 @@

 (defn pyin-content [execution-count message]
   {:execution_count execution-count
-   :code (get-in message [:content :code])})
+   :code            (get-in message [:content :code])})

 (defn pyout-content [execution-count message executer]
   {:execution_count execution-count
-   :data {:text/plain (pr-str (eval (read-string (get-in message [:content :code]))))}
-   :metadata {}
+   :data            {:text/plain (pr-str (eval (read-string (get-in message [:content :code]))))}
+   :metadata        {}
    })

@@ -119,12 +109,12 @@

 (defn read-message [socket]
-  {:uuid (read-until-delimiter socket)
-   :signature (read-blob socket)
-   :header (cheshire/parse-string (read-blob socket) keyword)
+  {:uuid          (read-until-delimiter socket)
+   :signature     (read-blob socket)
+   :header        (cheshire/parse-string (read-blob socket) keyword)
    :parent-header (cheshire/parse-string (read-blob socket) keyword)
-   :metadata (cheshire/parse-string (read-blob socket) keyword)
-   :content (cheshire/parse-string (read-blob socket) keyword)})
+   :metadata      (cheshire/parse-string (read-blob socket) keyword)
+   :content       (cheshire/parse-string (read-blob socket) keyword)})

 (defn execute-request-handler [shell-socket iopub-socket executer]
   (let [execution-count (atom 0N)]
@@ -137,18 +127,18 @@
         (send-message iopub-socket "pyin" (pyin-content @execution-count message)
                       parent-header {} session-id)
         (send-message shell-socket "execute_reply"
-                      {:status "ok"
-                       :execution_count @execution-count
-                       :user_variables {}
-                       :payload [{}]
+                      {:status           "ok"
+                       :execution_count  @execution-count
+                       :user_variables   {}
+                       :payload          [{}]
                        :user_expressions {}}
                       parent-header
                       {:dependencies_met "True"
-                       :engine session-id
-                       :status "ok"
-                       :started (now)} session-id)
-        (send-message iopub-socket "pyout"  (pyout-content @execution-count
-                                                           message executer)
+                       :engine           session-id
+                       :status           "ok"
+                       :started          (now)} session-id)
+        (send-message iopub-socket "pyout" (pyout-content @execution-count
+                                                          message executer)
                       parent-header {} session-id)
         (send-message iopub-socket "status" (status-content "idle")
                       parent-header {} session-id)))))
@@ -157,10 +147,10 @@
   "evaluates s-forms"
   ([request] (execute request *ns*))
   ([request user-ns]
-    (str
-      (try
-        (binding [*ns* user-ns] (eval (read-string request)))
-        (catch Exception e (.getLocalizedMessage e))))))
+   (str
+     (try
+       (binding [*ns* user-ns] (eval (read-string request)))
+       (catch Exception e (.getLocalizedMessage e))))))

 (defn generate-ns []
   "generates ns for client connection"
@@ -174,9 +164,9 @@
   (let [user-ns (generate-ns)]
     (fn [request]
       (str
-       (try
-         (binding [*ns* user-ns] (eval (read-string request)))
-         (catch Exception e (.getLocalizedMessage e)))))))
+        (try
+          (binding [*ns* user-ns] (eval (read-string request)))
+          (catch Exception e (.getLocalizedMessage e)))))))

 (defn configure-shell-handler [shell-socket iopub-socket]
@@ -196,14 +186,14 @@
             ))))))

 (defrecord Heartbeat [addr]
-    Runnable
-    (run [this]
-      (let [context (zmq/context 1)
-            socket (doto (zmq/socket context :rep)
-                     (zmq/bind addr))]
-        (while (not (.. Thread currentThread isInterrupted))
-          (let [message (zmq/receive socket)]
-            (zmq/send socket message))))))
+  Runnable
+  (run [this]
+    (let [context (zmq/context 1)
+          socket (doto (zmq/socket context :rep)
+                   (zmq/bind addr))]
+      (while (not (.. Thread currentThread isInterrupted))
+        (let [message (zmq/receive socket)]
+          (zmq/send socket message))))))

 (defrecord Shell [shell-addr iopub-addr]
   Runnable


Exercise 2.30, 2.31, 2.32

Exercise 2.30, 2.31, 2.32

--- src/sicp/chapter2/2_2.clj
+++ src/sicp/chapter2/2_2.clj
@@ -1,5 +1,6 @@
 (ns sicp.chapter2.2-2
-  (:require [sicp.chapter2.2-1 :refer [reverse']]))
+  (:require [sicp.chapter1.1-4 :refer [square]]
+            [sicp.chapter2.2-1 :refer [reverse']]))

 ;;;; 2.2  Hierarchical Data and the Closure Property

@@ -61,10 +62,24 @@
 ;; TODO

 ;; Exercise 2.30
-;; TODO
+(defn square-tree [tree]
+  (map (fn [t]
+         (if (not (seq? t))
+           (square t)
+           (square-tree t)))
+       tree))

 ;; Exercise 2.31
-;; TODO
+(defn tree-map [f tree]
+  (map (fn [t]
+         (if (not (seq? t))
+           (f t)
+           (tree-map f t)))
+       tree))

 ;; Exercise 2.32
-;; TODO
+(defn subsets [s]
+  (if (empty? s)
+    (list ())
+    (let [rest' (subsets (rest s))]
+      (concat rest' (map (fn [x] (cons (first s) x)) rest')))))


don't store _content, build index when loading

--- src/sledge/db.clj
+++ src/sledge/db.clj
@@ -172,5 +172,5 @@
     index))

 (defn save-entry [index k v]
-  (swap! (:data index) assoc k (assoc v "_content" (str/join " " (vals v))))
+  (swap! (:data index) assoc k v)
   v)


Add tracks api

Add tracks api

--- src/trak/api.cljs
+++ src/trak/api.cljs
@@ -43,3 +43,12 @@
             (fn [response] (pubsub/publish :actions {:action :api-call-result
                                                      :params {:call     :user-playlists
                                                               :response response}}))))
+
+(defn playlist [href auth]
+  (api-call (partial http/get)
+            href
+            {:with-credentials? false
+             :oauth-token       auth}
+            (fn [response] (pubsub/publish :actions {:action :api-call-result
+                                                     :params {:call     :playlist-tracks
+                                                              :response response}}))))


Parsing complete

Parsing complete

--- src/trek/core.clj
+++ src/trek/core.clj
@@ -8,18 +8,23 @@
 (def basic
   (insta/parser
     "S = line-number ws+ statement #';'?
-     statement = comment | gosub | print | print-using | input | if | assignment | dim | def | mat | for | goto | next | image
+     statement = comment | gosub | print | print-using | input | if | assignment | dim | def | mat | for | goto | next | image | return | end
      ws = #'[ \t]'
      comment = \"REM\" #'.*'
-     image = \"IMAGE\"
+     end = \"END\"
+     return = \"RETURN\"
+     image = \"IMAGE\" ws+ (format | quoted-string) (',' format-list)*
+     format-list = (format | quoted-string) (',' format-list)*
+     format = integer format-type | format-type | (integer \"(\" format-list \")\")
+     format-type = \"D\" | \"X\" | \"A\"
      gosub = \"GOSUB\" ws+ line-number
-     print = \"PRINT\" (ws+ value (value | ';')*)?
-     print-using = \"PRINT\" ws+ \"USING\" ws+ integer ';' expression (',' expression)*
-     input = \"INPUT\" ws+ identifier
+     print = \"PRINT\" (ws+ expression ((\",\")? expression | ';')*)?
+     print-using = \"PRINT\" ws+ \"USING\" ws+ integer (';' expression (',' expression)*)?
+     input = \"INPUT\" ws+ identifier (\",\" identifier)*
      dim = \"DIM\" ws+ array-defs
      def = \"DEF\" ws+ identifier '(' fn-args ')' '=' expression
      mat = \"MAT\" ws+ identifier '=ZER'
-     for = \"FOR\" ws+ identifier ws* '=' integer ws+ 'TO' ws+ (integer | identifier)
+     for = \"FOR\" ws+ identifier ws* '=' expression ws+ 'TO' ws+ expression
      if = \"IF\" ws+ bool-expression ws+ 'THEN' ws+ line-number
      goto = \"GOTO\" ws+ integer-expression (ws+ 'OF' ws+ integer (',' integer)*)?
      next = \"NEXT\" ws+ identifier
@@ -53,7 +58,9 @@
        (map basic)
        (filter :reason)
        first))
-(parse)
+
+
+
 (defn -main
   "I don't do a whole lot ... yet."
   [& args]


deleted pages

deleted pages

--- src/ui/pages.cljs
+++ src/ui/pages.cljs
@@ -1,10 +0,0 @@
-(ns ui.pages
-  (:require [om.core :as om]
-            [om.dom :as dom]
-            [sablono.core :as html :refer-macros [html]]))
-
-(defn about [_ _]
-  (om/component
-    (html
-     [:div
-      [:h2 "About Page"]])))


Nix unnecessary double-URI-ing

Nix unnecessary double-URI-ing

See comment on issue #12 - https://github.com/daveliepmann/uruk/issues/12#issuecomment-249600051

--- src/uruk/core.clj
+++ src/uruk/core.clj
@@ -583,7 +583,7 @@
   [{:keys [uri user password content-base]} & [content-source]]
   (let [cs (if (instance? ContentSource content-source)
              content-source
-             (make-uri-content-source (URI. uri)))]
+             (make-uri-content-source uri))]
     (cond
       (and (nil? content-base)
            (or (nil? user)


test hook

test hook

--- src/main/cawala/api/read.clj
+++ src/main/cawala/api/read.clj
@@ -6,7 +6,7 @@
                      :person/relation :friend}
                  2  {:db/id 2 :person/name "Sally" :person/age 22
                      :person/relation :friend}
-                 3  {:db/id 3 :person/name "Allie" :person/age 57
+                 3  {:db/id 3 :person/name "Allie" :person/age 56
                      :person/relation :enemy}
                  4  {:db/id 4 :person/name "Zoe" :person/age 32
                      :person/relation :friend}


fixed broken unit-test

fixed broken unit-test

--- test/org/domaindrivenarchitecture/pallet/servertest/test/netstat_test.clj
+++ test/org/domaindrivenarchitecture/pallet/servertest/test/netstat_test.clj
@@ -45,7 +45,7 @@
   (testing
     "test parsing netstat-output"
       (is (= "sshd"
-             (:program-name
+             (:process-name
                (first (sut/parse-netstat netstat-resource)))))
       ))


Resolved merge conflict.

Resolved merge conflict.

--- test/cmr/system_int_test/data2/granule.clj
+++ test/cmr/system_int_test/data2/granule.clj
@@ -3,7 +3,6 @@
   (:require [cmr.umm.granule :as g]
             [cmr.umm.collection :as c]
             [cmr.umm.granule.temporal :as gt]
-            [cmr.umm.granule.temporal-coverage :as gt]
             [cmr.system-int-test.data2.core :as d]
             [cmr.common.date-time-parser :as p]))


core/q was renamed to core/qws

core/q was renamed to core/qws

--- test/com/billpiel/mem_tracer/core_test.clj
+++ test/com/billpiel/mem_tracer/core_test.clj
@@ -470,7 +470,7 @@
           trace (mt/deref-workspace!)]

       (fact "find node by name and all parents"
-        (mt/q :a [:name] #".*func3-4")
+        (mt/qws :a [:name] #".*func3-4")
         =>  [{:path [:root10]
               :children
               [{:args [3 8]


Fix another test.

Fix another test.

--- test/onyx/coordinator/single_peer_test.clj
+++ test/onyx/coordinator/single_peer_test.clj
@@ -104,15 +104,20 @@
                 (let [task-nodes (extensions/bucket-at sync :task job-id)
                       tasks (map #(extensions/read-place-at sync :task job-id %) task-nodes)]
                   (fact (count task-nodes) => 3)
-                  (fact (into #{} (map :task/name tasks)) => #{:in :inc :out})))
-
-         #_(facts ":in's ingress queue is generated"
-                (let [query '[:find ?qs :where
-                              [?t :task/name :in]
-                              [?t :task/ingress-queues ?qs]]]
-                  (fact (d/q query db) =not=> empty?)))
-
-         #_(facts ":inc's ingress queue is :in's egress queue"
+                  (fact (into #{} (map :task/name tasks)) => #{:in :inc :out})
+
+                  (facts ":in has an ingress queue")
+                  (let [task (first (filter #(= (:task/name %) :in) tasks))
+                        in-queues (:task/ingress-queues task)]
+                    (fact in-queues =not=> nil?))
+
+                  (facts ":inc's ingress queue is one of :in's egress queues"
+                         (let [in (first (filter #(= (:task/name %) :in) tasks))
+                               inc (first (filter #(= (:task/name %) :inc) tasks))]
+                           (fact (:task/ingress-queues inc) =>
+                                 (first (:task/egress-queues in)))))))
+
+         #_(facts
                 (let [in-query '[:find ?qs :where
                                  [?t :task/name :in]
                                  [?t :task/egress-queues ?qs]]


made grammar threshold adjustable

made grammar threshold adjustable

--- src/ziad/pos.cljc
+++ src/ziad/pos.cljc
@@ -19,8 +19,9 @@
 ;; below this probability a token
 ;; will be marked as a grammar issues
 (def grammar-threshold
-  #?(:clj 4/1000000
-     :cljs 0.000004))
+  (atom
+   #?(:clj 4/1000000
+      :cljs 0.000004)))

 (defn word-toks
   "Given:
@@ -198,8 +199,10 @@
          (if (>= cnt 2)
            (let [tri (conj (subvec stack (- cnt 2) cnt) tok)
                  sem-tri (create-semantic-tri tri)
-                 prob (get-in model [:tri-model sem-tri] grammar-threshold)]
-             (if (<= prob grammar-threshold)
+                 prob (get-in model
+                              [:tri-model sem-tri]
+                              @grammar-threshold)]
+             (if (<= prob @grammar-threshold)
                (into (subvec stack 0 (- cnt 2))
                      (map #(assoc % :grammar-issue true
                                     :tr-prob prob) tri))


adds proper theshold to colours

adds proper theshold to colours

--- src/svg_thing/colour.cljs
+++ src/svg_thing/colour.cljs
@@ -15,7 +15,10 @@

 ;; Num -> String
 (defn- to-hex-channel [number]
-  (let [trimmed (mod number 255)]
+  (let [trimmed (cond
+                  (< number 0)  0
+                  (> number 255) 255
+                  :else number)]
     (if (>= trimmed 16)
       (.toString trimmed 16)
       (str \0 trimmed))))


gorilla repl update

gorilla repl update


Add more server related translation strings.

--- src/uxbox/locales/en.cljs
+++ src/uxbox/locales/en.cljs
@@ -52,6 +52,8 @@

    "history.alert-message" "You are seeng version %s"
    "errors.api.form.old-password-not-match" "Incorrect old password"
+   "errors.api.form.email-already-exists" "The email is already in use by other user."
+   "errors.api.form.username-already-exists" "The username is already in use by other user."
    "errors.form.required" "This field is mandatory"
    "errors.form.string" "Should be string"
    "errors.form.number" "Invalid number"


(maint) Whitespace and superfluous vec call

--- src/puppetlabs/trapperkeeper/authorization/acl.clj
+++ src/puppetlabs/trapperkeeper/authorization/acl.clj
@@ -48,14 +48,13 @@

 (schema/defn ^:private split-domain :- [String]
   "Given a domain string, split it on '.' and reverse it. For examples,
-  'sylvia.plath.net' becomes ['net' 'plath' 'sylvia']. This is used for domain
+  'sylvia.plath.net' becomes ('net' 'plath' 'sylvia'). This is used for domain
   matching."
-  [pattern :- String]
-  (-> pattern
+  [domain :- String]
+  (-> domain
       (clojure.string/lower-case)
       (clojure.string/split #"\.")
-      reverse
-      vec))
+      reverse))

 (schema/defn new-domain :- Entry
   "Creates a new ACE for a domain"
@@ -125,7 +124,7 @@
   (if (= (:match ace) :backreference)
     (new-domain (ace :auth-type)
                 (clojure.string/join "." (map #(substitute-backreference % captures)
-                                   (reverse (ace :pattern)))))
+                                              (reverse (ace :pattern)))))
     ace))

 (schema/defn match? :- schema/Bool


Minor cleanup.

Minor cleanup.

--- src/onyx/peer/read_batch.clj
+++ src/onyx/peer/read_batch.clj
@@ -14,21 +14,19 @@
   (:import [java.util.concurrent.locks LockSupport]))

 (defn read-function-batch [state]
-  (let [messenger (get-messenger state)
-        batch (m/poll messenger)]
-    (if batch
-      (let [pbatch (persistent! batch)]
-        (debug "Read batch:" pbatch (select-keys (get-event state) [:onyx.core/task-id]))
-        (-> state
-            (set-event! (assoc (get-event state) :onyx.core/batch pbatch))
-            (advance)))
-      (do
-       ;; not ideal to park here, as it's a bit of a special case, however
-       ;; this is the easiest way to achieve a backoff.
-       ;; It should be parking for batch-timeout.
-       ;; We can't simply block as we will not continue reading barriers.
-       (LockSupport/parkNanos (* 2 1000000))
-       (advance state)))))
+  (if-let [batch (m/poll (get-messenger state))]
+    (let [pbatch (persistent! batch)]
+      (debug "Read batch:" pbatch (select-keys (get-event state) [:onyx.core/task-id]))
+      (-> state
+          (set-event! (assoc (get-event state) :onyx.core/batch pbatch))
+          (advance)))
+    (do
+     ;; not ideal to park here, as it's a bit of a special case, however
+     ;; this is the easiest way to achieve a backoff.
+     ;; It should be parking for batch-timeout.
+     ;; We can't simply block as we will not continue reading barriers.
+     (LockSupport/parkNanos (* 2 1000000))
+     (advance state))))

 (defn read-input-batch [state]
   (let [{:keys [onyx.core/task-map onyx.core/id


massively simplify diotonic-modes

massively simplify diotonic-modes

--- src/overtone/music/pitch.clj
+++ src/overtone/music/pitch.clj
@@ -108,25 +108,27 @@

 (def DIOTONIC-MODES
   (let [ionian-sequence [2 2 1 2 2 2 1]
-        offset-order [:ionian :dorian :phrygian :lydian :mixolydian :aeolian :lochrian]
-        offsets (into {} (map-indexed (fn [i el] [el i]) offset-order))
         ionian-len (count ionian-sequence)
         rotate-ionian (fn [offset] (drop offset (take (+ ionian-len offset) (cycle ionian-sequence))))]
-    {:ionian     (rotate-ionian (:ionian offsets))
-     :major      (rotate-ionian (:ionian offsets))
-     :dorian     (rotate-ionian (:dorian offsets))
-     :phrygian   (rotate-ionian (:phrygian offsets))
-     :lydian     (rotate-ionian (:lydian offsets))
-     :mixolydian (rotate-ionian (:mixolydian offsets))
-     :aeolian    (rotate-ionian (:aeolian offsets))
-     :minor      (rotate-ionian (:aeolian offsets))
-     :lochrian   (rotate-ionian (:lochrian offsets))}))
-
-; Various scale intervals in terms of steps on a piano, or midi note numbers
+    {:ionian     (rotate-ionian 0)
+     :major      (rotate-ionian 0)
+     :dorian     (rotate-ionian 1)
+     :phrygian   (rotate-ionian 2)
+     :lydian     (rotate-ionian 3)
+     :mixolydian (rotate-ionian 4)
+     :aeolian    (rotate-ionian 5)
+     :minor      (rotate-ionian 5)
+     :lochrian   (rotate-ionian 6)}))
+
+;; Various scale intervals in terms of steps on a piano, or midi note numbers
+;; All sequences should add up to 12 - the number of semitones in an octave
 (def SCALES
-  {:pentatonic        [2 2 3 2]
-   :wholetone         [2 2 2 2 2]
-   :chromatic         [1 1 1 1 1 1 1 1 1 1 1]
+  {:diatonic          [2 2 1 2 2 2 1]
+   :pentatonic        [2 3 2 2 3]
+   :whole-tone        [2 2 2 2 2 2]
+   :chromatic         [1 1 1 1 1 1 1 1 1 1 1 1]
+   :harmonic-minor    [2 1 2 2 1 3 1]
+
    :octatonic         [2 1 2 1 2 1 2]
    :messiaen1         [2 2 2 2 2]
    :messiaen2         [2 1 2 1 2 1 2]
@@ -135,14 +137,8 @@
    :messiaen5         [1 4 1 1 4]
    :messiaen6         [2 2 1 1 2 2 1]
    :messiaen7         [1 1 1 2 1 1 1 1 2]
-   :ionian            [2 2 1 2 2 2]
-   :dorian            [2 1 2 2 2 1]
-   :phrygian          [1 2 2 2 1 2]
-   :lydian            [2 2 2 1 2 2]
-   :lydian-mixolydian [2 1 2 1 2 1 2]
-   :mixolydian        [2 2 1 2 2 1]
-   :aeolian           [2 1 2 2 1 2]
-   :locrian           [1 2 2 1 2 2]})
+   :lydian-mixolydian [2 1 2 1 2 1 2]})
+
 ;; * Diatonic function
 ;;   - in terms of centeredness around the root, this is the order
 ;; of chord degrees: I, V, IV, vi, iii, ii, vii (The first 3 chords


Add fps

Add fps

--- src/play_clj/core_global.clj
+++ src/play_clj/core_global.clj
@@ -15,6 +15,7 @@
   (case key
     :width `(.getWidth (Gdx/graphics))
     :height `(.getHeight (Gdx/graphics))
+    :fps `(.getFramesPerSecond (Gdx/graphics))
     :is-fullscreen? `(.isFullscreen (Gdx/graphics))
     :is-touched? `(.isTouched (Gdx/input))
     :x `(.getX (Gdx/input))


Rename function for consistency

Rename function for consistency

--- src/play_clj/core_render.clj
+++ src/play_clj/core_render.clj
@@ -142,19 +142,19 @@
   [screen new-width]
   (size! screen new-width (* new-width (/ (game :height) (game :width)))))

-(defn move-x!
+(defn x!
   [{:keys [^Camera camera]} x]
   (assert camera)
   (when x (set! (. (. camera position) x) x))
   (.update camera))

-(defn move-y!
+(defn y!
   [{:keys [^Camera camera]} y]
   (assert camera)
   (when y (set! (. (. camera position) y) y))
   (.update camera))

-(defn move!
+(defn position!
   [screen x y]
-  (move-x! screen x)
-  (move-y! screen y))
+  (x! screen x)
+  (y! screen y))


bump up the denorm relationship sizes

bump up the denorm relationship sizes

--- test/er_cassandra/model/alia/relationship_test.clj
+++ test/er_cassandra/model/alia/relationship_test.clj
@@ -144,13 +144,13 @@
 (deftest update-two-sources-many-records-test
   (let [[sa sb t] (create-two-source-relationship :none)

-        acnt 1
+        acnt 10
         ;; all source-a records start out with :factor 1
         saids (repeatedly acnt uuid/v1)
         sars (for [said saids] {:ida said :factor 1})

-        bcnt 10
+        bcnt 1000
         ;; initial source-b record :values are drawn from 1..bcnt
         sbids (repeatedly bcnt uuid/v1)
         sbrs (map (fn [sbid v] {:idb sbid :value v}) sbids (iterate inc 1))


Create player's React component with reagent/create-class

--- src/asciinema/player/view.cljs
+++ src/asciinema/player/view.cljs
@@ -1,5 +1,6 @@
 (ns asciinema.player.view
   (:require [clojure.string :as string]
+            [reagent.core :as reagent]
             [reagent.ratom :refer-macros [reaction]]
             [cljs.core.async :refer [chan >! <! put! alts! timeout dropping-buffer pipe]]
             [asciinema.player.messages :as m]
@@ -326,11 +327,17 @@
         loaded (reaction (:loaded @player))
         {:keys [title author author-url author-img-url]} @player]
     (pipe user-activity-ch msg-ch)
-    (fn []
-      [:div.asciinema-player-wrapper {:tab-index -1 :on-key-press on-key-press :on-key-down on-key-down :on-mouse-move on-mouse-move :class-name @wrapper-class-name}
-       [:div.asciinema-player {:class-name @player-class-name}
-        [terminal width height font-size screen cursor-on]
-        [recorded-control-bar playing current-time total-time msg-ch]
-        (when (or title author) [title-bar title author author-url author-img-url])
-        (when-not (or @loading @loaded) [start-overlay msg-ch])
-        (when @loading [loading-overlay])]])))
+    (reagent/create-class
+     {:display-name "asciinema-player"
+      :reagent-render (fn [player msg-ch]
+                        [:div.asciinema-player-wrapper {:tab-index -1
+                                                        :on-key-press on-key-press
+                                                        :on-key-down on-key-down
+                                                        :on-mouse-move on-mouse-move
+                                                        :class-name @wrapper-class-name}
+                         [:div.asciinema-player {:class-name @player-class-name}
+                          [terminal width height font-size screen cursor-on]
+                          [recorded-control-bar playing current-time total-time msg-ch]
+                          (when (or title author) [title-bar title author author-url author-img-url])
+                          (when-not (or @loading @loaded) [start-overlay msg-ch])
+                          (when @loading [loading-overlay])]])})))


Save all the maps attached to a wallet as well.

--- src/asid/wallet_repository.clj
+++ src/asid/wallet_repository.clj
@@ -13,7 +13,13 @@
         (nrl/create root asid-root :asid)
         {:root asid-root}))))

+(defn attach-to-node [node link data]
+  (let [data-node (nn/create data)]
+        (nrl/create node data-node link)))
+
 (defn save [ctxt wallet]
   (let [node (nn/create {:identity (:identity wallet)})]
+    (doseq [data [:bag :signatures :key]]
+      (attach-to-node node data (get wallet data)))
     (nrl/create (:root ctxt) node :wallet)
     wallet))


cleanup whitespace

cleanup whitespace

--- src/babel/english/grammar.cljc
+++ src/babel/english/grammar.cljc
@@ -181,10 +181,9 @@
                                        :cat :noun
                                        :propernoun propernoun
                                        :sem {:number number-agreement}}
-                              :head {:phrasal true
+                             :head {:phrasal true
                                      :synsem {:propernoun propernoun}}
                               :comp {:phrasal false}})) ;; rathole prevention ;; TODO: see if this can be removed.
-
                    (unifyc h10
                            {:rule "prepositional-phrase"
                             :synsem {:cat :prep}})


arrive + PP[at]

arrive + PP[at]

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -79,7 +79,11 @@
    "arrive" [{:synsem {:cat :verb
                        :sem {:pred :arrive
                              :subcat {:2 {:cat :prep
-                                          :sem {:pred :at}}}}}}]
+                                          :sem {:pred :at}}}}}}
+             {:synsem {:cat :verb
+                       :sem {:pred :arrive
+                             :subcat {:2 '()}}}}]
+
    "ask" {:synsem {:cat :verb
                    :sem {:pred :chiedere}}}


aspect: progressive -> simple

aspect: progressive -> simple

--- src/babel/espanol/grammar.cljc
+++ src/babel/espanol/grammar.cljc
@@ -309,7 +309,7 @@
                             :synsem {:aux false
                                      :infl :present
                                      :cat :verb
-                                     :sem {:aspect :progressive
+                                     :sem {:aspect :simple
                                            :tense :present}}})
                    (unifyc c10
                            root-is-head
@@ -318,7 +318,7 @@
                             :synsem {:aux false
                                      :infl :present
                                      :cat :verb
-                                     :sem {:aspect :progressive
+                                     :sem {:aspect :simple
                                            :tense :present}}})
                    (unifyc h21
                            {:rule "vp-infinitive"
@@ -471,7 +471,7 @@
      :generate {:lexicon lexicon-for-generation} ;; filter out null subjects.
      :grammar grammar
      :lexicon lexicon
-     :lexical-cache (atom (cache/fifo-cache-factory {} :threshold 1024))
+     :lexical-cache (cache/fifo-cache-factory {} :threshold 1024)
      :morph fo
      :morph-ps fo-ps
      :morph-walk-tree (fn [tree]


more rpg stuff

more rpg stuff

--- src/main/cljc/clojure_club/rpg_spec/mbastian.cljc
+++ src/main/cljc/clojure_club/rpg_spec/mbastian.cljc
@@ -55,4 +55,26 @@
 (s/def ::character
   (s/keys :req [::name ::race ::character-class ::character-stats ::skills ::weapon-class]))

-(gen/sample (s/gen ::character) 10)+(gen/sample (s/gen ::character) 10)
+
+(defn save [c attr]
+  {:pre [(s/assert ::character c)]}
+  (get-in c [::character-stats attr]))
+
+(save (first (gen/sample (s/gen ::character) 10)) ::str)
+
+(save
+  {:name "",
+   :race :clojure-club.rpg-spec.mbastian/elf,
+   :character-class :clojure-club.rpg-spec.mbastian/ranger,
+   :character-stats {:str 6,
+                     :dex 4,
+                     :con 4,
+                     :int 3,
+                     :wis 4,
+                     :cha 5},
+   :skills #{:survival},
+   :weapon-class :meelee}
+  ::str)
+
+(save 3 4)


added template module to returned model

added template module to returned model

--- src/crawler/crawl.clj
+++ src/crawler/crawl.clj
@@ -299,9 +299,12 @@

 (defn sample-sitemap
   ([start]
-     (let [start-body   (download-with-cookie start)
-           to-eliminate (template-removal/all-xpaths start-body start my-cs)]
-       (sample-sitemap [{:url start}] (set []) (set []) to-eliminate [] 10)))
+     (sample-sitemap start 10))   ; at least 10 threads please
+
+  ([start limit]
+     (let [start-body   (utils/download-with-cookie start)
+           to-eliminate (template-removal/all-xpaths start-body start utils/my-cs)]
+       (sample-sitemap [{:url start}] (set []) (set []) to-eliminate [] limit)))

   ([queue visited observed to-eliminate leaf-paths limit]
      (if (and
@@ -352,7 +355,7 @@
               _          (println :src-score (try (double (first src-nav-num))
                                                   (catch Exception e nil)))
               _          (println :target-score (try
-                                                  (double score)
+                                                  (double l-score)
                                                   (catch Exception e nil)))
               mined      (when-not leaf?
                            (rich-char-extractor/filter-content
@@ -377,7 +380,7 @@
                                concat
                                (map
                                 (fn [{xpath :xpath
-                                     score :score
+                                     l-score :score
                                      hrefs :hrefs
                                      text  :texts}]
                                   ;; take only a 25 % sample from here.
@@ -411,7 +414,7 @@
                                concat
                                (map
                                 (fn [{xpath :xpath
-                                     score :score
+                                     l-score :score
                                      hrefs :hrefs
                                      text  :texts}]
                                   ;; take only a 25 % sample from here.
@@ -460,7 +463,11 @@
              (cons nil src-xp)
              leaf-paths)
             (dec limit)))))
-      (frequencies leaf-paths))))
+       {:to-remove to-eliminate
+        :model     (reverse
+                    (sort-by
+                     second
+                     (frequencies leaf-paths)))})))

 (defn crawl
   [start crawler-type num-docs]


Left navbar is a single component now to make active work properly


Coils: Link records with SAVED in playback mode

--- src/webapp/server/fns.clj
+++ src/webapp/server/fns.clj
@@ -28,8 +28,11 @@

-(defn process-ask-for-endorsement [send-endorsement-neo4j-node]
+(defn process-ask-for-endorsement
+  [ send-endorsement-neo4j-node ]
+;----------------------------------------------------------------
   (if send-endorsement-neo4j-node
+
     (let
       [
        confirm-sender-code    (uuid-str)
@@ -153,6 +156,8 @@
     (check-timer)
     ))

+
+
 (defn create-session[{:keys [init-state browser]}]
   (let [
         session-id    (uuid-str)
@@ -191,6 +196,9 @@
     {:success false}

     ))
+
+
+

 (defn add-history [{:keys [session-id  history-order  timestamp  path new-value]}]
@@ -229,7 +237,7 @@
             ;(println web-record)
             (neo4j "START n=node(*), m=node(*)
                    where id(n)={ws} and id(m)={wr}
-                   create (n)-[:FRIENDSHIP {status:2}]->(m)
+                   create (n)-[:SAVED]->(m)
                    " {:ws (:neo-id session) :wr (:neo-id web-record)})

             []
@@ -392,6 +400,7 @@

+
 (defn get-company-details [{:keys [company-url]}]
   (neo4j "match
            (n:Company)<-[:WORKS_FOR]-(w:Person)<-[e:ENDORSE]-someone
@@ -410,6 +419,6 @@

-; read the reased schemer
-; does it work in clojurescript?
-
+; read the reasoned schemer
+; does core.logic work in clojurescript?
+


Upgrade deps.

Upgrade deps.

--- lein/.lein/profiles.clj
+++ lein/.lein/profiles.clj
@@ -7,10 +7,10 @@
   :dependencies [[clojure-ini "0.0.2"]
                  [me.raynes/fs "1.4.6"]]
   :plugins [[jonase/eastwood "0.2.3"]
-            [lein-ancient "0.6.8"]
-            [lein-bikeshed "0.3.0"]
+            [lein-ancient "0.6.10"]
+            [lein-bikeshed "0.4.1"]
             [lein-ns-dep-graph "0.1.0-SNAPSHOT"]
-            [refactor-nrepl "0.2.2"]]
+            [refactor-nrepl "2.2.0"]]
   ;; VisualVM profiling opts
   ;; :jvm-opts ["-Dcom.sun.management.jmxremote"
   ;;            "-Dcom.sun.management.jmxremote.ssl=false"


Point frontend WF ajax to api.circleci.com

--- src-cljs/frontend/api.cljs
+++ src-cljs/frontend/api.cljs
@@ -76,7 +76,7 @@

 (defn get-workflow-status [api-ch]
   (ajax/ajax :post
-             "http://localhost:3009/query"
+             "https://api.circleci.com/query"
              :workflow-status
              api-ch
              :format :transit))


fixed typo causing runtime exception

fixed typo causing runtime exception

--- src/clinvar_submitter/form.clj
+++ src/clinvar_submitter/form.clj
@@ -177,7 +177,7 @@
         codes, that may exist."
   [sym-tbl c interp-num]
   (let [full-moi (ld-> sym-tbl c "has disposition" "label")
-        [moi moiadj] (re-seq #"\w[\w\s\-]*\w", full-moi)
+        [moi moiadj] (re-seq #"\w[\w\s\-]*\w" full-moi)
         final-moi (if (and (some? moiadj) (= "Other" moi)) moiadj moi)]
     (csv-colval final-moi)))


Kaffidoktor

Kaffidoktor

--- src/clj/mokkameister/train.clj
+++ src/clj/mokkameister/train.clj
@@ -56,6 +56,7 @@
    (train-coffee :timwendelboe)
    (train-coffee :jan-richter)
    (train-coffee :scream)
+   (train-coffee :doctor)
    (train-coffee :smoking)
    (train-coffee :heavy_heart_exclamation_mark_ornament)
    (train-coffee :badger :mushroom)


Remove non-unicode emoji (for matrix.org)

--- src/clj/mokkameister/train.clj
+++ src/clj/mokkameister/train.clj
@@ -2,7 +2,6 @@
   (:require [mokkameister.random :refer [rand-nth-weighted rand-sexp]]))

 (def ^:private locomotives {:steam_locomotive 9
-                            :bybane2 3
                             :bullettrain_front 3
                             :train 1
                             :horse 2
@@ -12,7 +11,6 @@
                             :tractor 1})

 (def ^:private train-endings {:dash 8
-                              :afterburner 2
                               :sparkles 2
                               :sweat_drops 2
                               :exclamation 1
@@ -53,47 +51,29 @@
    (train-coffee :heart)
    (train-coffee :heartpulse)
    (train-coffee :heartbeat)
-   (train-coffee :blockchain)
    (train-coffee :syringe)
    (train-coffee :mushroom)
-   (train-coffee :coffeepot)
-   (train-coffee :chemex)
-   (train-coffee :coffeealarm)
    (train-coffee :hocho)
    (train-coffee :wrench)
    (train-coffee :tada)
    (train-coffee :bacon)
-   (train-coffee :nuclear)
-   (train-coffee :timwendelboe)
-   (train-coffee :jan-richter)
    (train-coffee :scream)
    (train-coffee :doctor)
    (train-coffee :smoking)
    (train-coffee :fingers_crossed)
    (train-coffee :battery)
    (train-coffee :bomb)
-   (train-coffee :iot)
-   (train-coffee :verynice)
    (train-coffee :zap)
    (train-coffee :cake)
    (train-coffee :notes)
    (train-coffee :fuelpump)
    (train-coffee :alarm_clock)
-   (train-coffee :sirene)
+   (train-coffee :rotating_light)
    (train-coffee :punch)
-   (train-coffee :el_kanno)
-   (train-coffee :arrow_right :el_kanno)
    (train-coffee :monkey_face :wrench)
    (train-coffee :heavy_heart_exclamation_mark_ornament)
    (train-coffee :badger :mushroom)
-   (train-coffee :coffeepot :heart)
-   (train-coffee :simply_overcaffeinated :coffeespin)
    (train :heartbeat :heartpulse)
-   (train :ffi :coffee)
-   (train :blockchain)
-   (train :coffeealarm)
-   (train :nespresso :ali)
-   (train :ali :gruff)
    (train :syringe :hocho)
    (train :scream_cat :scream)
    (train-custom :coffee :coffee :running :running :running :dash)
@@ -108,5 +88,5 @@
    "M-m-m-m-m-microdosing! :syringe::syringe::syringe::exclamation:"
    "PLEASE PROCEED IN ORDERLY FASHION TO RECEIVE COFFEE :syringe:"
    "COFFEES WILL CONTINUE UNTIL MORALE IMPROVES! :facepunch::coffee:"
-   ":coffeealarm: BALLISTIC COFFEE TREAT INBOUND TO REVOLVERHUSET. SEEK IMMEDIATE COFFEE CUP. THIS IS NOT A DRILL. :coffeealarm:"
+   ":rotating_light: BALLISTIC COFFEE TREAT INBOUND TO REVOLVERHUSET. SEEK IMMEDIATE COFFEE CUP. THIS IS NOT A DRILL. :rotating_light:"
    ":steam_locomotive::coffee::coffee::coffee::coffee::coffee::coffee::coffee::coffee::coffee::coffee::coffee::coffee::coffee::coffee::coffee::coffee::coffee::coffee::coffee::coffee::coffee::dash:"))


Fix linear index merge

Fix linear index merge

--- src/cljam/bam_index/writer.clj
+++ src/cljam/bam_index/writer.clj
@@ -223,7 +223,12 @@
 ;;; slow ...
 (defn- merge-lidx
   [lidx1 lidx2]
-  {:index (vec (map min (:index lidx1) (:index lidx2))) ; OPTIMIZE
+  {:index (vec (map (fn [l1 l2]
+                      (cond
+                        (zero? l1) l2
+                        (zero? l2) l1
+                        :else (min l1 l2)))
+                    (:index lidx1) (:index lidx2))) ; OPTIMIZE
    :largest-seen (max (:largest-seen lidx1) (:largest-seen lidx2))})


Fixes incorrect PGN tag ordering.

Fixes incorrect PGN tag ordering.

--- src/clojure/clj_chess/game.clj
+++ src/clojure/clj_chess/game.clj
@@ -17,7 +17,7 @@
 (defn new-game
   "Creates a new game object with the given PGN tags and start position. The
   seven standard tags that make up the \"Seven Tag Roster\" in the PGN standard
-  are supplied by induvidual keyword parameters, as is the start-fen parameter
+  are supplied by individual keyword parameters, as is the start-fen parameter
   that is used to specify the initial position of the game. If any further PGN
   tags are desired, they should be supplied in a sequence of two-element
   vectors of the form [<tag-name> <tag-value>]."
@@ -27,12 +27,12 @@
            start-fen board/start-fen}}]
   (let [root-node {:board (board/make-board start-fen)
                    :node-id (generate-id)}]
-     {:tags (concat [["White" white]
-                     ["Black" black]
-                     ["Event" event]
+     {:tags (concat [["Event" event]
                      ["Site" site]
                      ["Date" date]
                      ["Round" round]
+                     ["White" white]
+                     ["Black" black]
                      ["Result" result]]
                     other-tags)
       :root-node root-node


Fix for significant memory leak caused by not detaching node state from parent-state when disposing.

--- src/clojure/freactive/dom.cljs
+++ src/clojure/freactive/dom.cljs
@@ -102,7 +102,10 @@
    ;(println "disposing" dom-node)
    (let [node-id (get-node-id dom-node)
          state (aget element-state-lookup node-id)]
-     (dispose-node node-id state)))
+     (dispose-node node-id state)
+     (when-let [parent-state (.-parent-state state)]
+       (when-let [child-states (.-child-states parent-state)]
+         (js-delete child-states node-id)))))
   ([child-key state]
    (when state
      (set! (.-disposed state) true)


latest updates

latest updates

--- src/clojure_conj_talk/core.clj
+++ src/clojure_conj_talk/core.clj
@@ -88,6 +88,8 @@
 ;; But future doesn't really fit here, as it returns a promise, why not make
 ;; it return a channel? This is what core.async's thread macro does:

+(thread 42)
+
 (<!! (thread 42))

 (thread (println "It works!" (<!! (thread 42))))
@@ -99,6 +101,7 @@
 ;; does. It lets you write code that looks like the above code,
 ;; but it re-writes all your code to use callbacks.

+(go 42)

 (<!! (go 42))


don't invoke t.n.r from cljs

don't invoke t.n.r from cljs

--- src/deferst/core.cljc
+++ src/deferst/core.cljc
@@ -116,6 +116,12 @@
           (str/join "-")
           symbol)))

+(defn refresh-start
+  "refresh and start on clj... error on cljs"
+  [after-sym]
+  #?(:clj (tn/refresh :after after-sym)
+     :cljs (throw (js/Error. "not implemented on cljs"))))
+
 #?(:clj
    (defn- defsystem*
      [base-name builder default-conf]
@@ -136,11 +142,8 @@
           (defn ~stop-name [] (deferst/stop! ~name))
           (defn ~reload-name []
             (deferst/stop! ~name)
-            (tn/refresh
-             :after
-             (symbol
-              (name (ns-name *ns*))
-              (name '~start-name))))))))
+            (refresh-start
+             (symbol (name (ns-name *ns*)) (name '~start-name))))))))

 #?(:clj
    (defmacro defsystem


check for checked value when using multiple checkboxes with the same name (ie, the browser will send the values of a b and c as 'a,b,c')

--- src/ez_form/field.clj
+++ src/ez_form/field.clj
@@ -79,6 +79,8 @@
                                     (if (and
                                          (not (nil? value))
                                          (or checked?
+                                             (if (string? (:value opts))
+                                               (some #(= value %) (str/split #"," (:value opts))))
                                              (= value (:value opts))
                                              (= "on" (:value opts))
                                              (= "on" value)))


Update layout.clj

Update layout.clj

--- src/cornwalltechjam/layout.clj
+++ src/cornwalltechjam/layout.clj
@@ -97,7 +97,7 @@
             [:img {:src "/assets/img/meetup-logo.svg"}]]]]
          [:div {:class "dropdown animated fadeInDown animation-delay-11"}
           [:a {:href "/index.html", :class "dropdown-toggle", :data-toggle "dropdown"}
-           [:i {:class "fa fa-bullhorn"}] " Next Tech Jam: 12th Nov"]]]]]
+           [:i {:class "fa fa-bullhorn"}] " Next Tech Jam: 14th Jan"]]]]]

       [:nav {:class "navbar navbar-default navbar-header-full navbar-dark yamm navbar-static-top", :role "navigation", :id "header"}
        [:div {:class "container"}


handling of both channels and code templates

--- src/gitmirth/core.clj
+++ src/gitmirth/core.clj
@@ -6,7 +6,8 @@
              [zip :as zip]]
             [clojure.data.xml :as xml]
             [clojure.data.zip.xml :as zx]
-            [clojure.java.io :as io]))
+            [clojure.java.io :as io])
+  (:import java.io.File))

 (defn to-zip
   "Takes a string of xml and returns an xml zipper"
@@ -16,7 +17,7 @@
 (defn with-authentication
   "Binds a cookie store to keep auth cookies, authenticates using the
   supplied url/credentials, and returns the results of executing the
-  supplied fn"
+  supplied parameterless function for side effects"
   [base-url username password func]
   (binding [clj-http.core/*cookie-store* (clj-http.cookies/cookie-store)]
     (client/post
@@ -27,34 +28,44 @@
       :insecure? true})
     (func)))

-(defn fetch-all-channel-locs
-  "Fetch all channels from remote server and return a sequence of
-  channel locs within the zipper"
-  [base-url]
-  (-> base-url
-      (str "/channels")                 ;combine the base url with the rest path
-      (client/get                       ;fetch the channels via rest
-       {:insecure? true})
-      :body                             ;extract the response body
-      to-zip                            ;get an xml zipper
-      (zx/xml-> :list :channel)         ;get a loc per channel
-      ))
+(defn fetch-all
+  "Fetch everything at url from remote server and return a sequence of
+  channel locs based on the supplied predicates. In other words - grab
+  the xml from the url via a GET request, extract the :body of the
+  result, parse the XML, create a 'zipper', and return the result of
+  the query (predicates)"
+  [url predicates]
+  (as-> url v
+    (client/get v {:insecure? true})
+    (:body v)
+    (to-zip v)
+    (apply zx/xml-> v predicates)))

-(defn process-channel
-  "Take a channel zip and write to the filesystem"
-  [chanzip]
-  (let [channel-name (zx/xml1-> chanzip :name zip/down zip/node)
-        channel-xml (xml/indent-str (zip/node chanzip))
-        base-dir "blarfnarg" ;; (java.util.UUID/randomUUID)
-        file-path (str base-dir "/" channel-name)]
+(defn serialize-node
+  "Take an xml location and write to the filesystem with a meaningful
+  name and path"
+  [dirname xmlloc name-predicate]
+  (let [name (apply zx/xml1-> xmlloc name-predicate)
+        xml-str (xml/indent-str (zip/node xmlloc))
+        file-path (str "blarfnarg/" dirname (File/separator) "/" name)]
     (io/make-parents file-path)
-    (spit file-path channel-xml)))
+    (spit file-path xml-str)))
+
+(defn run-channels [base-url]
+  (doseq [loc (fetch-all (str base-url "/channels") [:list :channel])]
+    (serialize-node "channels" loc [:name zip/down zip/node])))
+
+(defn run-codeTemplates [base-url]
+  (doseq [loc (fetch-all (str base-url "/codeTemplates") [:list :codeTemplate])]
+    (serialize-node "codeTemplates" loc [:name zip/down zip/node])))

 (defn makeitso
   "App logic"
   [base-url username password]
   (with-authentication base-url username password
-    #(map process-channel (fetch-all-channel-locs base-url))))
+    (fn [] (do
+            (run-channels base-url)
+            (run-codeTemplates base-url)))))

 (defn -main
   [& args]


have a config per type of element

have a config per type of element

--- src/gitmirth/core.clj
+++ src/gitmirth/core.clj
@@ -51,21 +51,29 @@
     (io/make-parents file-path)
     (spit file-path xml-str)))

-(defn run-channels [base-url]
-  (doseq [loc (fetch-all (str base-url "/channels") [:list :channel])]
-    (serialize-node "channels" loc [:name zip/down zip/node])))
+(def channel-config
+  {:element-preds [:list :channel]
+   :name-preds [:name zip/down zip/node]
+   :path "channels"})

-(defn run-codeTemplates [base-url]
-  (doseq [loc (fetch-all (str base-url "/codeTemplates") [:list :codeTemplate])]
-    (serialize-node "codeTemplates" loc [:name zip/down zip/node])))
+(def codeTemplate-config
+  {:element-preds [:list :codeTemplate]
+   :name-preds [:name zip/down zip/node]
+   :path "codeTemplates"})
+
+(defn download
+  "Serializes all xml found at the api path using the supplied config"
+  [base-url {:keys [element-preds name-preds path]}]
+  (doseq [loc (fetch-all (str base-url (str "/" path)) element-preds)]
+    (serialize-node path loc name-preds)))

 (defn makeitso
   "App logic"
   [base-url username password]
   (with-authentication base-url username password
     (fn [] (do
-            (run-channels base-url)
-            (run-codeTemplates base-url)))))
+            (download base-url channel-config)
+            (download base-url codeTemplate-config)))))

 (defn -main
   [& args]


Update namespace and api doc.

Update namespace and api doc.

--- src/afterglow/controllers/launchpad_mini.clj
+++ src/afterglow/controllers/launchpad_mini.clj
@@ -1,17 +1,13 @@
 (ns afterglow.controllers.launchpad-mini
-  "Allows the Novation Launchpad Mini to be used as a control surface
-  for Afterglow."
+  "Allows the Novation Launchpad Mini and Launchpad S to be used as
+  control surfaces for Afterglow."
   {:author "James Elliott"}
   (:require [afterglow.controllers :as controllers]
             [afterglow.controllers.tempo :as tempo]
-            [afterglow.effects.cues :as cues]
             [afterglow.midi :as amidi]
             [afterglow.rhythm :as rhythm]
             [afterglow.show :as show]
             [afterglow.show-context :refer [with-show]]
-            [afterglow.util :as util]
-            [clojure.math.numeric-tower :as math]
-            [com.evocomputing.colors :as colors]
             [overtone.at-at :as at-at]
             [overtone.midi :as midi]
             [taoensso.timbre :as timbre :refer [warn]]
@@ -549,7 +545,7 @@
   by the watcher, if it is currently connected, and cancel the
   watcher itself. In such cases, `:disconnected` is meaningless."
   [controller & {:keys [disconnected] :or {disconnected false}}]
-  {:pre [(#{:launchpad-mini :launchpad-mini-watcher} (type controller))]}
+  {:pre [(have? #{:launchpad-mini :launchpad-mini-watcher} (type controller))]}
   (if (= (type controller) :launchpad-mini-watcher)
     (do ((:cancel controller))  ; Shut down the watcher
         (when-let [watched-controller @(:controller controller)]
@@ -648,7 +644,7 @@
   [show & {:keys [device-filter refresh-interval display-name skip-animation]
            :or   {device-filter    "Mini"
                   refresh-interval (/ 1000 15)}}]
-  {:pre [(some? show)]}
+  {:pre [(have? some? show)]}
   (let [port-in        (first (amidi/filter-devices device-filter (amidi/open-inputs-if-needed!)))
         port-out       (first (amidi/filter-devices device-filter (amidi/open-outputs-if-needed!)))
         [device model] (when (every? some? [port-in port-out]) (valid-identity port-in port-out))]
@@ -731,7 +727,7 @@
   [show & {:keys [device-filter refresh-interval display-name]
            :or {device-filter "Mini"
                 refresh-interval (/ 1000 15)}}]
-  {:pre [(some? show)]}
+  {:pre [(have? some? show)]}
   (let [idle (atom true)
         controller (atom nil)]
     (letfn [(disconnection-handler []


Fix bug with setting cookies in Safari

Fix bug with setting cookies in Safari

Apparently Safari refuses to set cookies with non-ASCII characters.
See: http://stackoverflow.com/a/1969339

In order to allow the application code to still use Clojure keywords as
cookie names, we now convert the given cookie name to a string before
writing or reading the cookie.

--- src/app/cljs/one/repmax/cookies.cljs
+++ src/app/cljs/one/repmax/cookies.cljs
@@ -3,12 +3,14 @@

 (def number-of-seconds-in-one-year (* 60 60 24 365))

-(defn get-cookie [name]
-  (let [value (.get goog.net.cookies name)]
+(defn get-cookie [cookie-name]
+  (let [normalized-cookie-name (name cookie-name)
+        value (.get goog.net.cookies normalized-cookie-name)]
     (if (= js/undefined value)
       nil
       value)))

-(defn set-cookie [name value]
-  (.set goog.net.cookies name value number-of-seconds-in-one-year))
+(defn set-cookie [cookie-name cookie-value]
+  (let [normalized-cookie-name (name cookie-name)]
+    (.set goog.net.cookies normalized-cookie-name cookie-value number-of-seconds-in-one-year)))


Now SINDRE have reserve data

Now SINDRE have reserve data

--- src/clj_simple_chart/ncs/reserve.clj
+++ src/clj_simple_chart/ncs/reserve.clj
@@ -48,7 +48,7 @@
 (def field-names (map :fldName data))

 (def field-names-all (vec (flatten [(map :fldName data)
-                                    ["SINDRE" "33/9-6 DELTA"]])))
+                                    ["33/9-6 DELTA"]])))

 (def banned-fields ["TAMBAR ØST"])

@@ -75,7 +75,7 @@
              (map kind)
              (reduce + 0))))

-(test/is (not (some #{"SINDRE"} field-names)))
+(test/is (some #{"SINDRE"} field-names))
 (test/is (not (some #{"33/9-6 DELTA"} field-names)))

 (test/is (= 8.6 (get-reserve "JOHAN SVERDRUP" :fldRecoverableGas)))


Deal with missing lesson types for modules in url hash

The user may have missed out on some lesson types (eg. Tutorial, Lab)
for certain modules in the url hash. We randomly pick a lesson group
for that missing lesson type to present a full picture of the module.
The user can later switch the lesson group for that lesson type as
he/she deems fit.

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


Increase hours between jobs.

Increase hours between jobs.

--- src/clj/clj_templates/config/main_config.clj
+++ src/clj/clj_templates/config/main_config.clj
@@ -9,7 +9,7 @@
    :db/postgres         {:jdbc-url          (env :db-url)
                          :driver-class-name "org.postgresql.Driver"}
    :logger/timbre       {:appenders {:println {:stream :auto}}}
-   :jobs/scheduled-jobs {:hours-between-jobs 2
+   :jobs/scheduled-jobs {:hours-between-jobs 8
                          :db                 (ig/ref :db/postgres)
                          :es-client          (ig/ref :search/elastic)}
    :search/elastic      {:hosts    [(env :bonsai-url)]


fix infinite loop bug

fix infinite loop bug

--- src/clj_money/models/storage/sql_storage.clj
+++ src/clj_money/models/storage/sql_storage.clj
@@ -319,7 +319,7 @@

   (select-prices-by-commodity-id
     [this commodity-id as-of]
-    (.select-prices-by-commodity-id this commodity-id {}))
+    (.select-prices-by-commodity-id this commodity-id as-of {}))

   (select-prices-by-commodity-id
     [_ commodity-id as-of options]


Display job metadata in job view

Display job metadata in job view

--- src/cljs/onyx_dashboard/components/jobs.cljs
+++ src/cljs/onyx_dashboard/components/jobs.cljs
@@ -143,7 +143,7 @@
 (defcomponent job-info [{:keys [replica job-info]} owner]
   (render [_]
           (let [{:keys [job id metrics exception]} job-info
-                {:keys [catalog workflow flow-conditions triggers windows]} job]
+                {:keys [catalog workflow flow-conditions triggers windows metadata]} job]
             (if (= :GCd (rq/job-state replica id))
               (p/panel
                 {:header (om/build section-header-collapsible {:text "Job State"} {})
@@ -157,6 +157,11 @@
                 (om/build task-panel {:replica replica :job-info job-info} {})
                 (om/build job-visualisation job-info {})

+                (p/panel
+                 {:header (om/build section-header-collapsible {:text "Metadata"} {})
+                  ;:collapsible? true
+                  :bs-style "primary"}
+                 (om/build clojure-block {:input (with-out-str (fipp/pprint (om/value metadata)))}))

                 (p/panel
                   {:header (om/build section-header-collapsible {:text "Workflow"} {})


Doubled max points

Doubled max points

--- src/clojush/problems/software/word_stats.clj
+++ src/clojush/problems/software/word_stats.clj
@@ -266,7 +266,7 @@
 (def argmap
   {:error-function (word-stats-error-function word-stats-data-domains)
    :atom-generators word-stats-atom-generators
-   :max-points 1600
+   :max-points 3200
    :max-genome-size-in-initial-program 400
    :evalpush-limit 6000
    :population-size 1000


support reloading css which was loaded via a relative path

--- src/main/shadow/cljs/devtools/client/browser.cljs
+++ src/main/shadow/cljs/devtools/client/browser.cljs
@@ -3,8 +3,6 @@
     [cljs.reader :as reader]
     [clojure.string :as str]
     [goog.dom :as gdom]
-    [goog.object :as gobj]
-    [goog.net.jsloader :as loader]
     [goog.userAgent.product :as product]
     [goog.Uri]
     [goog.net.XhrIo :as xhr]
@@ -153,14 +151,25 @@
             (load-sources sources-to-get #(do-js-reload msg % hud/load-end-success hud/load-failure))
             ))))))

+;; capture this once because the path may change via pushState
+(def ^goog page-load-uri
+  (when js/goog.global.document
+    (goog.Uri/parse js/document.location.href)))
+
 (defn handle-asset-watch [{:keys [updates] :as msg}]
   (doseq [path updates
           ;; FIXME: could support images?
           :when (str/ends-with? path "css")]
-    (when-let [node (js/document.querySelector (str "link[href^=\"" path "\"]"))]
+    (doseq [node (array-seq (js/document.querySelectorAll "link[rel=\"stylesheet\"]"))
+            :let [^goog node-uri (goog.Uri/parse (.getAttribute node "href"))
+                  node-uri-resolved (.resolve page-load-uri node-uri)
+                  node-abs (.getPath ^goog node-uri-resolved)]
+            :when (and (or (= (.hasSameDomainAs page-load-uri node-uri))
+                           (not (.hasDomain node-uri)))
+                       (= node-abs path))]
+
       (let [new-link
-            (doto (js/document.createElement "link")
-              (.setAttribute "rel" "stylesheet")
+            (doto (.cloneNode node true)
               (.setAttribute "href" (str path "?r=" (rand))))]

         (devtools-msg "load CSS" path)


update deps

update deps

--- src/leiningen/new/clanhr_service/project.clj
+++ src/leiningen/new/clanhr_service/project.clj
@@ -10,7 +10,7 @@

   :dependencies [[environ "1.0.1"]
                  [org.clojure/clojure "1.7.0"]
-                 [mvxcvi/puget "0.8.1"]
+                 [mvxcvi/puget "0.9.0"]
                  [clj-http "2.0.0"]
                  [ring/ring-core "1.4.0"]
                  [ring/ring-json "0.4.0"]
@@ -25,10 +25,10 @@
                  [clanhr/reply "0.6.4"]
                  [clanhr/logger "0.3.0"]
                  [clanhr/validators "0.5.2"]
-                 [clanhr/auth "0.4.5"]
+                 [clanhr/auth "0.5.1"]
                  [clanhr/analytics "1.5.0"]
                  [clanhr/ring-test-client "0.1.0"]
-                 [clanhr/postgres-gateway "1.0.1" :exclusions [[io.netty/netty-handler]]]
+                 [clanhr/postgres-gateway "1.4.0" :exclusions [[io.netty/netty-handler]]]
                  [clanhr/memory-gateway "0.9.0"]]

   :plugins [[lein-ring "0.8.10"]


Added some todos

Added some todos

--- src/main/clj/clojure/core/matrix/complex.clj
+++ src/main/clj/clojure/core/matrix/complex.clj
@@ -136,6 +136,7 @@
           imag-trace (m/trace (clojure.core.matrix.complex/imag m))]
       (complex real-trace imag-trace)))
   (determinant [m]
+    "Calculates the determinant of a matrix directly." ;; TODO: Can optimizations be made?
     (if (= 2 (first (m/shape m)))
       (reduce c/-
               (map #(reduce c/* (mp/element-seq %))
@@ -164,12 +165,16 @@
                                 (m/emap #(.getImaginary ^Complex %) wrapped))))))
                    (range (first (m/shape m)))))))
   (inverse [m]
+    "This implementation of inverse for complex numbers uses the (expected to be highly
+    optimized implementation of the matrix inverse for real numbers. This allows us to take
+    advantage of how the complex numbers are stored in the array (two seperate arrays).
+    If the matrix is singular, it returns an exception"
     (let [A (clojure.core.matrix.complex/real m)
           C (clojure.core.matrix.complex/imag m)
-          r0 (m/mul (m/inverse A) C)                        ; use the highly optimized real inverse from
+          r0 (m/mul (m/inverse A) C)
           y11 (m/inverse (m/add (m/mul C r0) A))
           y01 (m/mul r0 y11)]
-      (complex-array y11 (m/negate y01))))
+      (complex-array y11 (m/negate y01)))) ;; TODO: make sure IllegalArgument Exception is returned if m is singular

   mp/PMatrixProducts
   (inner-product [m a]


Clean up namespace declaration

Clean up namespace declaration

Signed-off-by: Daniel Borchmann <3d0f3b9ddcacec30c4008c5e030e6c13a478cb4f@algebra20.de>

--- src/main/clojure/conexp/fca/implications.clj
+++ src/main/clojure/conexp/fca/implications.clj
@@ -8,10 +8,9 @@

 (ns conexp.fca.implications
   "Implications for Formal Concept Analysis."
-  (:use conexp.base
-        conexp.fca.contexts)
-  (:require [clojure.core.reducers :as r])
-  (:import [java.util HashMap HashSet]))
+  (:require [clojure.core.reducers :as r]
+            [conexp.base :refer :all]
+            [conexp.fca.contexts :refer :all]))

 ;;;


Fix reflection warnings (fixes #277)

Fix reflection warnings (fixes #277)

--- ring-core/src/ring/util/response.clj
+++ ring-core/src/ring/util/response.clj
@@ -70,7 +70,7 @@
   [resp name value]
   (assoc-in resp [:headers name] (str value)))

-(defn- canonical-path [^File file]
+(defn- canonical-path ^String [^File file]
   (str (.getCanonicalPath file)
        (if (.isDirectory file) File/separatorChar)))

@@ -291,7 +291,7 @@
         (content-length (:content-length data))
         (last-modified (:last-modified data)))))

-(defn- get-resources [path loader]
+(defn- get-resources [path ^ClassLoader loader]
   (-> (or loader (.getContextClassLoader (Thread/currentThread)))
       (.getResources path)
       (enumeration-seq)))
@@ -302,7 +302,7 @@
       (let [root (.replaceAll (str root) "^/" "")]
         (or (str/blank? root)
             (let [path (canonical-path body)]
-              (some #(and (= "file" (.getProtocol %))
+              (some #(and (= "file" (.getProtocol ^URL %))
                           (.startsWith path (canonical-path (url-as-file %))))
                     (get-resources root loader)))))))


provide more details in case of unavailable dependencies

--- src/org/zalando/stups/friboo/system/http.clj
+++ src/org/zalando/stups/friboo/system/http.clj
@@ -154,7 +154,7 @@
         (let [reason (-> e .getCause .toString)
               failure-type (str (.getFailureType e))]
           (log/warn (str "Hystrix: " (.getMessage e) " %s occurred, because %s") failure-type reason)
-          (api/throw-error 503 "A dependency is unavailable."))))))
+          (api/throw-error 503 (str "A dependency is unavailable: " (.getMessage e))))))))

 (defn mark-transaction
   "Trigger the TransactionMarker with the swagger operationId for instrumentalisation."


Hook up zipper and diagram

Hook up zipper and diagram

--- src/gigrig/components/app.cljs
+++ src/gigrig/components/app.cljs
@@ -1,22 +1,15 @@
 (ns gigrig.components.app
   (:require [gigrig.actions :as a]
             [redux.core :refer [dispatch!]]
-            [gigrig.zipper :as gzip]
+            [gigrig.powertree :as ptree]
             [gigrig.components.diagram :as diagram]
             [gigrig.components.pedal-search :as pedal-search]))

-(def test-tree
-  [:distributor
-   [[:pedal "pedal1"]
-    [:pedal "pedal2"]
-    [:pedal "pedal3"]
-    [:pedal "pedal4"]
-    [:pedal "pedal5"]
-    [:distributor [[:pedal "pedal 6"]
-                   [:pedal "pedal 7"]
-                   [:isolator [[:pedal "pedal 8"]]]
-                   [:distributor [[:pedal "pedal 9"]
-                                  [:pedal "pedal 10"]]]]]]])
+(def test-pedals
+  [{:brand "Ibanez" :model "AD9 Analog Delay" :distributor true :isolator true :other false}
+   {:brand "Ibanez" :model "TubeScreamer" :distributor true :isolator false :other false}
+   {:brand "Ibanez" :model "Whammy" :distributor true :isolator false :other false}
+   {:brand "Ibanez" :model "BlueSky" :distributor true :isolator true :other false}])

 (defn component
   [state]
@@ -26,4 +19,4 @@
      ^{:key id}
      [pedal-search/component (assoc field :id id)])
    [:button {:on-click #(dispatch! a/add-pedal-button-clicked)} "+ Add pedal"]
-   [diagram/component {:zipper (gzip/zipper test-tree)}]])
+   [diagram/component {:zipper (ptree/build test-pedals)}]])


Now covered on socket_server testing.

Now covered on socket_server testing.

--- spec/navajo/socket_server_spec.clj
+++ spec/navajo/socket_server_spec.clj
@@ -34,11 +34,11 @@

   (it "reads a byte sequence from a stream"
     (let [msg "Hello"
-          pin (java.io.PipedInputStream.)
-          pout (java.io.PipedOutputStream. pin)
-          os (java.io.PrintStream. pout)]
-      (.write pout (.getBytes msg) 0 (.length msg))
-      (should= (.getBytes msg) (read-byte-seq-from-stream [pin]))))
+          os (java.io.ByteArrayOutputStream.)]
+      (.write os (.getBytes msg))
+      (.flush os)
+      (.close os)
+      (should= (seq (.getBytes msg)) (read-byte-seq-from-stream (java.io.ByteArrayInputStream. (.toByteArray os))))))

   (it "sends the client a message"
     (let [message "Hello, World!\r\n"


Whitespace.

Whitespace.

--- src/cbfg/kvs.cljs
+++ src/cbfg/kvs.cljs
@@ -64,9 +64,9 @@
            cb (fn [state kvs]
                 (act scan-work actx
                      (let [kc ((or kind :dirty) kvs)] ; Either :clean or :dirty.
-                       (doseq [[k v](subseq (into (sorted-map)
-                                                  (scan-kind kc)) ; :keys or :changes.
-                                            >= from < to)]
+                       (doseq [[k v] (subseq (into (sorted-map)
+                                                   (scan-kind kc)) ; :keys or :changes.
+                                             >= from < to)]
                          (when-let [entry (get-entry kc k v)]
                            (when (or include-deleted (not (:deleted entry)))
                              (aput scan-work res-ch


Passing the ch-name into vis delta and wait-chs for display.

--- src/cbfg/vis.cljs
+++ src/cbfg/vis.cljs
@@ -89,30 +89,38 @@
                                    (= (count ch-names)
                                       (count ch-bindings)))]
                 (apply concat
-                       (vec (map-indexed (fn [idx [ch action & msgv]]
-                                           (swap! vis #(-> %
-                                                           (vis-add-ch ch
-                                                                       (when (= action :take) actx))
-                                                           (assoc-in [:actxs actx :wait-chs ch]
-                                                                     (if use-names
-                                                                       [action (nth ch-names idx)]
-                                                                       [action]))))
-                                           (when (= action :put)
-                                             [{:delta :put :msg (first msgv) :actx actx :ch ch}]))
-                                         ch-actions)))))
+                       (doall (map-indexed (fn [idx [ch action & msgv]]
+                                             (swap! vis #(-> %
+                                                             (vis-add-ch ch
+                                                                         (when (= action :take) actx))
+                                                             (assoc-in [:actxs actx :wait-chs ch]
+                                                                       (if use-names
+                                                                         [action (nth ch-names idx)]
+                                                                         [action]))))
+                                             (when (= action :put)
+                                               [{:delta :put :msg (first msgv) :actx actx :ch ch
+                                                 :ch-name (when use-names (nth ch-names idx))}]))
+                                           ch-actions)))))
     :after (fn [vis actx [ch-names ch-bindings [result-msg result-ch]]]
              (let [; The ch-actions will be [[ch :take] [ch :put] ...].
                    ch-actions (map #(if (seq? %) [(first %) :put (second %)] [% :take])
-                                   ch-bindings)]
-               (doseq [[ch action] ch-actions]
-                 (swap! vis #(assoc-in % [:actxs actx :wait-chs ch] [:ghost])))
+                                   ch-bindings)
+                   use-names (and (seqable? ch-names)
+                                  (= (count ch-names)
+                                     (count ch-bindings)))]
+               (doall (map-indexed (fn [idx [ch action]]
+                                     (swap! vis #(assoc-in % [:actxs actx :wait-chs ch]
+                                                           (if use-names
+                                                             [:ghost (nth ch-names idx)]
+                                                             [:ghost]))))
+                                   ch-actions))
                (swap! vis #(dissoc-in % [:chs result-ch :msgs result-msg]))
                (when (nil? result-msg) ; The ch is closed.
                  (swap! vis #(-> %
                                  (dissoc-in [:actxs actx :wait-chs result-ch])
                                  (dissoc-in [:chs result-ch]))))
                (when (some #(= % result-ch) ch-bindings)
-                 [{:delta :take :msg result-msg :ch result-ch :actx actx}])))}})
+                 [{:delta :take :msg result-msg :actx actx :ch result-ch}])))}})

 ;; ------------------------------------------------


Display all centroids.

Display all centroids.

--- src/videotest/blob/find_centroids_cvgray.clj
+++ src/videotest/blob/find_centroids_cvgray.clj
@@ -75,13 +75,19 @@
       (update-gray-p-image)
       (update-blobs)))

+(defn draw-centroid [detector n]
+  (q/ellipse (.getCentroidX detector n)
+             (.getCentroidY detector n)
+             40 40))
+
 (defn draw-centroids [{:keys [detector]}]
   (q/push-style)
-  (q/stroke-weight 5)
-  (q/stroke 0 255 0)
+  (q/no-stroke)
+  (q/fill 0 255 0 80)
   (if (< 0 (.getBlobsNumber detector))
-   (q/point (.getCentroidX detector 0)
-            (.getCentroidY detector 0)))
+    (dorun
+     (map #(draw-centroid detector %)
+          (range 0 (.getBlobsNumber detector)))))
   (q/pop-style))

 (defn draw [state]


Testing reactivity with 10 ms.

Testing reactivity with 10 ms.

--- src/cljs/map.cljs
+++ src/cljs/map.cljs
@@ -68,7 +68,7 @@
                (.addLayer markers marker))))))
     (remote-callback :get-markers [dbb]
                      #(go (doseq [a (if (= maxi 0) % (take maxi %))]
-                            (<! (timeout 1))
+                            (<! (timeout 10))
                             (>! ch a))))
     (.addLayer mymap markers)
     (remote-callback


#28 change load-md

#28 change load-md

--- src/tamaki/template/page.clj
+++ src/tamaki/template/page.clj
@@ -20,10 +20,9 @@
           output (new StringWriter)
           metadata (md/md-to-html input output :parse-meta? true :heading-anchors true)
           body (.toString output)]
-      (merge metadata {:body body
-                       :title (-> metadata :title first)
-                       :link (-> metadata :link first)
-                       :template (-> metadata :template first)}))))
+      (merge {:body body} {:metadata (merge metadata {:title (-> metadata :title first)
+                                                      :link (-> metadata :link first)
+                                                      :template (-> metadata :template first)})}))))

 (defn load-markdown
   ([^String file]


disable compression

disable compression

--- src/bzzz/kv.clj
+++ src/bzzz/kv.clj
@@ -18,7 +18,7 @@
               path (index-directory/root-identifier-path)
               x (index-directory/try-create-prefix path)
               file (io/file (index-directory/root-identifier-path) acceptable-name)
-              db (.make (.compressionEnable (DBMaker/newFileDB file)))]
+              db (.make (DBMaker/newFileDB file))]
           (swap! db* assoc-in [file-name] db)
           db)))))


Clean reading of options from .cljs.edn

Clean reading of options from .cljs.edn

--- src/adzerk/boot_reload.clj
+++ src/adzerk/boot_reload.clj
@@ -38,7 +38,7 @@
     (util/info "Starting reload server on %s\n" (format "%s://%s:%d" proto listen-host port))
     (format "%s://%s:%d" proto client-host (or ws-port port))))

-(defn- write-cljs! [tmp client-ns url ws-host on-jsload asset-host]
+(defn- write-cljs! [tmp client-ns url ws-host {:keys [on-jsload asset-host]}]
   (util/info "Writing %s to connect to %s...\n" (.getPath (rutil/ns->file client-ns "cljs")) url)
   (let [out (doto (rutil/ns->file tmp client-ns "cljs")
               io/make-parents)]
@@ -99,7 +99,10 @@
   Arguments shouldn't have spaces.
   Examples:
   vim --remote +norm%sG%s| %s
-  emacsclient -n +%s:%s %s"
+  emacsclient -n +%s:%s %s
+
+  Client options can also be set in .cljs.edn file, using property :boot-reload, e.g.
+  :boot-reload {:on-jsload frontend.core/reload}"

   [b ids BUILD_IDS #{str} "Only inject reloading into these builds (= .cljs.edn files)"
    ;; Websocket Server
@@ -109,8 +112,8 @@
    w ws-host WSADDR  str  "The websocket host clients connect to. Defaults to current host. (optional)"
    s secure          bool "Flag to indicate whether the client should connect via wss. Defaults to false."
    ;; Other Configuration
-   j on-jsload SYM     sym "The callback to call when JS files are reloaded. (optional)"
-   _ asset-host HOST   str "The asset-host where to load files from. Defaults to host of opened page. (optional)"
+   j on-jsload SYM     sym "The callback to call when JS files are reloaded. (client, optional)"
+   _ asset-host HOST   str "The asset-host where to load files from. Defaults to host of opened page. (client, optional)"
    a asset-path PATH   str "Sets the output directory for temporary files used during compilation. (optional)"
    c cljs-asset-path PATH str "The actual asset path. This is added to the start of reloaded urls. (optional)"
    o open-file COMMAND str "The command to run when warning or exception is clicked on HUD. Passed to format. (optional)"
@@ -136,8 +139,12 @@
           (let [path     (tmp-path f)
                 spec     (-> f tmp-file slurp read-string)
                 client-ns (str "adzerk.boot-reload." (rutil/path->ns path))
-                out-file (io/file tmp path)]
-            (write-cljs! tmp client-ns url ws-host (get spec :on-jsload on-jsload) asset-host)
+                out-file (io/file tmp path)
+                client-opts (merge {:on-jsload on-jsload
+                                    :asset-host asset-host}
+                                   (:boot-reload spec))]
+            ;; ws-host is used by client, but is not client option because it mainly used by server
+            (write-cljs! tmp client-ns url ws-host client-opts)
             (add-init! client-ns spec out-file path)))

         ;; Special case: boot-cljs used without .cljs.edn
@@ -146,7 +153,8 @@
         ;; If file already exists, do nothing.
         (when (and (empty? (relevant-cljs-edn fileset ids))
                    (nil? (b/tmp-get (.getPath (rutil/ns->file "adzerk.boot-reload" "cljs")))))
-          (write-cljs! tmp "adzerk.boot-reload" url ws-host on-jsload asset-host))
+          (write-cljs! tmp "adzerk.boot-reload" url ws-host {:on-jsload on-jsload
+                                                             :asset-host asset-host}))

         (reset! prev-pre fileset)
         (let [fileset (-> fileset (add-resource tmp) commit!)


Add open-file option

Add open-file option

--- src/adzerk/boot_reload.clj
+++ src/adzerk/boot_reload.clj
@@ -79,7 +79,14 @@
   "Live reload of page resources in browser via websocket.

   The default configuration starts a websocket server on a random available
-  port on localhost."
+  port on localhost.
+
+  Open-file option takes three arguments: line number, column number, relative
+  file path. You can use positional arguments if you need different order.
+  Arguments shouldn't have spaces.
+  Examples:
+  vim --remote +norm%sG%s| %s
+  emacsclient -n +%s:%s %s"

   [b ids BUILD_IDS #{str} "Only inject reloading into these builds (= .cljs.edn files)"
    i ip ADDR         str  "The (optional) IP address for the websocket server to listen on."
@@ -87,14 +94,16 @@
    w ws-host WSADDR  str  "The (optional) websocket host address to pass to clients."
    j on-jsload SYM   sym  "The (optional) callback to call when JS files are reloaded."
    a asset-path PATH str  "The (optional) asset-path. This is removed from the start of reloaded urls."
-   s secure          bool "Flag to indicate whether the client should connect via wss. Defaults to false."]
+   s secure          bool "Flag to indicate whether the client should connect via wss. Defaults to false."
+   o open-file COMMAND str "The (optional) command to run when warning or exception is clicked on HUD. Passed to format."]

   (let [pod  (make-pod)
         src  (tmp-dir!)
         tmp  (tmp-dir!)
         prev (atom nil)
         out  (doto (io/file src "adzerk" "boot_reload.cljs") io/make-parents)
-        url  (start-server @pod {:ip ip :port port :ws-host ws-host :secure? secure})]
+        url  (start-server @pod {:ip ip :port port :ws-host ws-host :secure? secure
+                                 :open-file open-file})]
     (set-env! :source-paths #(conj % (.getPath src)))
     (write-cljs! out url on-jsload)
     (comp


Make code of conduct optional (+coc or +code-of-conduct)

--- src/leiningen/new/chestnut.clj
+++ src/leiningen/new/chestnut.clj
@@ -34,7 +34,7 @@
        ((indent n (next list)))))

 (def valid-options
-  ["http-kit" "site-middleware" "less" "sass" "reagent" "vanilla" "garden" "rum" "om-next" "re-frame"])
+  ["http-kit" "site-middleware" "less" "sass" "reagent" "vanilla" "garden" "rum" "om-next" "re-frame" "code-of-conduct" "coc"])

 (doseq [opt valid-options]
   (eval
@@ -148,7 +148,6 @@
            "dev/cljs/user.cljs"
            "LICENSE"
            "README.md"
-           "code_of_conduct.md"
            ".gitignore"
            "system.properties"
            ".dir-locals.el"
@@ -156,6 +155,7 @@
            "test/cljs/chestnut/core_test.cljs"
            "test/cljs/chestnut/test_runner.cljs"
            "test/cljc/chestnut/common_test.cljc"]
+    (or (coc? opts) (code-of-conduct? opts)) (conj "code_of_conduct.md")
     (less? opts) (conj "src/less/style.less")
     (sass? opts) (conj "src/scss/style.scss")
     (garden? opts) (conj "src/clj/chestnut/styles.clj")


set script permissions on running the template

--- src/leiningen/new/onyx_app.clj
+++ src/leiningen/new/onyx_app.clj
@@ -48,11 +48,10 @@
         render-instructions (render-files files name data)]
     (main/info "Generating fresh Onyx app.")
     (apply ->files data render-instructions)
-    (run! (fn [file]
-            (sh "chmod" "+x" (str name file)))
-          ["/script/build.sh"])
     (when (docker? args)
       (run! (fn [file]
               (sh "chmod" "+x" (str name file)))
-            ["/script/run_peers.sh" "/script/run_aeron.sh" "/script/kafka-meetup-streamer/script.sh"]))
+            ["/scripts/finish_media_driver.sh"
+             "/scripts/run_media_driver.sh"
+             "/scripts/run_peer.sh"]))
     (main/info (str "Building a new onyx app with: " args))))


Bump post-generation message version number

--- src/leiningen/new/sim_test.clj
+++ src/leiningen/new/sim_test.clj
@@ -33,5 +33,5 @@
              ["resources/logback.xml" (render "resources/logback.xml" data)]
              ["resources/schema.edn" (render "resources/schema.edn" data)]
              ["resources/simulant.edn" (render "resources/simulant.edn" data)])
-    (main/info "Project generated. Please entery directory and run\n\n\tgit init . && git add . && git commit --message \"Project Generation - sim-template 0.1.3\"")))
+    (main/info "Project generated. Please entery directory and run\n\n\tgit init . && git add . && git commit --message \"Project Generation - sim-template 0.1.4\"")))


Key exclusion test.

Key exclusion test.

--- test/onyx/generative/flow_conditions_gen_test.clj
+++ test/onyx/generative/flow_conditions_gen_test.clj
@@ -48,7 +48,8 @@
    base-gen
    (fn [v]
      (let [g (gen/return ::true-pred)
-           true-gen (gen/hash-map :flow/predicate g)]
+           true-gen (gen/hash-map :flow/predicate g
+                                  :pred/val (gen/return true))]
        (gen/fmap #(merge v %) true-gen)))))

 (defn false-flow-condition-gen [base-gen]
@@ -56,7 +57,8 @@
    base-gen
    (fn [v]
      (let [g (gen/return ::false-pred)
-           false-gen (gen/hash-map :flow/predicate g)]
+           false-gen (gen/hash-map :flow/predicate g
+                                   :pred/val (gen/return false))]
        (gen/fmap #(merge v %) false-gen)))))

 (defn short-circuit-flow-condition-gen [base-gen]
@@ -109,7 +111,7 @@
 (deftest conj-downstream-tasks-together
   (checking
    "It joins the :flow/to tasks together and limits selection"
-   (times 50)
+   (times 30)
    [flow-conditions
     (gen/not-empty
      (gen/vector (->> :a
@@ -128,7 +130,7 @@
 (deftest no-false-predicate-picks
   (checking
    "It doesn't pick any downstream tasks with false predicates"
-   (times 20)
+   (times 30)
    [true-fcs
     (gen/vector (->> :a
                      (flow-condition-gen)
@@ -150,7 +152,7 @@
 (deftest short-circuit
   (checking
    "It stops searching when it finds a short circuit true pred"
-   (times 20)
+   (times 30)
    [false-1
     (gen/vector (->> :a
                      (flow-condition-gen)
@@ -185,7 +187,7 @@
 (deftest retry-action
   (checking
    "Using a retry action with a true predicate flows to nil"
-   (times 20)
+   (times 30)
    [retry-false
     (gen/vector (->> :a
                      (flow-condition-gen)
@@ -227,3 +229,27 @@
          results (t/route-data event nil nil flow-conditions downstream)]
      (is (not (seq (:flow results))))
      (is (= :retry (:action results))))))
+
+(deftest key-exclusion
+  (checking
+   "Matched predicates excluded keys are conj'ed together"
+   (times 30)
+   [mixed
+    (gen/vector
+     (gen/one-of [(->> :a
+                       (flow-condition-gen)
+                       (flow-to-tasks-gen)
+                       (true-flow-condition-gen))
+                  (->> :a
+                       (flow-condition-gen)
+                       (flow-to-tasks-gen)
+                       (false-flow-condition-gen))]))]
+   (let [downstream (mapcat :flow/to mixed)
+         compiled (c/compile-fc-norms mixed :a)
+         event {:onyx.core/compiled-norm-fcs compiled}
+         results (t/route-data event nil nil mixed downstream)
+         matches (filter :pred/val mixed)
+         excluded-keys (mapcat :flow/exclude-keys matches)]
+     (prn excluded-keys)
+     (is (into #{} excluded-keys) (:exclusions results))
+     (is (nil? (:action results))))))


Add newline.

Add newline.

--- test/isla/test/parser.clj
+++ test/isla/test/parser.clj
@@ -99,4 +99,4 @@
              {:root [{:block [{:expression
                                [{:invocation
                                  [{:identifier ["write"]}
-                                  {:value [{:string ["My name is Isla"]}]}]}]}]}]}))+                                  {:value [{:string ["My name is Isla"]}]}]}]}]}]}))


Updates for Cider 0.10

Updates for Cider 0.10

--- link/.lein/profiles.clj
+++ link/.lein/profiles.clj
@@ -1,5 +1,5 @@
 {:user {:aliases {"slamhound" ["run" "-m" "slam.hound"]}
-        :plugins [[cider/cider-nrepl "0.9.1"]
+        :plugins [[cider/cider-nrepl "0.10.0"]
                   [refactor-nrepl "1.1.0"]
                   [lein-pprint "1.1.1"]
                   [lein-bikeshed "0.2.0"]
@@ -12,7 +12,7 @@
                      ;; Spyscope is for tracing.
                      (require 'spyscope.core)]
         :dependencies [[org.clojure/tools.namespace "0.2.11"]
-                       [org.clojure/tools.nrepl "0.2.10"]
+                       [org.clojure/tools.nrepl "0.2.12"]
                        [org.clojure/tools.trace "0.7.8"]
                        [pjstadig/humane-test-output "0.7.0"]
                        [slamhound "1.5.5"]


move interpolate

move interpolate

--- src/bardo/interpolate.cljx
+++ src/bardo/interpolate.cljx
@@ -95,19 +95,9 @@
                  [1 (_ :guard sequential?)] (take (count end) v)
                  [_ _] v))))))

+(declare interpolate)
+
 (defprotocol IInterpolate (-interpolate [start end]))
-
-(defn interpolate [start end]
-  (let [wrapped (some->> [start end]
-                         (apply wrap-nil)
-                         (apply wrap-errors)
-                         (apply wrap-infinite))]
-    (let [can-interpolate (mapv #(satisfies? IInterpolate %) wrapped)]
-      (if (apply = true can-interpolate)
-        ((apply wrap-size wrapped) (apply -interpolate wrapped))
-        (do
-          (throw
-           (#+cljs js/Exception #+clj Exception. (str "Cannot interpolate between " start " and " end))))))))

 (extend-protocol IInterpolate

@@ -140,3 +130,15 @@
                          (map k)
                          (apply interpolate)
                          (#(% t)))])))))
+
+(defn interpolate [start end]
+  (let [wrapped (some->> [start end]
+                         (apply wrap-nil)
+                         (apply wrap-errors)
+                         (apply wrap-infinite))]
+    (let [can-interpolate (mapv #(satisfies? IInterpolate %) wrapped)]
+      (if (apply = true can-interpolate)
+        ((apply wrap-size wrapped) (apply -interpolate wrapped))
+        (do
+          (throw
+           (#+cljs js/Exception #+clj Exception. (str "Cannot interpolate between " start " and " end))))))))


Emphasize title on /info page.

Emphasize title on /info page.

--- src/beebster_clj/views.clj
+++ src/beebster_clj/views.clj
@@ -130,7 +130,7 @@
      (header '(("/" "search") ("/about" "about")))
      [:h2.header "Info"]
      [:div.infotitle
-      [:p (first title)]]
+      [:p [:strong (first title)]]]
      [:div.infothumb
       [:img {:src (first thumb)}]]
      [:div.infoform


Fix HTML mails (correct multipart types and order)

--- systems/mail/src/containium/systems/mail.clj
+++ systems/mail/src/containium/systems/mail.clj
@@ -114,10 +114,15 @@
     clojure.java.io/file."
   [mail-system from to subject html & {:keys [cc bcc text attachments src-root src-map]}]
   (let [html-contents (make-inline html src-root src-map)
-        contents (remove nil? [:alternative
-                               (when text {:type "text/plain" :content text})
-                               (cons :related html-contents)])
-        attachments (map (fn [a] (assoc a :type :attachment)) attachments)]
-    (send-message mail-system from to subject (concat contents attachments)
+        attachment-contents (map (fn [a] (assoc a :type :attachment)) attachments)
+        body-contents (if text
+                        [:alternative
+                         {:type "text/plain" :content text}
+                         (cons :related html-contents)]
+                        (cons :related html-contents))
+        contents (if (seq attachment-contents)
+                   [:mixed body-contents attachments]
+                   body-contents)]
+    (send-message mail-system from to subject contents
                   (merge (when cc {:cc cc})
                          (when bcc {:bcc bcc})))))