Test exception handling

Test exception handling

* Exceptions thrown in properties should be caught
* `quick-check` should continue to shrink the property as long as the
   property throws

--- test/simple_check/core_test.clj
+++ test/simple_check/core_test.clj
@@ -56,3 +56,20 @@
                   (let [g (sc/gen-int 100)
                         v (sc/gen-vec g 100)]
                     (:result (sc/quick-check 100 first-is-gone v)))))))
+
+;; exceptions shrink and return as result
+;; ---------------------------------------------------------------------------
+
+(def exception (Exception. "I get caught"))
+
+(defn exception-thrower
+  [& args]
+  (throw exception))
+
+(deftest exceptions-are-caught
+  (testing "Exceptions during testing are caught. They're also shrunk as long
+           as they continue to throw."
+           (is (= [exception [0]]
+                  (let [i (sc/gen-int 100)
+                        result (sc/quick-check 100 exception-thrower i)]
+                    [(:result result) (get-in result [:shrunk :smallest])])))))


change default attrs for fileset-seq

change default attrs for fileset-seq

--- src/cake/ant.clj
+++ src/cake/ant.clj
@@ -72,7 +72,7 @@

 (defn fileset-seq [fileset]
   (if (map? fileset)
-    (fileset-seq (make FileSet fileset))
+    (fileset-seq (make FileSet (merge fileset {:error-on-missing-dir false})))
     (map #(.getFile %) (iterator-seq (.iterator fileset)))))

 (defn add-manifest [task attrs]


Update unit for tariff calculations.

Update unit for tariff calculations.


Update old hydrate documentation :page_facing_up:

--- src/metabase/models/hydrate.clj
+++ src/metabase/models/hydrate.clj
@@ -362,22 +362,21 @@

   You can hydrate several keys at one time:

-    (hydrate {:a (delay 1) :b (delay 2)} :a :b)
-      -> {:a 1 :b 2}
+    (hydrate {...} :a :b)
+      -> {:a 1, :b 2}

   ** Nested Hydration **

   You can do recursive hydration by listing keys inside a vector:

-    (hydrate {:a (delay {:b (delay 1)})} [:a :b])
+    (hydrate {...} [:a :b])
       -> {:a {:b 1}}

   The first key in a vector will be hydrated normally, and any subsequent keys
   will be hydrated *inside* the corresponding values for that key.

-    (hydrate {:a (delay {:b (delay {:c (delay 1)})
-                         :e (delay 2)})}
+    (hydrate {...}
              [:a [:b :c] :e])
       -> {:a {:b {:c 1} :e 2}}"
   [results k & ks]


Fix arity exception (fixes #166)

Fix arity exception (fixes #166)

--- boot/pod/src/boot/pod.clj
+++ boot/pod/src/boot/pod.clj
@@ -391,7 +391,7 @@
     (assoc env :dependencies (into dfl-deps dependencies))))

 (defn make-pod
-  ([] (init-pod! (boot.App/newPod)))
+  ([] (init-pod! env (boot.App/newPod)))
   ([{:keys [directories dependencies] :as env}]
      (let [dirs (map io/file directories)
            dfl  [['boot/pod (boot.App/getBootVersion)]


Delegate from payload.

Delegate from payload.

--- src/onyx/peer/task_pipeline.clj
+++ src/onyx/peer/task_pipeline.clj
@@ -21,7 +21,7 @@
   (if (= (extensions/version sync peer-node) peer-version)
     (let [node (new-payload sync peer-node payload-ch)]
       (extensions/on-change sync node #(>!! payload-ch %))
-      (assoc event :new-payload-node node))
+      (assoc event :new-payload-node node :completion? true))
     event))

 (defn munge-open-session [event session]
@@ -77,10 +77,9 @@
   (assoc event :closed true))

 (defn munge-complete-task
-  [{:keys [sync completion-node peer-node peer-version tail-batch?] :as event}]
-  (when tail-batch?
-    (when (= (extensions/version sync peer-node) (inc peer-version))
-      (extensions/touch-place sync completion-node)))
+  [{:keys [sync completion-node completion?] :as event}]
+  (when completion?
+    (extensions/touch-place sync completion-node))
   event)

 (defn open-session-loop [read-ch kill-ch pipeline-data]


Add default `:filterer`s to `ttr`, `word-count`, `gravatar`, and `build-date`

--- src/io/perun.clj
+++ src/io/perun.clj
@@ -165,39 +165,51 @@
 (def ^:private ttr-deps
   '[[time-to-read "0.1.0"]])

+(def ^:private +ttr-defaults+
+  {:filterer :content})
+
 (deftask ttr
   "Calculate time to read for each file. Add `:ttr` key to the files' meta"
-  []
-  (let [pod (create-pod ttr-deps)]
-    (boot/with-pre-wrap fileset
-      (let [files         (perun/get-meta fileset)
+  [_ filterer FILTER code "predicate to use for selecting entries (default: `:content`)"]
+  (let [pod     (create-pod ttr-deps)
+        options (merge +ttr-defaults+ *opts*)]
+    (boot/with-pre-wrap fileset
+      (let [files         (filter (:filterer options) (perun/get-meta fileset))
             updated-files (pod/with-call-in @pod
                             (io.perun.ttr/calculate-ttr ~files))]
         (perun/report-debug "ttr" "generated time-to-read" (map :ttr updated-files))
         (perun/set-meta fileset updated-files)))))

+(def ^:private +word-count-defaults+
+  {:filterer :content})
+
 (deftask word-count
   "Count words in each file. Add `:word-count` key to the files' meta"
-  []
-  (let [pod (create-pod ttr-deps)]
-    (boot/with-pre-wrap fileset
-      (let [files         (perun/get-meta fileset)
+  [_ filterer FILTER code "predicate to use for selecting entries (default: `:content`)"]
+  (let [pod (create-pod ttr-deps)
+        options (merge +word-count-defaults+ *opts*)]
+    (boot/with-pre-wrap fileset
+      (let [files         (filter (:filterer options) (perun/get-meta fileset))
             updated-files (pod/with-call-in @pod
                             (io.perun.word-count/count-words ~files))]
         (perun/report-debug "word-count" "counted words" (map :word-count updated-files))
         (perun/set-meta fileset updated-files)))))

-
 (def ^:private gravatar-deps
   '[[gravatar "0.1.0"]])
+
+(def ^:private +gravatar-defaults+
+  {:filterer :content})

 (deftask gravatar
   "Find gravatar urls using emails"
   [s source-key SOURCE-PROP kw "email property used to lookup gravatar url"
-   t target-key TARGET-PROP kw "property name to store gravatar url"]
-  (let [pod (create-pod gravatar-deps)]
-    (boot/with-pre-wrap fileset
-      (let [files         (perun/get-meta fileset)
+   t target-key TARGET-PROP kw "property name to store gravatar url"
+   _ filterer FILTER code "predicate to use for selecting entries (default: `:content`)"]
+  (let [pod (create-pod gravatar-deps)
+        options (merge +gravatar-defaults+ *opts*)]
+    (boot/with-pre-wrap fileset
+      (let [files         (filter (:filterer options) (perun/get-meta fileset))
             updated-files (pod/with-call-in @pod
                             (io.perun.gravatar/find-gravatar ~files ~source-key ~target-key))]
         (perun/report-debug "gravatar" "found gravatars" (map target-key updated-files))
@@ -213,11 +225,15 @@
       (perun/report-info "draft" "removed draft files. Remaining %s files" (count updated-files))
       (perun/set-meta fileset updated-files))))

+(def ^:private +build-date-defaults+
+  {:filterer :content})
+
 (deftask build-date
   "Add :date-build attribute to each file metadata and also to the global meta"
-  []
-  (boot/with-pre-wrap fileset
-    (let [files           (perun/get-meta fileset)
+  [_ filterer FILTER code "predicate to use for selecting entries (default: `:content`)"]
+  (boot/with-pre-wrap fileset
+    (let [options         (merge +build-date-defaults+ *opts*)
+          files           (filter (:filterer options) (perun/get-meta fileset))
           global-meta     (perun/get-global-meta fileset)
           now             (java.util.Date.)
           updated-files   (map #(assoc % :date-build now) files)


more logging

more logging

--- src/babel/forest.clj
+++ src/babel/forest.clj
@@ -191,7 +191,7 @@
               (filter (fn [result]
                         (not (fail? result)))
                       (map (fn [complement]
-                             (let [debug (log/debug (str "Trying lexical complement:" (morph complement)))
+                             (let [debug (log/debug (str (morph bolt) ": trying lexical complement:" (morph complement)))
                                    result
                                    (unifyc bolt
                                            (path-to-map path


cleanup debugging

cleanup debugging

--- src/babel/reader.clj
+++ src/babel/reader.clj
@@ -148,28 +148,12 @@
         (target-timing-fn
          (binding [babel.generate/truncate? true]
            (babel.generate/generate target-spec target-model)))
-
-        ;; imagine if we could figure out these extra constraints:
-        source-extra-constraints
-        {:head {:rule "transitive-vp-nonphrasal-head"
-                :phrasal true
-                :head {:phrasal false}
-                :comp {:synsem {:cat :noun
-                                :propernoun true}
-                       :phrasal false}}
-
-         :comp {:rule "noun-phrase"
-                :phrasal true
-                :head {:phrasal false}
-                :comp {:phrasal false}}}

         source-spec
         (u/strip-refs ;; TODO: consider removing strip-refs; not clear if there is any reason why we need to do it.
          (u/unify
           {:synsem {:sem (u/get-in target-expression [:synsem :sem])}}

-          ;; imagine if we could put:
-          (if false source-extra-constraints {})
           basic-spec))

         ;; TODO: catch possible deref NPE exception that can happen when model is not yet loaded.


truncate during source generation

truncate during source generation

--- src/babel/reader.clj
+++ src/babel/reader.clj
@@ -158,7 +158,9 @@
         ;; TODO: catch possible deref NPE exception that can happen when model is not yet loaded.
         source-model @@(get models source-language)
         source-expression
-        (source-timing-fn (generate source-spec source-model))]
+        (source-timing-fn
+         (binding [babel.generate/truncate? true]
+           (generate source-spec source-model)))]
     (let [pairing
           {:target ((:morph target-model) target-expression)
            :pred (u/strip-refs


make get-column-number and get-line-number return ints

--- src/blind/reader.clj
+++ src/blind/reader.clj
@@ -126,8 +126,8 @@
     (unread rdr ch))

   IndexingReader
-  (get-line-number [reader] (inc line))
-  (get-column-number [reader]  column))
+  (get-line-number [reader] (int (inc line)))
+  (get-column-number [reader]  (int column)))

 (extend-type java.io.PushbackReader
   Reader
@@ -425,7 +425,7 @@
       '()
       (if-not line
         (clojure.lang.PersistentList/create the-list)
-        (with-meta (clojure.lang.PersistentList/create the-list) {:line (int line) :column column})))))
+        (with-meta (clojure.lang.PersistentList/create the-list) {:line line :column column})))))

 (defn read-vector
   [rdr _]


Added session state to /admin routes

Added session state to /admin routes

--- src/portal_clj/routes/admin.clj
+++ src/portal_clj/routes/admin.clj
@@ -4,12 +4,18 @@
             [portal-clj.views.admin :as admin]
             [portal-clj.models.user :as user]))

-(defn home []
-  (layout/common (admin/index (user/all))))
+(defn with-session [template session]
+  {:body template
+   :session session})

-(defn do-post []
-  (layout/common (admin/post-post)))
+(defn home [session]
+  (-> (layout/common (admin/index (user/all)))
+      (with-session session)))
+
+(defn do-post [req]
+  (-> (layout/common (admin/post-post))
+      (with-session session)))

 (defroutes admin-routes
-  (GET "/admin/home" [] (home))
-  (POST "/admin/post" [] (do-post)))
+  (GET "/admin/home" {session :session} (home session))
+  (POST "/admin/post" req (do-post req)))


ansi escapes

ansi escapes

--- src/pretty/cli/ansi_escapes.clj
+++ src/pretty/cli/ansi_escapes.clj
@@ -1,7 +1,6 @@
 (ns pretty.cli.ansi-escapes)

 (def esc-code "\033[")
-;(def esc-code "debug-")

 (defn cursor-to
   "Move the cursor to the 'x, y' cell"


(maint) Update docstring for grammar

(maint) Update docstring for grammar

Incorrect conjugation of reference is used. This commit fixes that.

--- src/puppetlabs/ezbake/stage.clj
+++ src/puppetlabs/ezbake/stage.clj
@@ -41,7 +41,7 @@

 (defn files-from-dir-iter
   "Given an individual entry from a `fs/iterate-dir` result set, return a flat
-  list of File objects for all of the files reference in the entry."
+  list of File objects for all of the files referenced in the entry."
   [iter-entry]
   {:pre [(vector? iter-entry)
          (= 3 (count iter-entry))]


Update table visibility_type even if null

--- src/metabase/api/meta/table.clj
+++ src/metabase/api/meta/table.clj
@@ -49,8 +49,8 @@
   (check-500 (upd-non-nil-keys Table id
                                :display_name    display_name
                                :entity_type     entity_type
-                               :visibility_type visibility_type
                                :description     description))
+  (check-500 (upd Table id :visibility_type visibility_type))
   (Table id))

 (defendpoint GET "/:id/fields"


X-Token TODO

X-Token TODO

--- src/nube/app.clj
+++ src/nube/app.clj
@@ -236,7 +236,7 @@
                 "/kill" #'kill-app-instances}}])

 (defn controller-app [{:keys [params uri] :as req}]
-  (if-not (= (get-token) (params "x-token"))
+  (if-not (= (get-token) (params "x-token")) ; todo move to headers when the CLI is ready
     {:status 500
      :headers {"Content-Type" "text/plain"}
      :body (pr-str {:error "Bad token"})}


mixer now works

mixer now works

--- src/codemash/kit.clj
+++ src/codemash/kit.clj
@@ -64,8 +64,6 @@

 (lp-core/boot!)
 (nk2/start! banks cfg)
-
-

 (defsynth basic-mixer [boost 0 amp 1 mute 1 in-bus 0 out-bus 0 clamp-down-t 0.05]
   (out out-bus (* (+ boost 1) amp (lag mute clamp-down-t) (in:ar in-bus 2))))
@@ -472,7 +470,6 @@
                 :mixers mixers}
       {:type ::sequencer})))

-
 (defonce sequencer-64
   (mk-sequencer
    (nk-bank :lp64)
@@ -507,6 +504,8 @@
 (defonce seq-basic-mixer-g (group :after default-mixer-g))
 (defonce seq-mix-s64  (basic-mixer [:head seq-basic-mixer-g] :in-bus lp64-b :mute 0))

+(ctl seq-mix-s64 :mute 1)
+
 (def sample-selection [;;arp-s
                        ;;arp-chord-s
                        voice-1-s
@@ -529,8 +528,7 @@
                        ;;  gtr-str-s
                        ])

-;;(def seq-mixers  (doall (map-indexed (fn [idx _] (mixers/add-nk-mixer (nk-bank :lp64) (str "lp64-seq-" idx) seq-mixer-group lp64-b)) sample-selection)))
-(def seq-mixers [])
+(def seq-mixers (vec (doall (map-indexed (fn [idx _] (add-nk-mixer (nk-bank :lp64) (str "lp64-seq-" idx) seq-mixer-group lp64-b)) sample-selection))))

 (defonce rate-b  (control-bus 1 "Rate"))
 (defonce rater-s (rater :out-bus rate-b))


np-grammar: nbar1 & nbar2

np-grammar: nbar1 & nbar2

--- src/babel/italiano/grammar.cljc
+++ src/babel/italiano/grammar.cljc
@@ -553,7 +553,8 @@
 (def np-grammar
   (let [grammar
         (filter #(or (= (:rule %) "noun-phrase2")
-                     (= (:rule %) "nbar"))
+                     (= (:rule %) "nbar1")
+                     (= (:rule %) "nbar2"))
                 grammar)
         lexicon
         (into {}


fix typo in noun-determiner agreement

fix typo in noun-determiner agreement

--- src/babel/italiano/lexicon.cljc
+++ src/babel/italiano/lexicon.cljc
@@ -221,7 +221,7 @@
                             :cat cat}
                  :synsem {:cat cat
                           :agr agr
-                          :subcat {:agr agr}}})))
+                          :subcat {:1 {:agr agr}}}})))

       phonize2 ;; for each value v of each key k, set the [:italiano :italiano] of v to k, if not already set
       ;; e.g. by exception-generator2.


Fixed order of deseasonalize args

Fixed order of deseasonalize args

--- src/clj/forma/trends/filter.clj
+++ src/clj/forma/trends/filter.clj
@@ -19,7 +19,7 @@
   (i/matrix (take n (cycle (i/identity-matrix freq)))))

 (defn dummy-deseasonalize
-  [freq ts]
+  [ts freq]
   ts)

 (defn deseasonalize
@@ -29,8 +29,8 @@
   original time series.

   Example:
-    (deseasonalize 23 (s/sample-uniform 200))"
-  [freq ts]
+    (deseasonalize (s/sample-uniform 200) 23)"
+  [ts freq]
   (cond
       (nil? ts) nil
       :else (let [x (dummy-mat freq (i/nrow ts))
@@ -228,7 +228,7 @@
   "Interpolate over bad values and remove seasonal component using reliability."
   [freq good-set bad-set spectral-ts reli-ts]
   (-> (make-reliable good-set bad-set spectral-ts reli-ts)
-      (dummy-deseasonalize freq)))
+      (deseasonalize freq)))

 (defn reliable?
   "Checks whether the share of reliable pixels exceeds a supplied minimum.


change Comet to be a manually triggered effect

--- src/clj/game/cards-hardware.clj
+++ src/clj/game/cards-hardware.clj
@@ -99,14 +99,16 @@

    "Comet"
    {:effect (effect (gain :memory 1)) :leave-play (effect (lose :memory 1))
-    :events {:play-event
-             {:optional {:prompt "Play another event?"
-                         :req (req (and (first-event state side :play-event)
-                                        (not (empty? (filter #(has? % :type "Event") (:hand runner))))))
-                         :yes-ability {:prompt "Choose an Event to play"
-                                       :choices (req (filter #(has? % :type "Event") (:hand runner)))
-                                       :msg (msg "play " (:title target))
-                                       :effect (effect (play-instant target))}}}}}
+    :events {:play-event {:req (req (first-event state side :play-event))
+                          :effect (req (system-msg state :runner
+                                                   (str "can play another event without spending a [Click] by clicking on Comet"))
+                                       (update! state side (assoc card :comet-event true)))}}
+    :abilities [{:req (req (:comet-event card))
+                 :prompt "Choose an Event in your Grip to play"
+                 :choices {:req #(and (= (:type %) "Event") (= (:zone %) [:hand]))}
+                 :msg (msg "play " (:title target))
+                 :effect (effect (play-instant target)
+                                 (update! (dissoc (get-card state card) :comet-event)))}]}

    "Cortez Chip"
    {:abilities [{:prompt "Choose a piece of ICE" :choices {:req #(and (not (:rezzed %)) (= (:type %) "ICE"))}


update Off the Grid test for effect persisting into later turns

--- src/clj/test/cards-upgrades.clj
+++ src/clj/test/cards-upgrades.clj
@@ -191,6 +191,9 @@
      (is (not (core/can-run-server? state "Server 1")) "Runner can only run on centrals")
      (run-empty-server state "R&D")
      (is (not (core/can-run-server? state "Server 1")) "Runner cannot run on Off the Grid")
+     (take-credits state :runner)
+     (take-credits state :corp)
+     (is (not (core/can-run-server? state "Server 1")) "Off the Grid prevention persisted")
      (run-empty-server state "HQ")
      (is (boolean (core/can-run-server? state "Server 1")) "Runner can run on Server 1")
      (is (= nil (refresh otg)) "Off the Grid trashed"))))


Add `NO-EXAM` constant for "No Exam" string

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

--- src/cljs/cljs_nusmods/time.cljs
+++ src/cljs/cljs_nusmods/time.cljs
@@ -44,6 +44,9 @@
         (str "0" time502)
         (str time502))))

+(def ^{:doc "String for No Exam"}
+  NO-EXAM "No Exam")
+
 (def ^{:doc     "Regex for extracting info from Exam Date strings"
        :private true}
   EXAM-DATE-REGEX #"^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})")
@@ -57,7 +60,7 @@
   "Converts an exam date to a more friendly format.
    Time is assumed to be Singapore Time."
   [examDateString]
-  (if (= "No Exam" examDateString)
+  (if (= NO-EXAM examDateString)
       examDateString
       (let [matchArray (.match examDateString EXAM-DATE-REGEX)
             year       (nth matchArray 1)


Make public resolve-digest function on hash ns.

--- src/clojure/buddy/core/hash.clj
+++ src/clojure/buddy/core/hash.clj
@@ -42,7 +42,7 @@
    :sha3-384 #(SHA3Digest. 284)
    :sha3-512 #(SHA3Digest. 512)})

-(defn- resolve-digest
+(defn resolve-digest
   "Helper function for make Digest instances
   from algorithm parameter."
   [alg]


Fixed #1: Wrong number of args (2) passed to: core/identity

--- src/ring/middleware/transit.clj
+++ src/ring/middleware/transit.clj
@@ -48,7 +48,7 @@
 (def ^:private chain
   (if aleph-available?
     (find-var 'manifold.deferred/chain)
-    identity))
+    (fn [v f] (f v))))

 (declare -decode-request


Updated buffer size to 50

Updated buffer size to 50

--- src/grimmly/core.clj
+++ src/grimmly/core.clj
@@ -6,7 +6,7 @@
          '[environ.core :refer [env]])

 (def inventory (ref (array-map)))
-(def inventory-size 20)
+(def inventory-size 50)

 ; Filter out unneeded environment variables for security
 (def propnames


Pretty-printing for all baseline words.  Better results!

--- src/hangman/core.clj
+++ src/hangman/core.clj
@@ -4,15 +4,35 @@
     [clojure.set     :as set]
   ) )

+;----------------------------------------------------------------------
+; Simple logging tools for demo. Replace in production
+;
+(def ^:const LOG-LEVEL-ERROR    5 )
+(def ^:const LOG-LEVEL-WARN     4 )
+(def ^:const LOG-LEVEL-NORMAL   3 )
+(def ^:const LOG-LEVEL-EXTRA    2 )
+(def ^:const LOG-LEVEL-DBG      1 )
+
+(def logging-enabled           true )
+(def logging-min-level         LOG-LEVEL-NORMAL )
+
+(defn write-to-log
+  "Write log msg to console for debugging."
+  [ level & msgs]
+  (when (and logging-enabled
+             (<= logging-min-level level) )
+    (apply println msgs ) ))
+
+; Convenience functions
+(defn log-err   [& msgs] (apply write-to-log  LOG-LEVEL-ERROR    msgs ))
+(defn log-warn  [& msgs] (apply write-to-log  LOG-LEVEL-WARN     msgs ))
+(defn log-msg   [& msgs] (apply write-to-log  LOG-LEVEL-NORMAL   msgs ))
+(defn log-extra [& msgs] (apply write-to-log  LOG-LEVEL-EXTRA    msgs ))
+(defn log-dbg   [& msgs] (apply write-to-log  LOG-LEVEL-DBG      msgs ))
+
+;----------------------------------------------------------------------
+;
 (def ^:const all-letters (set (map char (range (int \a) (inc(int \z)) ))) )
-
-(def logging-enabled true)
-
-(defn log-msg
-  "Write log msg to console for debugging."
-  [& msgs]
-  (when logging-enabled
-    (apply println msgs)) )

 (def all-words
   "A collection of all words for the hangman game."
@@ -24,7 +44,7 @@
 (defn show-info
   "Print synopsis info about a sequence of strings"
   [ seqName seqVals ]
-  (log-msg
+  (log-extra
     (str seqName "("  (count seqVals) ") " )
         (take show-info-size (map #(str \" % \") seqVals)) ))

@@ -99,35 +119,50 @@

 (defonce test-results (do-tests) )

+(defn play-hangman
+  "Plays the hangman game for the supplied word.  Returns the number of letter guesses
+  required to find a unique match in the master words list."
+  [tgt-word]
+  (let [game-words    all-words
+        words-map     (group-by count game-words)  ; map keyed by word length
+        word-list     (words-map (count tgt-word)) ; words of correct length
+    ]
+    (loop [ guessed-chars   #{}
+            clue            (make-clue tgt-word guessed-chars) ]
+      (log-extra )
+      (let [ keep-words (filter-words clue guessed-chars word-list) ]
+        (show-info "keep-words" keep-words)
+        (if (= 1 (count keep-words))
+          (let [final-guess         (str/join (first keep-words))
+                num-letter-guesses  (count guessed-chars) ]
+            (log-extra (str "***** found word:  '" final-guess
+                        "'   Guesses:  " (count guessed-chars) "  *****") )
+            num-letter-guesses ; return value
+          )
+        ;else
+          (let [new-guess       (make-guess keep-words guessed-chars)
+                guessed-chars   (conj guessed-chars new-guess)
+                new-clue        (make-clue tgt-word guessed-chars) ]
+            (log-extra "clue: " clue "  new-guess" new-guess
+              "  guessed-chars (" (count guessed-chars) ")" guessed-chars)
+            (recur  (conj guessed-chars new-guess)  new-clue )
+          )
+        ) ))))
+
+(def baseline-scores {
+      "comaker" 25 "cumulate" 9 "eruptive" 5 "factual" 9 "monadism" 8
+      "mus" 25 "nagging" 7 "oses" 5 "remembered" 5 "spodumenes" 4
+      "stereoisomers" 2 "toxics" 11 "trichromats" 5 "triose" 5 "uniformed" 5 } )
+
+
 (defn main
-  ( []
-    (let [tgt-word      "stereoisomers"
-          game-words    all-words
-          words-map     (group-by count game-words)  ; map keyed by word length
-          word-list     (words-map (count tgt-word)) ; words of correct length
-      ]
-      (loop [ guessed-chars   #{}
-              clue            (make-clue tgt-word guessed-chars) ]
-        (log-msg)
-        (let [ keep-words (filter-words clue guessed-chars word-list) ]
-          (show-info "keep-words" keep-words)
-          (if (= 1 (count keep-words))
-            (let [final-guess (str/join (first keep-words)) ]
-              (log-msg (str "***** found word:  '" final-guess
-                "'   Guesses:  " (count guessed-chars) "  *****") )
-              (log-msg "matches:" (= final-guess tgt-word)) )
-          ;else
-            (let [new-guess       (make-guess keep-words guessed-chars)
-                  guessed-chars   (conj guessed-chars new-guess)
-                  new-clue        (make-clue tgt-word guessed-chars) ]
-              (log-msg "clue: " clue "  new-guess" new-guess
-                "  guessed-chars (" (count guessed-chars) ")" guessed-chars)
-              (recur  (conj guessed-chars new-guess)  new-clue )
-            )
-          )
-        ))
+  []
+  (doseq [ tgt-word (keys baseline-scores) ]
+    (let [ num-letter-guesses   (play-hangman tgt-word) ]
+      (log-msg (str   "word:  " (format "%-15s" tgt-word)
+                 "  guesses:  " (format "%2s" num-letter-guesses)
+                "  baseline:  " (format "%2s" (baseline-scores tgt-word)) ))))
+)

-  ))
-)
 (defn -main [& args] (apply main args) )


[#3026] Round coordinate

[#3026] Round coordinate

Round coordinate to 6 digits but go by bigdec rounding to remove
trailing zeros. This to be able to compare facts to values from Postgres

--- backend/specs/akvo/lumen/specs/import/values.clj
+++ backend/specs/akvo/lumen/specs/import/values.clj
@@ -1,9 +1,17 @@
 (ns akvo.lumen.specs.import.values
   (:require [clojure.spec.alpha :as s]
             [akvo.lumen.util :refer (squuid)]
-            [akvo.lumen.specs :as lumen.s :refer (sample)]
+            [akvo.lumen.specs :as lumen.s]
             [akvo.lumen.lib.import.csv :as csv]))

+(defn round-coordinate
+  "Round coordinate to 6 digits but go by bigdec rounding to remove trailing
+   zeros. This to be able to compare facts to values from Postgis"
+  [coordinate]
+  (-> coordinate
+      bigdec
+      (.setScale 6 java.math.RoundingMode/HALF_EVEN)
+      double))

 (defn rand-lng
   []
@@ -19,7 +27,8 @@
 (defn rand-point
   "Random geopoint with 6 decimals resolution"
   []
-  (format "POINT(%.6f %.6f)" (rand-lng) (rand-lat)))
+  (format "POINT(%s %s)"
+          (round-coordinate (rand-lng)) (round-coordinate (rand-lat))))

 (def point "POINT(10 10)")


Add table row entries for option query string data. Make the query string and body table rows optional on there being data to display. Reorg the cljs a bit and add some doc strings.

--- src/posthere/cljs/posthere.cljs
+++ src/posthere/cljs/posthere.cljs
@@ -44,13 +44,6 @@
     [selector]
     (.text ($ "#urlMethodInputDisplay") (.val ($ selector))))

-(declare row-for) ; HTML snippet coming later in the namespace
-
-(defn- table-rows
-  "Turn a cljs map into name/value rows in a table with hiccup."
-  [entries]
-  (reduce #(conj %1 (row-for %2 (get entries %2))) () (keys entries)))
-
 (defn- html-escape
   "Make a string possibly containing HTML display literally rather than as intepreted HTML."
   [string]
@@ -59,39 +52,60 @@
 (defn- time-ago
   "Use the momemnt.js library to return a human readable English string describing how long ago the request was made."
   [result]
-  ; moment(timestamp).fromNow();
   (.fromNow (js/moment. (aget result "timestamp"))))
+
+;; ----- Result Table Building Functions -----
+
+(defn- table-header [label]
+  [:tr [:th.text-center {:colspan 2} label]])
+
+(declare row-for) ; HTML snippet coming later in the namespace
+(defn- table-rows
+  "Turn a cljs map into name/value rows in a table with hiccup."
+  [entries]
+  (reduce #(conj %1 (row-for %2 (get entries %2))) () (keys entries)))
+
+(defn- string-content
+  "A hiccup table row with only one data element, the <pre> and <code> HTML escaped content."
+  [content]
+  [:tr [:td.text-left {:colspan 2} [:pre [:code (html-escape content)]]]])
+
+(defn- map-content
+  "
+  Try to treat the content as a map, and create table rows of name/value pairs.
+  If it's not a map, just create a single row with the content as the only data in the row.
+  "
+  [content]
+  (let [cljs-content (js->clj content)]
+    (if (map? cljs-content)
+      (table-rows cljs-content)
+      (string-content content))))

 ;; ----- Hiccup HTML snippets for the results page -----

 (defhtml row-for
-  ""
+  "Hiccup HTML for a key/value row in a table."
   [key val]
   [:tr
     [:td key]
     [:td val]])

-(defn- body-table-string-content [body]
-  [:tr
-    [:td.text-left [:pre [:code
-      (html-escape body)]]]])
-
-(defn- body-table-content [result]
-  (let [body (aget result "body")
-        cljs-body (js->clj body)]
-    (if (map? cljs-body)
-      (table-rows cljs-body)
-      (body-table-string-content body))))
-
 (defhtml body-table
-  "HTML for a 2 row table, containing a body label row and the body content that was POSTed."
+  "
+  HTML for a table, containing an optional query string row and the query string content
+  and a body label row and the body content that was POSTed.
+  "
   [result]
-  [:div.col-md-8
-    [:table.table.table-bordered.result-table
-      [:tbody
-        [:tr
-          [:th.text-center {:colspan 2} "Body"]]
-        (body-table-content result)]]])
+  (let [query-string (aget result "parsed-query-string")
+        body (aget result "body")]
+    [:div.col-md-8
+      (if (or query-string body)
+        [:table.table.table-bordered.result-table
+          [:tbody
+            (if query-string (table-header "Query String"))
+            (if query-string (map-content query-string))
+            (if body (table-header "Body"))
+            (if body (map-content body))]])]))

 (defhtml headers-table
   "HTML for a table with all the HTTP header name/value pairs."


Minor style change

Minor style change

Kibit suggestion

--- src/simple_check/generators.clj
+++ src/simple_check/generators.clj
@@ -495,7 +495,7 @@
   {:no-doc true}
   [inner-type]
   (fn [size]
-    (if (= size 0)
+    (if (zero? size)
       inner-type
       (one-of [inner-type
                (container-type (resize (quot size 2) (sized (sized-container inner-type))))]))))


Removed unused code

Removed unused code

--- src/research_clojure/runSimulation.clj
+++ src/research_clojure/runSimulation.clj
@@ -8,13 +8,13 @@
 (defn writeResults
   "Writes the results of each learner to an output file"
   [results]
-  (println results)
+  (println "Results: " results)
   (spit "out.csv" results))

 (defn updateTimeCourseVector
   "Updates the sentence number of any of
-  the 13 parameters (represented by oldGrammar)
+  the 13 parameters (represented by oldGrammar)
   recorded in timeCourseVector if their coresponding
   value in grammar has changed after being
   processed by setParameters"
@@ -30,7 +30,7 @@

 (defn doesChildLearnGrammar
-  "Runs sentence consuming functions until the
+  "Runs sentence consuming functions until the
   correct grammar is learned or the maximum number
   of sentences are processed. Needs infoList, grammar, expected grammar"
   [sentences max_num]
@@ -49,18 +49,38 @@
             (reset! grammarLearned (isGrammarLearned? grammar infoList1)))
           (swap! sentenceCount inc))

-        (println "Final grammar: " @grammar)
+        (println "Finished")
+        ;(writeResults @grammar)
         [@grammar @grammarLearned (get @timeCourseVector 0) (get @timeCourseVector 1)]))

 (defn runSimulation
-  "max_eChildren number of eChildren will process
+  "max_eChildren number of eChildren will process
   max_sentences number of sentences."
   [sentences max_eChildren max_sentences]
   (io/delete-file "out.csv" :silently true)
-  (loop [i 0 results []]
-    (if (< i max_eChildren)
-      (recur (inc i) (conj results (doesChildLearnGrammar sentences max_sentences)))
-      (writeResults results))))

-;(-> (enqueue grammar (doesChildLearnGrammar sentences max_sentences) (writeResults @grammar)))
+  (let [results []]
+    (loop [i 0]
+      (when (< i max_eChildren)
+        (conj results (future (doesChildLearnGrammar sentences max_sentences)))
+        (recur (inc i))))
+    (writeResults results))
+  (println "Finished simulation"))
+
+
+(comment
+working version
+(defn runSimulation
+  "max_eChildren number of eChildren will process
+  max_sentences number of sentences."
+  [sentences max_eChildren max_sentences]
+  (io/delete-file "out.csv" :silently true)
+
+  (loop [i 0]
+    (when (< i max_eChildren)
+      (future (doesChildLearnGrammar sentences max_sentences))
+      (recur (inc i))))
+  (println "Finished simulation"))
+
+)


DEal with NPE

DEal with NPE

--- src/rsvp_backend/view/invitee_list.clj
+++ src/rsvp_backend/view/invitee_list.clj
@@ -28,7 +28,8 @@
   [row]
   [:td
    (:rsvp_state row) [:br]
-   (when (> (:times_verified row) 1) "(Duplicate?)")])
+   (when (and (not (= (:times_verified row) nil))
+              (> (:times_verified row) (Integer/parseInt 1))) "(Duplicate?)")])

 (defn render
   [data]


Produce real rdf files

Produce real rdf files

not drf

--- src/mdr2/rdf.clj
+++ src/mdr2/rdf.clj
@@ -17,7 +17,7 @@
            multimedia_type multimedia_content narrator producer produced_date
            revision revision_date revision_description
            total_time audio_format periodical_number]}]
-  [:rdf:DRF {:xmlns:rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+  [:rdf:RDF {:xmlns:rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
              :xmlns:dc "http://purl.org/dc/elements/1.1/"
              :xmlns:dtb "http://www.daisy.org/z3986/2005/dtbook/"
              :xmlns:sbs "http://www.sbszh.ch/sbs/namespace"}


Fix doc-lookup for Namespaces

Fix doc-lookup for Namespaces

--- src/de/kotka/vimclojure/backend.clj
+++ src/de/kotka/vimclojure/backend.clj
@@ -37,7 +37,9 @@
         (print-special-doc sym "Special Form" (syntax-symbol-anchor sym))

         :else
-        (print-doc (ns-resolve namespace sym))))))
+        (if-let [nspace (find-ns sym)]
+          (print-namespace-doc nspace)
+          (print-doc (ns-resolve namespace sym)))))))

 (defn javadoc-path-for-class
   "Translate the name of a Class to the path of its javadoc file."


Fix Pars error

Fix Pars error

--- src/discuss/communication/main.cljs
+++ src/discuss/communication/main.cljs
@@ -33,7 +33,7 @@
   ([url body]
    (post-json url body process-url-handler {"Content-Type" "application/json"})))

-defn- dbas-conform-origin-author
+(defn- dbas-conform-origin-author
   [{:keys [is-dgep-native uid nickname]}]
   {:dgep-native is-dgep-native
    :name nickname


trim trailing newlines from namelist output

--- src/nml/core.clj
+++ src/nml/core.clj
@@ -166,5 +166,5 @@
     (if (:help options) (usage summary))
     (let [tree (nml-tree (first arguments))]
       (cond gets  (nml-gets tree gets (:values options))
-            sets  (println (nml-str (nml-sets tree sets)))
-            :else (println (nml-str tree))))))
+            sets  (println (string/trim (nml-str (nml-sets tree sets))))
+            :else (println (string/trim (nml-str tree)))))))


Remove dead code

Remove dead code

--- src/refactor_nrepl/refactor.clj
+++ src/refactor_nrepl/refactor.clj
@@ -152,16 +152,6 @@
     (transport/send transport (response-for msg :syms-count (count syms)
                                             :status :done))))

-(defn- form-contains-var [var-name node]
-  (let [form (:form node)]
-    (or (= var-name (str form)) ;; invoke
-        (and (coll? form) (= "def" (-> form first str))
-             (= var-name (-> form second str))) ; def/defn definition
-        (and (coll? form) (= "var" (-> form first str))
-             ;; #'varname style reference
-             (= (str/replace var-name "#'" "")
-                (-> form second str))))))
-
 (defn wrap-refactor
   "Ensures that refactor only triggered with the right operation and
   forks to the appropriate refactor function"


Refactor - more effort at catching / reporting errors in running flow graphs


remove coldstart

remove coldstart


Add element scrollWidth accessor

Add element scrollWidth accessor

--- src/lt/util/dom.cljs
+++ src/lt/util/dom.cljs
@@ -148,6 +148,9 @@

 (defn width [elem]
   (.-clientWidth elem))
+
+(defn scroll-width [elem]
+  (.-scrollWidth elem))

 (defn offset-top [elem]
   (.-offsetTop elem))


[fix 6047] fix bridge functions cofx position

Signed-off-by: yenda <96f164ad4d9b2b0dacf8ebee2bb1eeb3aa69adf1@status.im>

--- src/status_im/browser/core.cljs
+++ src/status_im/browser/core.cljs
@@ -225,8 +225,8 @@
               (update-browser browser)
               (navigation/navigate-to-cofx :browser nil))))

-(defn web3-send-async
-  [{:keys [method] :as payload} message-id {:keys [db]}]
+(fx/defn web3-send-async
+  [{:keys [db]} {:keys [method] :as payload} message-id]
   (if (or (= method constants/web3-send-transaction)
           (= method constants/web3-personal-sign))
     {:db       (update-in db [:wallet :transactions-queue] conj {:message-id message-id :payload payload})
@@ -244,17 +244,17 @@
   {:browser/send-to-bridge {:message message
                             :webview (get-in cofx [:db :webview-bridge])}})

-(defn web3-send-async-read-only
-  [dapp-name {:keys [method] :as payload} message-id {:keys [db] :as cofx}]
+(fx/defn web3-send-async-read-only
+  [{:keys [db] :as cofx} dapp-name {:keys [method] :as payload} message-id]
   (let [{:dapps/keys [permissions]} db]
     (if (and (#{"eth_accounts" "eth_coinbase" "eth_sendTransaction" "eth_sign"
                 "eth_signTypedData" "personal_sign" "personal_ecRecover"} method)
              (not (some #{"WEB3"} (get-in permissions [dapp-name :permissions]))))
-      (send-to-bridge {:type      constants/web3-send-async-callback
+      (send-to-bridge cofx
+                      {:type      constants/web3-send-async-callback
                        :messageId message-id
-                       :error     "Denied"}
-                      cofx)
-      (web3-send-async payload message-id cofx))))
+                       :error     "Denied"})
+      (web3-send-async cofx payload message-id))))

 (fx/defn handle-scanned-qr-code
   [cofx data message]
@@ -275,13 +275,13 @@
       (and (= type constants/history-state-changed)
            platform/ios?
            (not= "about:blank" url))
-      (update-browser-history browser url false cofx)
+      (update-browser-history cofx browser url false)

       (= type constants/web3-send-async)
-      (web3-send-async payload messageId cofx)
+      (web3-send-async cofx payload messageId)

       (= type constants/web3-send-async-read-only)
-      (web3-send-async-read-only dapp-name payload messageId cofx)
+      (web3-send-async-read-only cofx dapp-name payload messageId)

       (= type constants/scan-qr-code)
       (qr-scanner/scan-qr-code cofx


define find-node-container

define find-node-container

--- src/synthesis_crawlers/core.clj
+++ src/synthesis_crawlers/core.clj
@@ -148,6 +148,7 @@
 (s/fdef reach?
         :args (s/cat :a #(instance? Element %) :b #(instance? Element %)))
 (defn reach?
+  "returns true iff b is reachable from a"
   [a b]
   (->> (filter #(= % b) (.getAllElements a)) empty? not))

@@ -224,11 +225,11 @@

 (defn find-container-node
   [node-attrs all-attrs]
-  #_(reduce (fn [acc e]
-              (if  (reach? acc e)  ) )
-            (filter (fn [[node attrs]] (= all-attrs attrs))
-                    node))
-  nil)
+  (reduce (fn [acc e]
+            (if (reach? acc e) e) acc)
+          (keys (into {}
+                      (filter (fn [[node attrs]] (= all-attrs attrs))
+                              node-attrs)))))

 (s/fdef find-container
         :args (s/cat :reachable-attr-nodes


route for alerts

route for alerts

--- src/terraboot/elasticsearch.clj
+++ src/terraboot/elasticsearch.clj
@@ -148,7 +148,8 @@
                             :vpc_security_group_ids [(vpc-id-of "aws_security_group" "nrpe")
                                                      (id-of "aws_security_group" (str "uses-db-" (vpc-unique "alerts")))
                                                      (vpc-id-of "aws_security_group" "allow-elb-alerts")
-                                                     (vpc-id-of "aws_security_group" "all-servers")]})
+                                                     (vpc-id-of "aws_security_group" "all-servers")
+                                                     (vpc-id-of "aws_security_group" "sends_influx")]})

              (elb "alerts" resource {:name "alerts"
                                      :health_check {:healthy_threshold 2


Use region in logstash

Use region in logstash

--- src/terraboot/elasticsearch.clj
+++ src/terraboot/elasticsearch.clj
@@ -56,6 +56,7 @@
 (defn logstash-user-data-coreos [es-endpoint]
   (let [logstash (docker-systemd-unit "mastodonc" "logstash-ng"
                                       {:options [(str "--env " "ES_HOST=" es-endpoint)
+                                                 (str "--env " "REGION=" region)
                                                  "--net=host"]
                                        :entry-point "-f /etc/logstash/logstash.conf"})
         nginx (docker-systemd-unit "mastodonc" "kibana-nginx"


fn to issue queries across all shelves

fn to issue queries across all shelves

--- src/myshelf/core.clj
+++ src/myshelf/core.clj
@@ -192,6 +192,22 @@
          :content
          (map element->map)
          (map (comp (juxt :title :id :author) :best_book :work)))))
+
+(defn find-book-on-shelves
+  "Try to find a book on a user's shelves, given book title"
+  [consumer access-token user-id title]
+  (let [shelf-url (str "https://www.goodreads.com/review/list/"
+                       user-id)
+        params {:format "xml" :v 2 (keyword "search[query]") title}
+        resp (make-auth-request-GET consumer
+                                    access-token
+                                    shelf-url
+                                    params)]
+    (->> resp
+         :content
+         second
+         :content
+         (map extract-book-data))))

 (defn add-book-review
   "Add a book review. Automatically adds book to read shelf."


whitespace

whitespace

--- src/ontrail/core.clj
+++ src/ontrail/core.clj
@@ -168,7 +168,7 @@
            (json-response {:message "username-exists"} 400))))

   (wrap-multipart-params
-   (POST "/rest/v1/import" {params :params cookies :cookies}
+    (POST "/rest/v1/import" {params :params cookies :cookies}
          (redirect (import-from-tempfile (user-from-cookie cookies) (:tempfile (get params :file))))))

   (route/resources "/")


setting user and env, taking args from map

--- src/openstack/gc.clj
+++ src/openstack/gc.clj
@@ -13,8 +13,10 @@
   "GCing Vm's in openstack"
   (:refer-clojure :exclude [==])
   (:require
+    [celestial.security :refer (set-user)]
     [clojure.java.data :refer [from-java]]
     [openstack.common :refer (servers)]
+    [celestial.model :refer (set-env)]
     [celestial.common :refer (import-logging)]
     [cheshire.core :refer (generate-string)]
     [clojure.core.logic :refer (!= == run* membero fresh featurec run nafc)]
@@ -54,10 +56,12 @@
        (== q ?instance-id)))))

 (defn cleanup
-   "clears up instances"
-   [tenant env es]
-   (let [ds (ids tenant) ms (data env :openstack) cs (find-candidates ms ds es)]
-     (debug "following" cs "ids will be cleared")
-     (doseq [c cs]
-       #_(.delete servers c)
-       (debug "cleared" c))))
+  "Clears up instances not managed in Celestial"
+  [{:keys [tenant env es user]}]
+  (set-user {:username user}
+    (set-env env
+     (let [ds (ids tenant) ms (data env) cs (find-candidates ms ds es)]
+       (debug "following" cs "ids will be cleared")
+       (doseq [c cs]
+         #_(.delete servers c)
+         (info "cleared" c  "on gc task"))))))


Remove commented code.

Remove commented code.

--- src/uxbox/ui/workspace/options.cljs
+++ src/uxbox/ui/workspace/options.cljs
@@ -68,18 +68,9 @@
       [:div.element-set-content
        ;; SLIDEBAR FOR ROTATION AND OPACITY
        [:span "Color"]
-       #_(colorpicker (constantly nil))
-
        (colorpicker {:picker {:width 165 :height 165}
                      :bar {:width 15 :height 165}
                      :callback on-color-picker-event})
-
-       #_[:div.element-color-picker
-        [:div.color-picker-body
-          [:img {:src "images/color-gamma.png", :border "none"}]]
-        [:div.color-picker-bar
-          [:div.color-bar-select]
-          [:img {:src "images/color-bar.png", :border "none"}]]]
        [:div.row-flex
         [:input#width.input-text
          {:placeholder "#"


Fix macros and add texture-atlas

Fix macros and add texture-atlas

--- src/play_clj/g2d.clj
+++ src/play_clj/g2d.clj
@@ -2,7 +2,7 @@
   (:require [play-clj.utils :as u])
   (:import [com.badlogic.gdx.graphics Texture]
            [com.badlogic.gdx.graphics.g2d Animation BitmapFont NinePatch
-            ParticleEffect TextureRegion]))
+            ParticleEffect TextureAtlas TextureRegion]))

 (defmacro bitmap-font
   "Returns a [BitmapFont](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/g2d/BitmapFont.html)
@@ -72,7 +72,7 @@
     (nine-patch \"image.png\" :set-color (color :blue))
     (nine-patch {:image \"image.png\" :left 10 :right 10 :top 10 :bottom 10})"
   [arg & options]
-  `(let [entity# (texture* ~arg)]
+  `(let [entity# (nine-patch* ~arg)]
      (u/calls! ^NinePatch (u/get-obj entity# :object) ~@options)
      entity#))

@@ -98,7 +98,7 @@
                      (files! :internal \"fire.p\")
                      (files! :internal \"fire-images\"))"
   [& options]
-  `(let [entity# (texture*)]
+  `(let [entity# (particle-effect*)]
      (u/calls! ^ParticleEffect (u/get-obj entity# :object) ~@options)
      entity#))

@@ -108,6 +108,29 @@
     (particle-effect! entity :set-position 10 10)"
   [entity k & options]
   `(u/call! ^ParticleEffect (u/get-obj ~entity :object) ~k ~@options))
+
+; texture-atlas
+
+(defn texture-atlas*
+  "The function version of `texture-atlas`"
+  [^String path]
+  (TextureAtlas. path))
+
+(defmacro texture-atlas
+  "Returns a [TextureAtlas](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/g2d/TextureAtlas.html)
+
+    (texture-atlas \"packed.txt\")"
+  [path & options]
+  `(let [^TextureAtlas object# (texture-atlas* path)]
+     (u/calls! object# ~@options)
+     object#))
+
+(defmacro texture-atlas!
+  "Calls a single method on a `texture-atlas`
+
+    (texture-atlas! object :create-patch \"test\")"
+  [object k & options]
+  `(u/call! ^TextureAtlas ~object ~k ~@options))

 ; animation


lein: cider-nrepl 0.8.0

lein: cider-nrepl 0.8.0

--- lein_profiles.clj
+++ lein_profiles.clj
@@ -2,7 +2,7 @@
                   [lein-ring "0.8.13"]
                   [lein-ancient "0.5.5"]
                   [jonase/eastwood "0.2.0"]
-                  [cider/cider-nrepl "0.7.0"]
+                  [cider/cider-nrepl "0.8.0"]
                   ]}}
 {:dev {:dependencies
        [[com.cemerick/pomegranate "0.3.0"]]


fixing trace args

fixing trace args

--- src/vc/guest.clj
+++ src/vc/guest.clj
@@ -81,7 +81,7 @@
           timeout [(hypervisor :vcenter :guest-timeout) :second]
           args* (if uuid (<< "~{args} >> /tmp/run-~{uuid}.log") args)
           pid (.startProgramInGuest m (npa auth) (prog-spec cmd args* auth))]
-         (trace (<< "guest running: ~cmd ~args*"))
+         (trace (<< "guest running: ~{cmd} ~{args*}"))
          (wait-for {:timeout timeout :sleep [200 :ms]} #(-> (exit-code m pid auth) nil? not)
            {:type ::vc:guest-run-timeout :message (<< "Timed out on running ~{cmd} ~{args} in guest") :timeout timeout})
          (when-not (= (exit-code m pid auth) 0)


add adjective tests

add adjective tests

--- test/babel/test/it.cljc
+++ test/babel/test/it.cljc
@@ -3,8 +3,8 @@
   (:require [babel.engine :refer [generate]]
             [babel.italiano.grammar :refer [small medium]]
             [babel.italiano.lexicon :refer [lexicon]]
-            [babel.italiano.morphology :refer [analyze fo]]
-            [babel.italiano.workbook :refer [parse]]
+            [babel.italiano.morphology :refer [fo]]
+            [babel.italiano.workbook :refer [analyze parse]]
             #?(:clj [clojure.test :refer [deftest is]])
             #?(:cljs [cljs.test :refer-macros [deftest is]])
             #?(:clj [clojure.tools.logging :as log])
@@ -14,6 +14,12 @@
 (deftest analyze-1
   (let [singular (analyze "compito" (:lookup medium))
         plural  (analyze "compiti" (:lookup medium))]
+    (is (not (nil? singular)))
+    (is (not (nil? plural)))))
+
+(deftest analyze-2
+  (let [singular (analyze "difficile" (:lookup medium))
+        plural  (analyze "difficili" (:lookup medium))]
     (is (not (nil? singular)))
     (is (not (nil? plural)))))


refactor worker and fix log output a bit

--- src/cu/core.clj
+++ src/cu/core.clj
@@ -2,6 +2,7 @@
   (:require
     [aws.sdk.s3 :as s3]
     [cemerick.bandalore :as sqs]
+    [clojure.string :refer [split join]]
     [clojure.java.shell :refer [sh]]
     [cu.git :as git]
     [environ.core :refer [env]]
@@ -17,25 +18,29 @@
                                        (env :aws-secret-key)))
 (defn- sqs-queue [client queue-name] (sqs/create-queue client queue-name))

-(defn run
-  [queue-name]
-  (let [workspaces-dir (env :workspaces-path)
-        basedir (str workspaces-dir "/test-project")
-        workspace-dir (str basedir "/workspace")
-        client (sqs-client)
+(defn- clone-target-url [payload]
+  (if payload (get-in (read-string payload) ["repository" "url"])))
+
+(defn- workspace-dir [workspaces-dir url]
+  (join "/" [workspaces-dir
+             (last (split url #"/"))
+             "workspace"]))
+(comment
+  (workspace-dir "spaces" "http://github.bob/foobar/projectx"))
+
+(defn run [queue-name]
+  (let [client (sqs-client)
         q (sqs-queue client queue-name)
-        raw-payload (->> (sqs/receive client q)
-                         first
-                         :body)
-        payload (if raw-payload
-                  (read-string raw-payload)
-                  {})]
-    (when-let [url (get-in payload ["repository" "url"])]
-      (.mkdirs (java.io.File. basedir))
-      (git/fresh-clone url workspace-dir)
-      (s3/put-object aws-creds bucket log-key
-                     (:out (sh (str workspace-dir "/run-pipeline"))))
-      "Processed payload for URL" url)))
+        raw-payload (-> (sqs/receive client q)
+                        first
+                        :body)]
+    (when-let [url (clone-target-url raw-payload)]
+      (let [ws-dir (workspace-dir (env :workspaces-path) url)]
+        (git/fresh-clone url ws-dir)
+        (let [output (:out (sh (str ws-dir "/run-pipeline")))]
+          (s3/put-object aws-creds bucket log-key output)
+          (str
+            "Processed payload for URL " url " with output " output))))))

 (defn -main [& [queue-name]]
   (loop []


Added lift/apply funcs - ($ f x) and ($lift & fs)

Added ($ f x) and ($lift & fs) to save a few characters

--- src/hyjinks.clj
+++ src/hyjinks.clj
@@ -22,6 +22,10 @@
 (defn- capitalize [s] (case (= s "") "" (nil? s) nil true (str (Character/toUpperCase (.charAt s 0)) (.substring s 1))))

 (defn- readable-string [id] (join " " (map capitalize (split id #"-"))))
+
+(defn- $ [f x] (f x))
+
+(defn- $lift [& fs] (fn [xs] (map $ fs xs)))

 ;; Core types

@@ -108,7 +112,7 @@
 (defn map-table [m] (table (map (fn [[k v]] (tr (td (if (keyword? k) (readable-string (name k)) k)) (td v))) (sort-by key m))))

 (defn definitions [term-map]
-	(dl (mapcat (fn [[t d]] [(dt t) (dd d)]) (sort-by key term-map))))
+	(dl (mapcat ($lift dt dd) (sort-by key term-map))))

 (defn radio-list [param & opts]
 	(mapcat (fn [[t v]] [(label v {:for t}) (input {:id v :value v :name param :type "radio"})]) opts))


check for missing device adapters

check for missing device adapters

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

--- buildscripts/buildcheck/src/buildcheck/core.clj
+++ buildscripts/buildcheck/src/buildcheck/core.clj
@@ -17,8 +17,6 @@
     (.format format (.getTime one-hour-ago))))

 (def yyyymmdd (SimpleDateFormat. "yyyyMMdd"))
-
-(doto (Calendar/getInstance) (.add Calendar/HOUR -1))

 ;(defn result-file [bits mode]
 ;  (File. micromanager (str "/result" bits (name mode) ".txt")))
@@ -47,20 +45,21 @@
   (map first
     (re-seq #"\[javac\]\s\b([1-9]|[0-9][1-9]|[0-9][0-9][1-9])\b\serrors?" result-text)))

+(defn device-adapter-dlls [dir]
+  (filter
+      (fn [file]
+        (let [file-name (.getName file)]
+          (and (.endsWith file-name ".dll")
+               (.startsWith file-name "mmgr_dal"))))
+      (.listFiles dir)))
+
 (defn old-files [files time-limit-hours]
   (let [now (System/currentTimeMillis)
         before (- now (* time-limit-hours MS-PER-HOUR))]
     (filter #(< (.lastModified %) before) files)))

 (defn old-dlls [dir time-limit-hours]
-  (old-files
-    (filter
-      (fn [file]
-        (let [file-name (.getName file)]
-          (and (.endsWith file-name ".dll")
-               (.startsWith file-name "mmgr_dal"))))
-      (.listFiles dir))
-    time-limit-hours))
+  (old-files (device-adapter-dlls dir) time-limit-hours))

 (defn old-jars [dir time-limit-hours]
   (old-files
@@ -74,6 +73,29 @@
         pattern (re-pattern (str "MMSetup" bits "BIT_[^\\s]+?_" date-token ".exe"))]
     (re-find pattern txt)))

+(defn device-vcproj-files []
+  (let [device-adapter-dirs [(File. micromanager "/DeviceAdapters")
+                         (File. micromanager "/SecretDeviceAdapters")]]
+    (filter #(.. % getName (endsWith ".vcproj"))
+            (mapcat file-seq device-adapter-dirs))))
+
+(defn dll-name [file]
+  (second (re-find #"mmgr_dal_(.*?).dll" (.getName file))))
+
+(defn project-name [vcproj-file]
+  (-> vcproj-file clojure.xml/parse :attrs :Name))
+
+(defn bin-dir [bits]
+  (File. micromanager
+         (condp = bits
+           32 "bin_Win32"
+           64 "bin_x64")))
+
+(defn missing-device-adapters [bits]
+  (let [dll-names (map dll-name (device-adapter-dlls (bin-dir bits)))
+        project-names (map project-name (device-vcproj-files))]
+    (sort (clojure.set/difference (set project-names) (set dll-names)))))
+
 (defn str-lines [sequence]
   (apply str (interpose "\n" sequence)))

@@ -81,13 +103,11 @@
   (let [f (result-file bits mode)
         result-txt (slurp f)
         vs-error-text (visual-studio-error-text result-txt)
-        outdated-dlls (old-dlls (File. micromanager
-                                       (condp = bits
-                                         32 "bin_Win32"
-                                         64 "bin_x64")) 24)
+        outdated-dlls (old-dlls (bin-dir bits) 24)
         javac-errs (javac-errors result-txt)
         outdated-jars (old-jars (File. micromanager "Install_AllPlatforms") 24)
-        installer-ok (exe-on-server? bits today-token)]
+        installer-ok (exe-on-server? bits today-token)
+        missing-adapters (missing-device-adapters bits)]
     (when-not (and (empty? vs-error-text) (empty? outdated-dlls)
                    (empty? javac-errs) (empty? outdated-jars)
                    installer-ok)
@@ -111,6 +131,10 @@
         "\n\nOutdated jar files:\n"
         (if-not (empty? outdated-jars)
           (str-lines (map #(.getName %) outdated-jars))
+          "None.")
+        "\n\nUncompiled device adapters:\n"
+        (if-not (empty? missing-adapters)
+          (str-lines missing-adapters)
           "None.")
         "\n\nIs installer download available on website?\n"
         (if installer-ok


date picker dropdown WIP -  remove redundant style causing phantom arrow when droped down - remove duplicate function - simplify popover to not use anon function (thanks gregg) TODO more alignment, styling, autocolapse

--- src/re_com/date.cljs
+++ src/re_com/date.cljs
@@ -65,7 +65,7 @@
            :radius "4px"
            :border (when hide-border "none")
            :child [:div
-                   {:class "calendar-date daterangepicker opensleft show-calendar"
+                   {:class "calendar-date daterangepicker show-calendar"
                            ;; override inherrited body larger 14px font-size
                            ;; override position from css because we are inline
                     :style {:font-size "13px"
@@ -208,20 +208,6 @@

 (defn- anchor-button
-  [& {:keys [model]}]
-  [:div {:class "input-group date"
-         :style {:display "flex"
-                 :flex "none"}}
-   [h-box
-    :align :center
-    :children [[:label {:class "form-control"
-                        :style {:font-size "13px" :font-weight "normal"}}
-                (unparse date-format @model)]
-               [:span {:class "input-group-addon" :style {:width "40px" :height "34px"}}
-                [:i {:class "glyphicon glyphicon-th"}]]]]])
-
-
-(defn- anchor-button
   [shown? model]
   "Provide clickable field with current date label and dropdown button e.g. [ 2014 Sep 17 | # ]"
   ;;TODO: some temporary explicit styling overrides bellow should go into css etc
@@ -254,4 +240,4 @@
          :showing? shown?
          :options {:arrow-length 0 :arrow-width 0}
          :anchor  [anchor-button shown? model]
-         :popover {:body [#(into [inline-picker] passthrough-args)]}]))))+         :popover {:body (into [inline-picker] passthrough-args)}]))))


Add tooltip to validating status on input-text

--- src/re_com/misc.cljs
+++ src/re_com/misc.cljs
@@ -148,7 +148,9 @@
                           ;:width    "200px"
                           :showing? showing?
                           :anchor (if (= :validating status)
-                                    [throbber :size :regular :class "smaller"]
+                                    [throbber :size :regular :class "smaller"
+                                     :attr {:on-mouse-over (handler-fn (when (and status-icon? status) (reset! showing? true)))
+                                            :on-mouse-out  (handler-fn (reset! showing? false))}]
                                     [:i {:class         (str "zmdi zmdi-hc-fw " icon-class " form-control-feedback")
                                          :style         {:position "static"
                                                          :height   "auto"
@@ -168,7 +170,6 @@
                                                :font-size   "130%"
                                                :margin-left "4px"
                                                :opacity     (if (and status-icon? status) "1" "0")
-                                               :width       "auto"
                                                :height      "auto"})
                                 :title status-tooltip}]))))]]))))


Enforce using expected-version when defined in command

--- src/rill/handler.clj
+++ src/rill/handler.clj
@@ -46,9 +46,9 @@

 (defn try-command
   [event-store command]
-  (let [[id version & [primary-aggregate & rest-aggregates]] (prepare-aggregates event-store command)
-        expected-version (:expected-version command)]
-    (if (and expected-version (not= version expected-version))
+  (let [[id version & [primary-aggregate & rest-aggregates]] (prepare-aggregates event-store command)]
+    (if (and (contains? command :expected-version)
+             (not= version (:expected-version command)))
       [:out-of-date]
       (if-let [events (apply aggregate/handle-command primary-aggregate command rest-aggregates)]
         (if (commit-events event-store id version events)


Add more to the draft of this tutorial

Add more to the draft of this tutorial

I've finished a first pass of the Starting points and projection and
Splatter

--- src/uk/co/tombooth/pollock.cljs
+++ src/uk/co/tombooth/pollock.cljs
@@ -104,26 +104,37 @@
 (defn starting-point [] (map rand space))

-;; To start off with lets assume that the paint is falling and has 0
-;; velocity of its own when it starts from the brush
-
-
-;; we need to know the amount of time it is going to take the paint to
-;; fall, which we can work out based on the y dimension alone
-
-;; we know the initial position and velocity, final position and
-;; acceleration and we need to find the time. We cant use the equation
-;; r = r0 + v0 * t + at^2/2
-;; we need to use the quadratic equation to solve for t
-;;
-;; rearranged we get
-;;   at^2 + 2v0t + 2r0 - 2r = 0
-;; in quad equation:
-;;   a = a
-;;   b = 2v0
-;;   c = 2r0 - 2r
-;;     r (final position) is always going to be 0 so,
-;;   c = 2r0
+;; Now that we can generate a random point in space we want to project
+;; this to the canvas. We are going to use [Newtonian equations of
+;; motion](http://wiki), we know the position, velocity and acceleration of the
+;; point and we want to know what the position and velocity are when y
+;; is 0. In order to work out final positions we need to know the
+;; total time the point spent falling, we can do this using the y
+;; position as we know that the final position should be 0.
+
+;; To work out the time it takes for the point to reach the canvas we
+;; will solve the following equation for t:
+;;
+;;    - $r$  = final displacement,
+;;    - $r0$ = initial displacement,
+;;    - $v0$ = initial velocity,
+;;    - $a$  = acceleration,
+;;    - $t$  = time.
+;;
+;; $r = r0 + v0 * t + \frac{at^2}{2}$
+;;
+;; This rearranges to:
+;;
+;; $at^2 + 2v0t + 2r0 - 2r = 0$
+;;
+;; We can solve this using the Quadratic Equation, but this will yield
+;; us two results. In general we can say that we are interested in the
+;; result with the maxium value.
+;;
+;; In this function you can see an example of call out to Java.
+;; Clojure doesn't have an inbuilt sqrt function so we are calling out
+;; to the java version. A function named in the form `foo/bar` means
+;; it will call the function `bar` in the namespace `foo`. **WHAT IS A NAMESPACE?**

 (defn time-to-canvas [position velocity acceleration]
   (let [a acceleration
@@ -135,23 +146,28 @@
         minus-sqrt (/ (- minus-b (Math/sqrt discriminant)) (* 2 a))]
     (max add-sqrt minus-sqrt)))

-;; now we can get the time we need to be able to derive the final
-;; velocity and position of any dimension
-
-;; v = at + v0
-(defn velocity-at [time initial-velocity acceleration]
-  (+ (* acceleration time) initial-velocity))
-
-;; for position we can use the same equation we used to derive the
-;; time
+;; We can calculate the time but we want the final position and
+;; velocity. For position we can use the same function that we
+;; rearranged above to derive the time.

 (defn position-at [time initial-position initial-velocity acceleration]
   (+ initial-position
      (* initial-velocity time)
      (/ (* acceleration time time) 2)))

-;; we can now link these up into a function to get the final position
-;; and velocity for a point
+;; For velocity we can use another equation of motion:
+;;
+;; $v = at + v0$
+
+(defn velocity-at [time initial-velocity acceleration]
+  (+ (* acceleration time) initial-velocity))
+
+
+;; These functions we just implemented can be joined up to get given
+;; an initial position and velocity and return the final position and
+;; velocity. This function doesn't explicitly ask for the acceleration
+;; on the paint, it assumes only gravity is acting on it and uses the
+;; constant defined earlier on.

 (defn project-point [position velocity]
   (let [[i j k]            position
@@ -179,30 +195,45 @@

 ;; ## Paint splatter

-;; now that we know the impact velocity of a point, we know need to
-;; work out whether that impact should splatter
-
-;; we need to work out the impact force as a scalar so that we can
-;; define a cut off
-
-;; this will require working out the absolute value of a vector. We do
-;; this by summing up the squares of the dimensions and then taking th root
+;; An important aspect of Pollocks painting is the splatter of the
+;; paint hitting the canvas and what this adds to the images. We are
+;; going to add a simple splatter model based of the velocity at
+;; impact we calculated in the last part.
+
+;; Not all paint that hits the canvas will splatter, so we need to
+;; work out the impact force of the paint and use this as a cutoff for
+;; whether the paint should splatter.
+
+;; In order to work out this value as a scalar we will need to be able
+;; to calculate the absolute value of a vector. This can be done by
+;; summing the squares of the dimensions **is it dimensions and not
+;; some other lingo** and then take the square root of that summation.
+
+;; This function will introduce a shorthand for defining functions
+;; that is very useful in combination with functions like `map` and
+;; `reduce`. Rather than writing `(fn [args...] body)` you can use
+;; `#(body)` and if you want access to the arguments use `%n` where
+;; `n` is the position of the argument. If you are only expecting one
+;; argument then you can use just `%` on its own.

 (defn vector-absolute [vector]
   (Math/sqrt (reduce + (map #(* % %) vector))))

-;; need something about why it is ok this is velocity and not
+;; **need something about why it is ok this is velocity and not
 ;; acceleration, maybe because it is the relative acceleration of the
 ;; imapct of the two objects (paint has velocity, cavnas doesn't so
-;; accel = velocity?)
+;; accel = velocity?)**

 (defn impact-force [mass velocity]
   (* (vector-absolute velocity) mass))

-;; we need to work out if an impact should splatter off some of its
-;; paint. This should include some randomess as it is likely a
-;; consecutive points will all splatter and including some randomness
-;; will make it look at little less 'generated'
+;; Based of this function to calculate the impact force we can define
+;; a predicate that will tell us whether paint should splatter based
+;; off its mass and velocity. It is idiomatic in Clojure to end
+;; predicates with a `?`. We are going to add some randomness to this
+;; function so that we don't necessarily just get a uniform line of
+;; points. Also defined is a minimum force for us to consider whether
+;; some paint could splatter.

 (def min-impact-force-for-splatter 50)

@@ -210,18 +241,24 @@
   (and (> (impact-force mass velocity) min-impact-force-for-splatter)
        (> (rand) 0.8)))

-;; if an impact splatters then we will need to bounce its velocity
-;; vector as this is the direction it will exit its current position
-
-;; the equation to bounce a vector, V, off a plane with normal, N, is:
-;; needs rewriting http://mathworld.wolfram.com/Reflection.html
+;; If an impact splatters then we will need to bounce its velocity
+;; vector as this is the direction it will leave its current position.
+
+;; The equation to bounce a vector, $V$, off a plane with normal, $N$, is:
+;; **needs rewriting http://mathworld.wolfram.com/Reflection.html**
 ;;
-;;  N is the normal vector of the plane
-;;  R is the reflected vector
+;;    - $N$ is the normal vector of the plane
+;;    - $V$ = the incoming vector
+;;    - $B$ is the outgoing, bounced, vector
 ;;
-;;  R = V - (2 * (V.N) * N)
-
-;; dot product is he sum of the multiples of the dimensions
+;;  $B = V - (2 * (V.N) * N)$
+
+;; We are missing a few of the required vector operations used in this
+;; equation so we should define some more functions before trying to
+;; implement it. The first is the vector dot product, this is defined
+;; as the sum of the multiples of each dimension. Otherwise we need
+;; substraction of two vectors and a function to multiply a vector by
+;; a constant.

 (defn dot-product [vector1 vector2]
   (reduce + (map * vector1 vector2)))
@@ -233,16 +270,24 @@
   (map #(* % constant) vector))

-;; blah? need a better name for this variable
+;; Using the above functions we can now implement the vector bouncing
+;; equation. I have pulled $(2 * (V.N) * N)$ out into a variable
+;; called extreme for clarity. **I don't think extreme is a much
+;; better name than blah**

 (defn bounce-vector [vector normal]
   (let [vector-dot-normal (dot-product vector normal)
-        blah (vector-multiply-by-constant normal (* 2 vector-dot-normal))]
-    (vector-subtraction vector blah)))
-
-
-;; splatter will never take all of the paint and velocity with it so
-;; we need a dampening constant
+        extreme (vector-multiply-by-constant normal (* 2 vector-dot-normal))]
+    (vector-subtraction vector extreme)))
+
+
+;; When an impact splatters it will only take a fraction of the
+;; velocity, otherwise know as being elastic rather than inelastic
+;; **check these definitions**. We can define a constant that will be
+;; used to reduce the total velocity of the bounced vector to reflect
+;; this elasticity.
+
+;; **should this splatter vector be randomised a little bit?**

 (def splatter-dampening-constant 0.7)


Vectors have components

Vectors have components

--- src/uk/co/tombooth/pollock.cljs
+++ src/uk/co/tombooth/pollock.cljs
@@ -256,8 +256,8 @@

 ;; In order to work out this value as a scalar we will need to be able
 ;; to calculate the absolute value of a vector. This can be done by
-;; summing the squares of the dimensions **is it dimensions and not
-;; some other lingo** and then take the square root of that summation.
+;; summing the squares of the vector's components and then taking the
+;; square root of that summation.

 ;; This function will introduce a shorthand for defining functions
 ;; that is very useful in combination with functions like `map` and


adjust positions

adjust positions

--- src/splash/core.cljs
+++ src/splash/core.cljs
@@ -246,7 +246,7 @@
                 hh (/ h 2)
                 qh (/ h 4)]
             (sprite/set-pos! test-text 0 ;-200
-                             (+ (* 0.5 qh) (- (* 0.1 qh (Math/sin (* 0.1 n))) qh))
+                             (+ 80 (- (* 0.1 qh (Math/sin (* 0.1 n))) qh))
                              ))
           (<! (events/next-frame))
           (recur (inc n))))
@@ -273,7 +273,7 @@
                     hh (/ h 2)
                     qh (/ h 4)]
                 (set! (.-filterArea scroll-text) (PIXI/Rectangle. 0 hh win-w h))
-                (sprite/set-pos! scroll-text (* n -5) (- hh 120)))
+                (sprite/set-pos! scroll-text (* n -5) (- hh 40)))
               (<! (events/next-frame))
               (recur (if (> n off) (- off) (inc n)))))))


create piece-collide? function

create piece-collide? function

--- src/t3tr0s/core.cljs
+++ src/t3tr0s/core.cljs
@@ -70,6 +70,11 @@
   []
   (println (board-str (:board @state))))

+(defn read-board
+  "Get the current value from the given board position."
+  [x y]
+  (get-in @state [:board y x]))
+
 (defn write-to-board!
   "Writes a given value to the x,y position on the board."
   [ x y value ]
@@ -95,6 +100,19 @@
   [piece]
   (doall (map (fn [[x y]] [(- y) x]) piece)))

+(defn coord-collide?
+  [[cx cy] x y]
+  (not= 0 (read-board (+ cx x) (+ cy y))))
+
+(defn piece-collide?
+  "Determines if the given piece will collide with anything in the current board."
+  [piece x y]
+  (some #(coord-collide? % x y) piece))
+
+; ------------------------------------------------------------
+; TESTING FUNCTIONS
+; ------------------------------------------------------------
+
 (defn test-rotate-piece!
   "Clear the board, write the piece at 5, 9, rotate the piece, write the piece at 5, 1,
     print the board."


Add get-manifest equality test

Add get-manifest equality test

--- test/irresponsible/unscrew_test.clj
+++ test/irresponsible/unscrew_test.clj
@@ -11,6 +11,7 @@
          (u/with-jar jar "test/project.jar"
            (is (instance? JarFile jar))
            (is (map? (u/get-manifest jar)))
+           (is (= "1.0" (get (u/get-manifest jar) "Manifest-Version")))
            (is (= #{"META-INF/" "META-INF/MANIFEST.MF" "irresponsible/"
                     "irresponsible/unscrew.clj" "README.md"}
                   (u/paths jar)


Remove temporal file before testing

Remove temporal file before testing

--- test/photon/current/stream_test.clj
+++ test/photon/current/stream_test.clj
@@ -8,6 +8,8 @@
             [photon.core :as core]
             [clojure.tools.logging :as log])
   (:use midje.sweet))
+
+(.delete (java.io.File. "/tmp/temporalphoton.log"))

 (def temp-file (java.io.File/createTempFile "midje" ".json"))
 (def conf {:amqp.url :local


Fix #171 - require render namespaces ahead of time This is required to facilitate passing records to render functions. `boot.core/with-pod` was a promising candidate, but requires the record's namespace to be required in the calling pod, which doesn't fit with Perun's model.

--- src/io/perun.clj
+++ src/io/perun.clj
@@ -168,9 +168,11 @@
   [{:keys [task-name inputs tracer pod global-meta render-form-fn]}]
   (trace tracer
          (for [[path input] inputs]
-           (do
+           (let [[f :as render-form] (render-form-fn input)
+                 render-ns (symbol (namespace f))]
              (perun/report-debug task-name "rendered page for path" path)
-             (merge (pod/with-call-in @pod ~(render-form-fn input))
+             (pod/with-eval-in @pod (require '~render-ns))
+             (merge (pod/with-call-in @pod ~render-form)
                     (pm/path-meta path global-meta))))))

 (defn diff-inputs-meta


Update getting started example to use map resolvers

--- src-docs/com/wsscode/pathom/book/connect/getting_started.cljs
+++ src-docs/com/wsscode/pathom/book/connect/getting_started.cljs
@@ -3,30 +3,25 @@
             [com.wsscode.pathom.connect :as pc]
             [com.wsscode.pathom.profile :as pp]))

-; initialize a dispatch function
-(defmulti resolver-fn pc/resolver-dispatch)
-; initialize indexes
-(def indexes (atom {}))
-
-; this creates a factory that will add a new method on the resolver-fn and add it to the indexes
-(def defresolver (pc/resolver-factory resolver-fn indexes))
-
 ; creating our first resolver
-(defresolver `latest-product
+(pc/defresolver latest-product [_ _]
   {::pc/output [{::latest-product [:product/id :product/title :product/price]}]}
-  (fn [_ _]
-    {::latest-product {:product/id    1
-                       :product/title "Acoustic Guitar"
-                       :product/price 199.99M}}))
+  {::latest-product {:product/id    1
+                     :product/title "Acoustic Guitar"
+                     :product/price 199.99M}})

 (def parser
-  (p/parser {::p/plugins
-             [(p/env-plugin
-                {::p/reader             [p/map-reader
-                                         pc/all-readers]
-                 ::pc/resolver-dispatch resolver-fn
-                 ::pc/indexes           @indexes})
-              pp/profile-plugin]}))
+  (p/parallel-parser
+    {::p/env     {::p/reader               [p/map-reader
+                                            pc/parallel-reader
+                                            pc/open-ident-reader
+                                            p/env-placeholder-reader]
+                  ::p/placeholder-prefixes #{">"}}
+     ::p/mutate  pc/mutate-async
+     ::p/plugins [(pc/connect-plugin {::pc/register latest-product})
+                  p/error-handler-plugin
+                  p/request-cache-plugin
+                  p/trace-plugin]}))

 (comment
   (parser {} [::latest-product]))


Refactored multimethod -> protocol & corrected format


omit redundant test context entries

omit redundant test context entries

--- test/bract/core/keydef_test.clj
+++ test/bract/core/keydef_test.clj
@@ -108,8 +108,6 @@
     (is (thrown? IllegalArgumentException (kdef/cfg-launcher {}))))
   (testing "missing/bad config entries"
     (let [bad-context {"bract.core.inducers"     {:foo :bar}
-                       "bract.core.context-hook" 10
-                       "bract.core.config-hook"  15
                        "bract.core.exports"      20
                        "bract.core.launcher"     false}]
       (is (thrown? IllegalArgumentException (kdef/cfg-inducers bad-context)))


added missing :scm information for clojars

--- template/project.clj
+++ template/project.clj
@@ -1,6 +1,8 @@
 (defproject swagger1st/lein-template "0.15.0"
   :description "Leiningen template for creating a swagger1st app."
   :url "https://github.com/sarnowski/swagger1st"
+
+  :scm {:url "git@github.com:sarnowski/swagger1st.git"}

   :license {:name "ISC License"
             :url "http://opensource.org/licenses/ISC"


added failure tests

added failure tests

--- test/onyx/plugin/input_test.clj
+++ test/onyx/plugin/input_test.clj
@@ -47,6 +47,9 @@
 (def batch-size 20)

 (def workflow [[:read-messages :out]])
+
+(defn restartable? [e]
+  true)

 ;; Create catalogs with different search scenarios

@@ -113,6 +116,17 @@
 (def out-calls
   {:lifecycle/before-task-start inject-out-ch})

+(def batch-num (atom 0))
+
+(def read-crash
+  {:lifecycle/before-batch
+   (fn [event lifecycle]
+     ; give the peer a bit of time to write the chunks out and ack the batches,
+     ; since we want to ensure that the batches aren't re-read on restart for ease of testing
+     (Thread/sleep 7000)
+     (when (= (swap! batch-num inc) 2)
+       (throw (ex-info "Restartable" {:restartable? true}))))})
+
 (def lifecycles
   [{:lifecycle/task :read-messages
     :lifecycle/calls :onyx.plugin.elasticsearch/read-messages-calls}
@@ -121,23 +135,37 @@
    {:lifecycle/task :out
     :lifecycle/calls :onyx.plugin.core-async/writer-calls}])

+(def lifecycles-fail
+  [{:lifecycle/task :read-messages
+    :lifecycle/calls :onyx.plugin.elasticsearch/read-messages-calls}
+   {:lifecycle/task :read-messages
+    :lifecycle/calls ::read-crash}
+   {:lifecycle/task :out
+    :lifecycle/calls ::out-calls}
+   {:lifecycle/task :out
+    :lifecycle/calls :onyx.plugin.core-async/writer-calls}])
+
 (def v-peers (onyx.api/start-peers 2 peer-group))

 (defn submit-and-wait
-  [catalog]
-  (let [job-info (onyx.api/submit-job
-                   peer-config
-                   {:catalog catalog
-                    :workflow workflow
-                    :lifecycles lifecycles
-                    :task-scheduler :onyx.task-scheduler/balanced})]
-    (onyx.api/await-job-completion peer-config (:job-id job-info))
-    job-info))
+  ([catalog]
+   (submit-and-wait catalog lifecycles))
+  ([catalog lc]
+   (let [job-info (onyx.api/submit-job
+                    peer-config
+                    {:catalog catalog
+                     :workflow workflow
+                     :lifecycles lc
+                     :task-scheduler :onyx.task-scheduler/balanced})]
+     (onyx.api/await-job-completion peer-config (:job-id job-info))
+     job-info)))

 (defn run-job
-  [catalog]
-  (submit-and-wait catalog)
-  (take-segments! out-chan 5000))
+  ([catalog]
+   (run-job catalog lifecycles))
+  ([catalog lc]
+   (submit-and-wait catalog lc)
+   (take-segments! out-chan 5000)))

 (let [conn (u/connect-rest-client)]
   (esrd/create conn (.toString id) "_default_" {:foo "bar"})
@@ -163,6 +191,8 @@

   (let [job-info-restart (submit-and-wait (update-in catalog-http-q&map&idx [0] assoc :elasticsearch/restart-on-fail true))]
     (def task-chunk-restart (extensions/read-chunk (:log env) :chunk (get-in job-info-restart [:task-ids :read-messages :id]))))
+
+  (def res-multi-fail (run-job (update-in catalog-http-q&map&idx [0] assoc :onyx/restart-pred-fn ::restartable?) lifecycles-fail))

   (u/delete-indexes (.toString id)))

@@ -194,9 +224,11 @@
     (is (= "bar" (-> res-native-idx first :_source :foo)))))

 (deftest fault-logic
-  (testing "Successfully processed all messages"
+  (testing "Successfully processed all messages no failure"
     (is (= 11 (count res-multi))))
   (testing "Successfully wrote status to log for restart-on-fail=false"
     (is (= :complete (:status task-chunk-offset))))
   (testing "Updates not written to log for restart-on-fail=true"
-    (is (= -1 (:chunk-index task-chunk-restart)))))+    (is (= -1 (:chunk-index task-chunk-restart))))
+  (testing "Successfully processed all messages with failure"
+    (is (= 11 (count res-multi-fail)))))


Refactor: change fns to take map of data, not id for lookup

--- src/acfe/core.clj
+++ src/acfe/core.clj
@@ -78,9 +78,9 @@

 (defn place-html
-  "Generate html of facts for given place ID."
-  [id]
-  (let [grouped-facts (group-by :category (find-facts-by-place-id (:db config) id))
+  "Return HTML representation of given place facts."
+  [place-facts]
+  (let [grouped-facts (group-by :category place-facts)
 		any-fact (->> grouped-facts first val first)]
 	(->
 	 (e/html-resource "html/place.html")
@@ -98,29 +98,28 @@

 (defn area-html
-  "Generate html of facts for given area ID."
-  [id]
-  (let [area-facts (find-facts-by-area-id (:db config) id)]
-	(->
-	 (e/html-resource "html/area.html")
-	 (e/at
-	  [:h2 :span] (e/content (:area (first area-facts)))
-	  [:table :thead :td]
-	  (e/clone-for
-	   [fact (cons nil area-facts)]
-	   [:td] (e/content (:title fact)))
-	  [:table :tbody :tr.area :td]
-	  (e/clone-for
-	   [fact (cons {:detail_text "This LGA"} area-facts)]
-	   [:td] (e/content (if (nil? (:detail_text fact)) (str (:detail_value fact)) (:detail_text fact)))
-	   )))))
+  "Return HTML representation of given area facts."
+  [area-facts]
+  (->
+   (e/html-resource "html/area.html")
+   (e/at
+	[:h2 :span] (e/content (:area (first area-facts)))
+	[:table :thead :td]
+	(e/clone-for
+	 [fact (cons nil area-facts)]
+	 [:td] (e/content (:title fact)))
+	[:table :tbody :tr.area :td]
+	(e/clone-for
+	 [fact (cons {:detail_text "This LGA"} area-facts)]
+	 [:td] (e/content (if (nil? (:detail_text fact)) (str (:detail_value fact)) (:detail_text fact)))
+	 ))))

 (defroutes routes
   (GET "/data/places.clj" [] (str "#{" (reduce str (find-places (:db config))) "}"))
   (GET "/data/areas.clj" [] (str "#{" (apply str (get-areas)) "}"))
-  (GET "/api/place.html" [id] (e/emit* (place-html id)))
-  (GET "/api/area.html" [id] (e/emit* (area-html id)))
+  (GET "/api/place.html" [id] (e/emit* (place-html (find-facts-by-place-id (:db config) id))))
+  (GET "/api/area.html" [id] (e/emit* (area-html (find-facts-by-area-id (:db config) id))))
   (GET "/" [] (main-template))
   (resources "/")
   (not-found "Page not found"))


verbose switch on meta-config and install tasks

--- tasklib/src/boot_bowdlerize.clj
+++ tasklib/src/boot_bowdlerize.clj
@@ -379,21 +379,19 @@
                                  boot/input-files
                                  (boot/by-name [bowdlerize-edn]))]
           (condp = (count bowdlerize-fs)
-            0 (let [_ (util/info (str "Creating bowdlerize.edn\n"))
+            0 (let [_ (if verbose (util/info (str "Creating bowdlerize.edn\n")))
                     f (io/file tmp-dir bowdlerize-edn)]
                 (spit f (with-out-str (pp/pprint {:bower bower-content})))
                 fileset)
             1 (let [bowdlerize-f (first bowdlerize-fs)
-                    ;; _ (println bowdlerize-edn ": " bowdlerize-f)
                     bowdlerize-content (->  (boot/tmp-file bowdlerize-f) slurp read-string)
-                    ;; _ (println "bowdlerize-content: " bowdlerize-content)
                     path     (boot/tmp-path bowdlerize-f)
                     in-file  (boot/tmp-file bowdlerize-f)
                     out-file (io/file tmp-dir path)]
                 (if (:bower bowdlerize-content)
-                  (do (util/info (str bowdlerize-edn " Already elaborated with :bower\n"))
+                  (do (if verbose (util/info (str bowdlerize-edn " Already elaborated with :bower\n")))
                       fileset)
-                  (do (util/info (str "Elaborating " bowdlerize-edn " with :bower stanza\n"))
+                  (do (if verbose (util/info (str "Elaborating " bowdlerize-edn " with :bower stanza\n")))
                       (spit out-file (with-out-str
                                        (pp/pprint (assoc bowdlerize-content :bower bower-content)))))))
             (throw (Exception. (str "only one " bowdlerize-edn " file allowed"))))))
@@ -401,14 +399,14 @@

 (defn ->bowdlerize-fs
   "add bowdlerize-edn to fs if not already there"
-  [fileset]
+  [fileset verbose]
   ;; (println "->BOWDLERIZE-FS")
   (let [tmp-dir (boot/tmp-dir!)
         bowdlerize-fs (->> fileset
                            boot/input-files
                            (boot/by-name [bowdlerize-edn]))
         f (condp = (count bowdlerize-fs)
-                 0 (let [_ (util/info (str "Creating bowdlerize.edn\n"))
+                 0 (let [_ (if verbose (util/info (str "Creating bowdlerize.edn\n")))
                          f (io/file tmp-dir bowdlerize-edn)]
                      ;; (println "NEW BOWDLERIZE-EDN FILE: " f)
                      (spit f {})
@@ -427,15 +425,15 @@
   (let [tmp-dir (boot/tmp-dir!)]
     (boot/with-pre-wrap fileset
       (let [[edn-content pod] (->pkg-mgr-pod pkg-mgr fileset)
-            [bowdlerize-f newfs] (->bowdlerize-fs fileset)
+            [bowdlerize-f newfs] (->bowdlerize-fs fileset verbose)
             bowdlerize-content (-> bowdlerize-f slurp read-string)]
         (pod/with-eval-in @pod
           (require '[boot.util :as util]
                    '[clojure.pprint :as pp]
                    '[clojure.java.io :as io])
           (if (get '~bowdlerize-content ~pkg-mgr)
-            (util/info (str ~bowdlerize-edn " already elaborated with " ~pkg-mgr "\n"))
-            (do (util/info (str "Elaborating " ~bowdlerize-edn " with " ~pkg-mgr " stanza\n"))
+            (if ~verbose (util/info (str ~bowdlerize-edn " already elaborated with " ~pkg-mgr "\n")))
+            (do (if ~verbose (util/info (str "Elaborating " ~bowdlerize-edn " with " ~pkg-mgr " stanza\n")))
                 (let [path     ~(.getName bowdlerize-f)
                       out-file (io/file ~(.getPath tmp-dir) path)]
                   (spit out-file (with-out-str
@@ -449,9 +447,10 @@
   ;;  k keep bool "keep intermediate .clj files"

 (boot/deftask meta-config
-  [o pkg-mgrs PGKMGRS #{kw} "only these pkg mgrs (:bower, :npm :polymer, or :webjars; default is all 4)"]
+  [o pkg-mgrs PGKMGRS #{kw} "only these pkg mgrs (:bower, :npm :polymer, or :webjars; default is all 4)"
+   v verbose bool "verbose"]
   (let [pkg-mgrs (if pkg-mgrs pkg-mgrs #{:bower :npm :polymer :webjars})]
-    (apply comp (map #(meta-config-impl :pkg-mgr %) pkg-mgrs))))
+    (apply comp (map #(meta-config-impl :pkg-mgr % :verbose verbose) pkg-mgrs))))

 #_(boot/deftask webjars
   "process webjars.edn"
@@ -461,7 +460,7 @@
   (let [tmp-dir (boot/tmp-dir!)]
     (boot/with-pre-wrap fileset
       (let [[edn-content pod] (->pkg-mgr-pod :webjars fileset)
-            [bowdlerize-f newfs] (->bowdlerize-fs fileset)
+            [bowdlerize-f newfs] (->bowdlerize-fs fileset verbose)
             bowdlerize-content (-> bowdlerize-f slurp read-string)]
         (pod/with-eval-in @pod
           (require '[boot.util :as util]
@@ -747,7 +746,7 @@
    v verbose bool "verbose"]
   (let [tmp-dir     (boot/tmp-dir!)
         bower-cache (boot/cache-dir! :bowdlerize/bower :global true)
-        _ (if clean-cache (do (util/info (str "Cleaning bower cache\n"))
+        _ (if clean-cache (do (if verbose (util/info (str "Cleaning bower cache\n")))
                               (boot/empty-dir! bower-cache)))
         ;; _ (println "BOWER CACHE: " bower-cache)
         ;; bower-dir "bower"
@@ -774,7 +773,7 @@
               (if (not (.exists (io/file ~(.getPath bower-cache) path)))
                 (let [c [~bcmd "install" (last bower-pkg) :dir ~(.getPath bower-cache)]]
                   ;; (println "bower cmd: " c)
-                  (util/info (format "Installing bower pkg:   %s\n" bower-pkg))
+                  (if ~verbose (util/info (format "Installing bower pkg:   %s\n" bower-pkg)))
                   (apply sh c))
                 (if ~verbose (util/info (format "Found cached bower pkg: %s\n" bower-pkg))))))))
       (-> fileset (boot/add-resource bower-cache) boot/commit!))))
@@ -785,7 +784,7 @@
    v verbose bool "verbose"]
   (let [tmp-dir     (boot/tmp-dir!)
         webjars-cache (boot/cache-dir! :bowdlerize/webjars :global true)
-        _ (if clean-cache (do (util/info (str "Cleaning webjars cache\n"))
+        _ (if clean-cache (do (if verbose (util/info (str "Cleaning webjars cache\n")))
                               (boot/empty-dir! webjars-cache)))
         webjar-dir "webjars"
         destdir  (str (.getPath webjars-cache) "/" webjar-dir)]
@@ -815,16 +814,16 @@
                                             artifactid
                                             version])]
                     (if (not (.exists (io/file ~(.getPath webjars-cache) path)))
-                      (do (util/info (format "Installing webjar:   %s\n" coord))
+                      (do (if ~verbose (util/info (format "Installing webjar:   %s\n" coord)))
                           (pod/unpack-jar (:jar dep) ~destdir))
-                      (if ~verbose (util/info (format "Found cached webjar:   %s\n" coord)))))))))
+                      (if ~verbose (util/info (format "Found cached webjar: %s\n" coord)))))))))
       (-> fileset (boot/add-resource webjars-cache) boot/commit!))))

 (boot/deftask tester
   "test"
   [t type KW kw "type"]
   (boot/with-pre-wrap [fileset]
-    (let [[b-content pod] (->bowdlerize-pod fileset)]
+    (let [[b-content pod] (->bowdlerize-pod fileset true)]
       (println "B-CONTENT: " b-content)
 ;;      (println "POD: " pod)
       fileset))


Bug fix: display place fact whole numbers without decimals

--- src/acfe/core.clj
+++ src/acfe/core.clj
@@ -81,11 +81,13 @@
   "A fact contains one detail, which might be a string, int or decimal.
   Return detail in appropriate format."
   [fact]
-  (let [value (:detail_value fact)
+  (let [whole? #(== % (int %)) ; double equals to handle bigints properly
+		value (:detail_value fact)
 		text (:detail_text fact)]
-	(if
-	  (nil? value) text (str value)
-	  )))
+	(cond
+	 (nil? value) text
+	 (whole? value) (str (int value))
+	 :else (str value))))

 (defn place-html


fix failed tests

fix failed tests

--- test/leiningen/program_test.clj
+++ test/leiningen/program_test.clj
@@ -24,10 +24,8 @@
   (let [m {:a (fn [x y] (+ x y))
            :b (fn [x y] (* x y))
            :c (fn [_ _] (throw RuntimeException))}
-        [fn-1 fn-2 fn-3] (s/find-command [:a :b :c] m)]
-    (is (= 3 (fn-1 1 2)))
-    (is (= 2 (fn-2 1 2)))
-    (is (= nil (fn-3 1 2)))))
+        commands (s/find-command #{:a :b :c} m)]
+    (is (= 3 (count commands)))))

 (deftest ^:unit ->commands
   (testing "find correct commands"
@@ -40,5 +38,5 @@
     (let [m {:default [:a]
              :a       (fn [x y] (+ x y))
              :b       (fn [x y] (* x y))}
-          [fn-default & _] (s/->commands {:a "" :b ""} m)]
+          [fn-default & _] (s/->commands {:c "" :d ""} m)]
       (is (= 3 (fn-default 1 2))))))


Test fix :wrench:

Test fix :wrench:

--- test/metabase/api/card_test.clj
+++ test/metabase/api/card_test.clj
@@ -13,7 +13,8 @@
                              [view-log :refer [ViewLog]])
             [metabase.test.data :refer :all]
             [metabase.test.data.users :refer :all]
-            [metabase.test.util :refer [match-$ expect-eval-actual-first random-name with-temp with-temp* obj->json->obj expect-with-temp]]))
+            [metabase.test.util :refer [match-$ expect-eval-actual-first random-name with-temp with-temp* obj->json->obj expect-with-temp]]
+            [metabase.util :as u]))

 ;; # CARD LIFECYCLE

@@ -75,11 +76,11 @@
                    Card     [{card-3-id :id}]
                    Card     [{card-4-id :id}]
                    ;; 3 was viewed most recently, followed by 4, then 1. Card 2 was viewed by a different user so shouldn't be returned
-                   ViewLog  [_               {:model "card", :model_id card-1-id, :user_id (user->id :rasta),     :timestamp #inst "2015-12-01"}]
-                   ViewLog  [_               {:model "card", :model_id card-2-id, :user_id (user->id :trashbird), :timestamp #inst "2016-01-01"}]
-                   ViewLog  [_               {:model "card", :model_id card-3-id, :user_id (user->id :rasta),     :timestamp #inst "2016-02-01"}]
-                   ViewLog  [_               {:model "card", :model_id card-4-id, :user_id (user->id :rasta),     :timestamp #inst "2016-03-01"}]
-                   ViewLog  [_               {:model "card", :model_id card-3-id, :user_id (user->id :rasta),     :timestamp #inst "2016-04-01"}]]
+                   ViewLog  [_               {:model "card", :model_id card-1-id, :user_id (user->id :rasta),     :timestamp (u/->Timestamp #inst "2015-12-01")}]
+                   ViewLog  [_               {:model "card", :model_id card-2-id, :user_id (user->id :trashbird), :timestamp (u/->Timestamp #inst "2016-01-01")}]
+                   ViewLog  [_               {:model "card", :model_id card-3-id, :user_id (user->id :rasta),     :timestamp (u/->Timestamp #inst "2016-02-01")}]
+                   ViewLog  [_               {:model "card", :model_id card-4-id, :user_id (user->id :rasta),     :timestamp (u/->Timestamp #inst "2016-03-01")}]
+                   ViewLog  [_               {:model "card", :model_id card-3-id, :user_id (user->id :rasta),     :timestamp (u/->Timestamp #inst "2016-04-01")}]]
   [card-3-id card-4-id card-1-id]
   (mapv :id ((user->client :rasta) :get 200 "card", :f :recent)))


Add tests for streams with cardinality 0/1

--- test/muon_clojure/core_test.clj
+++ test/muon_clojure/core_test.clj
@@ -14,7 +14,15 @@
     [{:endpoint "stream-test" :type :hot-cold
       :fn-process (fn [params]
                     (to-chan
-                     [{:val 1} {:val 2} {:val 3} {:val 4} {:val 5}]))}])
+                     [{:val 1} {:val 2} {:val 3} {:val 4} {:val 5}]))}
+     {:endpoint "stream-test-0" :type :hot-cold
+      :fn-process (fn [params]
+                    (to-chan
+                     []))}
+     {:endpoint "stream-test-1" :type :hot-cold
+      :fn-process (fn [params]
+                    (to-chan
+                     [{:val 1}]))}])
   MicroserviceRequest
   (request-mappings [this]
     [{:endpoint "post-endpoint"
@@ -42,11 +50,23 @@
           stream-channel
           (with-muon c (subscribe!
                          (str "stream://" uuid "/stream-test")))
+          stream-channel-0
+          (with-muon c (subscribe!
+                         (str "stream://" uuid "/stream-test-0")))
+          stream-channel-1
+          (with-muon c (subscribe!
+                         (str "stream://" uuid "/stream-test-1")))
           _ (println "After stream-channel")
           stream-channel-order
           (with-muon c (subscribe!
                          (str "stream://" uuid "/stream-test")))
           _ (println "After stream-channel-order")
+          not-ordered-0 (<!! (clojure.core.async/reduce
+                              (fn [prev n] (concat prev `(~n)))
+                              '() stream-channel-0))
+          not-ordered-1 (<!! (clojure.core.async/reduce
+                              (fn [prev n] (concat prev `(~n)))
+                              '() stream-channel-1))
           not-ordered (<!! (clojure.core.async/reduce
                              (fn [prev n] (concat prev `(~n)))
                              '() stream-channel-order))
@@ -65,6 +85,10 @@
             (<!! stream-channel) => {:val 1.0})
       (fact "Stream results come ordered"
             (= not-ordered (sort-by :val not-ordered)) => true)
+      (fact "There are 0 elements"
+            (count not-ordered-0) => 0)
+      (fact "There is 1 element"
+            (count not-ordered-1) => 1)
       (fact "There are 5 elements"
             (count not-ordered) => 5)
       (fact "Posting many times in a row works as expected"