Look for all compiled ClojureScript files, not just core.js. Fixes #61

--- src/clj/cljs/closure.clj
+++ src/clj/cljs/closure.clj
@@ -12,12 +12,13 @@
   "Compile ClojureScript to JavaScript with optimizations from Google
    Closure Compiler producing runnable JavaScript.

+   The classpath must contain compiler.jar and cljs/core.js as well as
+   any other compiled ClojureScript files that you will need, all of
+   which must be under cljs/.
+
    Use the 'build' function for end-to-end compilation.

    build = compile -> add-dependencies -> optimize -> output
-
-   See comments for example usage. core.js and the Closure
-   compiler.jar must be on the classpath.

    Two protocols are defined: IJavaScript and Compilable. The
    Compilable protocol is satisfied by something which can return one
@@ -25,8 +26,9 @@

    With IJavaScriipt objects in hand, calling add-dependencies will
    produce a sequence of IJavaScript objects which includes all
-   required dependencies from the Closure library plus cljs.core, in
-   dependency order. This function replaces the closurebuilder tool.
+   required dependencies from the Closure library and ClojureScript,
+   in dependency order. This function replaces the closurebuilder
+   tool.

    The optimize function converts one or more IJavaScripts into a
    single string of JavaScript source code using the Closure Compiler
@@ -52,6 +54,10 @@
            com.google.javascript.jscomp.JSError
            com.google.javascript.jscomp.CommandLineRunner))

+;; The prefix under which compiled ClojureScript files may be found on
+;; the classpath.
+(def cljs-classpath-root "cljs/")
+
 (def name-chars (map char (concat (range 48 57) (range 65 90) (range 97 122))))

 (defn random-char []
@@ -195,7 +201,7 @@
   (-provides [this] (:provides (parse-js-ns (string/split-lines this))))
   (-requires [this] (:requires (parse-js-ns (string/split-lines this))))
   (-source [this] this)
-
+
   clojure.lang.IPersistentMap
   (-url [this] (:url this))
   (-provides [this] (:provides this))
@@ -217,10 +223,6 @@

 ;; Compile
 ;; =======
-
-;; TODO: Most of the code below assumes that core is the only file in
-;; ClojureScript. There are others and this will need to be changed to
-;; load them both as cljs source and as compiled JavaScript.

 (defmacro with-core
   "Ensure that core.cljs has been loaded."
@@ -272,8 +274,8 @@

   clojure.lang.PersistentList
   (-compile [this opts]
-            (compile-form-seq [this]))
-
+    (compile-form-seq [this]))
+
   String
   (-compile [this opts] (-compile (io/file this) opts))

@@ -299,8 +301,8 @@
 ;; Dependencies
 ;; ============
 ;;
-;; Find dependencies from goog js files on the classpath. Eliminates
-;; the need for closurebuilder.
+;; Find all dependencies from files on the classpath. Eliminates the
+;; need for closurebuilder.

 (defn build-index
   "Index a list of dependencies by namespace and file name. There can
@@ -318,9 +320,34 @@
           {}
           deps))

