Query tests

Query tests

--- iwaswhere-web/test/iwaswhere_web/store_query_test.clj
+++ iwaswhere-web/test/iwaswhere_web/store_query_test.clj
@@ -3,12 +3,7 @@
   (:require [clojure.test :refer [deftest testing is]]
             [iwaswhere-web.files :as f]
             [iwaswhere-web.store-test :as st]
-            [iwaswhere-web.graph :as g]
-            [me.raynes.fs :as fs]
-            [iwaswhere-web.files :as f]
-            [clojure.set :as set]
-            [iwaswhere-web.store :as s]
-            [clojure.pprint :as pp]))
+            [iwaswhere-web.store :as s]))

 (def simple-query
   {:search-text ""
@@ -19,37 +14,141 @@
    :timestamp   nil
    :n           40})

-(def task-done-query
+(def no-results-query
+  {:search-text "some #not-existing-tag"
+   :tags        #{"#not-existing-tag"}
+   :not-tags    #{}
+   :mentions    #{}
+   :date-string nil
+   :timestamp   nil
+   :n           40})
+
+(def tasks-query
+  (merge simple-query
+         {:search-text "#task"
+          :tags        #{"#task"}}))
+
+(def tasks-done-query
   (merge simple-query
          {:search-text "#task #done"
           :tags        #{"#task" "#done"}}))

-(def task-not-done-query
+(def tasks-not-done-query
   (merge simple-query
          {:search-text "#task ~#done ~#backlog"
           :tags        #{"#task"}
           :not-tags    #{"~#done" "~#backlog"}}))

+(def test-entries
+  [{:mentions  #{}
+    :tags      #{"#task"}
+    :timestamp 1450998000000
+    :md        "Some #task"}
+   {:mentions  #{}
+    :tags      #{"#task"}
+    :timestamp 1450998100000
+    :md        "Some other #task"}
+   {:mentions  #{}
+    :tags      #{"#task" "#done"}
+    :timestamp 1450998200000
+    :md        "Some other #task #done"}
+   {:mentions  #{}
+    :tags      #{"#task" "#completed" "#done"}
+    :timestamp 1450998300000
+    :md        "Yet another completed #task - #done"}
+   {:mentions  #{}
+    :tags      #{"#task" "#completed" "#done"}
+    :timestamp 1450998400000
+    :md        "And yet another completed #task - #done"}])
+
+(defn persist-reducer
+  "Reducing function for adding entries to component state."
+  [acc entry]
+  (:new-state (f/geo-entry-persist-fn {:current-state acc
+                                       :msg-payload   entry})))
+
+(defn extract-query-res
+  "Extracts entries from query result as returned by publish-state-fn."
+  [current-state client-id]
+  (-> (s/publish-state-fn {:current-state current-state
+                           :msg-payload   {:sente-uid client-id}})
+      :emit-msgs  ; get published messages
+      first       ; first msg
+      second      ; msg-payload
+      :entries))
+
+(defn add-query
+  "Adds query to state, returns new state."
+  [current-state query client-id]
+  (:new-state (s/state-get-fn {:current-state current-state
+                               :msg-payload   query
+                               :msg-meta      {:sente-uid client-id}})))
+
 (deftest query-test
-  ""
+  "Test that different queries return the expected results."
   (let [test-ts (System/currentTimeMillis)
-        {:keys [current-state]} (st/mk-test-state test-ts)
-        sente-uid1 (str (java.util.UUID/randomUUID))
-        sente-uid2 (str (java.util.UUID/randomUUID))
-        sente-uid3 (str (java.util.UUID/randomUUID))
-        w-query-1 (:new-state (s/state-get-fn {:current-state current-state
-                                               :msg-payload   simple-query
-                                               :msg-meta      {:sente-uid sente-uid1}}))
-        w-query-2 (:new-state (s/state-get-fn {:current-state w-query-1
-                                               :msg-payload   task-done-query
-                                               :msg-meta      {:sente-uid sente-uid2}}))
-        w-query-3 (:new-state (s/state-get-fn {:current-state w-query-2
-                                               :msg-payload   task-not-done-query
-                                               :msg-meta      {:sente-uid sente-uid3}}))
-        client-queries (:client-queries w-query-3)]
-    (testing "client queries associated with proper connection IDs"
-      (is (= (get client-queries sente-uid1) simple-query))
-      (is (= (get client-queries sente-uid2) task-done-query)))
-    (testing "client queries with not-tags properly re-formatted"
-      (is (= (get client-queries sente-uid3)
-             (merge task-not-done-query {:not-tags #{"#done" "#backlog"}}))))))
+        {:keys [current-state logs-path]} (st/mk-test-state test-ts)]
+    (with-redefs [f/daily-logs-path logs-path]
+      (let [simple-query-uid (str (java.util.UUID/randomUUID))
+            simple-query2-uid (str (java.util.UUID/randomUUID))
+            no-results-query-uid (str (java.util.UUID/randomUUID))
+            tasks-query-uid (str (java.util.UUID/randomUUID))
+            tasks-done-query-uid (str (java.util.UUID/randomUUID))
+            tasks-not-done-query-uid (str (java.util.UUID/randomUUID))
+
+            new-state (reduce persist-reducer current-state test-entries)
+            new-state (reduce persist-reducer new-state (map st/mk-test-entry (range 100)))
+
+            new-state (-> new-state
+                          (add-query simple-query simple-query-uid)
+                          (add-query (merge simple-query {:n 200}) simple-query2-uid)
+                          (add-query tasks-query tasks-query-uid)
+                          (add-query no-results-query no-results-query-uid)
+                          (add-query tasks-done-query tasks-done-query-uid)
+                          (add-query tasks-not-done-query tasks-not-done-query-uid))
+            client-queries (:client-queries new-state)]
+
+        (testing "client queries associated with proper connection IDs"
+          (is (= (get client-queries simple-query-uid) simple-query))
+          (is (= (get client-queries tasks-done-query-uid) tasks-done-query)))
+
+        (testing "client queries with not-tags properly re-formatted"
+          (is (= (get client-queries tasks-not-done-query-uid)
+                 (merge tasks-not-done-query {:not-tags #{"#done" "#backlog"}}))))
+
+        (testing "query with no matches should return 0 results"
+          (is (empty? (extract-query-res new-state no-results-query-uid))))
+
+        (testing "simple query has 40 results"
+          (is (= 40 (count (extract-query-res new-state simple-query-uid)))))
+
+        (testing "simple query2 returns all 105 results"
+          (is (= 105 (count (extract-query-res new-state simple-query2-uid)))))
+
+        (testing "tasks query has 5 results"
+          (is (= 5 (count (extract-query-res new-state tasks-query-uid)))))
+
+        (testing "tasks done query has 3 results"
+          (is (= 3 (count (extract-query-res new-state tasks-done-query-uid)))))
+
+        (testing "tasks - not done query has 2 results"
+          (is (= 2 (count (extract-query-res new-state tasks-not-done-query-uid)))))
+
+        (testing "stats show expected numbers"
+          (let [res (-> (s/publish-state-fn {:current-state new-state
+                                             :msg-payload {:sente-uid simple-query-uid}})
+                        :emit-msgs
+                        first
+                        second)
+                stats (:stats res)]
+            (is (= (:entry-count stats) 105))
+            (is (= (:node-count stats) 122))))
+
+        (testing "hashtags and mentions in results"
+          (let [res (-> (s/publish-state-fn {:current-state new-state
+                                             :msg-payload   {:sente-uid simple-query-uid}})
+                        :emit-msgs
+                        first
+                        second)]
+            (is (= (:hashtags res) #{"#task" "#entry" "#test" "#done" "#completed" "#blah" "#new"}))
+            (is (= (:mentions res) #{"@myself" "@someone"}))))))))


state ref

state ref

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

--- acqEngine/src/org/micromanager/acq_engine.clj
+++ acqEngine/src/org/micromanager/acq_engine.clj
@@ -38,6 +38,9 @@

 ;; general utils

+(defn log [& x]
+  (org.micromanager.utils.ReportingUtils/logMessage (apply str x)))
+
 (defn data-object-to-map [obj]
   (into {}
     (for [f (.getFields (type obj))
@@ -97,12 +100,7 @@

 ;; globals

-(declare last-wake-time)
-(def start-time 0)
-(declare interrupt-requests)
-(declare z-corrections)
-(declare init-auto-shutter)
-(declare default-z-position)
+(declare state)

 ;; metadata

@@ -118,7 +116,6 @@
     (assoc
       "PositionName" (get-in event [:position :label])
       "Channel" (get-in event [:channel :name])
-      "PixelType" (get-pixel-type)
       "ZPositionUm" (get event :z)
       "AxisPositions" (when-let [axes (get-in event [:position :axes])] (JSONObject. axes))
     )))
@@ -126,10 +123,11 @@
 (defn annotate-image [img event]
   (TaggedImage. img
     (JSONObject. (merge
-      {"ElapsedTime-ms" (- (clock-ms) start-time)
+      {"ElapsedTime-ms" (- (clock-ms) (@state :start-time))
        "Time" (get-current-time-str)
        "Width"  (. mmc getImageWidth)
        "Height" (. mmc getImageHeight)
+       "PixelType" (get-pixel-type)
        "Binning" (. mmc getProperty (. mmc getCameraDevice) "Binning")
        "UUID" (UUID/randomUUID)
       }
@@ -141,11 +139,11 @@

 (defn acq-sleep [interval-ms]
   (let [current-time (clock-ms)
-        target-time (+ @last-wake-time interval-ms)
+        target-time (+ (@state :last-wake-time) interval-ms)
         sleep-time (- target-time current-time)]
     (when (pos? sleep-time)
       (Thread/sleep sleep-time)
-      (reset! last-wake-time target-time))))
+      (alter state assoc :last-wake-time target-time))))

 (declare device-agents)

@@ -158,8 +156,11 @@
   (. mmc getPosition stage))

 (defn set-stage-position
-  ([stage-dev z] (when z (. mmc setPosition stage-dev z)))
-  ([stage-dev x y] (when (and x y) (. mmc setXYPosition stage-dev x y))))
+  ([stage-dev z] (log "setting z position to " z)
+		 (. mmc setPosition stage-dev z)
+		 (dosync alter state assoc :last-z-position z))
+  ([stage-dev x y] (log "setting x,y position to " x "," y)
+                   (when (and x y) (. mmc setXYPosition stage-dev x y))))

 (defn set-property
   ([dev prop] (. mmc setProperty (prop 0) (prop 1) (prop 2))))
@@ -171,7 +172,8 @@
   (concat
     (when-let [z-drive (:z-drive event)]
       (when-let [z (:z event)]
-        (list [z-drive #(set-stage-position z-drive z)])))
+        (when (and z (not= z (@state :last-z-position)))
+          (list [z-drive #(set-stage-position z-drive z)]))))
     (for [[axis pos] (get-in event [:position :axes])]
       [axis #(apply set-stage-position axis pos)])
     (for [prop (get-in event [:channel :properties])]
@@ -203,10 +205,10 @@
   (if close-after
     (. mmc setShutterOpen false))
     (. mmc waitForDevice (. mmc getShutterDevice))
-  (. mmc setAutoShutter init-auto-shutter))
+  (. mmc setAutoShutter (@state :init-auto-shutter)))

 (defn init-burst [length]
-  (. mmc setAutoShutter init-auto-shutter)
+  (. mmc setAutoShutter (@state :init-auto-shutter))
   (. mmc startSequenceAcquisition length 0 false))

 (defn expose [event]
@@ -233,16 +235,16 @@
     (.put out-queue (annotate-image image event))))

 (defn store-z-correction [z event]
-  (alter z-corrections assoc (get-in event [:position :label]) z))
+  (alter state assoc-in [:z-corrections (get-in event [:position :label])] z))

 (defn compute-z-position [event]
   (if-let [z-drive (:z-drive event)]
     (-> event
       (assoc :z
 				(+ (or (get-in event [:channel :z-offset]) 0)
-				   (or (get @z-corrections z-drive)
+				   (or (get (@state :z-corrections) z-drive)
 				     (:slice event)
-				     default-z-position)))
+				     (@state :last-z-position))))
       (assoc-in [:postion :axes z-drive] nil))
     event))

@@ -261,28 +263,29 @@
     )))

 (defn execute [event-fns]
-  (doseq [event-fn event-fns :while (not (:stop @interrupt-requests))]
-    (while (:pause @interrupt-requests) (Thread/sleep 5))
+  (doseq [event-fn event-fns :while (not (:stop (@state :interrupt-requests)))]
+    (while (:pause (@state :interrupt-requests)) (Thread/sleep 5))
     (event-fn)))

 (defn stop-acq []
-  (dosync (alter interrupt-requests assoc :stop true)))
+  (dosync (alter state assoc-in [:interrupt-requests :stop] true)))

 (defn pause-acq []
-  (dosync (alter interrupt-requests assoc :pause true)))
+  (dosync (alter state assoc-in [:interrupt-requests :pause] true)))

 (defn run-acquisition [settings out-queue]
   (def acq-settings settings)
-  (binding [interrupt-requests (ref {:pause false :stop false})
-            z-corrections (ref nil)
-            last-wake-time (atom (clock-ms))
-            start-time (clock-ms)
-            init-auto-shutter (. mmc getAutoShutter)
-            default-z-position (get-z-stage-position (. mmc getFocusDevice))]
+  (binding
+    [state (ref {:interrupt-requests {:pause false :stop false}
+                 :z-corrections nil
+                 :last-wake-time (clock-ms)
+		 :start-time (clock-ms)
+		 :init-auto-shutter (. mmc getAutoShutter)
+                 :last-z-position (get-z-stage-position (. mmc getFocusDevice))})]
     (let [acq-seq (generate-acq-sequence settings)]
        (def acq-sequence acq-seq)
        (execute (mapcat #(make-event-fns % out-queue) acq-seq))
-       (. mmc setAutoShutter init-auto-shutter))))
+       (. mmc setAutoShutter (@state :init-auto-shutter)))))

 (defn convert-settings [^SequenceSettings settings]
   (-> settings
@@ -310,7 +313,7 @@

 (defn run-pipeline [settings acq-eng]
   (create-device-agents)
-	(let [out-queue (GentleLinkedBlockingQueue.)]
+	(let [out-queue (LinkedBlockingQueue.)]
 		(.start (Thread. #(run-acquisition (set-to-absolute-slices (convert-settings settings)) out-queue)))
 		(.start (LiveAcqDisplay. mmc out-queue settings (.channels settings) (.save settings) acq-eng))))


fix bug in z position in acq eng

fix bug in z position in acq eng

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

--- acqEngine/src/org/micromanager/acq_engine.clj
+++ acqEngine/src/org/micromanager/acq_engine.clj
@@ -187,8 +187,9 @@
     (let [now (clock-ms)
           wake-time (if (> now (+ target-time 10)) now target-time)]
       (state-assoc! :last-wake-time wake-time
-                    :reference-z-position (- (get-z-stage-position (core getFocusDevice))
-                                             old-z)))))
+                    :reference-z-position (+ (@state :reference-z-position)
+                                             (- (get-z-stage-position (core getFocusDevice))
+                                                old-z))))))

 ;; image metadata


Make directory structure in write-Parse.

--- src/incise/parsers/html.clj
+++ src/incise/parsers/html.clj
@@ -1,6 +1,7 @@
 (ns incise.parsers.html
-  (:require [incise.parsers.helpers :as help]
-            [incise.parsers.core :refer [map->Parse]]
+  (:require (incise.parsers [helpers :as help]
+                            [core :refer [map->Parse]])
+            [incise.layouts.core :refer [Parse->string]]
             [clojure.edn :as edn]
             [clojure.string :as s]
             [clojure.java.io :refer [reader]])
@@ -17,7 +18,12 @@

 (defn write-Parse
   [^incise.parsers.core.Parse parse-data]
-  (spit (str "resources/public/" (help/Parse->path parse-data))))
+  (let [file-path (File. (str "resources/public/"
+                              (help/Parse->path parse-data)))]
+    (-> file-path
+        (.getParentFile)
+        (.mkdirs))
+    (spit file-path (Parse->string parse-data))))

 (defn html-parser
   "Take a function that parses a string into HTML and returns an HTML parser.


accessors: add with-value for every property

--- src/joda_time/accessors.clj
+++ src/joda_time/accessors.clj
@@ -3,13 +3,14 @@
             [joda-time.impl :as impl]
             [joda-time.core :as c]))

-(doseq [date-time-field-type-name impl/date-time-field-type-names]
+(doseq [date-time-field-type-name (concat impl/date-time-field-type-names impl/period-types)]
   (let [value-fn (symbol (impl/dashize (str date-time-field-type-name)))
         prop-fn (symbol (str value-fn "-" 'prop))
         max-fn (symbol (str 'max "-" value-fn))
         min-fn (symbol (str 'min "-" value-fn))
         with-max-fn (symbol (str 'with-max "-" value-fn))
-        with-min-fn (symbol (str 'with-min "-" value-fn))]
+        with-min-fn (symbol (str 'with-min "-" value-fn))
+        with-fn (symbol (str 'with "-" value-fn))]
     (eval
       `(do
          (defn ~prop-fn
@@ -35,4 +36,8 @@
          (defn ~with-min-fn
            ~(str "The same date/partial with its " value-fn " set to the maximum value.\n"
                  "Equivalent to `(with-min-value (property date :" date-time-field-type-name "))`")
-           [o#] (prop/with-min-value (~prop-fn o#)))))))
+           [o#] (prop/with-min-value (~prop-fn o#)))
+         (defn ~with-fn
+           ~(str "The same date/partial with its " value-fn " set to the provided value.\n"
+                 "Equivalent to `(with-value (property date :" date-time-field-type-name ") value)`")
+           [o# v#] (prop/with-value (~prop-fn o#) v#))))))


Fix typo.

Fix typo.

--- src/klangmeister/views.cljs
+++ src/klangmeister/views.cljs
@@ -22,7 +22,7 @@
      [:div
       [:table {:class "cheatsheet"}
        [:tbody
-        (row "(..)" "Evaluation an expression" "(+ 1 1)")
+        (row "(..)" "Evaluate an expression" "(+ 1 1)")
         (row "[..]" "Build a sequence." "[1 2 3]")
         (row "->>" "Thread together multiple expressions." "(->> (range) (take 4))")
         (row "A..G" "Translate a relative midi into the specified key." "(A 3) => 72")


Fix mistakes that crept in from last checkin

--- clojure-programming/src/clojure_programming/chp03.clj
+++ clojure-programming/src/clojure_programming/chp03.clj
@@ -410,12 +410,7 @@

 "Is this list lazy? Let's check:
 "
-(defnure and Java collections, Java maps, Java
-CharSequences (including Strings), Java Iterables, Arrays, nil (null), anything
-clojure.lang.Seq.
-
-"
-(facts "some examples:" random-ints
+(defn random-ints
   [limit]
   (lazy-seq
    (println "realizing random number") ;print when value is realized
@@ -603,12 +598,7 @@
 (facts
   (fact "String"
     (get "Clojure" 3)
-ure and Java collections, Java maps, Java
-CharSequences (including Strings), Java Iterables, Arrays, nil (null), anything
-clojure.lang.Seq.
-
-"
-(facts "some examples:"    => \j)
+    => \j)
   (fact "Java map"
     (contains? (java.util.HashMap.) "not-there")
     => false)
@@ -920,7 +910,7 @@
     (contains? a 1239)
     => true))

-"compare-magnitude rewritten to ensure that only equivalent number are
+"compare-magnitude rewritten to ensure that only equivalent number range are
 considered equal"

 (defn compare-magnitude
@@ -928,13 +918,9 @@
   (let [diff (- (magnitude a) (magnitude b))]
     (if (zero? diff)
       (compare a b)
-ure and Java collections, Java maps, Java
-CharSequences (including Strings), Java Iterables, Arrays, nil (null), anything
-clojure.lang.Seq.
-
-"
-(facts "some examples:"      diff)))
-(facts
+      diff)))
+
+(facts "some examples:"
   (def a
     (sorted-set-by compare-magnitude 10 1000 500))
   (fact
@@ -983,14 +969,15 @@
     (:foo map))
   (fact "using keyword avoids the exception"
     (get-foo nil)
-    => nil)
-
-  (defn get-bar
-    [map]
-    (map :bar))
-  (fact
-    (get-bar nil)
-    => (throws NullPointerException)) )
+    => nil))
+
+(defn get-bar
+  [map]
+  (map :bar))
+
+(fact
+  (get-bar nil)
+  => (throws NullPointerException))
 "
 also not all collections can act as functions

@@ -1070,12 +1057,8 @@
   => '(1 2 3))

 [[:subsection {:title "Vectors --  page: 115"}]]
-ure and Java collections, Java maps, Java
-CharSequences (including Strings), Java Iterables, Arrays, nil (null), anything
-clojure.lang.Seq.
-
-"
-(facts "some examples:""
+
+"
 Vectors are sequential data structures that support random lookup
 Vectors participate in associative, indexed and stack abstractions
 "
@@ -1108,12 +1091,7 @@
   ((juxt quot rem) 42 8)
   => [5 2])

-(fact "using destructuringure and Java collections, Java maps, Java
-CharSequences (including Strings), Java Iterables, Arrays, nil (null), anything
-clojure.lang.Seq.
-
-"
-(facts "some examples:" to unpack return values "
+(fact "using destructuring to unpack return values "
   (let [[q r] (euclidean-division 53 7)]
     (str "53/7 = " q " * 7 + " r))
   => "53/7 = 7 * 7 + 4")
@@ -1168,7 +1146,7 @@

 [[:subsection {:title "Maps --  page: 117"}]]

-(fact "the man literal"
+(fact "the map literal"
   {:a 5 :b 6} => {:a 5 :b 6}
 ;  {:a 5 :a 5}
 ;  => '(throws IllegalArgumentException)
@@ -1313,6 +1291,7 @@
               (assoc-in summaries ks
                         (f (get-in summaries ks init) x))))
           {} coll))
+
 (fact "now we get two level breakup"
   (reduce-by-in (juxt :customer :product)
                 #(+ %1 (:total %2)) 0 orders)
@@ -1377,7 +1356,7 @@
 (fact c => '(2 3))

 "
-Can maps and vectors and sets be as effiecient?
+Can maps and vectors and sets be as efficient?
 "

 ;; an example:
@@ -1479,12 +1458,7 @@
   (transient-capable? '(1 2 3)) => false
   (transient-capable? #{1 2 3}) => true
   (transient-capable? {:a 1 :b 2}) => true
-  (transient-capable? [1 2 ure and Java collections, Java maps, Java
-CharSequences (including Strings), Java Iterables, Arrays, nil (null), anything
-clojure.lang.Seq.
-
-"
-(facts "some examples:"3]) => true)
+  (transient-capable? [1 2 3]) => true)

 "
 a persistent collection used as a transient is unaffected


RS + GR | #98 | Display username for writers with no profile (i.e. no real name)

--- src/objective8/templates/page_furniture.clj
+++ src/objective8/templates/page_furniture.clj
@@ -83,7 +83,9 @@
                            [:.clj-writer-profile-link] (html/set-attr :href
                                                                       (utils/path-for :fe/profile
                                                                                :username (:username candidate)))
-                           [:.clj-writer-name] (html/content (:name (:profile candidate)))
+                           [:.clj-writer-name] (html/content (if-let [real-name (:name (:profile candidate))]
+                                                               real-name
+                                                               (:username candidate)))
                            [:.clj-writer-description] (html/content (:invitation-reason candidate)))))

 (defn writer-list [context]


Remove unnecessary comments

Remove unnecessary comments

--- src/onyx/log/commands/peer_replica_view.clj
+++ src/onyx/log/commands/peer_replica_view.clj
@@ -15,10 +15,8 @@
     (if job
       (let [peer-state (:peer-state new)
             backpressure? (common/backpressure? new job)
-            ;;; these could be filtered down to outgoing nodes only
+            ;;; these could be filtered down to outgoing tasks
             receivable-peers (common/job-receivable-peers peer-state allocations job)
-            ;; acker peers (TODO: only required when peers are on input task)
-            ;; Validate ackable needs to be re-implemented
             max-acker-links (arg-or-default :onyx.messaging/max-acker-links opts)
             job-ackers (get (:ackers new) job)
             acker-candidates (operation/select-n-peers peer-id job-ackers max-acker-links)]


Added make-guess function

Added make-guess function

--- src/hangman/core.clj
+++ src/hangman/core.clj
@@ -1,6 +1,7 @@
 (ns hangman.core
   (:require
     [clojure.string  :as str]
+    [clojure.set     :as set]
   ) )

@@ -12,6 +13,12 @@
   (println
     (str seqName "("  (count seqVals) ") " )
         (take show-info-size (map #(str \" % \") seqVals)) ))
+
+(def all-chars
+  "A set of all lowercase characters [a..z]"
+  (->> (range  (int \a)  (inc (int \z))  )
+       (map char)
+        set ))

 (def all-words
   "A collection of all words for the hangman game."
@@ -132,6 +139,21 @@
                       pair-seq) ]
     result ))

+(defn make-guess
+  "Generate the next guess char. clue-vec consists of chars or nil, where a char shows
+  correctly guessed letters, and nil shows chars not yet guessed.  "
+  [clue-vec col-char-freqs used-chars]
+  (let [
+    all-char-freqs  (apply merge-with + col-char-freqs)
+      _ (println "all-char-freqs" all-char-freqs)
+    avail-chars     (set/difference (set(keys all-char-freqs)) used-chars)
+      _ (println "avail-chars" avail-chars)
+    max-avail-char  (apply max-key all-char-freqs avail-chars ) ]
+      _ (println "max-avail-char" max-avail-char)
+    max-avail-char
+  )
+)
+
 (defn run-tests []
   (println "----------------------------------------")
   (println "Tests:")
@@ -180,33 +202,40 @@
              {\a 1 \b 2 \c 3} ))

   ; Test frequency function
-  (let [tst-words [ "abcd" "xbcd" "xxcd" "xxxd" ]
-        words-map (words-by-length tst-words)
-        curr-len  4
-        curr-words  (words-map curr-len)
-          _ (println "curr-words:" curr-words)
-        word-array  (to-word-array  curr-words)
-        col-char-freqs (freqs-by-col word-array)
-        all-char-freqs (apply merge-with + col-char-freqs)
-        max-freq-val (apply max-key all-char-freqs (keys all-char-freqs) )
-
-        wordVec    [ \x  \x  \c  \d  ]
-        guessVec   [ nil \b  nil nil ]
-        keepFlg    (map #(nil? %) guessVec )
-          _ (println "keepFlg" keepFlg)
-        keepFreqs  (filter-with keepFlg col-char-freqs)
-          _ (println "keepFreqs" keepFreqs)
-        keepWords  (filter-with keepFlg curr-words)
-          _ (println "keepWords" keepWords)
-       ]
-    (assert (= words-map   {4 ["abcd" "xbcd" "xxcd" "xxxd"]} ))
-    (assert (= curr-words     ["abcd" "xbcd" "xxcd" "xxxd"]  ))
-    (assert (= col-char-freqs [{\a 1, \x 3} {\b 2, \x 2} {\c 3, \x 1} {\d 4}] ))
-    (assert (= all-char-freqs { \a 1, \b 2, \c 3, \d 4, \x 6} ))
-    (assert (= max-freq-val \x ))
-  )
-
-  (println)
+  (let [
+    tst-words [ "abcd" "xbcd" "xxcd" "xxxd" ]
+    words-map           (words-by-length tst-words)
+      _ (assert (= words-map   {4 ["abcd" "xbcd" "xxcd" "xxxd"]} ))
+
+    curr-len            4
+    curr-words          (words-map curr-len)
+      _ (assert (= curr-words     ["abcd" "xbcd" "xxcd" "xxxd"]  ))
+      _ (println "curr-words:" curr-words)
+    word-array          (to-word-array  curr-words)
+    col-char-freqs      (freqs-by-col word-array)
+      _ (assert (= col-char-freqs [{\a 1, \x 3} {\b 2, \x 2} {\c 3, \x 1} {\d 4}] ))
+
+    all-char-freqs      (apply merge-with + col-char-freqs)
+      _ (assert (= all-char-freqs { \a 1, \b 2, \c 3, \d 4, \x 6} ))
+
+    max-freq-val        (apply max-key all-char-freqs (keys all-char-freqs) )
+      _ (assert (= max-freq-val \x ))
+
+    wordVec             [ \x  \x  \c  \d  ]
+    clue-vec            [ nil \b  nil nil ]
+    keepFlg             (map #(nil? %) clue-vec )
+      _ (println "keepFlg" keepFlg)
+    keepFreqs           (filter-with keepFlg col-char-freqs)
+      _ (println "keepFreqs" keepFreqs)
+    keepWords           (filter-with keepFlg curr-words)
+      _ (println "keepWords" keepWords)
+
+    used-chars #{ \b }
+    guess               (make-guess clue-vec col-char-freqs used-chars)
+      _ (println "guess" guess)
+
+  ]
+  )
 )

 (defn main


Add check fn for compander

Add check fn for compander

--- src/overtone/sc/ugen/metadata/compander.clj
+++ src/overtone/sc/ugen/metadata/compander.clj
@@ -65,6 +65,7 @@
        :scsynth-location "FilterUgens"
        :sclang-location "Compander"
        :rates #{:ar}
+       :check (first-n-inputs-ar 2)
        :doc "The compander will modify the amplitude of the in signal based on an analysis of the control signal. Typically the in and control signals are the same. The amplitude of the control signal is calcuated using RMS (Root Mean Square) and the final amplitude of the in signal is calculated as a function of the amplitude threshold, and slopes either side (below and above) with some temporal modifications in terms of attack and release phases. It is a hard-knee processor which means that the response curve is a sharp angle rather than a rounded edge.

 If the control amplitude is less than the threshold, the slope below is used to calculate the amplitude modification. If this is steep (greater than 1) this will reduce the amplitude of quiet signals (the quieter the control amplitude the greater the reduction affect).  Values < 1.0 are possible, but it means that a very low-level control signal will cause the input signal to be amplified, which would raise the noise floor.


catch errors when extracting content

catch errors when extracting content

--- src/brainbot/nozzle/extract2.clj
+++ src/brainbot/nozzle/extract2.clj
@@ -24,7 +24,10 @@
 (defn simple-extract_content
   [fs {directory :directory, {relpath :relpath :as entry} :entry, :as body} {publish :publish}]
   (let [path (vfs/join fs [directory relpath])
-        extract (vfs/extract-content fs path)
+        extract (try
+                  (vfs/extract-content fs path)
+                  (catch Throwable err
+                    nil))
         new-entry (if extract
                     (assoc entry :extract extract)
                     entry)]


Modify kibit/check to work with strings the way we want.

--- src/clj/sally/checkers/kibit.clj
+++ src/clj/sally/checkers/kibit.clj
@@ -1,25 +1,29 @@
 (ns sally.checkers.kibit
   (:require [kibit.check :as kc]
             [clojure.edn :as edn]
+            [clojure.java.io :as io]
             [sally.checkers.meta :refer [add-sally-metadata]])
-  (:import [java.io File Reader]
+  (:import [java.io File Reader StringReader]
            [clojure.lang PersistentList]))

 (defprotocol KibitCheck
-  (check [thing]))
+  (check-impl [thing]))

 (extend-protocol KibitCheck
   Reader
-  (check [r] (kc/check-reader r))
+  (check-impl [r] (kc/check-reader r))

   File
-  (check [f] (kc/check-file f))
+  (check-impl [f] (kc/check-file f))

   PersistentList
-  (check [expr] (kc/check-expr expr))
+  (check-impl [expr] (list (kc/check-expr expr)))

   String
-  (check [s] (check (edn/read-string s))))
+  (check-impl [s] (check-impl (StringReader. s))))
+
+(def kibit->issues identity) ;; No transformation necessary
+(defn check [thing] (kibit->issues (check-impl thing)))

 (add-sally-metadata check
                     :name "kibit"


code mirror

code mirror

--- src/cljs/dbquery/db_console.cljs
+++ src/cljs/dbquery/db_console.cljs
@@ -62,15 +62,17 @@

 (defn code-mirror [config]
   (r/create-class
-   {:reagent-render (fn[] [:text-area "//code here"])
-    :component-did-mount #(.fromTextArea js/CodeMirror (r/dom-node %) (clj->js config))}))
+   {:reagent-render (fn[config] [:textarea {:style {:width "100%" :height "100%"}}  "--SQL code here"])
+    :component-did-mount #(.fromTextArea js/CodeMirror (r/dom-node %) (clj->js config))
+    }))

 (defn sql-panel [db]
-  [:div.panel.panel-default.full-height
+  [:div.panel.panel-default.full-height {:style {:padding "0px" :margin "0px" :height "100%"}}
    [:div.panel-heading.compact
     "SQL Editor"]
-   [:div.panel-body
-    [code-mirror {:mode "text/x-sql"}]]])
+   [:div.panel-body {:style {:padding "0px" :overflow "hidden" :height "calc(100% - 48px)"}}
+    [code-mirror {:mode "text/x-sql" :autofocus true}]]
+   [:div.panel-footer]])

 (defn db-console [db active?]
   (let [active-tab (atom nil)


Ditto.

Ditto.

--- src/cljs/idealist/event_bus.cljs
+++ src/cljs/idealist/event_bus.cljs
@@ -15,11 +15,9 @@
   (got-event [_ ev]))

 ;; TODO: xform
-;; TODO: Terminate loop.
-;;

 ;; =============================================================================
-;; Helper functions.
+;; Event bus setup.

 (defn- init-event-bus!
   "Adds support for triggering events and, if the component reified IGotEvent, support for handling events
@@ -31,6 +29,7 @@

    Do not use the local state values directly; they are for internal use only."
   [this]
+  (println "Setting event bus for" (om/id this))
   (let [downstream (om/get-state this ::event-bus)
         c (om/children this)]
     (om/set-state! this ::trigger-fn #(async/put! downstream %))
@@ -41,12 +40,31 @@
         (async/tap fork branch)
         (async/tap fork downstream)
         (om/set-state! this ::event-bus upstream)
+        (om/set-state! this ::close-fn (fn []
+                                        (async/close! upstream)
+                                        (async/close! branch)))
         (async/go-loop []
-                 (let [e (async/<! branch)]
-                   (got-event c e))
-                 (recur))))))
+                       (let [[event ch] (async/alts! [branch (async/timeout 5000)])]
+                         (println (om/id this) "got " event)
+                         (if event
+                           (do
+                             (got-event c event)
+                             (recur))
+                           (when (not= ch branch)
+                             (println (om/id this) "is listening...")
+                             (recur)))))))))

+(defn- shutdown-event-bus!
+  [this]
+  (om/set-state! this ::trigger-fn #(throw (js/Error. "Event bus has already been shut down.")))
+  (let [c (om/children this)
+        close-fn (om/get-state this ::close-fn)]
+    (when (satisfies? IGotEvent c)
+      (println "Shutting down event bus for" (om/id this))
+      (close-fn))))

+;; =============================================================================
+;; Custom om component descriptor.

 (defn- around-method
   "Overrides a pure method by wrapping it in f."
@@ -85,18 +103,6 @@
         descriptor (om/specify-state-methods! (clj->js methods))]
     descriptor))

-(defn- make-instrument-fn
-  "Creates the function called whenever a component calls build, build-all or build*.
-
-  What this function does is to pass on event bus core.async channel from parent to child. It uses the bus
-  in the parent's local state except for top-level components when it uses 'event-bus' passed as an argument."
-  [event-bus]
-  (fn [f x m]
-    (let [parent-bus (or
-                       (and *parent* (om/get-state *parent* ::event-bus))
-                       event-bus)]
-      (om/build* f x (update-in m [:init-state] merge {::event-bus parent-bus})))))
-
 ;; =============================================================================
 ;; Public functions.

@@ -112,11 +118,19 @@
                                                            (fn [this super]
                                                              (init-event-bus! this)
                                                              (super))
+                                                           :componentWillUnmount
+                                                           (fn [this super]
+                                                             (shutdown-event-bus! this)
+                                                             (super))
                                                            :render
                                                            (fn [this super]
                                                              (binding [*parent* this]
                                                                (super)))})
-                             :instrument (make-instrument-fn event-bus)}))))
+                             :instrument (fn [f x m]
+                                           (let [parent-bus (or
+                                                              (and *parent* (om/get-state *parent* ::event-bus))
+                                                              event-bus)]
+                                             (om/build* f x (update-in m [:init-state] merge {::event-bus parent-bus}))))}))))

 (defn trigger
   "Sends an event from the component down through its parent components."


timer feature

timer feature

--- src/cljs/passa_paraula/core.cljs
+++ src/cljs/passa_paraula/core.cljs
@@ -34,6 +34,7 @@

 (def starting-state {:pos 0
                      :score 0
+                     :time 10
                      :status (vec (take num-letters (repeat :init)))})

 (def app-state (atom starting-state))
@@ -87,6 +88,7 @@
   [:div
    [:h2 "Welcome to passa-paraula"]
    [:div {:id "score"} (str "score:" (:score @app-state))]
+   [:div {:id "time:"} (str "time:" (:time @app-state))]
    [board-component]
    [:div [:a {:href "#/about"} "go to about page"]]])

@@ -147,8 +149,14 @@
     (swap! app-state update-in [:pos] #(or first-greater-pos first-pos))))

+(defn no-more-letters-to-answer? []
+  (every? #(or (= :failed %) (= :ok %)) (:status @app-state)))
+
+(defn no-more-time-left? []
+  (> 1 (:time @app-state)))
+
 (defn end-game? []
-  (every? #(or (= :failed %) (= :ok %)) (:status @app-state)))
+  (or (no-more-letters-to-answer?) (no-more-time-left?)))

 (defn end-game []
   (secretary/dispatch! "/end"))
@@ -159,6 +167,12 @@

 (defn update-score []
   (swap! app-state update-in [:score] score))
+
+(defn update-time []
+  (swap! app-state update-in [:time] dec)
+  (js/setTimeout update-time 1000)
+  (when (end-game?)
+    (end-game)))

 (defn handle-letter [letter-id status]
   (do
@@ -176,9 +190,13 @@
       107 (handle-letter (cur-letter-id) :failed)
       (.log js/console (str "key pressed not valid" key)))))

-(defn hook-keyboard-listener
+(defn hook-keyboard-listener!
   []
    (.addEventListener js/window "keypress" handle-keys))
+
+
+(defn hook-clock-update! []
+  (js/setTimeout update-time 1000))

 ;; -------------------------
 ;; Initialize app
@@ -189,5 +207,6 @@
 (defn init! []
   (reset-state!)
   (hook-browser-navigation!)
-  (hook-keyboard-listener)
+  (hook-keyboard-listener!)
+  (hook-clock-update!)
   (mount-root))


Docstrings.

Docstrings.

--- src/clojure/clj_chess/board.cljc
+++ src/clojure/clj_chess/board.cljc
@@ -53,15 +53,21 @@
   #?(:clj (Square/toString square)
      :cljs (jsc/squareToString square)))

-(defn piece-make [color type]
+(defn piece-make
+  "Returns a piece with a given color and type."
+  [color type]
   #?(:clj (Piece/make color type)
      :cljs (jsc/pieceMake color type)))

-(defn piece-type [piece]
+(defn piece-type
+  "Returns the type of a piece (pawn, knight, bishop, etc.)."
+  [piece]
   #?(:clj (Piece/type piece)
      :cljs (jsc/pieceType piece)))

-(defn piece-color [piece]
+(defn piece-color
+  "Returns the color of a piece (white or black)."
+  [piece]
   #?(:clj (Piece/color piece)
      :cljs (jsc/pieceColor piece)))


Add some more helpful reducers functions.

--- src/clojure/parkour/reducers.clj
+++ src/clojure/parkour/reducers.clj
@@ -1,7 +1,28 @@
 (ns parkour.reducers
+  (:refer-clojure :exclude [map-indexed reductions])
   (:require [clojure.core.reducers :as r]
             [clojure.core.protocols :as ccp]
             [parkour.util :refer [returning]]))
+
+(defn map-indexed
+  "Reducers version of `map-indexed`."
+  [f coll]
+  (r/reducer coll
+    (fn [f1]
+      (let [i (atom -1)]
+        (fn [acc x] (f1 acc (f (swap! i inc) x)))))))
+
+(defn reductions
+  "Reducers version of `reductions`."
+  [f init coll]
+  (r/reducer coll
+    (fn [f1]
+      (let [sentinel (Object.), state (atom sentinel)]
+        (fn [acc x]
+          (f1 (if (identical? sentinel @state)
+                (f1 acc (reset! state init))
+                acc)
+              (swap! state f x)))))))

 (defn reduce-by
   "Partition `coll` with `keyfn` as per `partition-by`, then reduce


Containers need to be placed under "produkt"

in order to be archived

--- src/mdr2/archive.clj
+++ src/mdr2/archive.clj
@@ -82,7 +82,7 @@
   `production` and `sektion`"
   [production sektion]
   (let [id (container-id production sektion)]
-    (.getPath (file spool-dir id))))
+    (.getPath (file spool-dir id "produkt"))))

 (defn- container-rdf-path
   "Return the path to the rdf file in the archive spool for a given


Allow user to override some defaults

Allow user to override some defaults

--- src/com/wsscode/pathom/core.cljc
+++ src/com/wsscode/pathom/core.cljc
@@ -928,14 +928,17 @@
    (fn wrap-normalize-env-internal
      ([env tx] (wrap-normalize-env-internal env tx nil))
      ([env tx target]
-      (parser (assoc env ::plugin-actions (group-plugins-by-action plugins)
-                         ::plugins plugins
-                         ::request-cache (atom {})
-                         ::entity (atom {})
-                         ::entity-key ::entity
-                         ::parent-query tx
-                         ::entity-path-cache (atom {})
-                         :target target)
+      (parser
+        (merge
+          {::entity            (atom {})
+           ::request-cache     (atom {})
+           ::entity-key        ::entity
+           ::entity-path-cache (atom {})
+           ::parent-query      tx}
+          env
+          {::plugin-actions (group-plugins-by-action plugins)
+           ::plugins        plugins
+           :target          target})
         tx)))))

 (defn wrap-setup-async-cache [parser]


dont kill unwanted backends with no channel

--- src/merlion/core.clj
+++ src/merlion/core.clj
@@ -337,7 +337,7 @@
         margin (:upstream-freshness (:config config))
         unwanted (set/difference (set existing) (set wanted))]
     (log/spy :trace unwanted)
-    (run! #(async/put! % :quit) (map #(:chan (get backends %)) unwanted))
+    (run! #(and % (async/put! % :quit)) (map #(:chan (get backends %)) unwanted))
     (reduce (fn [m [n spec]]
               (let [state (get backends [n listener] {})]
                 (assoc


memoize version info

memoize version info

--- src/ctia/http/routes/version.clj
+++ src/ctia/http/routes/version.clj
@@ -5,13 +5,16 @@
             [clojure.string :as st]
             [ctia.schemas.common :refer [VersionInfo]]
             [compojure.api.sweet :refer :all]
-            [ring.util.http-response :refer :all]))
+            [ring.util.http-response :refer :all]
+            [clojure.string :as st]))

-(defn current-build []
-  (if-let [built-version (io/resource "ctia-version.txt")]
-    built-version
-    (str (:out (shell/sh "git" "log" "-n" "1" "--pretty=format:%H "))
-         (:out (shell/sh "git" "symbolic-ref" "--short" "HEAD")))))
+(def version-file "ctia-version.txt")
+
+(def current-version
+  (memoize #(if-let [built-version (io/resource version-file)]
+              built-version
+              (str (:out (shell/sh "git" "log" "-n" "1" "--pretty=format:%H "))
+                   (:out (shell/sh "git" "symbolic-ref" "--short" "HEAD"))))))

 (defroutes version-routes
   (context "/version" []
@@ -22,6 +25,5 @@
       (ok {:base "/ctia"
            :version "0.1"
            :beta true
-           :build (-> (current-build)
-                      (st/replace #"\n" ""))
+           :build (st/replace (current-version) #"\n" "")
            :supported_features []}))))


Adds back the `project` field on tasks

Adds back the `project` field on tasks

--- src/great_things_done/state.cljs
+++ src/great_things_done/state.cljs
@@ -125,7 +125,7 @@
 ;;     - show-before: int >= 0 number of days before the due date when the instance should appear in the inbox

 (defn- new-task
-  [task-name parent task-type tags tasks description remind-date due-date show-before repeating done]
+  [task-name project parent task-type tags tasks description remind-date due-date show-before repeating done]
   (when-not (is-task {:type task-type})
     (throw (js/Error. (str "Task type must belong to ["
                            (clojure.string/join ", "
@@ -133,8 +133,19 @@
                            "]. Provided type was `"
                            task-type
                            "`"))))
+  (when (and (is-project parent)
+             (not= (:id parent)
+                   (:id project)))
+    ;; Ensure that parent is not another project if parent is a project
+    (throw (js/Error. (str "`parent` and `project` can't be different if parent is a project"))))
+  (when (and (is-task parent)
+             (not= (get-in parent [:project :id])
+                   (:id project)))
+    ;; Ensure that parent is in the same project if parent is a task
+    (throw (js/Error. (str "`parent` has to be a task of `project` if parent is a task"))))
   {:name        task-name
    :id          (build-id task-name)
+   :project     (select-keys project [:name :id])
    :parent      (:id parent)
    :type        (if (= (:type parent) "Project")
                   "Task"
@@ -177,8 +188,9 @@
   @tasks)

 (defn register-task
-              :or   {parent      (inbox)
-  [task-name {:keys [parent tags tasks description remind-date due-date show-before repeating]
+  [task-name {:keys [project parent tags tasks description remind-date due-date show-before repeating]
+              :or   {project     (inbox)
+                     parent      (inbox)
                      tags        []
                      tasks   []
                      description ""
@@ -187,6 +199,7 @@
                      show-before 0
                      repeating   false}}]
   (let [task (new-task task-name
+                       project
                        parent
                        tags
                        tasks


make data fetcher react on oldness

make data fetcher react on oldness

--- src/showkr/data.cljs
+++ src/showkr/data.cljs
@@ -4,6 +4,8 @@
 (def URL "https://api.flickr.com/services/rest/")
 (def OPTS {:api_key "1606ff0ad63a3b5efeaa89443fe80704"
            :format "json"})
+
+(def ^:dynamic *old-threshold* (* 1000 60 60 2)) ;; 2 hours

 (defonce world
   (atom {:opts {:target nil
@@ -19,17 +21,33 @@
   (let [q (Jsonp. URL "jsoncallback")]
     (.send q (clj->js (merge OPTS payload)) callback flickr-error)))

+(defn old? [data]
+  (> (- (.getTime (js/Date.))
+       (or (-> data meta :date) 0))
+    *old-threshold*))
+
 (defn flickr-fetch [path attr payload & [cb]]
-  (when-not (get-in @world path)
-    (swap! world assoc-in path ^{:state :waiting} {})
-    (flickr-call payload
-      (fn [data]
-        (let [data (js->clj data :keywordize-keys true)]
-          (swap! world assoc-in path
-            (condp = (:stat data)
-              "ok"   (with-meta (attr data) {:state :fetched})
-              "fail" (with-meta data {:state :failed})))
-          (when cb (cb)))))))
+  (let [data (get-in @world path)]
+    (when (empty? data)
+      (swap! world assoc-in path
+        ^{:state :waiting :date (.getDate (js/Date.))} {}))
+    (when (old? data)
+      (flickr-call payload
+        (fn [data]
+          (let [data (js->clj data :keywordize-keys true)]
+            (swap! world assoc-in path
+              (condp = (:stat data)
+                "ok"
+                (with-meta (attr data)
+                  {:state :fetched
+                   :date (.getTime (js/Date.))})
+
+                "fail"
+                (if (>= (:code data) 100) ;; not user input fault
+                  nil
+                  (with-meta data
+                    {:state :failed}))))
+            (when cb (cb))))))))

 (defn fetched? [data]
   (= :fetched (:state (meta data))))


ensure polyfills has correct output mode

--- src/main/shadow/build/closure.clj
+++ src/main/shadow/build/closure.clj
@@ -2391,14 +2391,15 @@
 (def get-polyfill-infos (memoize get-polyfill-infos*))

 (defn get-polyfills
-  ([]
-   (get-polyfills (into ["base"] (map :lib) (get-polyfill-infos))))
-  ([libs]
+  ([state]
+   (get-polyfills state (into ["base"] (map :lib) (get-polyfill-infos))))
+  ([state libs]
    (let [cc
          (data/make-closure-compiler)

          co-opts
-         {:optimizations :simple}
+         (assoc (get-output-options state)
+           :optimizations :simple)

          closure-opts
          (doto (make-options)
@@ -2459,14 +2460,14 @@
             (= all (:polyfill-libs state)))
       state
       (util/with-logged-time [state {:type ::make-polyfill-js :polyfill-libs all}]
-        (assoc state :polyfill-libs all :polyfill-js (get-polyfills all))))))
+        (assoc state :polyfill-libs all :polyfill-js (get-polyfills state all))))))

 (defmethod build-log/event->str ::make-polyfill-js
   [{:keys [polyfill-libs]}]
   (format "Generating %d Polyfills" (count polyfill-libs)))

 (comment
-  (let [p (get-polyfills)]
+  (let [p (get-polyfills {})]
     (println p)
     (count p)
     ))


Start implementing partition/split.

Start implementing partition/split.

--- src/merkle_db/partition.clj
+++ src/merkle_db/partition.clj
@@ -1,5 +1,7 @@
 (ns merkle-db.partition
-  (:refer-clojure :exclude [read])
+  "Partitions contain non-overlapping ranges of the records witin a table.
+  Partition nodes contain metadata about the contained records and links to the
+  tablets where the data for each field family is stored."
   (:require
     [clojure.spec :as s]
     [merkledag.link :as link]
@@ -230,10 +232,6 @@
         (assoc ::data/families families))))

-; TODO: split
-; TODO: join
-
-

 ;; ## Deletion Functions

@@ -248,3 +246,75 @@
     (->> (::tablets part)
          (into {} (map (juxt key #(update (val %) :id update-tablet!))))
          (assoc part ::tablets))))
+
+
+
+;; ## Utilities
+
+(defn- divide-tablets
+  "Take a map of tablet links and a split key and returns a vector of two
+  tablet maps, each containing the left and right tablet splits, respectively."
+  [store tablets split-key]
+  (reduce-kv
+    (fn divide
+      [[left right] family-key tablet-link]
+      (let [tablet (node/get-data store tablet-link)]
+        (cond
+          ; All tablet data is in the left split.
+          (key/before? (tablet/last-key tablet) split-key)
+          [(assoc left family-key tablet-link) right]
+
+          ; All tablet data is in the right split.
+          (key/after? (tablet/first-key tablet) split-key)
+          [left (assoc right family-key tablet-link)]
+
+          ; Split tablet into two pieces.
+          :else
+          (let [[ltab rtab] (tablet/split tablet split-key)]
+            [(conj left (store-tablet! store family-key ltab))
+             (conj right (store-tablet! store family-key rtab))]))))
+    [{} {}]
+    tablets))
+
+
+(defn split
+  "Split the partition into two partitions at the given key. All records less
+  than the split key will be contained in the first partition, all others in
+  the second."
+  [store part split-key]
+  (when-not (and (key/after? split-key (::first-key part))
+                 (key/before? split-key (::last-key part)))
+    (throw (ex-info (format "Cannot split partition with key %s which falls outside the contained range [%s, %s]"
+                            split-key (::first-key part) (::last-key part))
+                    {:split-key split-key
+                     :first-key (::first-key part)
+                     :last-key (::last-key part)})))
+  (let [defaults (select-keys part [:data/type ::data/families])
+        [left right] (divide-tablets store (::tablets part) split-key)]
+    ; Construct new partitions from left and right tablet maps.
+    [(let [base-keys (tablet/keys (node/get-data store (:base left)))]
+       (assoc defaults
+              ::data/count (count base-keys)
+              ::membership (reduce bloom/insert
+                                   (bloom/create (count base-keys))
+                                   base-keys)
+              ::first-key (first base-keys)
+              ::last-key (last base-keys)
+              ::tablets left))
+     (let [base-keys (tablet/keys (node/get-data store (:base right)))]
+       (assoc defaults
+              ::data/count (count base-keys)
+              ::membership (reduce bloom/insert
+                                   (bloom/create (count base-keys))
+                                   base-keys)
+              ::first-key (first base-keys)
+              ::last-key (last base-keys)
+              ::tablets right))]))
+
+
+(defn join
+  "Join two partitions into a single partition. The partition key ranges must
+  not overlap."
+  [store left right]
+  ; TODO: implement
+  (throw (UnsupportedOperationException. "NYI")))


Appshare apps can now call the server

Appshare apps can now call the server

Since core.async is not supported in bootstrapped clojurescript we had
to choose a method of calling the server by using callbacks

--- src/webapp/framework/client/coreclient.cljs
+++ src/webapp/framework/client/coreclient.cljs
@@ -2581,3 +2581,16 @@

 (defn ^:export callresetclientstate []
   (resetclientstate))
+
+
+
+(defn remote-callback [function-name    function-params   function-callback]
+  (do
+    (go
+      (let [result
+            (<! (remote-fn
+                  function-name
+                  function-params))]
+        (function-callback   result)
+        ))
+    {}))


Refactoring.

Refactoring.

--- src/ahnentafel/gedcom.clj
+++ src/ahnentafel/gedcom.clj
@@ -16,24 +16,28 @@
      :value value}
     (throw (ahnentafel.ParseError. line))))

-(defn- records-subordinate-to [record]
-  (fn [r] (> (:level r) (:level record))))
+(defn- split-out-subordinate-records [records]
+  (letfn [(subordinate-to-first [r] (> (:level r) (:level (first records))))]
+   (split-with subordinate-to-first (rest records))))

 (defn group-records
   ([records] (group-records (first records)
-                            (split-with (records-subordinate-to (first records)) (rest records))
+                            (split-out-subordinate-records records)
                             []))
   ([current-record [subordinate-records unprocessed-records] processed-records]
-   (println [current-record subordinate-records unprocessed-records processed-records])
-   (cond (and (empty? unprocessed-records) (empty? subordinate-records)) (conj processed-records current-record)
-         (empty? unprocessed-records) (group-records (assoc current-record :subordinate-lines (group-records subordinate-records))
-                                                     (list nil unprocessed-records)
-                                                     processed-records)
-         (empty? subordinate-records) (group-records (first unprocessed-records)
-                                                     (split-with (records-subordinate-to (first unprocessed-records)) (rest unprocessed-records))
-                                                     (conj processed-records current-record))
-         :else (group-records (first unprocessed-records)
-                              (split-with (records-subordinate-to (first unprocessed-records)) (rest unprocessed-records))
-                              (conj processed-records current-record)))
+   (cond (and (empty? unprocessed-records) (empty? subordinate-records))
+         (conj processed-records current-record)
+
+         (empty? unprocessed-records)
+         (group-records (assoc current-record
+                               :subordinate-lines
+                               (group-records subordinate-records))
+                        (list nil unprocessed-records)
+                        processed-records)
+
+         :else
+         (group-records (first unprocessed-records)
+                        (split-out-subordinate-records unprocessed-records)
+                        (conj processed-records current-record)))
    )
 )


(PE-5769) Replace and conflict rubycas-server in pe-console-services

pe-console-services will include an rbac component, which will replace
pe-rubycas-server. This commit adds a replaces-pkgs declaration for this
package, at the versions shipped in PE 3.3.1.

--- configs/pe-console-services/pe-console-services.clj
+++ configs/pe-console-services/pe-console-services.clj
@@ -18,4 +18,5 @@

   :ezbake {:user "pe-console-services"
            :group "pe-console-services"
-           :build-type "pe"})
+           :build-type "pe"
+           :replaces-pkgs [{:package "pe-rubycas-server", :version "1.1.17.3"}]})


Fix write datoms schema check

Fix write datoms schema check

--- src/onyx/plugin/datomic.clj
+++ src/onyx/plugin/datomic.clj
@@ -524,7 +524,7 @@

 (defn write-bulk-datoms [pipeline-data]
   (let [task-map (:onyx.core/task-map pipeline-data)
-        _ (s/validate DatomicWriteDatoms task-map)
+        _ (s/validate DatomicWriteDatomsTaskMap task-map)
         conn (safe-connect task-map)]
     (->DatomicWriteBulkDatoms conn)))


no need to set log level here

no need to set log level here

--- src/overtone/libs/event.clj
+++ src/overtone/libs/event.clj
@@ -13,10 +13,6 @@
 (defonce thread-pool (Executors/newFixedThreadPool NUM-THREADS))
 (defonce event-handlers* (ref {}))
 (defonce sync-event-handlers* (ref {}))
-
-; * Need to add a handler key for events
-
-(log/level :debug)

 (defn- on-event*
   [handler-ref* event-type key handler]


change initial state of atom

change initial state of atom

--- src/background_on/web.clj
+++ src/background_on/web.clj
@@ -7,7 +7,7 @@
             [background-on.nyt :as nyt])
   (:gen-class))

-(def snapshot-json-atom (atom nil))
+(def snapshot-json-atom (atom {}))

 (defroutes app-routes
   (GET "/snapshot" [] @snapshot-json-atom)


cleanup + bufix for regexp literal

cleanup + bufix for regexp literal

--- ccw.core/src/ccw/editors/antlrbased/ClojureFormat.clj
+++ ccw.core/src/ccw/editors/antlrbased/ClojureFormat.clj
@@ -1,9 +1,5 @@
 (ns ccw.editors.antlrbased.ClojureFormat
-  (:use [clojure.contrib.pprint])
-  (:import
-    [org.eclipse.jface.text IAutoEditStrategy
-     IDocument
-     DocumentCommand])
+  (:use [clojure.test])
   (:gen-class
     :init init
     :state state
@@ -11,7 +7,11 @@

 (defn -init [])

+(declare format-code)
 (defn -formatCode [this string]
+  (format-code string))
+
+(defn format-code [string]
   (loop [s string col 0 dstack [] out [] space nil incl false
          insl false incm false lwcr false sups true cmindent nil]
     (if-let [c (first s)] ; test comment 1 { ; )
@@ -52,7 +52,7 @@
                    r (if nl (dec (count cc)) (+ col (count cc)))
                    dstack (into out cc) nil false false
                    (if-not nl incm) (= c \return) nl cmindent))
-          (= c \") (let [cc (if (or incl insl) [c] [\space c])]
+          (= c \") (let [cc (if (or incl insl sups) [c] [\space c])]
                      (recur
                        r (+ col (count cc)) dstack (into out cc)
                        (if (and insl (not incl)) [\space]) false
@@ -110,3 +110,7 @@
                     false false false false (sups-char? c)
                     cmindent))))
       (apply str out))))
+
+
+(deftest code-formatting
+  (is (= "#\"something\"" (format-code "#\"something\""))))


wrong arity in call now

wrong arity in call now

--- test/infinitelives/utils/pathfind_test.cljs
+++ test/infinitelives/utils/pathfind_test.cljs
@@ -115,7 +115,7 @@
         end [10 10]
         [{:keys [open-set came-from g-score] :as state} next-cell]
         (-> (pf/->state #{} #{start} {} {start 0} {start 10})
-            (pf/A*-step (constantly true) start end))]
+            (pf/A*-step (constantly true) start end false))]
     (is (= open-set #{[-1 -1] [0 -1] [1 -1] [-1 0] [1 0] [-1 1] [0 1] [1 1]}))
     (is (= came-from
            {


Added test.

Added test.

--- test/midje/parsing/util/t_file_position.clj
+++ test/midje/parsing/util/t_file_position.clj
@@ -177,16 +177,23 @@
     (:meta (meta (nth result 1))) => :data))

+(defmacro make-form [] `(quote by macro))
+
+
 (fact "adding line number information"
   (let [form-without-line-number (cons 'without '(line))
-        form-with-line-number '(with line)]
+        form-with-line-number '(with line)
+        form-generated-by-macro (make-form)]
     (fact "to a form without one updates it"
       (:line (meta (positioned-form form-without-line-number 8888))) => 8888)
     (fact "to a form with one does not"
       (:line (meta (positioned-form form-with-line-number 8888))) =not=> 8888)
     (fact "the source of the line number can be a form"
       (:line (meta (positioned-form form-without-line-number form-with-line-number)))
-      => (:line (meta form-with-line-number)))))
+      => (:line (meta form-with-line-number)))
+    (fact "forms generated by macros don't have metadata"
+      (:line (meta (positioned-form form-without-line-number form-generated-by-macro)))
+      => 0)))

 (fact "compile-time-fallback-position returns current file name with the fallback line number"


[#429] apply-operation wip (with @peeb)

[#429] apply-operation wip (with @peeb)

--- backend/src/org/akvo/lumen/transformation/engine.clj
+++ backend/src/org/akvo/lumen/transformation/engine.clj
@@ -236,10 +236,43 @@
        :message (:getMessage e)})))

+#_;; -> "d3"
+
+(require '[clojure.string :as str])
+
+(defn next-derived-column-name [columns]
+  (let [nums (->> columns
+                  (map #(get % "columnName"))
+                  (filter #(str/starts-with? % "d"))
+                  (map #(subs % 1))
+                  (map #(Long/parseLong %)))]
+    (str "d"
+         (if (empty? nums)
+           1
+           (inc (apply max nums))))))
+
 (defmethod apply-operation :core/derive
   [tenant-conn table-name columns op-spec]
-  ;; This is where the magic will happen.
-  )
+  (let [code (get-in op-spec ["args" "code"])
+        column-title (get-in op-spec ["args" "newColumnTitle"])
+        column-type (get-in op-spec ["args" "newColumnType"])
+        column-name (next-derived-column-name columns)
+        transform (row-transform code)]
+    (doseq [row (select * from table-name)]
+      (let [row (row-context columns row)
+            val (row-transform row)]
+        (if (type= column-type (type val))
+          (insert into table-name (column-name) the-new-column (values))
+          (do ;; follow some error strategy
+            ))))
+    {:success? true
+     :execution-log [(format "Derived column %s" column-name)]
+     :columns (conj columns {"title" column-title
+                             "type" column-type
+                             "sort" nil
+                             "hidden" false
+                             "direction" nil
+                             "columnName" column-name})}))

 (hugsql/def-db-fns "org/akvo/lumen/transformation.sql")


Actually expose bytes=

Actually expose bytes=

--- src/caesium/byte_bufs.clj
+++ src/caesium/byte_bufs.clj
@@ -2,6 +2,8 @@
   "Byte buffer utilities, like conversions and length."
   (:require [byte-streams :as bs])
   (:import (java.nio ByteBuffer)))
+
+(def bytes= bs/bytes=)

 (defn ^ByteBuffer ->indirect-byte-buf
   "Convert buffer to a [[ByteBuffer]].


Reimplement test runner without using private methods

--- src/radicalzephyr/boot_junit.clj
+++ src/radicalzephyr/boot_junit.clj
@@ -2,6 +2,7 @@
   {:boot/export-tasks true}
   (:require [boot.core :as core])
   (:import org.junit.runner.JUnitCore
+           org.junit.runner.notification.RunListener
            (org.junit.internal JUnitSystem
                                RealSystem)
            (org.reflections Reflections
@@ -12,12 +13,6 @@
            (org.reflections.util ClasspathHelper
                                  ConfigurationBuilder
                                  FilterBuilder)))
-
-(defn invoke-private-method [obj fn-name-string & args]
-  (let [m (first (filter (fn [x] (.. x getName (equals fn-name-string)))
-                         (.. obj getClass getDeclaredMethods)))]
-    (. m (setAccessible true))
-    (. m (invoke obj (into-array Object args)))))

 (defn failure->map [failure]
   {:description (.. failure (getDescription) (toString))
@@ -49,20 +44,29 @@
          set
          vec)))

+(def run-listener
+  (proxy [RunListener]
+      []
+    (testRunStarted [description]
+      (println "Test started!"))
+    (testRunFinished [result]
+      (println "\nTest run finished!"))
+    (testStarted [description]
+      (print "."))
+    (testFinished [description]
+      (print "F"))))
+
 (core/deftask junit
   "Run the jUnit test runner."
   [p packages PACKAGE #{sym} "The set of Java packages to run tests in."]
   (core/with-pre-wrap fileset
     (if (seq packages)
-      (let [^JUnitCore core (JUnitCore.)
-            ^JUnitSystem system (RealSystem.)
-            result (invoke-private-method core "runMain"
-                                          system
-                                          (into-array String
-                                                      (map (memfn getName)
-                                                           (find-all-tests packages))))]
+      (let [^JUnitCore core (doto (JUnitCore.)
+                              (.addListener run-listener))
+            result (.run core
+                         (into-array Class
+                                     (find-all-tests packages)))]
         (when (> (.getFailureCount result) 0)
-          #_(throw (ex-info "There were some test failures."
-                            (result->map result)))))
+          (println (result->map result))))
       (println "No packages were tested."))
     fileset))


Fix insertion of blank lines by pprint

Fix insertion of blank lines by pprint

--- src/refactor_nrepl/ns/pprint.clj
+++ src/refactor_nrepl/ns/pprint.clj
@@ -64,15 +64,14 @@
   [[_ name & more :as ns-form]]
   (let [docstring? (when (string? (first more)) (first more))
         attrs? (when (map? (second more)) (second more))
-        forms (cond (and docstring? attrs?) (nthrest more 3)
+        forms (cond (and docstring? attrs?) (nthrest more 2)
                     (not (or docstring? attrs?)) more
                     :else (rest more))]
     (-> (with-out-str
-          (printf "(ns %s" name)
-          (when docstring? (printf "\n\"%s\"\n" docstring? ))
-          (when attrs? (println) (pprint attrs?))
-          (if forms
-            (println)
+          (printf "(ns %s\n" name)
+          (when docstring? (printf "\"%s\"\n" docstring? ))
+          (when attrs? (pprint attrs?))
+          (when-not forms
             (print ")"))
           (dorun
            (map-indexed


Add arithmetic rules that I missed from chapter 3

--- src/chapter3/leibniz.cljs
+++ src/chapter3/leibniz.cljs
@@ -57,15 +57,17 @@
                  (list '* (list 'exp (d 'e1) (list 'dec (d 'e2)))
                        (list 'd (d 'e1) (d 'v1)))))
    "diff-power-rule"])
-(def math-ladd-zero-rule ['(+ (? x) 0) #(% 'x) "math-ladd-zero-rule"])
-(def math-radd-zero-rule ['(+ 0 (? x)) #(% 'x) "math-radd-zero-rule"])
-(def math-lprod-zero-rule ['(* (? x) 0) (fn [d] 0) "math-lprod-zero-rule"])
-(def math-rprod-zero-rule ['(* 0 (? x)) (fn [d] 0) "math-rprod-zero-rule"])
-(def math-lprod-id-rule ['(* (? x) 1) #(% 'x) "math-lprod-id-rule"])
-(def math-rprod-id-rule ['(* 1 (? x)) #(% 'x) "math-rprod-id-rule"])
-(def math-exp-zero-rule ['(exp (? x) 0) (fn [d] 1) "math-exp-zero-rule"])
-(def math-exp-id-rule ['(exp (? x) 1) #(% 'x) "math-exp-id-rule"])
-(def math-dec-rule ['(dec (number-state? x)) #(dec (% 'x)) "math-dec-rule"])
+(def ladd-zero-rule ['(+ (? x) 0) #(% 'x) "ladd-zero-rule"])
+(def radd-zero-rule ['(+ 0 (? x)) #(% 'x) "radd-zero-rule"])
+(def add-const-rule ['(+ (number-state? x) (number-state? y)) #(+ (% 'x) (% 'y)) "add-const-rule"])
+(def lprod-zero-rule ['(* (? x) 0) (fn [d] 0) "lprod-zero-rule"])
+(def rprod-zero-rule ['(* 0 (? x)) (fn [d] 0) "rprod-zero-rule"])
+(def lprod-id-rule ['(* (? x) 1) #(% 'x) "lprod-id-rule"])
+(def rprod-id-rule ['(* 1 (? x)) #(% 'x) "rprod-id-rule"])
+(def prod-const-rule ['(* (number-state? x) (number-state? y)) #(* (% 'x) (% 'y)) "prod-const-rule"])
+(def exp-zero-rule ['(exp (? x) 0) (fn [d] 1) "exp-zero-rule"])
+(def exp-id-rule ['(exp (? x) 1) #(% 'x) "exp-id-rule"])
+(def dec-rule ['(dec (number-state? x)) #(dec (% 'x)) "dec-rule"])
 ; other rules go here ...

 ; TODO: Clojure HAS to have a class/record facility to do this...
@@ -75,7 +77,7 @@

 (def rules
   [[diff-sum-rule diff-x-rule diff-const-rule diff-product-rule diff-power-rule]
-   [math-ladd-zero-rule math-radd-zero-rule math-lprod-zero-rule math-rprod-zero-rule math-lprod-id-rule math-rprod-id-rule math-exp-zero-rule math-exp-id-rule math-dec-rule
+   [ladd-zero-rule radd-zero-rule add-const-rule lprod-zero-rule rprod-zero-rule lprod-id-rule rprod-id-rule prod-const-rule exp-zero-rule exp-id-rule dec-rule
     ]])

 ;;; control scheme ;;;
@@ -127,4 +129,6 @@
   (is (= 1 (control '(dec 2) rules)))
   (is (= '(+ (* 2 x) 2) (control '(d (+ (exp x 2) (* 2 x)) x) rules)))
   (is (= 2 (control '(+ (* x 0) (* 2 1)) rules)))
+  (is (= 2 (control '(+ 1 1) rules)))
+  (is (= 4 (control '(* 2 2) rules)))
   )


Add error check for nil mixer in ChannelMixer.

--- src/org/playasophy/wonderdome/system.clj
+++ src/org/playasophy/wonderdome/system.clj
@@ -10,7 +10,7 @@
 ;;;;; CHANNEL MIXER ;;;;;

 (defrecord ChannelMixer
-  [inputs output mix]
+  [inputs output mixer]

   component/Lifecycle

@@ -19,15 +19,16 @@
     (when-not output
       (throw (IllegalStateException.
                "ChannelMixer can't be started without an output channel")))
-    (let [mix (or (:mix this) (async/mix output))]
+    (let [mix (or (:mixer this) (async/mix output))]
       (doall (map (partial async/admix mix) inputs))
-      (assoc this :mix mix)))
+      (assoc this :mixer mix)))

   (stop
     [this]
-    (doall (map (partial async/unmix mix) inputs))
-    (assoc this :mix nil)))
+    (when mixer
+      (dorun (map (partial async/unmix mixer) inputs)))
+    (assoc this :mixer nil)))

 (defn mixer


CLJS-488: resolve aliased keywords properly

--- src/clj/cljs/analyzer.clj
+++ src/clj/cljs/analyzer.clj
@@ -655,6 +655,11 @@
                                      {alias :as referred :refer :or {alias lib}} (apply hash-map opts)
                                      [rk uk] (if macros? [:require-macros :use-macros] [:require :use])]
                                  (when alias
+                                   ;; we need to create a fake namespace so the reader knows about aliases
+                                   ;; for resolving keywords like ::f/bar
+                                   (binding [*ns* (create-ns name)]
+                                     (let [^clojure.lang.Namespace ns (create-ns lib)]
+                                       (clojure.core/alias alias (.name ns))))
                                    (let [alias-type (if macros? :macros :fns)]
                                      (assert (not (contains? (alias-type @aliases)
                                                              alias))


Cleaner binding

Cleaner binding

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -1587,9 +1587,7 @@
       (binding [*out* out
                 *cljs-ns* 'cljs.user
                 *cljs-file* (.getPath ^java.io.File src)
-                *data-readers* {'queue read-queue
-                                'uuid  read-uuid
-                                'inst  read-inst}
+                *data-readers* *cljs-data-readers*
                 *position* (atom [0 0])]
         (loop [forms (forms-seq src)
                ns-name nil


added methods to reserved words to fix gclosure compile warning WARNING - function methods masks variable (IE bug)

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -28,7 +28,7 @@
     "return" "short" "static" "super" "switch"
     "synchronized" "this" "throw" "throws"
     "transient" "try" "typeof" "var" "void"
-    "volatile" "while" "with" "yield"})
+    "volatile" "while" "with" "yield" "methods"})

 (defonce namespaces (atom '{cljs.core {:name cljs.core}
                             cljs.user {:name cljs.user}}))


#5 populate top-level form's env with *cljs-ns*, per load-stream

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -890,7 +890,8 @@
        (binding [*out* out
                  *cljs-ns* 'cljs.user]
          (doseq [form (forms-seq src)]
-           (emit (analyze {} form)))))))
+           (let [env {:ns (@namespaces *cljs-ns*) :context :statement :locals {}}]
+             (emit (analyze env form))))))))

 (comment
   ;; flex compile-file


don't emit def's w/o init. this prevents declares from appearing in
compiled code. we may want to revisit special handling for REPLs.

for spectral norm benchmark code this results in ~500 fewer lines
being emitted under pretty printed advanced compilation.

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -364,17 +364,16 @@
 (defmethod emit :def
   [{:keys [name var init env doc export]}]
   (let [mname (munge name)]
-    (emit-comment doc (:jsdoc init))
-    (emits var)
     (when init
+      (emit-comment doc (:jsdoc init))
+      (emits var)
       (emits " = " init)
       ;; NOTE: JavaScriptCore does not like this under advanced compilation
       ;; this change was primarily for REPL interactions - David
       ;(emits " = (typeof " mname " != 'undefined') ? " mname " : undefined")
-      )
-    (when-not (= :expr (:context env)) (emitln ";"))
-    (when export
-      (emitln "goog.exportSymbol('" (munge export) "', " mname ");"))))
+      (when-not (= :expr (:context env)) (emitln ";"))
+      (when export
+        (emitln "goog.exportSymbol('" (munge export) "', " mname ");")))))

 (defn emit-apply-to
   [{:keys [name params env]}]


Tune animation delay; should have be "rules for Game of Life").

--- src/cljs/beatha/core.cljs
+++ src/cljs/beatha/core.cljs
@@ -223,4 +223,4 @@
 (om/root (gen-app-view a/game-of-life)
          app-state
          {:target (. js/document (getElementById "app"))
-          :init-state {:animation-step 500}})
+          :init-state {:animation-step 750}})


* src/cljs/cljs/reader.cljs: add missing boolean type hints

--- src/cljs/cljs/reader.cljs
+++ src/cljs/cljs/reader.cljs
@@ -35,22 +35,22 @@
 ;; predicates
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-(defn- whitespace?
+(defn- ^boolean whitespace?
   "Checks whether a given character is whitespace"
   [ch]
   (or (gstring/isBreakingWhitespace ch) (identical? \, ch)))

-(defn- numeric?
+(defn- ^boolean numeric?
   "Checks whether a given character is numeric"
   [ch]
   (gstring/isNumeric ch))

-(defn- comment-prefix?
+(defn- ^boolean comment-prefix?
   "Checks whether the character begins a comment."
   [ch]
   (identical? \; ch))

-(defn- number-literal?
+(defn- ^boolean number-literal?
   "Checks whether the reader is at the start of a number literal"
   [reader initch]
   (or (numeric? initch)
@@ -70,7 +70,7 @@
   [rdr & msg]
   (throw (apply str msg)))

-(defn macro-terminating? [ch]
+(defn ^boolean macro-terminating? [ch]
   (and (coercive-not= ch "#")
        (coercive-not= ch \')
        (coercive-not= ch ":")


Pass some opts to project-row.

Pass some opts to project-row.

--- src/cljs/tunnit/core.cljs
+++ src/cljs/tunnit/core.cljs
@@ -40,20 +40,23 @@
    })

 (def project-seq
-  [{:id 111 :name "Projekti 1"
+  [{:id 111
+    :name "Projekti 1"
     :entries {
               1 {:hours 4.5}
               2 {:hours 7.5}
               }
     }
-   {:id 222 :name "Projekti 2"
+   {:id 222
+    :name "Projekti 2"
     :entries {
               1 {:hours 3.5}
               2 {:hours 0}
               3 {:hours 7.5}
               }
     }
-   {:id 333 :name "Projekti 3"
+   {:id 333
+    :name "Projekti 3"
     :entries {
               1 {:hours 3.5}
               2 {:hours 0}
@@ -85,9 +88,12 @@
 (defn week-dates []
   (map-kv day-map count-date))

-(defcomponent project-row [app]
+(defcomponent project-row [app owner m]
               (render [this]
-                      (map (fn []))
+                      (print (str "day: " (:day m)))
+                      (print (str "proj: " (get (first (:projects app)) :id)))
+                      ;(print (str "proj: " (:projects app)))
+                      (.log js/console app)
                       (ot/div {:class "hour-input"} nil
                               (ot/input {:class "hour-entry" :value 7.5})
                               )))
@@ -99,7 +105,9 @@
                                      (ot/div {:class "day-col"}
                                              (ot/output {:class "day-label"}
                                                         (str (:name day) " " (unparse-date (:date day))))
-                                             (om/build-all project-row (:projects app))))
+
+                                             (om/build-all project-row (:projects app) {:opts {:day key}})
+                                             ))
                                    (week-dates))
                               )))


Reorder geo functions to make reading slightly more intuitive

--- src/cljs_leaflet/geo.cljs
+++ src/cljs_leaflet/geo.cljs
@@ -16,6 +16,19 @@
                                        "Imagery © Mapbox")
                      :id "mapbox.streets"} }})

+; return L.map(div-id).setView(map-info.center, map-info.zoom);
+(defn instantiate-map! [div-id]
+  (.setView (.map js/L div-id)
+            (clj->js (:center map-info))
+            (:zoom map-info)))
+
+(defonce tile-layer
+  (.tileLayer js/L
+              (:url (:tiles map-info))
+              (clj->js (:options (:tiles map-info))) ))
+
+(defonce vector-layer (.layerGroup js/L))
+
 ;; cljsjs doesn't come with image assets, so substitute with circlemarker settings
 (defonce gj-marker-settings
   {:radius 8
@@ -25,21 +38,8 @@
    :opacity 1
    :fillOpacity 0.6} )

-; return L.map(div-id).setView(map-info.center, map-info.zoom);
-(defn instantiate-map! [div-id]
-  (.setView (.map js/L div-id)
-            (clj->js (:center map-info))
-            (:zoom map-info)))
-
 (defn point-to-layer [feature, latlng]  ;; http://leafletjs.com/examples/geojson.html
   (.circleMarker js/L latlng (clj->js gj-marker-settings)))
-
-(defonce tile-layer
-  (.tileLayer js/L
-              (:url (:tiles map-info))
-              (clj->js (:options (:tiles map-info))) ))
-
-(defonce vector-layer (.layerGroup js/L))

 (defn create-geojson [features]
   (let [fc {:type "FeatureCollection" :features features}]


adding started and finished to checkpoint entries

--- src/co/nclk/flax/node.clj
+++ src/co/nclk/flax/node.clj
@@ -192,10 +192,12 @@
     (assoc checkpoint :out {:keys (:out checkpoint)}
                       :err {:keys (:err checkpoint)}
                       :exit {:keys (:exit checkpoint) :value 0})
-    (if (= "local" (full-node-name self node))
-      (invoke-local checkpoint)
-      (invoke-remote checkpoint (get-node self node))
-      )
+    (let [ts (java.util.Date.)]
+      (assoc (if (= "local" (full-node-name self node))
+               (invoke-local checkpoint)
+               (invoke-remote checkpoint (get-node self node)))
+             :started (.getTime ts)
+             :finished (.getTime (java.util.Date.))))
     )
   (remove-node [self node] nodes)
   (full-node-name [self node]


(PDB-4308) Be more responsive to a shutdown request during init

It appears that db pool connection timeouts may still apply for any
connection attempts that start before the pool is closed.  Decrease
that timeout for the initialization/migrations pool so we'll respond
more quickly to a shutdown request (e.g. via C-c).

While decreasing the timeout to 3s makes pdb much more responsive, it
also causes a duplicate "connection has temporarily failed" log
message to appear every 3s.  To decrease the noise, suppress those
duplicates so that they appear no more than once per minute.

--- src/puppetlabs/puppetdb/cli/services.clj
+++ src/puppetlabs/puppetdb/cli/services.clj
@@ -344,7 +344,7 @@
   ;; SQLException.
   (with-open [db-pool (-> (assoc write-db-config
                                  :pool-name "PDBMigrationsPool"
-                                 :connection-timeout 15000)
+                                 :connection-timeout 3000)
                           (jdbc/make-connection-pool database-metrics-registry))]
     (let [runtime (Runtime/getRuntime)
           on-shutdown (doto (Thread.
@@ -356,13 +356,23 @@
                         (.setName "PuppetDB migration pool closer"))]
       (.addShutdownHook runtime on-shutdown)
       (try
-        (while (not (try
-                      (initialize-schema {:datasource db-pool} config)
-                      true
-                      (catch java.sql.SQLTransientConnectionException e
-                        (log/error (str (trs "Will retry database connection after temporary failure: ")
-                                        ex))
-                        false))))
+        (loop [i 0
+               last-ex nil]
+          (let [result (try
+                         (initialize-schema {:datasource db-pool} config)
+                         true
+                         (catch java.sql.SQLTransientConnectionException ex
+                           ;; When coupled with the 3000ms timout, this
+                           ;; is intended to log a duplicate message no
+                           ;; faster than once per minute.
+                           (when (or (not= (str ex) (str last-ex))
+                                     (zero? (mod i 20)))
+                             (log/error (str (trs "Will retry database connection after temporary failure: ")
+                                             ex)))
+                           ex))]
+            (if (true? result)
+              result
+              (recur (inc i) result))))
         (finally
           (try
             (.removeShutdownHook runtime on-shutdown)


Update examples to new create-session scheme

--- src/uruk/examples/types.clj
+++ src/uruk/examples/types.clj
@@ -3,8 +3,9 @@
   (:require [uruk.core :refer :all]))

 (def session
-  (create-session "xdbc://localhost:8383/"
-                  "rest-admin" "x" "TutorialDB" {}))
+  (create-session {:uri "xdbc://localhost:8383/"
+                   :user "rest-admin" :password "x"
+                   :content-base "TutorialDB"}))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;; Interfaces for JSON


Add connection & socket timeouts to s3 operations

Add connection and get/put specific socket timeouts to the s3
operations.

/cc @nmonterroso

--- src/vignette/storage/s3.clj
+++ src/vignette/storage/s3.clj
@@ -8,6 +8,10 @@
             [vignette.util.filesystem :refer :all])
   (:use [environ.core])
   (:import [com.amazonaws.services.s3.model AmazonS3Exception]))
+
+(def default-storage-connection-timeout 100)
+(def default-storage-get-socket-timeout 500)
+(def default-storage-put-socket-timeout 10000)

 (declare create-stored-object)

@@ -31,7 +35,10 @@
   (try
     (statsd/with-sampled-timing "vignette.s3.get"
                                 sample-rate
-                                (s3/get-object creds bucket path))
+                                (s3/get-object (merge creds
+                                                      {:conn-timeout (Integer. (env :storage-connection-timeout default-storage-connection-timeout))
+                                                       :socket-timeout (Integer. (env :storage-get-socket-timeout default-storage-get-socket-timeout))})
+                                               bucket path))
     (catch AmazonS3Exception e
       (if (= (.getStatusCode e) 404)
         nil
@@ -50,7 +57,9 @@
           mime-type (content-type resource)]
       (when-let [response (statsd/with-sampled-timing "vignette.s3.put"
                                                       sample-rate
-                                                      (s3/put-object (:creds this)
+                                                      (s3/put-object (merge (:creds this)
+                                                                            {:conn-timeout (Integer. (env :storage-connection-timeout default-storage-connection-timeout))
+                                                                             :socket-timeout (Integer. (env :storage-put-socket-timeout default-storage-put-socket-timeout))})
                                                                      bucket
                                                                      path
                                                                      file


Assert flat-list sequential data

Assert flat-list sequential data

Deals with vector-of-maps vs map-of-maps issues, e.g. map-of-maps hangs with
bad errors from React Native side

--- src/status_im/components/list/views.cljs
+++ src/status_im/components/list/views.cljs
@@ -86,6 +86,7 @@
   "A wrapper for FlatList.
    See https://facebook.github.io/react-native/docs/flatlist.html"
   [{:keys [data render-fn empty-component] :as props}]
+  {:pre [(sequential? data)]}
   (if (and (empty? data) empty-component)
     ;; TODO(jeluard) remove when native :ListEmptyComponent is supported
     empty-component


new bangs for jquery and underscore docs

--- src/xebang/models/bangs.clj
+++ src/xebang/models/bangs.clj
@@ -11,6 +11,8 @@
    '!js         "http://devdocs.io/#q=js {{{s}}}"
    '!css        "http://devdocs.io/#q=css {{{s}}}"
    '!html       "http://devdocs.io/#q=html {{{s}}}"
+   '!jquery     "http://devdocs.io/#q=jquery {{{s}}}"
+   '!underscore "http://devdocs.io/#q=underscore {{{s}}}"
    '!namecheap  "http://www.namecheap.com/domains/domain-name-search/results.aspx?domain={{{s}}}&tlds=&searchall=&type=single&"})

 (def mock-config


Correct error (function order)

Correct error (function order)

--- src/test_utils/fracture_diagnostics.cljc
+++ src/test_utils/fracture_diagnostics.cljc
@@ -412,16 +412,16 @@
         sigma (/ mean 6)]
     (tuc/draw-normal mean sigma)))

-(defn typical-monitor-pressure
-  ([] (take 1 (typical-monitor-pressure-seq)))
-  ([pressure-unit] (take 1 (typical-monitor-pressure-seq pressure-unit))))
-
 (defn typical-monitor-pressure-seq
   ([] (typical-monitor-pressure-seq (rand-pressure-unit)))
   ([pressure-unit] (cond (= pressure-unit :psi)
                          (map #(make-measurement % :psi) (p-mon-seq))
                          (= pressure-unit :kPa)
                          (map #(pressure-as % pressure-unit) (typical-monitor-pressure-seq :psi)))))
+
+(defn typical-monitor-pressure
+  ([] (take 1 (typical-monitor-pressure-seq)))
+  ([pressure-unit] (take 1 (typical-monitor-pressure-seq pressure-unit))))

 (def measured-at-location [:downhole :surface])


Add typical-density

Add typical-density

Previous commits ...

This commit ...

--- src/test_utils/fracture_diagnostics.cljc
+++ src/test_utils/fracture_diagnostics.cljc
@@ -8,27 +8,33 @@
   (rand-nth physical-quantities))

 (defn rand-unit [physical-quantity]
-  (let [quantity-units-map {:length [:ft :m]
+  (let [quantity-units-map {:density [:lb-per-cu-ft :kg-per-m3]
+                            :length [:ft :m]
                             :mass [:lb :kg]
                             :pressure [:psi :kPa :MPa]
-                            :volume [:bbl :m3]
+                            :proppant-concentration [:lb-per-gal :lb/gal :kg-per-m3 :kg/m3]
                             :slurry-rate [:bbl-per-min :bpm :m3-per-min :m3/min]
-                            :proppant-concentration [:lb-per-gal :lb/gal :kg-per-m3 :kg/m3]}]
+                            :volume [:bbl :m3]}]
+
+
     (fn [] (rand-nth (get quantity-units-map physical-quantity)))))

+(def rand-density-unit (rand-unit :density))
 (def rand-length-unit (rand-unit :length))
 (def rand-mass-unit (rand-unit :mass))
 (def rand-pressure-unit (rand-unit :pressure))
+(def rand-proppant-concentration-unit (rand-unit :proppant-concentration))
+(def rand-slurry-rate-unit (rand-unit :slurry-rate))
 (def rand-volume-unit (rand-unit :volume))
-(def rand-slurry-rate-unit (rand-unit :slurry-rate))
-(def rand-proppant-concentration-unit (rand-unit :proppant-concentration))
+
 (defn convert-units-f [from to]
   (let [factors {[:m :ft] 3.28084
                  [:kg :lb] 2.20462262185
                  [:m3 :bbl] 6.28981077
                  [:psi :kPa] 6.894757293168361
                  [:M :k] 1000
-                 [:lb-per-gal :kg-per-m3] 119.826}
+                 [:lb-per-gal :kg-per-m3] 119.826
+                 [:lb-per-cu-ft :kg-per-m3] 16.0185}
         converter {[:ft :m] #(/ % (factors [:m :ft]))
                    [:m :ft] #(* % (factors [:m :ft]))
                    [:lb :kg] #(/ % (factors [:kg :lb]))
@@ -43,6 +49,8 @@
                    [:kg-per-m3 :lb-per-gal] #(/ % (factors [:lb-per-gal :kg-per-m3]))
                    [:m3-per-min :bbl-per-min] #(* % (factors [:m3 :bbl]))
                    [:bbl-per-min :m3-per-min] #(/ % (factors [:lb-per-gal :kg-per-m3]))
+                   [:lb-per-cu-ft :kg-per-m3] #(* % (factors [:lb-per-cu-ft :kg-per-m3]))
+                   [:kg-per-m3 :lb-per-cu-ft] #(/ % (factors [:lb-per-cu-ft :kg-per-m3]))
                    [:C :F] #(+ (* % 1.8) 32)}]
     (converter [from to])))

@@ -499,3 +507,38 @@
      :psi (tuc/draw-normal 7569.89 663.65)
      :kPa (tuc/draw-normal 64.1635 7.0987)
      :MPa (/ (typical-median-pressure :kPa) 1000))))
+
+(def substances [:gas :liquid :rock :metal])
+
+(defn typical-density
+  ([]
+   (let [density-unit (rand-density-unit)
+         substance (rand-nth substances)]
+     (typical-density density-unit substance)))
+  ([density-unit-or-substance]
+   (let [is-density-unit (fn [to-test] (#{:kg-per-m3 :lb-per-cu-ft} to-test))
+         is-substance (fn [to-test] ((set substances) to-test))
+         [density-unit substance] (cond
+                                      (is-density-unit density-unit-or-substance)
+                                      [density-unit-or-substance (rand-nth substances)]
+                                      (is-substance density-unit-or-substance)
+                                      [(rand-nth [:kg-per-m3 :lb-per-cu-ft]) density-unit-or-substance])]
+     (typical-density density-unit substance)))
+  ([density-unit substance]
+   (condp = density-unit
+     :lb-per-cu-ft (let [[density density-unit substance] (typical-density :kg-per-m3)]
+                     [((convert-units-f :kg-per-m3 :lb-per-cu-ft) density) :lb-per-cu-ft substance])
+     :kg-per-m3 (condp = substance
+                  ;; Typical values for different substances taken from
+                  ;; https://serc.carleton.edu/mathyouneed/density/index.html#:~:text=Typical%20densities%20for%20gasses%20are,or%207%20g%2Fcm3.
+                  ;; accessed on 23-Dec-2020. Additionally, the data for metals was taken from
+                  ;; https://theengineeringmindset.com/density-of-metals/ accessed on 23-Dec-2020.
+                  (let [density (condp = substance
+                                  :gas (tuc/draw-normal 1 0.11)
+                                  :liquid (tuc/draw-normal 1000 110)
+                                  :rock (tuc/draw-normal 3000 330)
+                                  :metal (tuc/draw-normal) 10355 5431)]
+                    [density density-unit substance])))))
+
+
+


Typical stage completion changeover

Typical stage completion changeover

--- src/test_utils/fracture_diagnostics.cljc
+++ src/test_utils/fracture_diagnostics.cljc
@@ -162,6 +162,21 @@
   ([] (second (typical-stage-extent)))
   ([length-unit]
    (second (typical-stage-extent (constantly (typical-stage-top length-unit))))))
+
+(defn typical-stage-completion-changeover
+  "Calculates the typical (empirically determined) time (in seconds) to change completion operationss from one stage to another"
+  ([]
+   (let [global-stage-seq-no (tuc/rand-range 150)]
+     (typical-stage-completion-changeover global-stage-seq-no)))
+  ([global-stage-seq-no]
+   ;; Empirically, a model for generating these times seems to be a generally linearly decreasing component (the team gets
+   ;; better at changeover as the job goes on) with a "normally distibuted" "noise" or error component (with a large variance).
+   ;; (I think I may have miscalculated this component)
+   (let [slope -38.5634
+         intercept 10115.1
+         noise (tuc/draw-normal 0 1555.5)]
+     (+ (+ (* slope global-stage-seq-no) intercept)
+        noise))))

 (defn rand-easting []
   (let [minimum-easting 167000


matcher-combinators: Consolidate `match-with-explicit-matchers-test`

--- test/com/nomistech/clojure_the_language/c_800_libraries/s_106_matcher_combinators/matcher_generators_test.clj
+++ test/com/nomistech/clojure_the_language/c_800_libraries/s_106_matcher_combinators/matcher_generators_test.clj
@@ -11,6 +11,14 @@
 ;;;; ++use-of-mismatch++
 ;;;; We use `m/mismatch` to demo what would otherwise be failing tests.
 ;;;; Note that `m/mismatch` should generally be avoided.
+
+(deftest match-with-explicit-matchers-test
+  ;; TODO: When is this useful? /eg/ Just `(is (match? 37 (+ 29 8)))`
+  ;;       works fine.
+  (is (match? (m/equals 37)
+              (+ 29 8)))
+  (is (match? (m/regex #"fox")
+              "The quick brown fox jumps over the lazy dog")))

 (deftest most-scalars-use-equality-test
   ;; Most scalar values are interpreted as an `equals` matcher.
@@ -31,12 +39,6 @@
   (is (match? (m/pred even?)
               1234)) ; TODO: I guess we need this in contexts where `even?` would not be treated as a pred -- but what are those contexts?
   )
-
-(deftest first-equals-example-from-documentation-test
-  ;; From https://github.com/nubank/matcher-combinators
-  ;; TODO: Why this? Just `(is (match? 37 (+ 29 8)))` works fine.
-  (is (match? (m/equals 37)
-              (+ 29 8))))

 (deftest equals-overrides-predicate-test
   (is (match? (m/equals even?)
@@ -89,11 +91,6 @@

 ;;;; From docs

-(deftest test-matching-with-explicit-matchers
-  ;; TODO: When is this useful?
-  (is (match? (m/equals 37) (+ 29 8)))
-  (is (match? (m/regex #"fox") "The quick brown fox jumps over the lazy dog")))
-
 (deftest test-matching-sequences
   ;; A sequence is interpreted as an `equals` matcher, which specifies
   ;; count and order of matching elements. The elements, themselves,


Fix branch changing within project insights

--- src-cljs/frontend/controllers/controls.cljs
+++ src-cljs/frontend/controllers/controls.cljs
@@ -1383,7 +1383,7 @@
   [target message {:keys [new-branch]} _ current-state]
   (let [nav-data (get-in current-state [:navigation-data])
         comms (get-in current-state [:comms])]
-    (put! (:nav comms) [:navigate! {:path (routes/v1-insights-project (assoc nav-data :branch new-branch))}])
+    (put! (:nav comms) [:navigate! {:path (routes/v1-insights-project-path (assoc nav-data :branch new-branch))}])
     (analytics/track {:event-type :project-branch-changed
                       :current-state current-state
                       :properties {:new-branch new-branch}})))


element macro asserts it's in a component

Also, its body is an implicit do.

--- src-cljs/frontend/utils.clj
+++ src-cljs/frontend/utils.clj
@@ -160,9 +160,10 @@

 (defmacro element
   "Assigns an element name (a data-element attribute) to a React element.
-  body should be an expression which returns a React element (such as a call to
-  sablono.core/html) and element-name should be an unqualified keyword which is
-  unique within the component.
+  `body` is wrapped in an implicit `do`, and should evaluate to a React
+  element (such as a call to `sablono.core/html`).`name` is an unqualified
+  keyword. The full element name will take the form
+  `component-namespace/component-name/element-name`

   The element macro is used to give a component-namespaced identifier to a DOM
   node which is passed to another component as a param. Without this, the
@@ -219,8 +220,10 @@
         > .books > li > .title

   That will always match exactly the node we mean."
-  [element-name body]
+  [element-name & body]
   (assert (and (keyword? element-name)
                (nil? (namespace element-name)))
           (str "Element name should be given as an unqualified keyword, but was given as " (prn-str element-name)))
-  `(element* ~(name element-name) ~component-name-symbol ~body))
+  (assert (contains? (:locals &env) component-name-symbol)
+          "element form must appear within a component form.")
+  `(element* ~(name element-name) ~component-name-symbol (do ~@body)))


Added an anchor tag to facilitate keyboard only naving.

--- src-cljs/tea_time/core.cljs
+++ src-cljs/tea_time/core.cljs
@@ -191,7 +191,8 @@
             :style {:margin-right "10px"}}
            "Delete"]]]
         [:tr {:on-click #(swap! edit? not)}
-         [:td.pull-left (:name tea)]]))))
+          [:td.pull-left
+           [:a (:name tea)]]]))))

 (defn tealister
   "The page component for listing tea"


update

update


separation of concern for logs

separation of concern for logs

--- src/clj/algorithms_clj/macro_initiation.clj
+++ src/clj/algorithms_clj/macro_initiation.clj
@@ -4,7 +4,7 @@
     ))

-(set! *warn-on-reflection* true)
+;; (set! *warn-on-reflection* true)
 ;; (set! *unchecked-math* :warn-on-boxed)

@@ -400,10 +400,10 @@
 ;; Macros can help address operational constraints
 ;; --------------------------------------------------------

-(defn log-enter-message
-  "Returns the log message for the function and its arguments"
-  [log-prefix arg-names arg-values]
-  (str log-prefix (zipmap arg-names arg-values)))
+(defn log-symbol-values
+  "Log the values of a list of symbols, with a prefix"
+  [prefix symbols values]
+  (str prefix (zipmap symbols values)))

 (defn bindings->bound-vars
   "Clean the bindings to remove the restructuring artifacts"
@@ -421,7 +421,7 @@
 (defn compile-log-message
   [fct-name binding-vec]
   (let [bindings (bindings->bound-vars binding-vec)]
-    `(log-enter-message
+    `(log-symbol-values
        ~(log-prefix fct-name)
        (quote ~bindings)
        ~bindings)))
@@ -436,6 +436,10 @@
 (defn-log add-with-log
   [a b]
   (+ a b))
+
+(defn-log repeat-n
+  [n s]
+  (apply str (repeat n s)))

 (defn test-add-with-log
   []


fix issue with printing win/loss on playerlog

--- src/cljs/foosball/locations/player-log.cljs
+++ src/cljs/foosball/locations/player-log.cljs
@@ -51,7 +51,11 @@
                               :key     :expected
                               :printer (fn [v] (when v (f/style-match-percentage true (* 100 v))))}
                              {:heading "Actual"
-                              :key     :win?}
+                              :key     :win?
+                              :printer (fn [v] (f/style-value v
+                                                             :class?  nil
+                                                             :printer {true "Won" false "Lost"}
+                                                             :checker true?))}
                              {:heading "Inactive matches"
                               :key     :inactivity}
                              {:heading "Diff rating"


Rename release-bindings to release-bindings!

--- src/clojure/uncomplicate/clojurecl/core.clj
+++ src/clojure/uncomplicate/clojurecl/core.clj
@@ -96,7 +96,7 @@
        :doc "Dynamic var for binding the default command queue."}
   *command-queue*)

-(defn release-bindings
+(defn release-bindings!
   "Release global platform, context, and command queue (if any exists)."
   []
   (release *platform*)


accept filename on command line

accept filename on command line

--- src/nml/core.clj
+++ src/nml/core.clj
@@ -53,7 +53,7 @@
              :ws       ""
              :wsopt    ""))))

-(defn -main
-  [& args]
+(defn -main [& args]
   (alter-var-root #'*read-eval* (constantly false))
-  (println (prpr (nml "a"))))
+  (let [namelist-file (last args)]
+    (println (prpr (nml (slurp "nl"))))))