+(defn all-goog-js
+  "Return the list of all Google Closure library JavaScript files."
+  []
+  (for [g (filter #(.endsWith (.getName %) "goog.jar") (classpath-jarfiles))
+        file (filenames-in-jar g)
+        :when (.endsWith file ".js")]
+    file))
+
+(defn all-cljs-js
+  "Return the list of all ClojureScript JavaScript files. First try to
+  get them from a directory on the classpath. Then, and only then,
+  look in jar files."
+  []
+  (letfn [(compiled-cljs? [d f] (and (.startsWith f (str (.getPath d) File/separator cljs-classpath-root))
+                                      (.endsWith f ".js")))
+          (remove-dot-prefix [s] (if (.startsWith s (str "." File/separator))
+                                   (.substring s (count (str "." File/separator)))
+                                   s))]
+    (let [compiled-cljs (for [dir (remove jar-file? (classpath))
+                              path (map #(.getPath %) (file-seq dir))
+                              :when (compiled-cljs? dir path)]
+                          (remove-dot-prefix path))]
+      (if (seq compiled-cljs)
+        compiled-cljs
+        (for [j (classpath-jarfiles) f (filenames-in-jar j) :when (.startsWith f cljs-classpath-root)] f)))))
+
 (defn dependency-index*
-  "Create an indexed list of all namespaces in the Closure library
-  plus cljs.core."
+  "Create an index of dependencies by namespace and file name."
   []
   (letfn [(graph-node [res]
                       (-> (io/resource res)
@@ -328,12 +355,7 @@
                           line-seq
                           parse-js-ns
                           (assoc :file res)))]
-    (let [goog (->> (classpath-jarfiles)
-                    (filter #(.endsWith (.getName %) "goog.jar"))
-                    first
-                    filenames-in-jar
-                    (filter #(.endsWith % ".js")))
-          all-nodes (map graph-node (conj goog "core.js"))]
+    (let [all-nodes (map graph-node (concat (all-goog-js) (all-cljs-js)))]
       (build-index all-nodes))))

 (def dependency-index (memoize dependency-index*))
@@ -366,8 +388,8 @@

 (defn add-dependencies
   "Given one or more IJavaScript objects in dependency order, produce
-  a new sequence of IJavaScript objects which includes all dependencies
-  from the Closure library, plus cljs.core, in dependency order."
+  a new sequence of IJavaScript objects which includes the input list
+  plus all dependencies in dependency order."
   [& inputs]
   (let [required (dependencies (mapcat -requires inputs))
         index (dependency-index)]
@@ -491,9 +513,9 @@
   (apply str (interpose "\n" (map #(add-dep-string opts %) sources))))

 (comment
-  (path-relative-to (io/file "out/goog/base.js") {:url (io/resource "core.js")})
-  (add-dep-string {} {:url (io/resource "core.js") :requires ["goog.string"] :provides ["cljs.core"]})
-  (deps-file {} [{:url (io/resource "core.js") :requires ["goog.string"] :provides ["cljs.core"]}])
+  (path-relative-to (io/file "out/goog/base.js") {:url (io/resource "cljs/core.js")})
+  (add-dep-string {} {:url (io/resource "cljs/core.js") :requires ["goog.string"] :provides ["cljs.core"]})
+  (deps-file {} [{:url (io/resource "cljs/core.js") :requires ["goog.string"] :provides ["cljs.core"]}])
   )

 (defn output-one-file [{:keys [output-to]} js]
@@ -508,7 +530,7 @@
   directory."
   [js]
   (if-let [url ^URL (-url js)]
-    (last (string/split (.getFile url) #"/goog.jar!/"))
+    (last (string/split (.getFile url) #"\.jar!/"))
     (str (random-string 5) ".js")))

 (defn write-javascript


will-mount widget

will-mount widget

--- src/cljs/ufo/client.cljs
+++ src/cljs/ufo/client.cljs
@@ -87,27 +87,25 @@
                 cols)]))))
 (def tbody-row (om/factory TBodyRow))

+(defn will-mount [widget]
+  (let [{:keys [cols sqlfn] :as prm} (om/props widget)
+        tbeg (time/now)]
+    (utils/ednxhr
+     {:reqprm {:f sqlfn :rowlim 4 :log t :nocache t}
+      :on-complete
+      (fn [resp]
+        ;; map returs a lazy sequence therefore doseq must be used
+        ;; (map #(add-person! widget %) (:rows resp))
+        (doseq [p (:rows resp)]
+          (add-person! widget p))
+        ;; TODO transact {:resp (str resp) :tbeg tbeg :tend (time/now)})
+        :on-error (fn [resp] (println resp)))})
+    ;; TODO Searching DB should be returned by ednxhr and displayed here
+    #_(html [:div "Searching DB..."])))
+
 (defui TBodyUsers
-  static om/IQuery
-  (query [this] `[{:list/trows ~(om/get-query ColsUsers)}])
-  Object
-  (componentWillMount
-   [this]
-   (let [{:keys [cols sqlfn] :as prm} (om/props this)
-         tbeg (time/now)]
-     (println "willMount" "TBodyUsers" "prm" prm)
-     (utils/ednxhr
-      {:reqprm {:f sqlfn :rowlim 4 :log t :nocache t}
-       :on-complete
-       (fn [resp]
-         ;; map returs a lazy sequence therefore doseq must be used
-         ;; (map #(add-person! this %) (:rows resp))
-         (doseq [p (:rows resp)]
-           (add-person! this p))
-         ;; TODO transact {:resp (str resp) :tbeg tbeg :tend (time/now)})
-         :on-error (fn [resp] (println resp)))})
-     ;; TODO Searching DB should be returned by ednxhr and displayed here
-     #_(html [:div "Searching DB..."])))
+  static om/IQuery (query [this] `[{:list/trows ~(om/get-query ColsUsers)}])
+  Object (componentWillMount [this] (will-mount this))
   (render
    [this]
    (let [{:keys [list/trows]} (om/props this)]
@@ -118,26 +116,8 @@
 (def tbody-users (om/factory TBodyUsers {:keyfn :sqlfn}))

 (defui TBodySalaries
-  static om/IQuery
-  (query [this] `[{:list/trows ~(om/get-query ColsSalaries)}])
-  Object
-  (componentWillMount
-   [this]
-   (let [{:keys [cols sqlfn] :as prm} (om/props this)
-         tbeg (time/now)]
-     (println "willMount" "TBodySalaries" "prm" prm)
-     (utils/ednxhr
-      {:reqprm {:f sqlfn :rowlim 4 :log t :nocache t}
-       :on-complete
-       (fn [resp]
-         ;; map returs a lazy sequence therefore doseq must be used
-         ;; (map #(add-person! this %) (:rows resp))
-         (doseq [p (:rows resp)]
-           (add-person! this p))
-         ;; TODO transact {:resp (str resp) :tbeg tbeg :tend (time/now)})
-         :on-error (fn [resp] (println resp)))})
-     ;; TODO Searching DB should be returned by ednxhr and displayed here
-     #_(html [:div "Searching DB..."])))
+  static om/IQuery (query [this] `[{:list/trows ~(om/get-query ColsSalaries)}])
+  Object (componentWillMount [this] (will-mount this))
   (render
    [this]
    (let [{:keys [list/trows]} (om/props this)]


More colors

More colors

--- src/clojure/yaw/spec.clj
+++ src/clojure/yaw/spec.clj
@@ -64,7 +64,7 @@
 (s/def :params/pos :vector/gen)
 (s/def :params/rot :vector/gen)
 (s/def :params/scale :vector/gen)
-(s/def :params/color (s/or :kw #{:red :blue :yellow :white :black} ;;more?
+(s/def :params/color (s/or :kw #{:red :green :blue :yellow :cyan :magenta :white :black } ;;more?
                            :rgb :vector/pnorm))
 (s/def :params/texture string?)
 (s/def :params/mat (s/or :color :params/color


Experiment more with meta-errors

Experiment more with meta-errors

--- src/clojush/evaluate.clj
+++ src/clojush/evaluate.clj
@@ -255,6 +255,36 @@
                                                  (-> (:history sib)
                                                      (second)
                                                      (nth case-index)))))
+                                     siblings)
+                               0
+                               1)))))))
+              ;
+              (= cat :case-family-non-improvement)
+              (if (not (:print-history argmap))
+                (throw
+                  (Exception.
+                    ":print-history must be true for :case-family-non-improvement"))
+                (if (or (empty? (:parent-uuids ind))
+                        (empty? (rest (:history ind))))
+                  (vec (repeat (count (:errors ind)) 1))
+                  (let [siblings (filter #(and (= (first (:parent-uuids ind))
+                                                  (first (:parent-uuids %)))
+                                               (not (empty? (rest (:history %))))) ; new random sibs don't count
+                                         evaluated-population)]
+                    (vec (for [case-index (range (count (:errors ind)))]
+                           (if (zero? (nth (:errors ind) case-index)) ;; solved
+                             0
+                             (if
+                               (some (fn [sib]
+                                       (or (zero? (-> (:history sib) ;; sib solved
+                                                      (first)
+                                                      (nth case-index)))
+                                           (< (-> (:history sib) ;; sib error better than mom's
+                                                  (first)
+                                                  (nth case-index))
+                                              (-> (:history sib)
+                                                  (second)
+                                                  (nth case-index)))))
                                      siblings)
                                0
                                1)))))))


x simply needs to be a member of the events

--- src/desdemona/query.clj
+++ src/desdemona/query.clj
@@ -5,8 +5,8 @@
   [n-answers query events]
   `(l/run ~n-answers [results#]
      (l/fresh [~'x]
-       (l/everyg #(l/membero % results#) ~events)
        (l/== [~'x] results#)
+       (l/membero ~'x ~events)
        ~query)))

 (defn run-query


Re-enable median response time statistic

--- src/engulf/recorder.clj
+++ src/engulf/recorder.clj
@@ -32,7 +32,7 @@
         sorted-runtimes (vec runtimes)]
     {:runtime runtime
      :runs-sec (/ runs-total (/ runtime 1000))
-     :median-runtime 0
+     :median-runtime (median sorted-runtimes)
      :runtime-percentiles (percentiles sorted-runtimes)}))

 (defprotocol Recordable


Naively assume the existence of an svg element for some reason

--- src/fatlip/draw/d3.cljs
+++ src/fatlip/draw/d3.cljs
@@ -16,23 +16,17 @@

 (defn draw-d3!
   [plot-data]
-  (let [{:keys [min-x max-x min-y max-y]} plot-data
-        width (- max-x min-x)
-        height (- max-y min-y)
-        svg (-> js/d3 (.select "#app") (.append "svg") (.attr "viewBox" (s/join " " [min-x
-                                                                                min-y
-                                                                                width
-                                                                                height])))]
-    (-> svg
-        (.selectAll "path")
-        (.data (clj->js (:plots plot-data)))
-        (.enter)
-        (.append "path")
-        (.attr "d" #(s/join " " (map data->path (.-plots %))))
-        (.attr "class" #(.-character %))
-        (.attr "stroke" "#000000")
-        (.attr "fill" "none"))
-    #_(-> svg
+  (-> js/d3
+      (.select "svg")
+      (.selectAll "path")
+      (.data (clj->js (:plots plot-data)))
+      (.enter)
+      (.append "path")
+      (.attr "d" #(s/join " " (map data->path (.-plots %))))
+      (.attr "class" #(.-character %))
+      (.attr "stroke" "#000000")
+      (.attr "fill" "none"))
+  #_(-> svg
         (.selectAll "circle")
         (.data (clj->js (drop 8 (take 20 (filter #(= (:type %) :a) (mapcat :plots (drop 0 (take 1 plot-data))))))))
         (.enter)
@@ -42,4 +36,4 @@
         (.attr "r" #(.-radius %))
         (.attr "class" #(.-character %))
         (.attr "stroke" "red")
-        (.attr "fill" "none"))))
+        (.attr "fill" "none")))


set up team permission granted

set up team permission granted

--- src-cljs/frontend/controllers/controls.cljs
+++ src-cljs/frontend/controllers/controls.cljs
@@ -1257,6 +1257,13 @@
                                                                              :email email
                                                                              :invite-loc :overlay}])))

+(defmethod post-control-event! :team-permission-grant-submitted
+  [browser-state message {:keys [email]} previous-state current-state]
+  (let [team-uuid (get-in current-state [:team :team/uuid])]
+    (sente/send-msg (:sente current-state) [:team/send-permission-grant {:team/uuid team-uuid
+                                                                         :email email
+                                                                         :invite-loc :overlay}])))
+

 (defmethod post-control-event! :document-privacy-changed
   [browser-state message {:keys [doc-id setting]} previous-state current-state]


switch back to the default session store

--- src/greybear/server.clj
+++ src/greybear/server.clj
@@ -1,8 +1,8 @@
 (ns greybear.server
   (:require [compojure.route :as route]
             [compojure.handler :as handler])
-  (:use [ring.adapter.jetty]
-        [ring.middleware.session]
+  (:use
+        [ring.middleware.session :only [wrap-session]]
         [hiccup core element page]
         [hiccup.middleware :only [wrap-base-url]]
         [compojure.core :only [defroutes GET]]
@@ -40,5 +40,5 @@

 (def app
   (-> (handler/site main-routes)
-      (wrap-session {:store (cookie-store {:key "a 16-byte secret"})})
+      (wrap-session)
       (wrap-base-url)))


add quote danger condition to finalize state

--- lib/src/parinfer/indent_mode.cljc
+++ lib/src/parinfer/indent_mode.cljc
@@ -320,8 +320,9 @@
      state)))

 (defn finalize-state
-  [{:keys [stack] :as state}]
-  (let [valid? (not (in-str? stack)) ;; invalid if unclosed string
+  [{:keys [stack quote-danger?] :as state}]
+  (let [valid? (and (not (in-str? stack))
+                    (not quote-danger?))
         close-delims? (and valid? (seq stack))]
     (cond-> (assoc state :valid? valid?)
       close-delims? close-delims)))


Fix overshadowing warning #4830

Fix overshadowing warning #4830

--- src/metabase/routes.clj
+++ src/metabase/routes.clj
@@ -12,7 +12,7 @@
             [metabase.util :as u]
             [metabase.util.embed :as embed]))

-(defn- load-file [path]
+(defn- load-file-at-path [path]
   (slurp (or (io/resource path)
              (throw (Exception. (str "Cannot find '" path "'. Did you remember to build the Metabase frontend?"))))))

@@ -24,7 +24,7 @@
         (load-template (str "frontend_client/" entry ".html")
                        {:bootstrap_json (json/generate-string (public-settings/public-settings))
                         :embed_code     (when embeddable? (embed/head uri))})
-        (load-file "frontend_client/init.html"))
+        (load-file-at-path "frontend_client/init.html"))
       resp/response
       (resp/content-type "text/html; charset=utf-8")))


draw multiple circles

draw multiple circles

--- src/minkowski/core.cljs
+++ src/minkowski/core.cljs
@@ -9,14 +9,17 @@
 (def canvas (aget (.getElementsByTagName js/document "canvas") 0))
 (def slider (aget (.getElementsByTagName js/document "input") 0))
 (def drawing (.getContext canvas "2d"))
-(def width 800)
-(def height 800)
+(def unit-pixels 100)
+(def width (* 8 unit-pixels))
+(def height (* 8 unit-pixels))
 (aset canvas "width" width)
 (aset canvas "height" height)
-(defn canvas-point [[x y]] [(+ x (/ width 2)) (+ y (/ height 2))])
+
+(defn canvas-point [[x y]] [(+ (* unit-pixels x) (/ width 2)) (+ (* unit-pixels y) (/ height 2))])

 (def radius 30)
 (def draw-points '())
+(def circles [])

 (defn angles [n] (range 0 doublepi (/ doublepi n)))

@@ -24,17 +27,24 @@

 (.addEventListener slider "input" (fn []
   (let [value (aget slider "value")]
-    (set! radius value)
-    (set! draw-points (points 360 radius))
-  )))
+    (set! radius (/ value 100))
+    (set! circles (map (fn [radius] (points 360 radius)) (range 1 4))
+  ))))
+
+(defn draw-circle [circle]
+  (do
+    (.beginPath drawing)
+    (doall (for [point circle] (let [[x y] (canvas-point point)] (.lineTo drawing x y))))
+    (.closePath drawing)
+    (.setLineDash drawing (array 3 5))
+    (aset drawing "strokeStyle" "gray")
+    (.stroke drawing)
+  ))

 (defn draw-scene []
   (do
     (.clearRect drawing 0 0 (aget canvas "width") (aget canvas "height"))
-    (.beginPath drawing)
-    (doall (for [point draw-points] (let [[x y] (canvas-point point)] (.lineTo drawing x y))))
-    (.closePath drawing)
-    (.stroke drawing)))
+    (doall (for [circle circles] (draw-circle circle)))))

 (defn request-frame []
   (.requestAnimationFrame js/window


CMR-3525: Add more tests for background jobs

--- common-lib/test/cmr/common/test/background_jobs.clj
+++ common-lib/test/cmr/common/test/background_jobs.clj
@@ -5,19 +5,58 @@
             [cmr.common.lifecycle :as lifecycle]
             [clj-time.core :as t]))

-;; Multiple lifecycle/stop and lifecycle/start calls to make sure that won't throw an error
-(deftest increment-counter-test
-  (let [counter (atom 1)]
+(deftest background-jobs-test
+  (let [counter1 (atom 0)
+        counter2 (atom 0)
+        counter3 (atom 0)
+        job-10-times-a-second (background-jobs/create-background-job #(swap! counter1 inc) 0.1)
+        job-5-times-a-second (background-jobs/create-background-job #(swap! counter2 inc) 0.2)
+        job-1-time-a-second (background-jobs/create-background-job #(swap! counter3 inc) 1)]
+    (testing "None of the counters are updated until prior to start being called"
+      (Thread/sleep 200)
+      (is (= 0 @counter1 @counter2 @counter3)))

-   (def job (background-jobs/create-background-job #(swap! counter inc) 0.1))
-   (def job (lifecycle/start job nil))
-   (def job (lifecycle/start job nil))
-   (def job (lifecycle/start job nil))
-   (Thread/sleep 1000)
-   (def job (lifecycle/stop job nil))
-   (def job (lifecycle/stop job nil))
-   (def job (lifecycle/stop job nil))
-   (def job (lifecycle/stop job nil))
+    (testing "Start all the jobs and verify each job is called the correct number of times"
+      (let [job-10-times-a-second (lifecycle/start job-10-times-a-second nil)
+            job-5-times-a-second (lifecycle/start job-5-times-a-second nil)
+            job-1-time-a-second (lifecycle/start job-1-time-a-second nil)]
+        (Thread/sleep 1000)
+        ;; Allow for small discrepancy based on CPU times
+        (is (<= 10 @counter1 11))
+        (is (<= 5 @counter2 6))
+        (is (<= 1 @counter3 2))

-   (testing "Has counter been incremented"
-     (is (> @counter 1)))))
+        (testing "When jobs are stopped the counter stops incrementing"
+          (let [job-10-times-a-second (lifecycle/stop job-10-times-a-second nil)
+                job-5-times-a-second (lifecycle/stop job-5-times-a-second nil)
+                job-1-time-a-second (lifecycle/stop job-1-time-a-second nil)
+                counter1-value @counter1
+                counter2-value @counter2
+                counter3-value @counter3]
+            (Thread/sleep 1000)
+            (is (= counter1-value @counter1))
+            (is (= counter2-value @counter2))
+            (is (= counter3-value @counter3))
+
+            (testing "Calling stop on a stopped job is ok"
+              (let [job-10-times-a-second (lifecycle/stop job-10-times-a-second nil)]
+                (Thread/sleep 200)
+                (is (= counter1-value @counter1))
+
+                (testing "Previously stopped jobs can be started"
+                  (let [job-10-times-a-second (lifecycle/start job-10-times-a-second nil)
+                        job-5-times-a-second (lifecycle/start job-5-times-a-second nil)]
+                    (Thread/sleep 550)
+                    (is (<= (+ 5 counter1-value) @counter1 (+ 6 counter1-value)))
+                    (is (<= (+ 2 counter2-value) @counter2 (+ 3 counter2-value)))
+                    (is (= counter3-value @counter3))
+
+                    (testing (str "Calling start on an already running job restarts the job and "
+                                  "only 1 thread is running")
+                      (let [job-10-times-a-second (lifecycle/start job-10-times-a-second nil)]
+                        (Thread/sleep 550)
+                        (is (<= (+ 10 counter1-value @counter1 (+ 12 counter1-value))))
+                        ;; Stop all the jobs
+                        (lifecycle/stop job-10-times-a-second nil)
+                        (lifecycle/stop job-5-times-a-second nil)
+                        (lifecycle/stop job-1-time-a-second nil)))))))))))))


1 Region per server enforcement

1 Region per server enforcement

--- src/node/game/core.cljs
+++ src/node/game/core.cljs
@@ -611,7 +611,9 @@
                dest-zone (get-in @state (cons :corp slot))
                install-cost (if (and (= (:type c) "ICE") (not no-install-cost))
                               (count dest-zone) 0)]
-           (when (pay state side card extra-cost :credit install-cost)
+           (when (and (not (and (has? c :subtype "Region")
+                                (some #(has? % :subtype "Region") dest-zone)))
+                      (pay state side card extra-cost :credit install-cost))
              (when (#{"Asset" "Agenda"} (:type c))
                (when-let [prev-card (some #(when (#{"Asset" "Agenda"} (:type %)) %) dest-zone)]
                  (system-msg state side (str "trashes " (if (:rezzed prev-card)


Remove useless requirement

Remove useless requirement

--- src/whisper2cyanite/path_store.clj
+++ src/whisper2cyanite/path_store.clj
@@ -4,8 +4,7 @@
             [clojurewerkz.elastisch.rest.document :as esrd]
             [clojure.string :as str]
             [clojure.tools.logging :as log]
-            [whisper2cyanite.logging :as wlog]
-            [whisper2cyanite.utils :as utils]))
+            [whisper2cyanite.logging :as wlog]))

 (defprotocol PathStore
   (insert [this tenant path file])


provide better error message on database failures

--- db-binding/src/com/sixsq/slipstream/db/es/utils.clj
+++ db-binding/src/com/sixsq/slipstream/db/es/utils.clj
@@ -105,7 +105,8 @@
       (log/warn "index" index "not found, returning empty search result")
       {})
     (catch SearchPhaseExecutionException spee
-      (log/warn "search failed:" (.getMessage spee) ", returning empty search result")
+      (log/warn "search failed on" index "for" type "with parameters" cimi-params
+                ", returning empty search result; message:" (.getMessage spee))
       {})))

 ;;


Fix display of completed message

Fix display of completed message

--- src/cljs/geoforms/forms.cljs
+++ src/cljs/geoforms/forms.cljs
@@ -361,9 +361,9 @@
               (seq @db/ideas))
      [:div
       [step-1]
-      (when (seq (selected-districts))
-        (if (completed?)
-          [completed-view]
+      (if (completed?)
+        [completed-view]
+        (when (seq (selected-districts))
           [:div
            [step-2]
            (when @db/selected-district


Reduce use of alts!! in critical path Supports reduction of core async thread pool count which is too high

--- src/onyx/messaging/aeron.clj
+++ src/onyx/messaging/aeron.clj
@@ -1,5 +1,5 @@
 (ns ^:no-doc onyx.messaging.aeron
-  (:require [clojure.core.async :refer [chan >!! <!! alts!! timeout close! sliding-buffer]]
+  (:require [clojure.core.async :refer [chan >!! <!! poll! timeout close! sliding-buffer]]
             [com.stuartsierra.component :as component]
             [taoensso.timbre :refer [fatal info warn] :as timbre]
             [onyx.messaging.aeron.peer-manager :as pm]
@@ -341,13 +341,17 @@
   (let [ch (:inbound-ch messenger-buffer)
         batch-size (long (:onyx/batch-size task-map))
         ms (arg-or-default :onyx/batch-timeout task-map)
-        timeout-ch (timeout ms)]
+        yield-time (+ (System/currentTimeMillis) ms)]
     (loop [segments (transient []) i 0]
-      (if (< i batch-size)
-        (if-let [v (first (alts!! [ch timeout-ch]))]
-          (recur (conj! segments v) (inc i))
-          (persistent! segments))
-        (persistent! segments)))))
+      (if-let [v (poll! ch)]
+        (recur (conj! segments v) (inc i))
+        (if (or (> (System/currentTimeMillis) yield-time)
+                (>= i batch-size))
+          (persistent! segments)
+          (do
+           ;; less than the resolution for alts!!
+           (Thread/sleep 5)
+           (recur segments i)))))))

 (defn lookup-channels [messenger id]
   (-> messenger


set the query preprocessor limit on bare rows queries to 2000 max.

--- src/metabase/driver/query_processor.clj
+++ src/metabase/driver/query_processor.clj
@@ -22,6 +22,10 @@
 (def ^:const max-result-rows
   "Maximum number of rows the QP should ever return."
   10000)
+
+(def ^:const max-result-bare-rows
+  "Maximum number of rows the QP should ever return specifically for 'rows' type aggregations."
+  2000)

 ;; # DYNAMIC VARS
@@ -106,7 +110,7 @@
   [{:keys [limit aggregation] :as query}]
   (if (and (= aggregation ["rows"])
            (not limit))
-    (assoc query :limit max-result-rows)
+    (assoc query :limit max-result-bare-rows)
     query))


Avoid error when title is nil.

Avoid error when title is nil.

--- src/oc/email/mailer.clj
+++ src/oc/email/mailer.clj
@@ -240,7 +240,7 @@
           mention? (:mention? notification)
           comment? (:interaction-id notification)
           title (:headline post-data)
-          parsed-title (.text (soup/parse title))
+          parsed-title (if title (.text (soup/parse title)) "")
           updated-post-data (assoc post-data :parsed-headline parsed-title)
           msg-title (assoc-in msg [:notification :entry-data] updated-post-data)
           pre-subject (content/notify-entry-intro msg)


jobs/post/getindexes.clj: change directory for unpacking distindex files

--- src/org/altlaw/jobs/post/getindexes.clj
+++ src/org/altlaw/jobs/post/getindexes.clj
@@ -16,8 +16,8 @@
         lines (duck/read-lines (.open fs (Path. "/v4/distindex/part-00000")))
         files (map #(first (.split % "\t")) lines)
         zipfiles (map #(str "/v4/distindex/" %) files)
-        unzipdirs (map #(str "/mnt/mergeindex/" (.replace % ".zip" "")) files)]
-    (println "Unpacking indexed ZIP files...")
+        unzipdirs (map #(str "/mnt/distindexes/" (.replace % ".zip" "")) files)]
+    (println "Unpacking distindex ZIP files to /mnt/distindexes/...")
     (doseq [[zipfile unzipdir] (map vector zipfiles unzipdirs)]
       (println zipfile)
       (with-open [stream (.open fs (Path. zipfile))]


delaney.clj: fixed a small bug

delaney.clj: fixed a small bug

--- clojure/org/gavrog/clojure/delaney.clj
+++ clojure/org/gavrog/clojure/delaney.clj
@@ -234,7 +234,8 @@
     (keep (partial morphism ds ds D) (elements ds))))

 (defn automorphism-orbits [ds]
-  (or (seq (into pempty (apply concat (automorphisms ds)))) (elements ds)))
+  (or (seq (into pempty (apply concat (automorphisms ds))))
+      (map list (elements ds))))

 ;; === Persistent Clojure implementation of IDSymbol with some common


fix the doc-id in precursor pings

fix the doc-id in precursor pings

--- src/pc/http/datomic.clj
+++ src/pc/http/datomic.clj
@@ -182,7 +182,7 @@
 (defn handle-precursor-pings [transaction]
   (let [db (:db-after transaction)
         datoms (:tx-data transaction)
-        document-id (delay (:transaction/document (get-annotations transaction)))
+        document-id (delay (:db/id (:transaction/document (get-annotations transaction))))
         chat-body-eid (d/entid db :chat/body)]
     (when-let [chat-datom (first (filter #(= chat-body-eid (:a %)) datoms))]
       (let [slack-url (if (profile/prod?)


debug helper

debug helper

--- src/pc/models/layer.clj
+++ src/pc/models/layer.clj
@@ -13,11 +13,23 @@
 ;; This will work as long as other things don't get a document id
 (defn all [db]
   (pcd/touch-all '{:find [?t]
-                   :where [[?t :document/id]
-                           [?t :layer/name]]}
+                   :where [[?t :layer/name]]}
                  db))

 (defn find-by-document [db document]
   (pcd/touch-all '{:find [?t] :in [$ ?document-id]
                    :where [[?t :document/id ?document-id]]}
                  db (:db/id document)))
+
+
+(comment
+  (d/transact (pcd/conn)
+              [{:db/id (d/tempid :db.part/user)
+                :layer/name "Test Layer 1"
+                :layer/fill "red"}
+               {:db/id (d/tempid :db.part/user)
+                :layer/name "Test Layer 2"
+                :layer/fill "blue"}
+               {:db/id (d/tempid :db.part/user)
+                :layer/name "Test Layer 3"
+                :layer/fill "green"}]))


choose the best voter

choose the best voter

--- src/pc/product_hunt.clj
+++ src/pc/product_hunt.clj
@@ -37,7 +37,7 @@
    19567 {"name" "Precursor",
           "votes_count" 3,
           "comments_count" 1,
-          "tagline" "We make prototyping and team collaboration quick and simple"
+          "tagline" "We make prototyping and team collaboration simple and easy"
           "discussion_url" "http://www.producthunt.com/posts/precursor-for-teams"
           "makers" [{"image_url" {"30px" "http://avatars-cdn.producthunt.com/106624/30?1430244521"}}
                     {"image_url" {"30px" "http://avatars-cdn.producthunt.com/106635/30?1430312595"}}]
@@ -56,7 +56,8 @@
   (let [info (post-info post-id)
         make-link (fn [content]
                     [:a {:href (get info "discussion_url")}
-                     content])]
+                     content])
+        maker-ids (set (map #(get % "id") (get info "makers")))]
     (h/html
      [:div.product-hunt-card
       [:a.ph-big-link {:href (get info "discussion_url")}]
@@ -70,7 +71,14 @@
         (for [maker (get info "makers")]
           [:div.ph-maker
            [:img.ph-avatar {:src (get-in maker ["image_url" "30px"])}]])]
-       (when-let [voter (some-> info (get "votes") first (get "user"))]
+       (when-let [voter (some-> info
+                          (get "votes")
+                          (#(remove (fn [u] (contains? maker-ids (get-in u ["user" "id"])))
+                                    %))
+                          (#(sort-by (fn [u] (get u "id"))
+                                     %))
+                          last
+                          (get "user"))]
          [:div.ph-hunter
           [:img.avatar {:src (get-in voter ["image_url" "30px"])}]])]
       [:div.ph-comments-icon ph-comments]


Unnecessarily passing *default-session*.

--- src/clojure/clojurewerkz/cassaforte/cql.clj
+++ src/clojure/clojurewerkz/cassaforte/cql.clj
@@ -18,7 +18,7 @@
 (defn ^:private execute-
   [query-params builder]
   (let [rendered-query (client/render-query (client/compile-query query-params builder))]
-    (client/execute client/*default-session* rendered-query :prepared cql/*prepared-statement*)))
+    (client/execute rendered-query :prepared cql/*prepared-statement*)))

 ;;
 ;; Schema operations
@@ -147,7 +147,7 @@
                    (apply query/queries)
                    query/batch-query
                    client/render-query)]
-    (client/execute client/*default-session* query :prepared cql/*prepared-statement*)))
+    (client/execute query :prepared cql/*prepared-statement*)))

 (defn update
   "Updates one or more columns for a given row in a table. The `where` clause


Improve comment

Improve comment

--- src/re_frame/middleware.cljs
+++ src/re_frame/middleware.cljs
@@ -190,10 +190,11 @@

   (on-changes my-f [:c]  [:a] [:b])

-  Put the middlware above on the right handlers (ones which might change :a or :b.
+  Put the middlware above on the right handlers (ones which might change :a or :b).
   It will:
-     - run 'f' each time the value at path [:a] or [:b] changes
-     - put the return value from f into the path  [:c]
+     - call 'f' each time the value at path [:a] or [:b] changes
+     - call 'f' with the values extracted from [:a] [:b]
+     - assoc the return value from 'f' into the path  [:c]
   "
   [f out-path & in-paths]
   (fn on-changed-middleware


Support disconnecting ADSR nodes

Support disconnecting ADSR nodes

--- src/alder/audio/adsr.cljs
+++ src/alder/audio/adsr.cljs
@@ -26,6 +26,9 @@
     (letfn [(connect [param]
               (set! (.-param audio-node) param))

+            (disconnect [param]
+              (set! (.-param audio-node) nil))
+
             (set-gate [value]
               (when (.-param audio-node)
                 (if (> value 0.0)
@@ -40,4 +43,5 @@
                             (.-release audio-node)))))]
       (set! (.-connect audio-node) connect)
       (set! (.-gate audio-node) set-gate)
+      (set! (.-disconnect audio-node) disconnect)
       audio-node)))


atomize fill-in

atomize fill-in

--- src/riemann/streams.clj
+++ src/riemann/streams.clj
@@ -620,7 +620,7 @@
          new-deferrable (fn new-deferrable [] (every! interval
                                                       interval
                                                       fill))
-         deferrable (ref (new-deferrable))]
+         deferrable (atom (new-deferrable))]
     (fn stream [event]
       (let [d (deref deferrable)]
         (if d
@@ -628,13 +628,13 @@
           (if (expired? event)
             (do
               (cancel d)
-              (dosync (ref-set deferrable nil)))
+              (reset! deferrable nil))
             (defer d interval))
           ; Create a deferrable
           (when-not (expired? event)
             (locking deferrable
               (when-not (deref deferrable)
-                (dosync (ref-set deferrable (new-deferrable))))))))
+                (reset! deferrable (new-deferrable)))))))

       ; And forward
       (call-rescue event children)))))


(with) is a plain old function now, not a multimethod.

--- src/riemann/streams.clj
+++ src/riemann/streams.clj
@@ -717,26 +717,27 @@
   [& children]
   (apply match :state "expired" children))

-(defmulti with
+(defn with
   "Transforms an event by associng a set of new k:v pairs, and passes the
   result to children. Use:

   (with :service \"foo\" prn)
   (with {:service \"foo\" :state \"broken\"} prn)"
-  (fn [& args] (map? (first args))))
-(defmethod with true [m & children]
-  (fn [event]
-;    Merge on protobufs is broken; nil values aren't applied.
-;    (let [e (merge event m)]
-    (let [e (reduce (fn [m, [k, v]]
-                      (if (nil? v) (dissoc m k) (assoc m k v)))
-                    event m)]
-      (call-rescue e children))))
-(defmethod with false [k v & children]
-  (fn [event]
-;    (let [e (assoc event k v)]
-    (let [e (if (nil? v) (dissoc event k) (assoc event k v))]
-      (call-rescue e children))))
+  [& args]
+  (if (map? (first args))
+    (let [[m & children] args]
+      (fn [event]
+        ;    Merge on protobufs is broken; nil values aren't applied.
+        ;    (let [e (merge event m)]
+        (let [e (reduce (fn [m, [k, v]]
+                          (if (nil? v) (dissoc m k) (assoc m k v)))
+                        event m)]
+          (call-rescue e children))))
+    (let [[k v & children] args]
+      (fn [event]
+        ;    (let [e (assoc event k v)]
+        (let [e (if (nil? v) (dissoc event k) (assoc event k v))]
+          (call-rescue e children))))))

 (defmulti default
   "Transforms an event by associng a set of new key:value pairs, wherever the


Reduce hunger and thirst rates

Reduce hunger and thirst rates

--- src/robinson/update.clj
+++ src/robinson/update.clj
@@ -2601,8 +2601,8 @@
           (update-in [:world :player :hunger] (partial + 0.01))
           (update-in [:world :player :thirst] (partial + 0.05)))
         (-> state
-          (update-in [:world :player :hunger] (partial + 0.09 (* 0.025 (count (ri/player-inventory state)))))
-          (update-in [:world :player :thirst] (partial + 0.19))))
+          (update-in [:world :player :hunger] (partial + 0.03 (* 0.025 (count (ri/player-inventory state)))))
+          (update-in [:world :player :thirst] (partial + 0.12))))
       (if (> (rp/player-hunger state) (rp/player-max-hunger state))
         (do
           (log/info "Player died from hunger")


CMR-1718: A minor refactoring of a test.

--- system-int-test/test/cmr/system_int_test/health_test.clj
+++ system-int-test/test/cmr/system_int_test/health_test.clj
@@ -89,14 +89,7 @@
   (s/only-with-real-database
     (is (= [200 {:metadata-db good-metadata-db-health
                  :internal-metadata-db good-metadata-db-health
-                 :indexer {:ok? true
-                           :dependencies {:elastic_search {:ok? true}
-                                          :echo {:ok? true}
-                                          :cubby {:ok? true,
-                                                  :dependencies
-                                                  {:elastic_search {:ok? true}, :echo {:ok? true}}}
-                                          :metadata-db good-metadata-db-health
-                                          :index-set good-index-set-db-health}}}]
+                 :indexer (update-in good-indexer-health [:dependencies] dissoc :rabbit-mq)}]
            (get-app-health (url/bootstrap-health-url))))))

 (deftest virtual-product-health-test


CLJS-601: Function overloaded with same arity count now fails to compile.

--- src/clj/cljs/analyzer.clj
+++ src/clj/cljs/analyzer.clj
@@ -478,7 +478,10 @@
                   ;; lets us optimize self calls
                   (no-warn (doall (map #(analyze-fn-method menv locals % type) meths)))
                   methods)]
-    ;;todo - validate unique arities, at most one variadic, variadic takes max required args
+    ;;todo - at most one variadic, variadic takes max required args
+    (let [param-counts (map (comp count :params) methods)]
+      (when (not= (distinct param-counts) param-counts)
+        (throw (error env "Can't have 2 overloads with same arity"))))
     {:env env :op :fn :form form :name name-var :methods methods :variadic variadic
      :recur-frames *recur-frames* :loop-lets *loop-lets*
      :jsdoc [(when variadic "@param {...*} var_args")]


Handle comments in reader

Handle comments in reader

Useful for reading eg project.clj

--- src/cljs/cljs/reader.cljs
+++ src/cljs/cljs/reader.cljs
@@ -383,7 +383,7 @@
   (cond
    (identical? c \") read-string*
    (identical? c \:) read-keyword
-   (identical? c \;) not-implemented ;; never hit this
+   (identical? c \;) read-comment
    (identical? c \') (wrapping-reader 'quote)
    (identical? c \@) (wrapping-reader 'deref)
    (identical? c \^) read-meta


Remove commented fn

Remove commented fn

--- src/doctopus/storage/impls/permanent_fs.clj
+++ src/doctopus/storage/impls/permanent_fs.clj
@@ -21,15 +21,6 @@
       (and (fs/exists? result)
            (fs/readable? result)))))

-;; This might be totally deprecated.
-;; (defn load-fn
-;;   "Uh."
-;;   [key]
-;;   (binding [fs/*cwd* root]
-;;     (let [dir (fs/file key)
-;;           rel-path-html-pairs (files/read-html dir)]
-;;       (into [] (map (fn [[rel-path html]] [rel-path (fn [_] html)]) rel-path-html-pairs)))))
-
 (defn load-fn
   "Returns the routes this serves"
   [key]


[#9268] fix Multiaccount is currently empty on login

--- src/status_im/multiaccounts/login/core.cljs
+++ src/status_im/multiaccounts/login/core.cljs
@@ -68,7 +68,10 @@
   {:events [:multiaccounts.login.ui/password-input-submitted]}
   [{:keys [db] :as cofx}]
   (let [{:keys [address password name photo-path]} (:multiaccounts/login db)]
-    {:db (assoc-in db [:multiaccounts/login :processing] true)
+    {:db (-> db
+             (assoc-in [:multiaccounts/login :processing] true)
+             (dissoc :intro-wizard)
+             (update :hardwallet dissoc :flow))
      ::login [(types/clj->json {:name name :address address :photo-path photo-path})
               (ethereum/sha3 (security/safe-unmask-data password))]}))


add test from DJSON-28 which is now covered by the DJSON-34 change

--- src/test/clojure/clojure/data/json_test.clj
+++ src/test/clojure/clojure/data/json_test.clj
@@ -204,6 +204,7 @@

 (deftest print-nonescaped-unicode
   (is (= "\"\\u0000\\t\\u001f \"" (json/write-str "\u0000\u0009\u001f\u0020" :escape-unicode true)))
+  (is (= "\"\\u0000\\t\\u001f \"" (json/write-str "\u0000\u0009\u001f\u0020" :escape-unicode false)))
   (is (= "\"\u1234\u4567\"" (json/write-str "\u1234\u4567" :escape-unicode false))))

 (deftest escape-special-separators


More async.

More async.

--- src/datascript/query.cljs
+++ src/datascript/query.cljs
@@ -446,8 +446,8 @@
       (update-in context [:rels] collapse-rels rel))
     (-resolve-clause context clause)))

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

 (defn -collect
   ([context symbols]
@@ -519,13 +519,12 @@
         ins       (:in q '[$])
         wheres    (:where q)
         context   (-> (Context. [] {} {})
-                    (parse-ins ins inputs))
-        resultset (-> context
-                    (-q wheres)
-                    (collect find))]
-    (callback
-      (cond->> resultset
-        (:with q)
-          (mapv #(subvec % 0 (count (:find q))))
-        (not-empty (filter sequential? (:find q)))
-          (aggregate q context)))))
+                        (parse-ins ins inputs))]
+        (-q context wheres (fn [data]
+                             (callback
+                               (let [resultset (collect data find)]
+                                 (cond->> resultset
+                                   (:with q)
+                                     (mapv #(subvec % 0 (count (:find q))))
+                                   (not-empty (filter sequential? (:find q)))
+                                     (aggregate q context))))))))


Have to parse int

Have to parse int

--- src/wishlistd/models/sql.clj
+++ src/wishlistd/models/sql.clj
@@ -66,8 +66,8 @@

 (defn update-wish [{:keys [id] :as w}]
   (update wish
-    (where {:id id})))
     (set-fields (dissoc w :wishlist_code :id))
+    (where {:id (Integer/parseInt id)})))

 (defn delete-wish [id]
   (delete wish


Add display names to Om components.

Add display names to Om components.

--- src/wrongtangular/views.cljs
+++ src/wrongtangular/views.cljs
@@ -13,6 +13,8 @@
 ;; Expects a wrongtangular.core/image-set.
 (defn tinder [{:keys [image-set last-action direction]} owner]
   (reify
+    om/IDisplayName
+    (display-name [_] "Tinder")
     om/IRender
     (render [_]
       (let [[previous-image current-image next-image] image-set
@@ -46,6 +48,8 @@

 (defn progress-text [{:keys [app approved-count rejected-count]} owner]
   (reify
+    om/IDisplayName
+    (display-name [_] "ProgressText")
     om/IRender
     (render [_]
       (let [index (count (:complete app))
@@ -57,6 +61,8 @@

 (defn progress-bar [{:keys [app approved-count rejected-count]} owner]
   (reify
+    om/IDisplayName
+    (display-name [_] "ProgressBar")
     om/IRender
     (render [_]
       (let [index (count (:complete app))
@@ -73,12 +79,16 @@

 (defn loading [owner]
   (reify
+    om/IDisplayName
+    (display-name [_] "Loading")
     om/IRender
     (render [_]
       (html [:div nil "loading..."]))))

 (defn main [{:keys [app current-id]} owner]
   (reify
+    om/IDisplayName
+    (display-name [_] "Main")
     om/IRender
     (render [_]
       (html
@@ -108,6 +118,8 @@

 (defn results [app owner]
   (reify
+    om/IDisplayName
+    (display-name [_] "Results")
     om/IRender
     (render [_]
       (html


fully qualify ns and packages in build

fully qualify ns and packages in build

--- examples/war/build.clj
+++ examples/war/build.clj
@@ -3,12 +3,11 @@
   (println "compiling...")
   (println (ns-name *ns*))
   (let [root       (:root project)
-        classpath  (for [dir ["/src" "/lib*"]] (str root dir))
-        cp-fileset (ant FileSet)]
+        classpath  (for [dir ["/src" "/lib*"]] (str root dir))]
     (println classpath)
-    (ant Javac {:destdir (java.io.File. root "classes")
+    (cake.ant/ant org.apache.tools.ant.taskdefs.Javac {:destdir (java.io.File. root "classes")
                 :fork true
-                :classpath (ant Path {:path (apply str (interpose ":" classpath))})
-                :srcdir (ant Path {:path (java.io.File. root "src")})
+                :classpath (cake.ant/ant org.apache.tools.ant.types.Path {:path (apply str (interpose ":" classpath))})
+                :srcdir (cake.ant/ant org.apache.tools.ant.types.Path {:path (java.io.File. root "src")})
                 :includes "*.clj"})))


Inline TxReport constructor

Inline TxReport constructor

--- src/datascript/core.cljc
+++ src/datascript/core.cljc
@@ -260,12 +260,7 @@
     {:pre [(db/db? db)]}
     (if (is-filtered db)
       (throw (ex-info "Filtered DB cannot be modified" {:error :transaction/filtered}))
-      (db/transact-tx-data (db/map->TxReport
-                             { :db-before db
-                               :db-after  db
-                               :tx-data   []
-                               :tempids   {}
-                               :tx-meta   tx-meta}) tx-data))))
+      (db/transact-tx-data (db/->TxReport db db [] {} tx-meta) tx-data))))

 (defn db-with


Add pool name to jobs created metric (#990)

--- scheduler/src/cook/mesos/api.clj
+++ scheduler/src/cook/mesos/api.clj
@@ -1518,8 +1518,6 @@
     x
     [x]))

-(meters/defmeter [cook-mesos scheduler jobs-created])
-
 (defn create-jobs!
   "Based on the context, persists the specified jobs, along with their groups,
   to Datomic.
@@ -1568,7 +1566,9 @@
              (into job-txns)
              (into group-txns)))

-      (meters/mark! jobs-created (count jobs))
+      (meters/mark! (meters/meter ["cook-mesos" "scheduler" "jobs-created"
+                                   (str "pool-" (pool/pool-name-or-default (:pool/name pool)))])
+                    (count jobs))
       {::results (str/join
                    \space (concat ["submitted jobs"]
                                   (map (comp str :uuid) jobs)


improved some trace messages

improved some trace messages

--- src/distillery/tasks.clj
+++ src/distillery/tasks.clj
@@ -165,7 +165,7 @@

 (defn- build-video-statistics
   [{:keys [id results] :as video}]
-  (trace-message "Building statistics for " id)
+  (trace-message "Building statistics for video '" id "'")
   (let [last-result (last results)
         duration (+ (:start last-result) (:duration last-result))]
     (assoc video
@@ -178,7 +178,7 @@
 (defn- build-video-index
   "Analyzes the speech recognition results of a single video and builds the video word index."
   [job video]
-  (trace-message "Building index for " (:id video))
+  (trace-message "Building index for video '" (:id video) "'")
   (let [index (proc/video-word-index video :predicate (word-predicate job))]
     (assoc video :index index)))


updated comment numbers

updated comment numbers

--- src/atom_finder/questions/comment_counts.clj
+++ src/atom_finder/questions/comment_counts.clj
@@ -138,10 +138,13 @@
        expand-home
        list-dirs
        (map str)
-       (mapcat (partial pmap-dir-trees atoms-by-comments&function))
-       flatten
-       (map (juxt :comment :atom))
-       ;(take 2000)
+       (mapcat (fn [dir]
+                 (let [proj (str/replace dir #".*\/" "")]
+                   (->> dir
+                    (pmap-dir-trees atoms-by-comments&function)
+                    flatten
+                    (map #(assoc % :proj proj))))))
+       (map (juxt :proj :comment :atom))
        frequencies
        (map prn)
        dorun
@@ -151,54 +154,493 @@

 (->>
  [
-[[true :omitted-curly-braces] 45892]
-[[nil :conditional] 273]
-[[nil nil] 6]
-[[true :operator-precedence] 23890]
-[[false :reversed-subscript] 23]
-[[true :literal-encoding] 733]
-[[nil :assignment-as-value] 104]
-[[nil :omitted-curly-braces] 568]
-[[true :conditional] 5082]
-[[false :type-conversion] 12099]
-[[nil :comma-operator] 5528]
-[[nil :operator-precedence] 537]
-[[false :literal-encoding] 3127]
-[[false :omitted-curly-braces] 1583210]
-[[false :comma-operator] 64706]
-[[true :macro-operator-precedence] 240]
-[[true :comma-operator] 2129]
-[[nil :pre-increment] 14]
-[[true :repurposed-variable] 3907]
-[[true :post-increment] 4942]
-[[true nil] 11497007]
-[[true :preprocessor-in-statement] 177]
-[[false :preprocessor-in-statement] 11568]
-[[true :pre-increment] 1099]
-[[true :reversed-subscript] 28]
-[[false :post-increment] 72713]
-[[false :implicit-predicate] 264357]
-[[false :conditional] 151645]
-[[false :assignment-as-value] 91731]
-[[true :logic-as-control-flow] 420]
-[[false :pre-increment] 22596]
-[[true :assignment-as-value] 3419]
-[[nil :implicit-predicate] 12841]
-[[false :operator-precedence] 992817]
-[[true :type-conversion] 1754]
-[[false :logic-as-control-flow] 9547]
-[[false nil] 277808231]
-[[false :macro-operator-precedence] 3768]
-[[nil :post-increment] 10]
-[[true :implicit-predicate] 7997]
-[[false :repurposed-variable] 79250]
-[[nil :type-conversion] 9]
+[["mongo" true nil] 538153]
+[["gcc" nil :operator-precedence] 62]
+[["subversion" false :macro-operator-precedence] 19]
+[["httpd" false :macro-operator-precedence] 48]
+[["httpd" true :post-increment] 35]
+[["clang" false :operator-precedence] 11576]
+[["mysql-server" true :logic-as-control-flow] 39]
+[["mongo" nil :operator-precedence] 30]
+[["freebsd" false :logic-as-control-flow] 4054]
+[["gcc" false :assignment-as-value] 5376]
+[["emacs" nil :omitted-curly-braces] 13]
+[["linux" false :type-conversion] 2185]
+[["vim" false :operator-precedence] 2086]
+[["clang" false :type-conversion] 753]
+[["clang" true :type-conversion] 460]
+[["linux" true :logic-as-control-flow] 63]
+[["linux" true :operator-precedence] 7246]
+[["subversion" true :conditional] 54]
+[["clang" true :post-increment] 130]
+[["gecko-dev" nil :omitted-curly-braces] 51]
+[["mongo" true :conditional] 229]
+[["gcc" true :assignment-as-value] 334]
+[["gcc" nil :omitted-curly-braces] 138]
+[["freebsd" false :comma-operator] 27431]
+[["webkit" true :assignment-as-value] 30]
+[["gecko-dev" nil :conditional] 77]
+[["git" true :post-increment] 16]
+[["mysql-server" true nil] 534013]
+[["subversion" true :operator-precedence] 73]
+[["linux" true :implicit-predicate] 2391]
+[["webkit" false :operator-precedence] 33551]
+[["freebsd" true :assignment-as-value] 1257]
+[["mysql-server" false :assignment-as-value] 7520]
+[["git" true :implicit-predicate] 32]
+[["git" false :macro-operator-precedence] 27]
+[["freebsd" false :operator-precedence] 219729]
+[["nginx" false :omitted-curly-braces] 1]
+[["gecko-dev" true nil] 1762118]
+[["httpd" true :omitted-curly-braces] 89]
+[["clang" false nil] 9534863]
+[["webkit" false :omitted-curly-braces] 68842]
+[["gecko-dev" true :logic-as-control-flow] 59]
+[["git" false :implicit-predicate] 2750]
+[["subversion" false :implicit-predicate] 386]
+[["clang" nil :type-conversion] 1]
+[["freebsd" nil :type-conversion] 4]
+[["nginx" false nil] 721857]
+[["vim" false nil] 595692]
+[["vim" false :logic-as-control-flow] 82]
+[["mongo" false :literal-encoding] 96]
+[["mysql-server" true :literal-encoding] 3]
+[["linux" false :post-increment] 20354]
+[["emacs" false :type-conversion] 368]
+[["linux" nil :post-increment] 2]
+[["mysql-server" true :implicit-predicate] 226]
+[["nginx" nil :comma-operator] 2]
+[["emacs" nil :assignment-as-value] 1]
+[["subversion" nil :comma-operator] 20]
+[["vim" nil :conditional] 3]
+[["clang" false :conditional] 4937]
+[["gcc" false :omitted-curly-braces] 172948]
+[["vim" true nil] 70797]
+[["httpd" nil :operator-precedence] 8]
+[["gcc" true :literal-encoding] 64]
+[["emacs" false :operator-precedence] 4279]
+[["gcc" false :type-conversion] 3824]
+[["linux" nil :assignment-as-value] 33]
+[["clang" true :operator-precedence] 828]
+[["mongo" nil :comma-operator] 601]
+[["vim" false :post-increment] 508]
+[["gecko-dev" false :post-increment] 9433]
+[["subversion" true :type-conversion] 1]
+[["linux" nil :pre-increment] 5]
+[["httpd" false :assignment-as-value] 1412]
+[["nginx" true :operator-precedence] 29]
+[["clang" nil :omitted-curly-braces] 19]
+[["gcc" true :conditional] 838]
+[["mongo" false :preprocessor-in-statement] 175]
+[["subversion" true :assignment-as-value] 9]
+[["mysql-server" true :conditional] 243]
+[["mysql-server" false :preprocessor-in-statement] 220]
+[["vim" true :post-increment] 91]
+[["mysql-server" true :type-conversion] 50]
+[["webkit" false :assignment-as-value] 1788]
+[["clang" false :comma-operator] 1760]
+[["webkit" true :logic-as-control-flow] 1]
+[["mysql-server" true :operator-precedence] 1112]
+[["mysql-server" nil :operator-precedence] 11]
+[["httpd" true nil] 38751]
+[["httpd" false :pre-increment] 124]
+[["mysql-server" true :assignment-as-value] 401]
+[["freebsd" false :type-conversion] 1849]
+[["gecko-dev" false :comma-operator] 11428]
+[["clang" false :pre-increment] 267]
+[["gcc" true :comma-operator] 306]
+[["mysql-server" false :type-conversion] 422]
+[["gcc" true :preprocessor-in-statement] 10]
+[["clang" nil :implicit-predicate] 19]
+[["linux" true :conditional] 856]
+[["mysql-server" true :omitted-curly-braces] 2145]
+[["httpd" nil :implicit-predicate] 38]
+[["gcc" false :pre-increment] 1746]
+[["mysql-server" nil :pre-increment] 1]
+[["freebsd" false :preprocessor-in-statement] 4528]
+[["linux" false :literal-encoding] 1142]
+[["gcc" false :preprocessor-in-statement] 1872]
+[["webkit" true :literal-encoding] 11]
+[["clang" false :assignment-as-value] 1167]
+[["emacs" true :type-conversion] 6]
+[["gcc" false :logic-as-control-flow] 952]
+[["linux" true :repurposed-variable] 705]
+[["git" false :repurposed-variable] 600]
+[["gecko-dev" true :pre-increment] 148]
+[["clang" nil :comma-operator] 7]
+[["mongo" true :omitted-curly-braces] 4132]
+[["mongo" false :macro-operator-precedence] 82]
+[["clang" nil :assignment-as-value] 1]
+[["freebsd" nil :omitted-curly-braces] 189]
+[["freebsd" true :literal-encoding] 113]
+[["gcc" true nil] 1077981]
+[["httpd" false :implicit-predicate] 1225]
+[["linux" nil :comma-operator] 1316]
+[["mongo" false :assignment-as-value] 3961]
+[["webkit" false :implicit-predicate] 3198]
+[["webkit" false :repurposed-variable] 2799]
+[["webkit" true :type-conversion] 16]
+[["webkit" nil :operator-precedence] 14]
+[["webkit" false :type-conversion] 613]
+[["mongo" true :logic-as-control-flow] 48]
+[["mysql-server" false :logic-as-control-flow] 684]
+[["gecko-dev" false :type-conversion] 1784]
+[["freebsd" false nil] 73872133]
+[["emacs" nil :implicit-predicate] 143]
+[["emacs" false nil] 1315213]
+[["gecko-dev" true :macro-operator-precedence] 99]
+[["gecko-dev" false :conditional] 22362]
+[["gecko-dev" false :literal-encoding] 336]
+[["mongo" true :preprocessor-in-statement] 11]
+[["clang" true :macro-operator-precedence] 7]
+[["nginx" true nil] 10951]
+[["freebsd" true :type-conversion] 119]
+[["nginx" false :conditional] 303]
+[["freebsd" false :implicit-predicate] 64049]
+[["nginx" false :repurposed-variable] 148]
+[["mongo" true :implicit-predicate] 137]
+[["gcc" true :reversed-subscript] 21]
+[["webkit" false :literal-encoding] 87]
+[["gecko-dev" nil :assignment-as-value] 14]
+[["mongo" false :repurposed-variable] 2570]
+[["webkit" true :conditional] 136]
+[["mysql-server" true :repurposed-variable] 162]
+[["httpd" true :conditional] 15]
+[["freebsd" nil :comma-operator] 1651]
+[["git" false :conditional] 1204]
+[["vim" true :repurposed-variable] 73]
+[["clang" true :omitted-curly-braces] 2257]
+[["httpd" true :assignment-as-value] 43]
+[["httpd" true :operator-precedence] 101]
+[["subversion" false :assignment-as-value] 456]
+[["httpd" nil :omitted-curly-braces] 1]
+[["git" false :omitted-curly-braces] 15205]
+[["linux" false :operator-precedence] 511708]
+[["emacs" false :macro-operator-precedence] 1]
+[["httpd" false :omitted-curly-braces] 2121]
+[["freebsd" true :reversed-subscript] 2]
+[["emacs" false :repurposed-variable] 959]
+[["nginx" true :pre-increment] 3]
+[["freebsd" true :post-increment] 1235]
+[["clang" false :repurposed-variable] 1717]
+[["mysql-server" true :macro-operator-precedence] 28]
+[["nginx" false :pre-increment] 78]
+[["nginx" false :assignment-as-value] 8]
+[["gecko-dev" false :repurposed-variable] 10486]
+[["gcc" true :omitted-curly-braces] 4702]
+[["emacs" false :omitted-curly-braces] 12245]
+[["mongo" false :post-increment] 2894]
+[["gcc" false :macro-operator-precedence] 16]
+[["vim" true :pre-increment] 19]
+[["nginx" false :logic-as-control-flow] 6]
+[["webkit" true :pre-increment] 42]
+[["clang" nil :operator-precedence] 1]
+[["vim" false :conditional] 571]
+[["webkit" false :pre-increment] 1158]
+[["mongo" false :comma-operator] 2768]
+[["gecko-dev" false :pre-increment] 2638]
+[["clang" true :implicit-predicate] 590]
+[["gecko-dev" nil :operator-precedence] 99]
+[["subversion" nil :conditional] 1]
+[["emacs" false :literal-encoding] 3]
+[["git" true nil] 27928]
+[["mongo" false nil] 12196722]
+[["gecko-dev" false :implicit-predicate] 11339]
+[["webkit" true :implicit-predicate] 58]
+[["subversion" false :operator-precedence] 4299]
+[["mongo" true :operator-precedence] 966]
+[["gcc" nil nil] 4]
+[["gecko-dev" true :post-increment] 675]
+[["subversion" nil :implicit-predicate] 57]
+[["emacs" false :comma-operator] 609]
+[["clang" false :macro-operator-precedence] 54]
+[["clang" true :conditional] 727]
+[["freebsd" nil :operator-precedence] 152]
+[["gecko-dev" false :operator-precedence] 95871]
+[["subversion" false :post-increment] 299]
+[["git" nil :comma-operator] 4]
+[["httpd" false :repurposed-variable] 117]
+[["freebsd" true :repurposed-variable] 939]
+[["freebsd" nil :conditional] 97]
+[["git" true :assignment-as-value] 24]
+[["gecko-dev" true :preprocessor-in-statement] 13]
+[["gcc" true :operator-precedence] 2279]
+[["clang" nil nil] 1]
+[["emacs" true :omitted-curly-braces] 386]
+[["mysql-server" false :implicit-predicate] 5481]
+[["mongo" true :repurposed-variable] 227]
+[["freebsd" false :repurposed-variable] 23331]
+[["gcc" true :repurposed-variable] 720]
+[["git" false :comma-operator] 182]
+[["webkit" true :comma-operator] 31]
+[["freebsd" true nil] 3223577]
+[["linux" nil :omitted-curly-braces] 80]
+[["gecko-dev" nil :comma-operator] 384]
+[["httpd" false :post-increment] 547]
+[["linux" nil :type-conversion] 1]
+[["mongo" false :logic-as-control-flow] 434]
+[["freebsd" true :pre-increment] 325]
+[["gecko-dev" true :operator-precedence] 2902]
+[["vim" true :assignment-as-value] 34]
+[["gcc" false :repurposed-variable] 13523]
+[["clang" false :omitted-curly-braces] 57280]
+[["mysql-server" false :omitted-curly-braces] 36712]
+[["clang" true :logic-as-control-flow] 28]
+[["subversion" true :preprocessor-in-statement] 1]
+[["subversion" false :repurposed-variable] 276]
+[["gecko-dev" nil :implicit-predicate] 1025]
+[["clang" false :reversed-subscript] 10]
+[["linux" nil :operator-precedence] 156]
+[["subversion" nil :omitted-curly-braces] 8]
+[["mysql-server" false :pre-increment] 775]
+[["httpd" false :operator-precedence] 2674]
+[["mongo" true :assignment-as-value] 192]
+[["git" nil :assignment-as-value] 1]
+[["mongo" false :omitted-curly-braces] 42598]
+[["nginx" false :comma-operator] 58]
+[["webkit" true nil] 377950]
+[["webkit" nil :conditional] 11]
+[["linux" false :logic-as-control-flow] 1723]
+[["vim" false :repurposed-variable] 269]
+[["gecko-dev" true :repurposed-variable] 470]
+[["httpd" nil :type-conversion] 1]
+[["nginx" true :comma-operator] 5]
+[["emacs" false :preprocessor-in-statement] 131]
+[["mysql-server" true :pre-increment] 70]
+[["clang" false :logic-as-control-flow] 65]
+[["vim" nil :implicit-predicate] 6]
+[["vim" false :pre-increment] 148]
+[["mongo" false :operator-precedence] 18343]
+[["nginx" false :post-increment] 633]
+[["subversion" false :conditional] 1707]
+[["vim" true :type-conversion] 3]
+[["subversion" nil :operator-precedence] 1]
+[["mysql-server" false :repurposed-variable] 1779]
+[["mysql-server" false :post-increment] 3726]
+[["gecko-dev" false :omitted-curly-braces] 110248]
+[["webkit" true :macro-operator-precedence] 6]
+[["httpd" true :pre-increment] 4]
+[["webkit" false :post-increment] 2405]
+[["httpd" false :logic-as-control-flow] 171]
+[["subversion" false :pre-increment] 86]
+[["gecko-dev" true :assignment-as-value] 315]
+[["vim" nil :omitted-curly-braces] 4]
+[["gcc" false nil] 32080162]
+[["vim" true :implicit-predicate] 114]
+[["linux" true :comma-operator] 161]
+[["webkit" false nil] 14781487]
+[["gcc" nil :assignment-as-value] 3]
+[["vim" false :omitted-curly-braces] 6584]
+[["freebsd" true :conditional] 1212]
+[["subversion" true :omitted-curly-braces] 254]
+[["emacs" nil :comma-operator] 2]
+[["freebsd" nil :post-increment] 4]
+[["clang" true :pre-increment] 145]
+[["clang" false :implicit-predicate] 1405]
+[["httpd" false :conditional] 1101]
+[["mysql-server" true :post-increment] 261]
+[["vim" true :preprocessor-in-statement] 18]
+[["linux" true :literal-encoding] 397]
+[["gcc" nil :implicit-predicate] 1407]
+[["subversion" false nil] 2658157]
+[["vim" true :omitted-curly-braces] 903]
+[["linux" true :preprocessor-in-statement] 13]
+[["linux" false :omitted-curly-braces] 549487]
+[["subversion" false :comma-operator] 89]
+[["emacs" false :conditional] 1481]
+[["freebsd" false :omitted-curly-braces] 494893]
+[["subversion" true :implicit-predicate] 14]
+[["freebsd" false :pre-increment] 7622]
+[["git" true :comma-operator] 4]
+[["nginx" true :repurposed-variable] 2]
+[["emacs" true :operator-precedence] 157]
+[["linux" true :post-increment] 1720]
+[["emacs" true :logic-as-control-flow] 21]
+[["linux" false :conditional] 42039]
+[["clang" false :literal-encoding] 16]
+[["gcc" true :pre-increment] 82]
+[["subversion" true nil] 52210]
+[["nginx" true :conditional] 2]
+[["linux" true :type-conversion] 324]
+[["freebsd" true :preprocessor-in-statement] 94]
+[["subversion" true :post-increment] 17]
+[["linux" false :implicit-predicate] 130192]
+[["mongo" false :conditional] 5679]
+[["linux" nil :conditional] 54]
+[["vim" false :implicit-predicate] 963]
+[["gecko-dev" false :preprocessor-in-statement] 1284]
+[["emacs" true :repurposed-variable] 25]
+[["mongo" nil :implicit-predicate] 224]
+[["emacs" false :post-increment] 741]
+[["mysql-server" nil :conditional] 2]
+[["linux" true nil] 3138913]
+[["freebsd" nil :pre-increment] 5]
+[["clang" false :post-increment] 606]
+[["gecko-dev" true :omitted-curly-braces] 5129]
+[["gecko-dev" true :comma-operator] 270]
+[["freebsd" nil :assignment-as-value] 45]
+[["httpd" false nil] 991826]
+[["subversion" false :logic-as-control-flow] 24]
+[["mongo" nil :omitted-curly-braces] 22]
+[["nginx" true :assignment-as-value] 4]
+[["subversion" true :pre-increment] 1]
+[["mongo" true :post-increment] 237]
+[["linux" true :pre-increment] 175]
+[["mysql-server" false :conditional] 6150]
+[["gcc" false :literal-encoding] 979]
+[["vim" false :type-conversion] 5]
+[["linux" false :pre-increment] 5211]
+[["gcc" nil :conditional] 17]
+[["nginx" true :post-increment] 8]
+[["git" true :operator-precedence] 138]
+[["emacs" true :pre-increment] 11]
+[["mysql-server" true :comma-operator] 130]
+[["vim" true :conditional] 31]
+[["httpd" true :logic-as-control-flow] 3]
+[["httpd" true :comma-operator] 7]
+[["mysql-server" false :literal-encoding] 13]
+[["httpd" false :type-conversion] 26]
+[["vim" false :comma-operator] 41]
+[["vim" true :logic-as-control-flow] 3]
+[["git" false :operator-precedence] 6348]
+[["emacs" true :conditional] 24]
+[["freebsd" true :operator-precedence] 7183]
+[["mysql-server" false :comma-operator] 4491]
+[["gcc" false :post-increment] 8406]
+[["emacs" true :post-increment] 47]
+[["nginx" false :implicit-predicate] 50]
+[["httpd" false :preprocessor-in-statement] 29]
+[["mysql-server" nil :assignment-as-value] 6]
+[["gecko-dev" true :literal-encoding] 47]
+[["git" nil :conditional] 1]
+[["linux" false :macro-operator-precedence] 414]
+[["mysql-server" nil :implicit-predicate] 339]
+[["git" true :type-conversion] 1]
+[["gcc" false :comma-operator] 4485]
+[["freebsd" true :logic-as-control-flow] 129]
+[["gcc" false :implicit-predicate] 40272]
+[["freebsd" false :assignment-as-value] 40837]
+[["linux" false nil] 76927576]
+[["vim" false :preprocessor-in-statement] 123]
+[["gcc" false :conditional] 14497]
+[["httpd" true :repurposed-variable] 3]
+[["freebsd" true :omitted-curly-braces] 14272]
+[["gcc" false :operator-precedence] 57360]
+[["mysql-server" false nil] 9280437]
+[["git" true :conditional] 5]
+[["httpd" true :type-conversion] 6]
+[["mysql-server" true :preprocessor-in-statement] 10]
+[["linux" false :preprocessor-in-statement] 2228]
+[["linux" nil :implicit-predicate] 4768]
+[["gecko-dev" nil :pre-increment] 2]
+[["gcc" true :post-increment] 388]
+[["clang" true :literal-encoding] 2]
+[["mongo" false :implicit-predicate] 1601]
+[["webkit" false :preprocessor-in-statement] 239]
+[["gcc" true :logic-as-control-flow] 18]
+[["clang" true :assignment-as-value] 219]
+[["emacs" true :assignment-as-value] 32]
+[["vim" nil :operator-precedence] 3]
+[["mysql-server" nil :comma-operator] 60]
+[["freebsd" true :macro-operator-precedence] 9]
+[["git" false :pre-increment] 209]
+[["webkit" false :conditional] 9431]
+[["mongo" true :pre-increment] 68]
+[["clang" true nil] 602826]
+[["git" true :omitted-curly-braces] 332]
+[["clang" true :repurposed-variable] 480]
+[["webkit" false :logic-as-control-flow] 133]
+[["linux" false :assignment-as-value] 16448]
+[["httpd" nil :comma-operator] 17]
+[["git" nil :implicit-predicate] 37]
+[["mongo" true :type-conversion] 25]
+[["git" false :type-conversion] 7]
+[["httpd" true :preprocessor-in-statement] 1]
+[["clang" false :preprocessor-in-statement] 659]
+[["mongo" true :comma-operator] 112]
+[["subversion" false :type-conversion] 6]
+[["mongo" true :literal-encoding] 96]
+[["webkit" nil :comma-operator] 1290]
+[["git" false nil] 1158478]
+[["freebsd" nil :implicit-predicate] 4432]
+[["linux" true :omitted-curly-braces] 10415]
+[["webkit" true :post-increment] 82]
+[["mongo" false :pre-increment] 2340]
+[["freebsd" false :post-increment] 21425]
+[["httpd" false :comma-operator] 123]
+[["emacs" false :implicit-predicate] 1446]
+[["clang" true :reversed-subscript] 5]
+[["subversion" false :omitted-curly-braces] 14046]
+[["webkit" true :operator-precedence] 676]
+[["git" true :pre-increment] 6]
+[["gecko-dev" nil nil] 1]
+[["subversion" true :repurposed-variable] 11]
+[["git" true :logic-as-control-flow] 7]
+[["linux" true :assignment-as-value] 525]
+[["vim" false :reversed-subscript] 2]
+[["webkit" true :repurposed-variable] 78]
+[["emacs" false :assignment-as-value] 933]
+[["gcc" nil :type-conversion] 2]
+[["gcc" true :type-conversion] 524]
+[["mongo" false :type-conversion] 257]
+[["emacs" false :pre-increment] 194]
+[["gcc" true :implicit-predicate] 1913]
+[["linux" false :repurposed-variable] 20676]
+[["nginx" false :operator-precedence] 3390]
+[["vim" nil :comma-operator] 2]
+[["git" true :repurposed-variable] 12]
+[["emacs" false :logic-as-control-flow] 276]
+[["emacs" true nil] 40839]
+[["mysql-server" false :operator-precedence] 21603]
+[["vim" true :operator-precedence] 200]
+[["clang" true :comma-operator] 202]
+[["gecko-dev" true :type-conversion] 219]
+[["webkit" false :comma-operator] 3757]
+[["git" false :post-increment] 736]
+[["gecko-dev" false :macro-operator-precedence] 1034]
+[["emacs" true :comma-operator] 22]
+[["mongo" nil :conditional] 3]
+[["subversion" false :preprocessor-in-statement] 67]
+[["mongo" nil :pre-increment] 1]
+[["clang" true :preprocessor-in-statement] 6]
+[["webkit" nil :omitted-curly-braces] 22]
+[["webkit" nil :implicit-predicate] 346]
+[["linux" true :macro-operator-precedence] 80]
+[["gcc" false :reversed-subscript] 11]
+[["gcc" true :macro-operator-precedence] 3]
+[["mysql-server" nil :omitted-curly-braces] 21]
+[["freebsd" false :conditional] 40183]
+[["mongo" nil :post-increment] 4]
+[["git" false :assignment-as-value] 688]
+[["httpd" true :macro-operator-precedence] 3]
+[["gecko-dev" false nil] 41693628]
+[["nginx" true :logic-as-control-flow] 1]
+[["gecko-dev" true :conditional] 710]
+[["freebsd" false :literal-encoding] 455]
+[["freebsd" true :implicit-predicate] 1979]
+[["gcc" nil :comma-operator] 172]
+[["git" false :logic-as-control-flow] 97]
+[["freebsd" true :comma-operator] 879]
+[["gecko-dev" true :implicit-predicate] 423]
+[["webkit" false :macro-operator-precedence] 356]
+[["gecko-dev" false :logic-as-control-flow] 846]
+[["clang" nil :conditional] 7]
+[["mongo" true :macro-operator-precedence] 5]
+[["webkit" true :omitted-curly-braces] 876]
+[["git" false :preprocessor-in-statement] 13]
+[["freebsd" false :macro-operator-precedence] 1350]
+[["httpd" true :implicit-predicate] 56]
+[["mysql-server" false :macro-operator-precedence] 367]
+[["emacs" true :implicit-predicate] 64]
+[["linux" false :comma-operator] 7484]
+[["vim" false :assignment-as-value] 433]
+[["gecko-dev" false :assignment-as-value] 10704]
 ]

- (map #(update-in % [0 0] boolean))
+ (map #(update-in % [0 1] boolean))
  (map (partial apply array-map))
  (apply merge-with +)
- (map (fn [[[comment atom] count]] {:comment comment :atom (when atom (name atom)) :count count}))
- (maps-to-csv "comment-summary_2017-12-31.csv")
+ (map (fn [[[project comment atom] count]] {:project project :comment comment :atom (when atom (name atom)) :count count}))
+ (maps-to-csv "comment-summary-projects_2018-01-02.csv")

  )


small fixes to partitioned select logic

small fixes to partitioned select logic

--- src/clj_money/models/storage/sql_storage.clj
+++ src/clj_money/models/storage/sql_storage.clj
@@ -245,10 +245,10 @@
      (->> tables#
           (map keyword)
           (reduce (fn [records# table#]
-                    (let [sql# (-> table#
-                                   sql-fn#
-                                   sql/format)
-                          updated-records# (concat records# (query ~db-spec sql#))]
+                    (let [updated-records# (->> table#
+                                                sql-fn#
+                                                (query ~db-spec)
+                                                (concat records#))]
                       (if (and (= 1 (:limit ~options))
                                (seq updated-records#))
                         (reduced updated-records#)
@@ -350,10 +350,10 @@
   [storage range-value]
   (if (sequential? range-value)
     (-> range-value
-        rest
-        (update-in [0] #(or % (.get-setting storage
+        (update-in [1] #(or % (.get-setting storage
                                             "earliest-partition-date"
-                                            (fnil read-string "#local-date \"2000-01-01\"")))))
+                                            (fnil read-string "#local-date \"2000-01-01\""))))
+        rest)
     [range-value range-value]))

 (deftype SqlStorage [db-spec]
@@ -588,7 +588,7 @@
             (merge-where-range :trade-date d-range)
             (append-sort options)
             (append-limit options)
-            (append-paging options)))))
+            #_(append-paging options))))) ; paging will have to be reworked

   (update-price
     [_ price]


White space fix

White space fix

--- src/cljs/mdr2/productions/in_production.cljs
+++ src/cljs/mdr2/productions/in_production.cljs
@@ -31,7 +31,7 @@
  ::fetch-productions-success
  (fn [db [_ productions]]
    (let [productions (->> productions
-                    (map #(assoc % :uuid (str (random-uuid)))))
+                          (map #(assoc % :uuid (str (random-uuid)))))
          next? (-> productions count (= pagination/page-size))]
      (-> db
          (assoc-in [:productions :in-production] (zipmap (map :uuid productions) productions))


Retain sent-block state changes (WIP)

Retain sent-block state changes (WIP)

Especially things like the transmission count and time.

Not tested.

--- src/clojure/frereth_cp/message/to_parent.clj
+++ src/clojure/frereth_cp/message/to_parent.clj
@@ -167,7 +167,8 @@
             ::specs/un-ackd-blocks]
      :as outgoing} ::specs/outgoing
     :keys [::specs/message-loop-name]
-    :as state}]
+    :as state}
+   updated-block]
   (assert (= ::specs/un-sent-blocks
              (::specs/next-block-queue outgoing)))
   (let [block-to-move (peek un-sent-blocks)]
@@ -181,12 +182,31 @@
                     ")\nfrom\n"
                     un-sent-blocks
                     "\nto\n"
-                    un-ackd-blocks))
+                    un-ackd-blocks
+                    "\nas\n"
+                    updated-block))
     (-> state
-        ;; Since I'm having issues with this, it seems worth mentioning that
+        ;; Since I've had issues with this, it seems worth mentioning that
         ;; this is a sorted-set (by specs/time)
-        (update-in [::specs/outgoing ::specs/un-ackd-blocks] conj block-to-move)
+        (update-in [::specs/outgoing ::specs/un-ackd-blocks] conj updated-block)
         (update-in [::specs/outgoing ::specs/un-sent-blocks] pop))))
+
+(s/fdef mark-block-resent
+        :args (s/cat :state ::specs/state
+                     :updated-block ::specs/block)
+        :ret ::specs/state)
+(defn mark-block-resent
+  [{:keys [::specs/message-loop-name
+           ::specs/outgoing]
+    :as state}
+   updated-block]
+  (log/debug (str message-loop-name ": Resending a block"))
+  (assert (= ::specs/un-ackd-blocks
+             (::specs/next-block-queue outgoing)))
+  (update-in state
+             [::specs/outgoing ::specs/un-ackd-blocks]
+             (fn [cur]
+               (conj (pop cur) updated-block))))

 (s/fdef pre-calculate-state-after-send
         :args (s/cat :state ::specs/state)
@@ -201,7 +221,7 @@
      :as outgoing} ::specs/outgoing
     :as state}]
   ;; Really just for timing info
-  (log/debug (str message-loop-name ": top of pre-calculate ofter-send"))
+  (log/debug (str message-loop-name ": top of pre-calculate after-send"))
   (assert next-block-queue
           (str message-loop-name
                ": No next-block-queue to tell us what to send\nAvailable:\n"
@@ -221,6 +241,13 @@
 ;;;                len/16 byte.
 ;;;                So everything else is shifted right by 8 bytes
   (let [q (get-in state [::specs/outgoing next-block-queue])]
+    (log/debug (str message-loop-name
+                    ": Next message should come from "
+                    (count q)
+                    " block(s) in\n"
+                    next-block-queue
+                    "\ninside\n"
+                    (::specs/outgoing state)))
     (let [transmission-count (-> q
                                  peek
                                  ::specs/transmissions)]
@@ -228,13 +255,6 @@
               (str message-loop-name
                    ": Missing ::transmissions under "
                    next-block-queue)))
-    (log/debug (str message-loop-name
-                    ": Next message should come from "
-                    (count q)
-                    " blocks in\n"
-                    next-block-queue
-                    "\ninside\n"
-                    (::specs/outgoing state)))
     (let [next-message-id (let [n' (inc current-message-id)]
                             ;; Stupid unsigned math
                             ;; Actually, this seems even more problematic
@@ -256,6 +276,13 @@
       ;; un-ackd queue.
       ;; But that's an operation to handle elsewhere.
       (assert current-message)
+      ;; It's tempting to try to re-use a previously sent message ID for a re-send.
+      ;; After all, if I send message 39, then resend it as message 50, then get
+      ;; an ACK for message 39, the only way I have to correlate that to message
+      ;; 50 is the stream address.
+      ;; Which should be good enough.
+      ;; And this seems like a better way to debug messages on the wire.
+      ;; And this is the way the reference implementation works.
       (let [state' (assoc-in state [::specs/outgoing ::specs/next-message-id] next-message-id)
             updated-message (-> current-message
                                 (update ::specs/transmissions inc)
@@ -266,7 +293,7 @@
                         current-message-id
                         "\nbased on:\n")
                    (utils/pretty current-message))
-        (let [buf (build-message-block current-message-id current-message)
+        (let [buf (build-message-block current-message-id updated-message)
               ;; Reference implementation waits until after the actual write before setting any of
               ;; the next pieces. But it's a single-threaded process that's going to block at the write,
               ;; and this part's purely functional anyway. So it should be safe enough to set up
@@ -281,20 +308,19 @@
                                       ;; TODO: Track down everywhere it's used and think
                                       ;; about it.
                                       ::specs/last-block-time recent
-                                      ;; Q: Am I still using this?
+                                      ;; Q: How wise is this approach?
                                       ::specs/send-buf buf
                                       ::specs/want-ping false)))]
           (log/debug (str message-loop-name
                           ": Next block built and stats updated"))
           ;; It's tempting to split this part up to avoid the conditional.
           ;; Maybe turn the call into a multimethod.
-          ;; The latter would be a terrible mistake, since there are
-          ;; really only 2 possibilities. But this does smell.
+          ;; The latter would be a mistake, since there are
+          ;; really only 2 possibilities (I'm sending a new block or
+          ;; resending one that had its ACK timeout)
           (if (= ::specs/un-sent-blocks next-block-queue)
-            (mark-block-sent result)
-            (do
-              (log/debug (str message-loop-name ": Resending a block"))
-              result)))))))
+            (mark-block-sent result updated-message)
+            (mark-block-resent result updated-message)))))))

 (s/fdef check-for-previous-block-to-resend
         :args ::specs/state
@@ -325,10 +351,10 @@
   (assert earliest-time (str "Missing earliest-time among " (keys outgoing)))
   (log/debug (str message-loop-name ": Checking for a block to resend"))
   (if (and (not= 0 earliest-time)
-             (< recent (+ earliest-time n-sec-per-block))
-             (>= recent (+ earliest-time rtt-timeout)))
+           (< recent (+ earliest-time n-sec-per-block))
+           (>= recent (+ earliest-time rtt-timeout)))
     (do
-      (log/debug (str message-loop-name ": It's been long enough to justify resending"))
+      (log/debug (str message-loop-name ": It has been long enough to justify resending"))
       ;; This gets us to line 344
       ;; It finds the first block that matches earliest-time
       ;; It's going to re-send that block (it *does* exist...right?)
@@ -355,7 +381,11 @@
                       ": Hasn't been long enough to justify"
                       " resending any of our "
                       (count un-ackd-blocks)
-                      " previously sent un-ack'd blocks"))
+                      " previously sent un-ack'd blocks, based on"
+                      "\nEarliest time: " earliest-time
+                      "\nnanoseconds per block: " n-sec-per-block
+                      "\nrtt-timeout: " rtt-timeout
+                      "\nrecent: " recent))
       nil)))

 (s/fdef check-for-new-block-to-send


Dispatch input events + code cleanup.

Dispatch input events + code cleanup.

--- src/fm/simrunner/app.clj
+++ src/fm/simrunner/app.clj
@@ -8,7 +8,9 @@
     [fm.simrunner (config :as config)]
     [fm.simrunner.gui (core :as gui)
                       (view :as view)
-                      (wiring :as wiring)]))
+                      (wiring :as wiring)])
+  (:import
+    (javax.swing JOptionPane)))

 (defn- lock [app-state]
   (update-in app-state [:ui :model :locked] inc))
@@ -23,8 +25,6 @@
 (defn- unlock! [{app-state :state}]
   (swap! app-state unlock))

-(defmulti on-action {:private true} (fn [action & _] action))
-
 (defn- run-task [{worker :worker :as app} task & args]
   (send-off worker
             (fn [_ &]
@@ -33,26 +33,82 @@
                 nil
                 (finally (unlock! app))))))

-(defn- open-config [app file]
-  (println (config/read-config-file file)))
+(defn- start-rendering [app-state]
+  (assoc-in app-state [:ui :model :rendering?] true))

-(defmethod on-action :open-config [_ app & args]
-  (if-let [file (gui/choose-file (-> args first :widget) :title "Open Config")]
-    (run-task app open-config file)
+(defn- start-rendering! [{app-state :state}]
+  (when (-> @app-state :ui :model :dirty?)
+    (swap! app-state start-rendering)))
+
+(defn- stop-rendering [app-state]
+  (-> app-state
+      (assoc-in [:ui :model :rendering?] false)
+      (assoc-in [:ui :model :dirty?] false)))
+
+(defn- stop-rendering! [{app-state :state}]
+  (when (-> @app-state :ui :model :rendering?)
+    (swap! app-state stop-rendering)))
+
+(defn render [app]
+  (gui/gui-do
+    (when (start-rendering! app)
+      (try
+        (let [{:keys [view model]} (-> app :state deref :ui)]
+          (io! "Do not update the ui in a transaction!"
+            (view/render view (:inputs model))))
+        (finally
+          (stop-rendering! app))))))
+
+(defn- open-config [{app-state :state :as app} widget file]
+  (let [config (config/read-config-file file)]
+    (if (config/valid? config)
+      (do
+        (swap! app-state #(-> %
+                              (assoc-in [:ui :model :inputs :eps] "Mausi")
+                              (assoc-in [:ui :model :dirty?] true)))
+        (render app))
+      @(gui/gui-do
+        (JOptionPane/showMessageDialog (:widget widget)
+                                       "The selected config file is not valid."
+                                       "Open Config"
+                                       JOptionPane/ERROR_MESSAGE)))))
+
+(defmulti on-action {:private true} (fn [action & _] action))
+
+(defmethod on-action :open-config [_ app & [widget]]
+  (if-let [file (gui/choose-file (:widget widget) :title "Open Config")]
+    (run-task app open-config widget file)
     (unlock! app)))

 (defmethod on-action :default [action app & args]
   (println (format "on-action{action: %s args: %s}" action args))
   (unlock! app))

-(defmulti on-event {:private true} (fn [_ event-id & _] event-id))
-
 (defn- dispatch-action [action app args]
   (when (lock! app)
     (apply on-action action app args)))

+(defmulti on-input {:private true} (fn [id & _] id))
+
+(defmethod on-input :default [id app & args]
+  (println (format "on-input{id: %s args: %s}" id args)))
+
+(defn- handle-input? [{app-state :state}]
+  (let [model (-> @app-state :ui :model)]
+    (and (not (:locked? model))
+         (not (:rendering? model)))))
+
+(defn- input-changed [id app args]
+  (when (handle-input? app)
+    (apply on-input id app args)))
+
+(defmulti on-event {:private true} (fn [_ event-id & _] event-id))
+
 (defmethod on-event :action-performed [app _ & args]
   (dispatch-action (-> args first meta :action) app args))
+
+(defmethod on-event :input-changed [app _ & args]
+  (input-changed (-> args first meta :id) app args))

 (defmethod on-event :default [app event-id & args]
   (println (format "on-event{id: %s args: %s}" event-id args)))
@@ -81,27 +137,3 @@
       (.setTitle frame "SimRunner (c) 2014 DEINC")
       (.show frame))))

-(defn- start-rendering [app-state]
-  (assoc-in app-state [:ui :model :rendering?] true))
-
-(defn- start-rendering! [{app-state :state}]
-  (when (-> @app-state :ui :model :dirty?)
-    (swap! app-state start-rendering)))
-
-(defn- stop-rendering [app-state]
-  (-> app-state
-      (assoc-in [:ui :model :rendering?] false)
-      (assoc-in [:ui :model :dirty?] false)))
-
-(defn- stop-rendering! [{app-state :state}]
-  (when (-> @app-state :ui :model :rendering?)
-    (swap! app-state stop-rendering)))
-
-(defn render [app]
-  (gui/gui-do
-    (when (start-rendering! app)
-      (try
-        (io! "Do not update the ui in a transaction!")
-        (finally
-          (stop-rendering! app))))))
-


implement as-time-since

implement as-time-since

--- frontend/datetime.cljs
+++ frontend/datetime.cljs
@@ -1,5 +1,7 @@
 (ns frontend.datetime
   (:require [frontend.utils :as utils :include-macros true]
+            [cljs-time.coerce :refer [from-long]]
+            [cljs-time.format :as time-format]
             [goog.string :as g-string]
             goog.string.format
             [goog.i18n.DateTimeFormat.Format :as date-formats]))
@@ -143,3 +145,14 @@
       (if (pos? hours)
         (g-string/format "%s:%s:%s" hours display-minutes display-seconds)
         (g-string/format "%s:%s" display-minutes display-seconds)))))
+
+(defn as-time-since [date-string]
+  (let [time (.getTime (js/Date. date-string))
+        now (.getTime (js/Date.))
+        ago (.floor js/Math (/ (- now time) 1000))]
+    (cond (< ago minute) "just now"
+          (< ago hour) (str ago "m ago")
+          (< ago day) (time-format/unparse (time-format/formatter "h:mma") (from-long time))
+          (< ago (* 2 day)) "yesterday"
+          (< ago year) (time-format/unparse (time-format/formatter "MMM d") (from-long time))
+          :else (time-format/unparse (time-format/formatter "MMM yyyy") (from-long time)))))


[trees] Add better tests of tree namespace. (#93)

--- cortex/test/cljc/cortex/tree_test.cljc
+++ cortex/test/cljc/cortex/tree_test.cljc
@@ -12,13 +12,17 @@
 (def X (mat/matrix (map drop-last IRISES)))
 (def Y (mat/matrix (map last IRISES)))

-(defn iris-tree-test
+(deftest tree-classify-test
   []
-  (let [tree (tree/decision-tree X Y {:split-fn tree/rand-splitter})]
-    tree))
+  (let [tree (tree/decision-tree X Y {:split-fn tree/best-splitter})
+        sample (first IRISES)
+        classification (tree/tree-classify tree (butlast sample))]
+    (is (= classification (last sample)))))

-(defn iris-forest-test
+(deftest forest-classify-test
   []
   (let [forest (tree/random-forest X Y {:n-trees 100
-                                        :split-fn tree/best-splitter})]
-    forest))
+                                        :split-fn tree/best-splitter})
+        sample (first IRISES)
+        classification (tree/forest-classify forest (butlast sample))]
+    (is (= classification (last sample)))))


More experiments with the way data is enqueued.

--- src/dsbdp/local_data_processing_pipeline.clj
+++ src/dsbdp/local_data_processing_pipeline.clj
@@ -35,7 +35,7 @@
 ;                  "ArrayBlockingQueue_add-counted-yield_remove-yield"))]
 ;                  "ArrayBlockingQueue_add-counted_remove"))]
 ;                  "LinkedBlockingQueue_add-counted_remove"))]
-                  "OneToOneConcurrentArrayQueue3_add-counted-yield_remove-yield"))]
+;                  "OneToOneConcurrentArrayQueue3_add-counted-yield_remove-yield"))]
 ;                  "OneToOneConcurrentArrayQueue3_add-counted_remove-yield"))]
 ;                  "OneToOneConcurrentArrayQueue3_add-counted_remove"))]
 ;                  "ArrayBlockingQueue_offer-counted"))]
@@ -43,7 +43,7 @@
 ;                  "LinkedTransferQueue_transfer"))]
 ;                  "LinkedTransferQueue_tryTransfer-counted-no-timeout"))]
 ;                  "LinkedTransferQueue_transfer-counted-yield"))]
-;                  "LinkedTransferQueue_tryTransfer-counted-10ms"))]
+                  "LinkedTransferQueue_tryTransfer-counted-10ms"))]
     (println "Using queue-setup:" setup)
     setup))

@@ -75,6 +75,8 @@
                                   (.add ~queue ~data)
                                   (.inc ~enqueued-counter))
                                 (.inc ~dropped-counter))
+               "add" `(if (< (.size ~queue) queue-size)
+                        (.add ~queue ~data))
                "put-counted-yield" `(if (< (.size ~queue) queue-size)
                                       (do
                                         (.put ~queue ~data)


Add experimental fill-when function

Add experimental fill-when function

--- src/grafter/sequences.clj
+++ src/grafter/sequences.clj
@@ -1,5 +1,6 @@
 (ns grafter.sequences
-  "A library of useful lazy sequences.")
+  "A library of useful lazy sequences."
+  (:require [clojure.string :refer [blank? split]]))

 (defn integers-from
   "Returns an infinite sequence of integers counting from the supplied
@@ -36,3 +37,28 @@
   ... ZZZA ... etc"
   []
   (column-names-seq "abcdefghijklmnopqrstuvwxyz"))
+
+(defn fill-when
+  "EXPERIMENTAL FUNCTION:
+
+  Takes a sequence of values and copies a
+  value through the sequence depending on the supplied predicate
+  function.
+
+  The default predicate function is not-blank? which means that a cell
+  will be copied through the sequence over blank cells until the next
+  non-blank one.  For example:
+
+  (fill-when [:a \"\" \" \" :b nil nil nil]) ; => (:a :a :a :b :b :b :b)
+
+  A start value to copy can also be provided as the 3rd argument.
+"
+  ([col] (fill-when (complement blank?) col))
+  ([p col]
+     (fill-when p col (first col)))
+  ([p col start]
+     (when (seq col)
+       (let [f (first col)]
+         (if (p f)
+           (cons f (lazy-seq (fill-when p (next col) f)))
+           (cons start (lazy-seq (fill-when p (next col) start))))))))


Change core module to use multiplication.

Change the code module function `hello-world.core/foo` to multiply its
arguments instead of adding them. By requiring the namespace with the
:reload option, it reloads the namespace allowing us afterward to invoke
the **changed** version of `hello-world.core/foo` in th REPL connected
to our browser.

In addition, the default source map allows the browser and other tools
to report errors against the original ClojureScript instead of the
generated JavaScript.

--- src/hello_world/core.cljs
+++ src/hello_world/core.cljs
@@ -10,6 +10,5 @@
 (enable-console-print!)
 (println "Hello ClojureScript QuickStart!")

-;; ADDED
 (defn foo [a b]
-  (+ a b))
+  (* a b)) ;; CHANGED


Four functions to export products, chapters, groups, and components to selected output format

--- src/hurvinek/exporter.clj
+++ src/hurvinek/exporter.clj
@@ -131,3 +131,43 @@
                      (for [component components]
                           [(:id component) (:name component)]))))

+(defn product-output-data
+    "Export product list into selected output format."
+    [output-format product-list]
+    (case output-format
+        :json (data->json     product-list)
+        :txt  (products->text product-list)
+        :xml  (products->xml  product-list)
+        :csv  (products->csv  product-list)
+        :edn  (data->edn      product-list)))
+
+(defn chapters-output-data
+    "Export chapter list into selected output format."
+    [output-format chapter-list]
+    (case output-format
+        :json (data->json     chapter-list)
+        :txt  (chapters->text chapter-list)
+        :xml  (chapters->xml  chapter-list)
+        :csv  (chapters->csv  chapter-list)
+        :edn  (data->edn      chapter-list)))
+
+(defn groups-output-data
+    "Export group list into selected output format."
+    [output-format group-list]
+    (case output-format
+        :json (data->json     group-list)
+        :txt  (groups->text   group-list)
+        :xml  (groups->xml    group-list)
+        :csv  (groups->csv    group-list)
+        :edn  (data->edn      group-list)))
+
+(defn components-output-data
+    "Export component list into selected output format."
+    [output-format component-list]
+    (case output-format
+        :json (data->json        component-list)
+        :txt  (components->text  component-list)
+        :xml  (components->xml   component-list)
+        :csv  (components->csv   component-list)
+        :edn  (data->edn         component-list)))
+


fix: parallel check in init dataset

fix: parallel check in init dataset

--- src/main/clojure/pdok/featured/geoserver.clj
+++ src/main/clojure/pdok/featured/geoserver.clj
@@ -228,7 +228,8 @@
           flush-fn (make-flush-fn inited)
           ready (assoc inited :flush-fn flush-fn)]
       (when (not (gs-dataset-exists? ready))
-        (gs-create-dataset ready))
+        (checked (gs-create-dataset ready)
+                 (gs-dataset-exists? ready)))
       ready))
   (proj/new-collection [this collection parent-collection])
   (proj/flush [this]