Reformatted src/clj_flotr/examples.clj by zprint

--- src/clj_flotr/examples.clj
+++ src/clj_flotr/examples.clj
@@ -23,64 +23,66 @@
 ; the function (generator/pie-chart) could be used.
 ;
 (defn test-pie-charts
-    "Creates HTML page with various types of pie-charts."
-    []
-    (let [data [{:values 10 :label "foo"}
-                {:values 10 :label "bar"}
-                {:values 30 :label "baz"}]]
-        (spit "test-pie-charts.html" (page/xhtml
-            [:head
-                [:title "Test Pie Charts"]
-                [:meta {:name "Generator" :content "Clojure"}]
-                [:meta {:http-equiv "Content-type" :content "text/html; charset=utf-8"}]
-                ; we need to include all Flotr JavaScript libraries.
-                (generator/flotr-scripts nil nil nil)
-            ]
-            [:body
-                [:h1 "Test Pie Charts"]
-                [:table
-                    [:tr
-                        [:td (generator/pie-chart "chart1" "300px" "300px" data)]
-                        [:td (generator/pie-chart "chart2" "300px" "300px" data
-                                :vertical-lines true)]
-                        [:td (generator/pie-chart "chart3" "300px" "300px" data
-                                :horizontal-lines true)]
-                        [:td (generator/pie-chart "chart4" "300px" "300px" data
-                                :horizontal-lines true
-                                :vertical-lines true)]
-                    ] ; </tr>
-                    [:tr
-                        [:td (generator/pie-chart "chart5" "300px" "300px" data
-                                 :show-legend true)]
-                        [:td (generator/pie-chart "chart6" "300px" "300px" data
-                                 :show-legend true
-                                 :legend-position "sw")]
-                        [:td (generator/pie-chart "chart7" "300px" "300px" data
-                                 :show-legend true
-                                 :legend-position "ne"
-                                 :legend-background "#D2E8FF")]
-                        [:td (generator/pie-chart "chart8" "300px" "300px" data
-                                 :show-legend true
-                                 :legend-position "sw"
-                                 :legend-background "#FFFFFF")]
-                    ] ; </tr>
-                    [:tr
-                        [:td (generator/pie-chart "chart9" "300px" "300px" data
-                                 :title "Chart title")]
-                        [:td (generator/pie-chart "chart10" "300px" "300px" data
-                                 :subtitle "Chart subtitle")]
-                        [:td (generator/pie-chart "chart11" "300px" "300px" data
-                                 :title "Chart title"
-                                 :subtitle "Chart subtitle")]
-                        [:td (generator/pie-chart "chart12" "300px" "300px" data
-                                 :show-legend true
-                                 :legend-position "sw"
-                                 :legend-background "#FFFFFF"
-                                 :title "Chart title"
-                                 :subtitle "Chart subtitle")]
-                    ] ; </tr>
-                ] ; </table>
-                [:h1 "done"]]))))
+  "Creates HTML page with various types of pie-charts."
+  []
+  (let [data [{:values 10, :label "foo"}
+              {:values 10, :label "bar"}
+              {:values 30, :label "baz"}]]
+    (spit
+      "test-pie-charts.html"
+      (page/xhtml
+        [:head
+         [:title "Test Pie Charts"]
+         [:meta {:name "Generator", :content "Clojure"}]
+         [:meta {:http-equiv "Content-type", :content "text/html; charset=utf-8"}]
+         ; we need to include all Flotr JavaScript libraries.
+         (generator/flotr-scripts nil nil nil)
+        ]
+        [:body
+         [:h1 "Test Pie Charts"]
+         [:table
+                  [:tr
+                           [:td (generator/pie-chart "chart1" "300px" "300px" data)]
+                           [:td (generator/pie-chart "chart2" "300px" "300px" data
+                                   :vertical-lines true)]
+                           [:td (generator/pie-chart "chart3" "300px" "300px" data
+                                   :horizontal-lines true)]
+                           [:td (generator/pie-chart "chart4" "300px" "300px" data
+                                   :horizontal-lines true
+                                   :vertical-lines true)]
+                  ] ; </tr>
+                  [:tr
+                           [:td (generator/pie-chart "chart5" "300px" "300px" data
+                                    :show-legend true)]
+                           [:td (generator/pie-chart "chart6" "300px" "300px" data
+                                    :show-legend true
+                                    :legend-position "sw")]
+                           [:td (generator/pie-chart "chart7" "300px" "300px" data
+                                    :show-legend true
+                                    :legend-position "ne"
+                                    :legend-background "#D2E8FF")]
+                           [:td (generator/pie-chart "chart8" "300px" "300px" data
+                                    :show-legend true
+                                    :legend-position "sw"
+                                    :legend-background "#FFFFFF")]
+                  ] ; </tr>
+                  [:tr
+                           [:td (generator/pie-chart "chart9" "300px" "300px" data
+                                    :title "Chart title")]
+                           [:td (generator/pie-chart "chart10" "300px" "300px" data
+                                    :subtitle "Chart subtitle")]
+                           [:td (generator/pie-chart "chart11" "300px" "300px" data
+                                    :title "Chart title"
+                                    :subtitle "Chart subtitle")]
+                           [:td (generator/pie-chart "chart12" "300px" "300px" data
+                                    :show-legend true
+                                    :legend-position "sw"
+                                    :legend-background "#FFFFFF"
+                                    :title "Chart title"
+                                    :subtitle "Chart subtitle")]
+                  ] ; </tr>
+         ] ; </table>
+         [:h1 "done"]]))))

@@ -90,66 +92,68 @@
 ; the function (generator/line-chart) could be used.
 ;
 (defn test-line-charts
-    "Creates HTML page with various types of line-charts."
-    []
-    (let [data [{:values [[1 1] [2 2] [3 3]] :label "foo"}
-                {:values [[1 0] [2 5] [3 0]] :label "bar"}
-                {:values [[1 4] [2 2] [3 4]] :label "baz"}]]
-        (spit "test-line-charts.html" (page/xhtml
-            [:head
-                [:title "Test Line Charts"]
-                [:meta {:name "Generator" :content "Clojure"}]
-                [:meta {:http-equiv "Content-type" :content "text/html; charset=utf-8"}]
-                ; we need to include all Flotr JavaScript libraries.
-                (generator/flotr-scripts nil nil nil)
-            ]
-            [:body
-                [:h1 "Test Line Charts"]
-                [:table
-                    [:tr
-                        [:td (generator/line-chart "chart1" "300px" "300px" data)]
-                        [:td (generator/line-chart "chart2" "300px" "300px" data
-                                :vertical-lines true)]
-                        [:td (generator/line-chart "chart3" "300px" "300px" data
-                                :horizontal-lines true)]
-                        [:td (generator/line-chart "chart4" "300px" "300px" data
-                                :horizontal-lines true
-                                :vertical-lines true)]
-                    ] ; </tr>
-                    [:tr
-                        [:td (generator/line-chart "chart5" "300px" "300px" data
-                                 :show-legend true)]
-                        [:td (generator/line-chart "chart6" "300px" "300px" data
-                                 :show-legend true
-                                 :legend-position "sw")]
-                        [:td (generator/line-chart "chart7" "300px" "300px" data
-                                 :show-legend true
-                                 :legend-position "ne"
-                                 :legend-background "#D2E8FF")]
-                        [:td (generator/line-chart "chart8" "300px" "300px" data
-                                 :show-legend true
-                                 :legend-position "sw"
-                                 :legend-background "#FFFFFF")]
-                    ] ; </tr>
-                    [:tr
-                        [:td (generator/line-chart "chart9" "300px" "300px" data
-                                 :title "Chart title")]
-                        [:td (generator/line-chart "chart10" "300px" "300px" data
-                                 :subtitle "Chart subtitle")]
-                        [:td (generator/line-chart "chart11" "300px" "300px" data
-                                 :title "Chart title"
-                                 :subtitle "Chart subtitle")]
-                        [:td (generator/line-chart "chart12" "300px" "300px" data
-                                 :title "Chart title"
-                                 :subtitle "Chart subtitle"
-                                 :horizontal-lines true
-                                 :vertical-lines true
-                                 :show-legend true
-                                 :legend-position "sw"
-                                 :legend-background "#FFFFFF")]
-                    ] ; </tr>
-                ] ; </table>
-                [:h1 "done"]]))))
+  "Creates HTML page with various types of line-charts."
+  []
+  (let [data [{:values [[1 1] [2 2] [3 3]] :label "foo"}
+              {:values [[1 0] [2 5] [3 0]] :label "bar"}
+              {:values [[1 4] [2 2] [3 4]] :label "baz"}]]
+    (spit
+      "test-line-charts.html"
+      (page/xhtml
+        [:head
+         [:title "Test Line Charts"]
+         [:meta {:name "Generator", :content "Clojure"}]
+         [:meta {:http-equiv "Content-type", :content "text/html; charset=utf-8"}]
+         ; we need to include all Flotr JavaScript libraries.
+         (generator/flotr-scripts nil nil nil)
+        ]
+        [:body
+         [:h1 "Test Line Charts"]
+         [:table
+                  [:tr
+                 [:td (generator/line-chart "chart1" "300px" "300px" data)]
+                 [:td (generator/line-chart "chart2" "300px" "300px" data
+                         :vertical-lines true)]
+                 [:td (generator/line-chart "chart3" "300px" "300px" data
+                         :horizontal-lines true)]
+                 [:td (generator/line-chart "chart4" "300px" "300px" data
+                         :horizontal-lines true
+                         :vertical-lines true)]
+                  ] ; </tr>
+                  [:tr
+                 [:td (generator/line-chart "chart5" "300px" "300px" data
+                          :show-legend true)]
+                 [:td (generator/line-chart "chart6" "300px" "300px" data
+                          :show-legend true
+                          :legend-position "sw")]
+                 [:td (generator/line-chart "chart7" "300px" "300px" data
+                          :show-legend true
+                          :legend-position "ne"
+                          :legend-background "#D2E8FF")]
+                 [:td (generator/line-chart "chart8" "300px" "300px" data
+                          :show-legend true
+                          :legend-position "sw"
+                          :legend-background "#FFFFFF")]
+                  ] ; </tr>
+                  [:tr
+                 [:td (generator/line-chart "chart9" "300px" "300px" data
+                          :title "Chart title")]
+                 [:td (generator/line-chart "chart10" "300px" "300px" data
+                          :subtitle "Chart subtitle")]
+                 [:td (generator/line-chart "chart11" "300px" "300px" data
+                          :title "Chart title"
+                          :subtitle "Chart subtitle")]
+                 [:td (generator/line-chart "chart12" "300px" "300px" data
+                          :title "Chart title"
+                          :subtitle "Chart subtitle"
+                          :horizontal-lines true
+                          :vertical-lines true
+                          :show-legend true
+                          :legend-position "sw"
+                          :legend-background "#FFFFFF")]
+             ] ; </tr>
+         ] ; </table>
+         [:h1 "done"]]))))

@@ -159,12 +163,14 @@
 ; the function (generator/stacked-bars) could be used.
 ;
 (defn test-stacked-bars
-    "Creates HTML page with various types of stacked-bars chart."
-    []
-    (let [data [{:values [[0 1] [1 2] [2 3] [3 3]] :label "foo"}
-                {:values [[0 1] [1 4] [2 6] [3 6]] :label "bar"}
-                {:values [[0 0] [1 1] [2 0] [3 0]] :label "baz"}]]
-        (spit "test-stacked-bars.html" (page/xhtml
+  "Creates HTML page with various types of stacked-bars chart."
+  []
+  (let [data [{:values [[0 1] [1 2] [2 3] [3 3]], :label "foo"}
+              {:values [[0 1] [1 4] [2 6] [3 6]], :label "bar"}
+              {:values [[0 0] [1 1] [2 0] [3 0]], :label "baz"}]]
+    (spit
+      "test-stacked-bars.html"
+      (page/xhtml
             [:head
                 [:title "Test Stacked Bars"]
                 [:meta {:name "Generator" :content "Clojure"}]


Better colortest for colorized messages

Better colortest for colorized messages

--- src/clj_mrazik/irc_bot.clj
+++ src/clj_mrazik/irc_bot.clj
@@ -156,7 +156,7 @@
                           "Good bot" "I know"
                           "Good bot." "I know"
                           "rainbow"   (apply str (for [color (range 16)]
-                                                     (str (char 3) (format "%02d" color) "test" (char 3) "99")))
+                                                     (str (char 3) (format "%02d" color) (format "test%02d " color) (char 3) "99")))
                           (cond
                               (and number-cruncher? (is-number? input))               (print-prime-factors input)
                               (and number-cruncher? (is-two-numbers? input))          (print-gcd input)


Minor refactoring. Using threading macro, tidying up and destructoring bulk op.

--- src/clj_ravendb/client.clj
+++ src/clj_ravendb/client.clj
@@ -21,9 +21,9 @@
   (client/get url {:as :json-string-keys}))

 (defn- is-valid-client?
-  [{:keys [address replications replicated? master-only-write?]}]
+  [{:keys [address replications replicated? master-only-writes?]}]
   {:pre [(not-nil? address) (not-nil? replications)
-         (not-nil? replicated?) (not-nil? master-only-write?)]}
+         (not-nil? replicated?) (not-nil? master-only-writes?)]}
   true)

 (defn- no-retry-replicas
@@ -50,11 +50,11 @@

   Optionally takes a map of options.
   :replicated? is used to find replicated endpoints.
-  :master-only-write? is used to indicate that write operations only go to the master"
+  :master-only-writes? is used to indicate that write operations only go to the master"
   ([url database]
    (client url database {}))
-  ([url database {:keys [replicated? master-only-write?]
-                  :or {replicated? false master-only-write? true}}]
+  ([url database {:keys [replicated? master-only-writes?]
+                  :or {replicated? false master-only-writes? true}}]
    (let [fragments (list url "Databases" database)
          address (clojure.string/join "/" fragments)
          load-replications (fn []
@@ -65,7 +65,7 @@
                         '())]
     {
      :replicated? replicated?
-     :master-only-write? master-only-write?
+     :master-only-writes? master-only-writes?
      :address address
      :replications (map (fn
                           [r]
@@ -86,9 +86,9 @@
     {:keys [request-builder response-parser]
      :or {request-builder req/load-documents response-parser res/load-documents}}]
    {:pre [(client? client) (not-empty document-ids)]}
-   (let [request (request-builder client document-ids)
-         response (wrap-retry-replicas request post-req)]
-     (response-parser response))))
+   (-> (request-builder client document-ids)
+       (wrap-retry-replicas post-req)
+       (response-parser))))

 (defn bulk-operations
   "Handles a given set of bulk operations that
@@ -99,19 +99,19 @@
   :response-parser is a customer response parser fn."
   ([client operations]
    (bulk-operations client operations {}))
-  ([client operations
+  ([{:keys [master-only-writes?] :as client}
+    operations
     {:keys [request-builder response-parser]
      :or {request-builder req/bulk-operations response-parser res/bulk-operations}}]
    {:pre [(client? client)
           (not-empty (filter
                        (comp not nil?)
-                       (map (fn[op]
+                       (map (fn[{:keys [Method Document Metadata Key]}]
                               (cond
-                                (= (:Method op) "PUT") (and (:Document op) (:Metadata op) (:Key op))
-                                (= (:Method op) "DELETE") (:Key op))) operations)))]}
-   (let [request (req/bulk-operations client operations)
-         master-only-write? (:master-only-write? client)]
-     (response-parser (if master-only-write?
+                                (= Method "PUT") (and Document Metadata Key)
+                                (= Method "DELETE") Key)) operations)))]}
+   (let [request (req/bulk-operations client operations)]
+     (response-parser (if master-only-writes?
                         (no-retry-replicas request post-req)
                         (wrap-retry-replicas request post-req))))))

@@ -135,9 +135,9 @@
      :or {request-builder req/put-index response-parser res/put-index}}]
    {:pre [(client? client)
           (:name index) (:alias index) (:where index) (:select index)]}
-   (let [request (request-builder client index)
-         response (put-req request)]
-     (response-parser response))))
+   (-> (request-builder client index)
+       (put-req)
+       (response-parser))))

 (defn put-document
   "Creates or updates a document by its key. Where 'document'
@@ -180,11 +180,10 @@
                          request-builder req/query-index
                          response-parser res/query-index}}]
    {:pre [(client? client) (:index query)]}
-   (let [get-result (fn
-                      []
-                      (response-parser
-                        (wrap-retry-replicas
-                          (request-builder client query) get-req)))]
+   (let [get-result (fn[]
+                      (-> (request-builder client query)
+                          (wrap-retry-replicas get-req)
+                          (response-parser)))]
      (loop [result (get-result) attempt 0]
        (if (or (not (:stale? result))
                (= attempt max-attempts))


Improve performance of FASTA reading

Improve performance of FASTA reading

--- src/cljam/fasta/reader.clj
+++ src/cljam/fasta/reader.clj
@@ -82,18 +82,16 @@
 (def newline? (memoize newline*?))

 (defn- read-sequence-with-offset
-  [rdr offset-start offset-end]
+  [^FASTAReader rdr offset-start offset-end]
   (let [len (- offset-end offset-start)
         ba (byte-array len)
-        r (.reader rdr)
-        buf (StringBuffer. len)]
-    (.seek r offset-start)
-    (.read r ba 0 len)
-    (doseq [b ^byte ba]
-      (let [c (char ^byte b)]
-        (when-not (newline? c)
-          (.append buf (Character/toUpperCase c)))))
-    (.toString buf)))
+        r ^RandomAccessFile (.reader rdr)]
+    (doto r
+      (.seek offset-start)
+      (.read ba 0 len))
+    (-> (String. ba)
+        (cstr/replace #"\n" "")
+        cstr/upper-case)))

 (defn read-whole-sequence
   [^FASTAReader rdr name]
@@ -111,10 +109,10 @@
 (defn read
   "Reads FASTA sequence data, returning its information as a lazy sequence."
   [^FASTAReader rdr]
-  (let [r (.reader rdr)]
+  (let [r ^RandomAccessFile (.reader rdr)]
     (read* (.readLine r) r)))

 (defn reset
   [^FASTAReader rdr]
-  (let [r (.reader rdr)]
+  (let [r ^RandomAccessFile (.reader rdr)]
     (.seek r 0)))


Added some comments.

Added some comments.

--- src/cljs/geometer/app.cljs
+++ src/cljs/geometer/app.cljs
@@ -11,14 +11,23 @@
             [thi.ng.geom.webgl.animator :refer [animate]]
             [thi.ng.geom.webgl.shaders.basic :as basic]))

+;; we use defonce for the webgl context and mouse tracking atoms so
+;; they won't be re-initialed when the namespace is reloaded
+(defonce gl (gl/gl-context "main"))
+(defonce view-rect (gl/get-viewport-rect gl))
 (defonce mouse-x (atom 0))
 (defonce mouse-y (atom 0))

-(defonce gl (gl/gl-context "main"))
-(defonce view-rect (gl/get-viewport-rect gl))
-
 (def model
+  "Our model is a collection of vertices and colors that will be rendered by the animation loop started in `start`."
+  ;; This vector of 1s and -1s is a pattern that represents the
+  ;; relative positions of a series of points that make a series of
+  ;; triangles that make a cube. We add some random jitter to those
+  ;; points to make the shape slightly more interesting. Removing the
+  ;; call to `(rand)` will cause the cube to coalesce.
   (let [vertices (map #(* % (+ 0.3 (* 0.3 (rand)))) [1 -1 1 1 -1 -1 1 1 -1 1 -1 1 1 1 -1 1 1 1 -1 -1 -1 -1 -1 1 -1 1 1 -1 -1 -1 -1 1 1 -1 1 -1 -1 1 -1 -1 1 1 1 1 1 -1 1 -1 1 1 1 1 1 -1 -1 -1 -1 1 -1 -1 1 -1 1 -1 -1 -1 1 -1 1 -1 -1 1 -1 -1 1 1 -1 1 1 1 1 -1 -1 1 1 1 1 -1 1 1 -1 -1 -1 -1 1 -1 1 1 -1 -1 -1 -1 1 1 -1 1 -1 -1])
+        ;; We color the six points for the six faces of the cube by
+        ;; repeating each of these six colors six times.
         colors   (flatten (map (partial repeat 6)
                                [[0.9 0.3 0.3 1]
                                 [0.3 0.9 0.3 1]
@@ -26,6 +35,8 @@
                                 [0.9 0.9 0.3 1]
                                 [0.9 0.3 0.9 1]
                                 [0.0 0.9 0.9 1]]))]
+    ;; ... and then pack it all into a data structure that geom's
+    ;; WebGL interface understands
     (-> {:attribs {:position {:data (arrays/float32 vertices) :size 3}
                    :color    {:data (arrays/float32 colors) :size 4}}
          :uniforms     {:proj (gl/perspective 45 view-rect 0.1 100.0)
@@ -36,7 +47,9 @@
                             (sh/make-shader-from-spec gl))}
                       (buf/make-attribute-buffers-in-spec gl gl/static-draw))))

-(defn ^:export start []
+(defn ^:export start
+  "This function is called when `index.html` is loaded. We use it to kick off the mouse tracking function and the animation loop."
+  []
   (.addEventListener
    js/document "mousemove"
    #(do


Fixing style regression

Fixing style regression

The URL on the info alert for the reminders was showing up as blue, which
was downright unreadable. I expect this was caused by the CSS update
during #72.

I've removed the URL altogether and make the entire panel clickable,
which will likely be more usable anyway.

--- src/cljs/memento/core.cljs
+++ src/cljs/memento/core.cljs
@@ -250,14 +250,14 @@
         ;; Reminder notice
         (when (and (not-empty @reminders)
                    (not @is-focused?))
-          [:div {:class "alert alert-info"}
+          [:div {:class    "alert alert-info"
+                 :on-click #(dispatch [:state-show-reminders true])}
            [:p
             [:strong "Hi!"]
             " "
             "You have some thoughts you wanted to be reminded of."]
            [:p
-            [:a {:on-click #(dispatch [:state-show-reminders true])}
-             "Click here when you are ready to read them."]]]))
+            "Click this section when you are ready to read them."]]))

       )))


At least better now...

At least better now...

--- src/cljs/moon/workout.cljs
+++ src/cljs/moon/workout.cljs
@@ -43,7 +43,7 @@
 (defn prepare [workout]
   (mapcat expand (add-id workout)))

-(defn update-current [current-exercise]
+(defn create-update-current-event [current-exercise]
   {:event :update-current
          :current-exercise current-exercise})

@@ -53,9 +53,9 @@
       (put! flux {:event :start-exercise}))
     (go-loop [i 0]
       (<! clock-chan)
-      (let [current-exercise (update-current exercise)]
+      (let [current-exercise (update-current exercise i)]
         (>! flux (assoc (done? (:remaining current-exercise)) :event :play))
-        (>! flux (update-current current-exercise))
+        (>! flux (create-update-current-event current-exercise))
         (when (< i total)
           (recur (inc i)))))))


Fix a bug in result->string not printing stack traces.

--- src/cljs/replumb/core.cljs
+++ src/cljs/replumb/core.cljs
@@ -90,7 +90,7 @@
   ([result-map print-stack?]
    (if (:success? result-map)
      (:value result-map)
-     (common/extract-message (:error result-map) print-stack?))))
+     (common/extract-message (:error result-map) false print-stack?))))

 (defn ^:export nodejs-options
   "Creates a Node.js option map for read-eval-call.


Improve rendering with ability to add points in bulk

This makes point rendering significantly more efficient.
Additionally, we eliminate the need to clear the map on every update
by calculating the diff of what's new, and adding the new items to the
layer.

--- src/cljs_leaflet/core.cljs
+++ src/cljs_leaflet/core.cljs
@@ -1,7 +1,8 @@
 (ns cljs-leaflet.core
   (:require [cljsjs.leaflet]
             [reagent.core :as r]
-            [clojure.string :as str]))
+            [clojure.string :as str]
+            [clojure.data]))

 (enable-console-print!)

@@ -32,7 +33,7 @@
    :color "#000"
    :weight 1
    :opacity 1
-   :fillOpacity 0.8} )
+   :fillOpacity 0.6} )

 (defn point-to-layer [feature, latlng]  ;; http://leafletjs.com/examples/geojson.html
   (.circleMarker js/L latlng (clj->js gj-marker-settings)))
@@ -52,47 +53,53 @@

 (defonce vector-layer (.layerGroup js/L))

-(defn setup-map! [lmap]
-  (.addTo tile-layer lmap)
-  (.addTo vector-layer lmap))
-
-;; -- Function to add a point directly to the map -- ;;
-(defn add-point-directly! [layer coords]
-  (println (str "Adding point to map at coords" coords))
-  (.addTo (.marker js/L
-                   (clj->js coords)
-                   (clj->js map-icon))
-          layer))
-;;(add-point-directly! vector-layer [51.5, -0.09])
-;; -------------------------------------------------- ;;
-
-;; Gets a unique identifier for layers by incrementing an int in the app state
-(defn get-layer-id! []
-  (:latest-id (swap! app-state update-in [:latest-id] inc)))
-
-;; Functions to swap data into (or out of) our atom
-(defn add-point! [point-data]
-  (swap! app-state assoc-in [:map-layers (get-layer-id!)] point-data))
-
-(defn remove-point! [id]
-  (println (str "Removing point " id))
-  (swap! app-state update-in [:map-layers] dissoc id))
-
 (defn create-geojson [features]
   (let [fc {:type "FeatureCollection" :features features}
         fcjs (clj->js fc)]
     (.geoJson js/L fcjs
                    (clj->js {:pointToLayer point-to-layer}) )))

+(defonce gj-layer (create-geojson []))
+
+(defn setup-map! [lmap]
+  (.addTo tile-layer lmap)
+  (.addTo vector-layer lmap)
+  (.addLayer vector-layer gj-layer))
+
+;; Gets a unique identifier for layers by incrementing an int in the app state
+(defn get-layer-id! []
+  (:latest-id (swap! app-state update-in [:latest-id] inc)))
+
+;; Get n valid IDs
+(defn get-layer-ids! [n]
+  (let [id (:latest-id (swap! app-state update-in [:latest-id]  #(+ % n)))]
+    (range (- id n) id) ))
+
+;; Functions to swap data into (or out of) our atom
+(defn add-point! [point-data]
+  (swap! app-state assoc-in [:map-layers (get-layer-id!)] point-data))
+
+(defn add-points! [points-list]
+  (let [ids (get-layer-ids! (count points-list))
+        points-map (zipmap ids points-list)]
+    (swap! app-state assoc :map-layers (merge (:map-layers @app-state) points-map)) ))
+
+(defn remove-point! [id]
+  (println (str "Removing point " id))
+  (swap! app-state update-in [:map-layers] dissoc id))
+
+(defn add-to-geojson! [data]
+  (.addData gj-layer (clj->js data)))
+
  ;; Listens for state changes in the atom and updates the map accordingly
 (add-watch app-state :map-layers-watcher
   (fn [r k old-state new-state]
     (when (not= (:map-layers old-state) (:map-layers new-state))
-      (let [features (vals (:map-layers new-state))
-            gj (create-geojson features)]
-        ;; Clear map layers and re-add the new layer
-        (.clearLayers vector-layer)
-        (.addLayer vector-layer gj) ))))
+      (let [diffs (clojure.data/diff
+                    (:map-layers old-state)
+                    (:map-layers new-state) )
+            values-added (vals (second diffs)) ]
+        (doseq [p values-added] (add-to-geojson! p)) ))))

 (defn get-map-bounds [lmap]
   (let [bbox-string (.toBBoxString (.getBounds lmap))
@@ -107,16 +114,16 @@
         lat-range (- (last lats) (first lats) ) ]
     [(+ (first lngs) (rand lng-range)) (+ (first lats) (rand lat-range))] ))

-(defn generate-random-point! [n]
-  (println "Generating random point" n)
-  (add-point! {:coordinates (random-coords-in-view main-map)
-               :type "Point"} ))
+(defn generate-random-point []
+  {:coordinates (random-coords-in-view main-map) :type "Point"})
+
+(defn generate-random-points [n]
+  (repeatedly n #(generate-random-point)))

 (defn on-js-reload []
   ;; optionally touch your app-state to force rerendering depending on
   ;; your application
-  (swap! app-state update-in [:__figwheel_counter] inc)
-)
+  (swap! app-state update-in [:__figwheel_counter] inc))

 ;; Button to generate 10 random points on the map
 (defn add-points-btn [num-points]
@@ -124,12 +131,22 @@
    [:br]
    [:input {:type "button"
             :value "Add points to Map"
-            :on-click #(dotimes [n num-points] (generate-random-point! n))}] ])
+            :on-click #(time (add-points! (generate-random-points num-points)))
+            }]])
+
+;; TODO: Automatically increment
+;(defn total-points-count []
+  ;[:div
+   ;[:b "Total Points:"] (count (:map-layers @app-state)) ])

 (defn render-page []
   (r/render-component
-   [add-points-btn 10]
-   (.getElementById js/document "app"))
+    [:div
+     [add-points-btn 50]
+     [:br]
+     ;[total-points-count]
+     ]
+    (.getElementById js/document "app"))
   (setup-map! main-map))

 (render-page)


CMR-563: Added TODO to determine which ISO types to support.

--- src/cmr/umm/mime_types.clj
+++ src/cmr/umm/mime_types.clj
@@ -3,6 +3,8 @@

 ;; body element (metadata) of a request arriving at ingest app should be in xml format and mime type
 ;; should be of the items in this def.
+
+;; TODO Need to determine which ISO types will be supported when implementing ISO user stories.
 (def CMR_VALID_CONTENT_TYPES
   {:collection #{"application/echo10+xml", "application/iso_prototype+xml", "application/iso:smap+xml",
                  "application/iso19115+xml", "application/dif+xml"}


Update parse_lisp.clj

Update parse_lisp.clj

--- src/iyye/bios/parse_lisp.clj
+++ src/iyye/bios/parse_lisp.clj
@@ -17,6 +17,32 @@
 (ns iyye.bios.parse-lisp
   (:require [clojure.string :as str]))

+(defn partition
+  "Splits the string into a lazy sequence of substrings, alternating
+  between substrings that match the patthern and the substrings
+  between the matches.  The sequence always starts with the substring
+  before the first match, or an empty string if the beginning of the
+  string matches.
+
+  For example: (partition #\"[a-z]+\" \"abc123def\")
+  returns: (\"\" \"abc\" \"123\" \"def\")"
+  [re s]
+  (let [m (re-matcher re s)]
+    ((fn step [prevend]
+       (lazy-seq
+         (if (.find m)
+           (cons (.subSequence s prevend (.start m))
+                 (cons (re-groups m)
+                       (step (+ (.start m) (count (.group m))))))
+           (when (< prevend (.length s))
+             (list (.subSequence s prevend (.length s)))))))
+      0)))
+
+(defn tokenize [s]
+  (filter #(not (= "" %))
+          (map #(str/trim %)
+               (partition #"\(| |\)|\"[^\"]*\"" s))))
+
 (defn balanced? [tokens]
   (let [n (count tokens)]
     (loop [i 0, current 0]
@@ -29,7 +55,62 @@
             (= (nth tokens i) ")") (recur (inc i) (dec current))
             :default (recur (inc i) current)))))))

-(defn make-syntax-tree [text]
+(defn valid-text? [tokens]
+  (and (= "(" (first tokens))
+       (= ")" (last tokens))
+       (balanced? tokens)))
+
+; Easy recursive parsing, text has been validated already so no error checks
+(defn build-tree2 [tokens]
+  (let [len (count tokens)]
+    (loop [i (dec len) ret-list '()]
+      (let [current (nth tokens i)
+            find-j (fn [j]
+                     (loop [k j count 1]
+                       (let [current (nth tokens k)]
+                         (cond
+                           (= ")" current) (recur (dec k) (inc count))
+                           (= "(" current) (if (= 0 (dec count))
+                                             k
+                                             (recur (dec k) (dec count)))
+                           :default (recur (dec k) count)))))]
+        (if (= 0 i)
+          ret-list
+          (if (= current ")")
+            (let [j (find-j (dec i))]
+              (recur (dec (dec j)) (cons
+                                     {:syntax (apply str (butlast (nth tokens (dec j))))
+                                      :subtree (build-tree2 (subvec tokens j i))} ret-list)))
+            (recur (dec i) (cons current ret-list))))))))
+
+(defn count-tokens [node]
+  (loop [i 0 counter 2]
+    (if (>= i (count node))
+      counter
+      (let [elem (nth node i)]
+        (if (not (seq? elem))
+          (recur (inc i) (inc counter))
+          (recur (inc i) (+ counter (count-tokens elem))))))))
+
+(defn build-tree [tokens]
+  (loop [i 0 node ()]
+    (if (>= i (count tokens))
+      node
+      (let [token (nth tokens i)]
+        (cond (= "(" token)
+              (let [sub-node (build-tree (drop (inc i) tokens))]
+                (recur (+ i (count-tokens sub-node))
+                       (concat node (list sub-node))))
+              (= ")" token)
+              node
+              :default
+              (recur (inc i) (concat node (list token)))))))
   )

-(defn test [])
+
+(defn get-syntax-tree [text]
+  (let [tokens (tokenize text)]
+    (when (valid-text? tokens) ; Text syntax is valid
+      (let [tree (build-tree tokens)]
+        (when (= 1 (count tree))
+          (first tree))))))


Added PSimsControl to simulator, for controlled simulated inputs

--- src/clj_bots/pin_ctrl_simulator/implementation.clj
+++ src/clj_bots/pin_ctrl_simulator/implementation.clj
@@ -24,6 +24,11 @@
     (get (current-pin-modes board) pin-n)))

 (declare current-pin-mode writeable-pin? ok-val?)
+
+(defprotocol PSimControl
+  "Protocol for simulation control functions"
+  (set-state! [this pin-n val] "Set the state of a digital or analog input pin"))
+

 (defrecord SimBoard
   [pin-state pin-modes edge-channels config]
@@ -82,7 +87,14 @@
                      (when (match new-val)
                        (>!! c new-val))))))))
   (get-edge-mult [board pin-n]
-    (second (get @edge-channels pin-n))))
+    (second (get @edge-channels pin-n)))
+
+  PSimControl
+  (set-state! [board pin-n val]
+    (assert (ok-val? board pin-n val)
+            (str "The value " val " is not an acceptable value for pins of type " (current-pin-mode board pin-n)))
+    (swap! pin-state pin-n val)))
+

 (defmethod read-pin* :input
   [board pin-n]


[CIRCLE-4471] Highlight aside-nav on child pages (#1927)

* Highlight aside-nav on child pages

* Streamline subpage lists

--- src-cljs/frontend/components/aside.cljs
+++ src-cljs/frontend/components/aside.cljs
@@ -536,11 +536,15 @@
       [:i.material-icons "power_settings_new"]
       [:div.nav-label "Log Out"]]]))

+(def insights-subpages #{:build-insights :project-insights})
+(def dashboard-subpages #{:dashboard :build})
+
 (defn aside-nav-new [{:keys [current-route org owner]}]
   "New side nav, to be used in conjunction with the top bar"
   (html
     [:nav.aside-left-nav
-     [:a.aside-item {:class (when (= :dashboard current-route) "current")
+     [:a.aside-item {:class (when (dashboard-subpages current-route)
+                              "current")
                      :data-placement "right"
                      :data-trigger "hover"
                      :title "Builds"
@@ -558,7 +562,8 @@
         (icon/workflows)
         [:div.nav-label "Workflows"]])

-     [:a.aside-item {:class (when (= :build-insights current-route) "current")
+     [:a.aside-item {:class (when (insights-subpages current-route)
+                              "current")
                      :data-placement "right"
                      :data-trigger "hover"
                      :title "Insights"


The new stage in expanding fact bodies.

The new stage in expanding fact bodies.

--- src/midje/parsing/1_to_explicit_form/facts.clj
+++ src/midje/parsing/1_to_explicit_form/facts.clj
@@ -31,6 +31,8 @@
             [midje.data.compendium :as compendium]
             [midje.parsing.1-to-explicit-form.future-facts :as parse-future-facts]
             [midje.parsing.1-to-explicit-form.metadata :as parse-metadata]
+            [midje.parsing.2-to-lexical-maps.fakes :as parse-fakes]
+            [midje.parsing.2-to-lexical-maps.examples :as parse-examples]
             [midje.parsing.2-to-lexical-maps.folded-fakes :as parse-folded-fakes]
             [midje.data.fact :as fact-data]))

@@ -103,6 +105,11 @@
     sequential?  (preserve-type form (eagerly (map midjcoexpand form)))
     :else        form))

+(defn parse-expects [form]
+  (translate-zipper form
+     expect? (fn [loc]
+               (zip/replace loc (parse-examples/to-lexical-map-form (zip/node loc))))))
+
 (defn expand-fact-body [forms metadata]
   (-> forms
       annotate-embedded-arrows-with-line-numbers
@@ -110,6 +117,7 @@
       parse-folded-fakes/unfold-fakes
       surround-with-background-fakes
       midjcoexpand
+      parse-expects
       (multiwrap (forms-to-wrap-around :facts))))


Update to Planck’s load-core-analysis-cache

--- ClojureScript/replete/src/replete/repl.cljs
+++ ClojureScript/replete/src/replete/repl.cljs
@@ -128,20 +128,16 @@

 (defn- load-core-analysis-cache
   [eager ns-sym file-prefix]
-  (let [keys        [:use-macros :excludes :name :imports :requires :uses :defs :require-macros :cljs.analyzer/constants :doc]
-        load-single (fn [key]
-                      (transit-json->cljs (js/REPLETE_LOAD (str file-prefix (munge key) ".json"))))
-        load-all    (fn []
-                      (zipmap keys (map load-single keys)))
-        load        (fn [key]
-                      (let [cache (load-all)]
-                        (cljs/load-analysis-cache! st ns-sym cache)
-                        (key cache)))]
+  (let [keys [:rename-macros :renames :use-macros :excludes :name :imports :requires :uses :defs :require-macros :cljs.analyzer/constants :doc]
+        load (fn [key]
+               (transit-json->cljs (js/REPLETE_LOAD (str file-prefix (munge key) ".json"))))]
     (cljs/load-analysis-cache! st ns-sym
       (if eager
-        (load-all)
+        (zipmap keys (map load keys))
         (lazy-map
-          {:use-macros              (load :use-macros)
+          {:rename-macros           (load :rename-macros)
+           :renames                 (load :renames)
+           :use-macros              (load :use-macros)
            :excludes                (load :excludes)
            :name                    (load :name)
            :imports                 (load :imports)


properly assign goog.global in react-native builds

--- src/main/shadow/build/targets/react_native.clj
+++ src/main/shadow/build/targets/react_native.clj
@@ -111,6 +111,9 @@
     :configure
     (configure state mode config)

+    :compile-prepare
+    (node/replace-goog-global state)
+
     :flush
     (flush state mode config)


bra va så länge

bra va så länge

--- test/bluebell/bubble/core_test.clj
+++ test/bluebell/bubble/core_test.clj
@@ -3,6 +3,12 @@
             [bluebell.bubble.core :refer :all]))

 (def my-add (protect-fn +))
+(def my-mul (protect-fn *))
+(defn my-sqr [x] (my-mul x x))
+(def my-sqrt (protect-fn #(Math/sqrt %)))
+
+(defn pythagoras [a b]
+  (my-sqrt (my-add (my-sqr a) (my-sqr b))))

 (deftest bubble-test
   (is (bubble? (bubble 3)))
@@ -25,4 +31,6 @@
   (is (nil? (filter-first number? :a :b :c)))
   (is (= 3 (protect-if true 3 4)))
   (is (= 4 (protect-if false 3 4)))
-  (is (= nil (protect-if false 3))))
+  (is (= nil (protect-if false 3)))
+  (is (= 5.0 (pythagoras 3 4)))
+  (is (= (bubble 3) (pythagoras (bubble 3) 4))))


fix naming in tests for cacher

fix naming in tests for cacher

--- test/cljc/commos/service_test.cljc
+++ test/cljc/commos/service_test.cljc
@@ -27,7 +27,7 @@
                                         ;; subs
                                  ]}}
                     (dummy-service)
-                    (service/cache (fn [_ v] v)))
+                    (service/cacher (fn [_ v] v)))
         target (memoize (fn [_] (chan)))]
     (service/request service 0 (target 0))
     (test-async
@@ -45,7 +45,7 @@
                                  break
                                  v-ch]}}
                     (dummy-service)
-                    (service/cache (fn [_ _] :cache)))
+                    (service/cacher (fn [_ _] :cache)))
         target (chan)]
     (service/request service 0 target)
     (test-async
@@ -65,8 +65,8 @@
                                  break
                                  v-ch]}}
                     (dummy-service)
-                    (service/cache (fn [_ _] :cache)
-                                   :forward :cache))
+                    (service/cacher (fn [_ _] :cache)
+                                    :forward :cache))
         target (chan)]
     (service/request service 0 target)
     (test-async


some more space under the big scren

some more space under the big scren

--- cljs-client/cljsinfo_client/threading_macro.cljs
+++ cljs-client/cljsinfo_client/threading_macro.cljs
@@ -439,7 +439,7 @@
   (set-html! "bubblesContainer" (bubble-links a))
   (set-html! "bigScreen" (big-screen-chars a))
   (let [max-y (max-y-value-in-frames (:frames a))
-        big-screen-height (+ (* max-y reg-y-unit) (half reg-y-unit))]
+        big-screen-height (* (inc max-y) reg-y-unit)]
     (.height ($ "#bigScreen") big-screen-height)))

 (defn- on-change-animation [_kwd _atom old-a new-a]


new protograph

new protograph

--- resources/config/ophion.clj
+++ resources/config/ophion.clj
@@ -21,5 +21,5 @@
          :port 27017
          :database "pentomino"}
  :server {:port 4443}
- :protograph {:path "resources/config/protograph.long.yml"
+ :protograph {:path "resources/config/protograph.yml"
               :prefix "protograph"}}


Add some tests for defstep

Add some tests for defstep

--- test/icecap/handlers/core_test.clj
+++ test/icecap/handlers/core_test.clj
@@ -74,3 +74,22 @@
                      ordered-tail)
           spec [[1 2 3] #{4 5 6} [7 8 9]]]
       (is (match-seq-spec spec (execution-order plan))))))
+
+(deftest defstep-tests
+  (testing "literal schema"
+    (try
+      (defstep ::defstep-tests {} [step] nil)
+      (is (::defstep-tests (methods get-schema)))
+      (is (::defstep-tests (methods execute)))
+      (finally
+        (remove-method get-schema ::defstep-tests)
+        (remove-method execute ::defstep-tests))))
+  (testing "symbol schema"
+    (try
+      (let [schema {}]
+        (defstep ::defstep-tests schema [step] nil))
+      (is (::defstep-tests (methods get-schema)))
+      (is (::defstep-tests (methods execute)))
+      (finally
+        (remove-method get-schema ::defstep-tests)
+        (remove-method execute ::defstep-tests)))))


add a test for user defined separator

add a test for user defined separator

--- test/testdouble/cljs/csv_test.cljs
+++ test/testdouble/cljs/csv_test.cljs
@@ -1,7 +1,12 @@
 (ns testdouble.cljs.csv-test
   (:require [testdouble.cljs.csv :as csv]
             [cemerick.cljs.test :as t])
-  (:require-macros [cemerick.cljs.test :refer [deftest is]]))
+  (:require-macros [cemerick.cljs.test :refer [deftest testing is]]))

 (deftest write-csv-test
-  (is (= "1,2,3\n4,5,6" (csv/write-csv [[1 2 3] [4 5 6]]))))
+  (let [data [[1 2 3] [4 5 6]]]
+    (testing "default separator ','"
+      (is (= "1,2,3\n4,5,6" (csv/write-csv data))))
+
+    (testing "user defined separator '|'"
+      (is (= "1|2|3\n4|5|6" (csv/write-csv data :separator "|"))))))


Further tweaks to tests

Further tweaks to tests

--- test/yada/representations_test.clj
+++ test/yada/representations_test.clj
@@ -105,7 +105,7 @@
       (and (= (mime/media-type acceptable) "*/*"))
       [(:quality acceptable) 1 (count (:parameters rep)) (:quality rep)])))

-(defn best-content-type-acceptable?
+(defn highest-content-type-quality
   "Given a collection of acceptable mime-types, return a function that will return the quality."
   [accepts]
   (fn [rep]
@@ -115,63 +115,64 @@
   [req k]
   (->
    (->> (get-in req [:headers "accept"]) parse-csv (map mime/string->media-type))
-   best-content-type-acceptable?
+   highest-content-type-quality
    (wrap-quality-assessor :content-type)
    skip-rejected))

-(defn get-content-type-quality
-  "Given the request and a representation, get the quality of the representation."
+(defn- get-highest-content-type-quality
+  "Given the request and a representation, get the highest possible
+  quality value. Convenience function for independent testing. "
   [req rep]
   (let [k :content-type
-        f (make-content-type-quality-assessor req k)
-        rep (f rep)]
+        qa (make-content-type-quality-assessor req k)
+        rep (qa rep)]
     (or (get-in rep [:qualities k])
         (when (:rejected rep) :rejected))))

 (deftest content-type-test

   (testing "Basic match"
-    (is (= (get-content-type-quality
+    (is (= (get-highest-content-type-quality
             {:headers {"accept" "text/html"}}
             {:content-type (mime/string->media-type "text/html")})
            [(float 1.0) 3 0 (float 1.0)])))

   (testing "Basic match, with multiple options"
-    (is (= (get-content-type-quality
+    (is (= (get-highest-content-type-quality
             {:headers {"accept" "image/png,text/html"}}
             {:content-type (mime/string->media-type "text/html")})
            [(float 1.0) 3 0 (float 1.0)]))

     (testing "Basic match, with multiple options and q values"
-      (is (= (get-content-type-quality
+      (is (= (get-highest-content-type-quality
               {:headers {"accept" "image/png,text/html;q=0.9"}}
               {:content-type (mime/string->media-type "text/html;q=0.8")})
              [(float 0.9) 3 0 (float 0.8)]))))

   (testing "Basic reject"
-    (is (= (get-content-type-quality
+    (is (= (get-highest-content-type-quality
             {:headers {"accept" "text/html"}}
             {:content-type (mime/string->media-type "text/plain")})
            :rejected)))

   (testing "Basic reject with multiple options"
-    (is (= (get-content-type-quality
+    (is (= (get-highest-content-type-quality
             {:headers {"accept" "image/png,text/html"}}
             {:content-type (mime/string->media-type "text/plain")})
            :rejected)))

   (testing "Wildcard match"
-    (is (= ((get-content-type-quality
+    (is (= ((get-highest-content-type-quality
              {:headers {"accept" "image/png,text/*"}}
              {:content-type (mime/string->media-type "text/html")}) 1)
            ;; We get a match with a specificty score of 2
            2)))

   (testing "Specific match beats wildcard"
-    (is (= ((get-content-type-quality
+    (is (= ((get-highest-content-type-quality
              {:headers {"accept" "image/png,text/*,text/html"}}
              {:content-type (mime/string->media-type "text/html")}) 1)
            ;; We get a specificty score of 3, indicating we matched on the
@@ -179,13 +180,13 @@
            3)))

   (testing "Specific match beats wildcard, different order"
-    (is (= ((get-content-type-quality
+    (is (= ((get-highest-content-type-quality
              {:headers {"accept" "text/html,text/*,image/png"}}
              {:content-type (mime/string->media-type "text/html")}) 1)
            3)))

   (testing "Parameter alignment"
-    (is (= (get-content-type-quality
+    (is (= (get-highest-content-type-quality
             {:headers {"accept" "text/html;level=2"}}
             {:content-type (mime/string->media-type "text/html;level=1")})
            ;; We get a specificty score of 3, indicating we matched on the
@@ -193,7 +194,7 @@
            :rejected)))

   (testing "Greater number of parameters matches"
-    (is (= ((get-content-type-quality
+    (is (= ((get-highest-content-type-quality
              {:headers {"accept" "text/html,text/html;level=1"}}
              {:content-type (mime/string->media-type "text/html;level=1")}) 2)
            ;; We get a specificty score of 3, indicating we matched on the


Add button to play back a concatenated stream of all MP3 files

--- src/devcards/audio_utils/devcards/mp3_encoder.cljs
+++ src/devcards/audio_utils/devcards/mp3_encoder.cljs
@@ -1,4 +1,5 @@
 (ns audio-utils.devcards.mp3-encoder
+  (:refer-clojure :exclude [load-file])
   (:require-macros [cljs.core.async.macros :refer [go]])
   (:require [cljs.core.async :refer [<! timeout]]
             [devcards.core :refer-macros [defcard defcard-doc]]
@@ -10,59 +11,107 @@
   [data]
   (js/Blob. data #js {:type "audio/mp3"}))

+(defn play-audio
+  [ctx buffer]
+  (js/console.log "PLAY AUDIO BUFFER" "\n"
+                  "length" (.-length buffer))
+  (let [source (a/create-buffer-source ctx)]
+    (doto source
+      (aset "buffer" buffer)
+      (aset "onended"
+            (fn []
+              (.disconnect source)
+              (.close ctx)))
+      (.connect (.-destination ctx))
+      (.start))))
+
+(defn load-file
+  [file ready-fn]
+  (doto (js/FileReader.)
+    (aset "onload" #(this-as this (ready-fn (.-result this))))
+    (.readAsArrayBuffer file)))
+
+(defn decode-buffer
+  [ctx buffer ready-fn error-fn]
+  (js/console.log "DECODE BUFFER" buffer)
+  (.decodeAudioData ctx buffer ready-fn error-fn))
+
 (defn play-file
   [data]
-  (letfn [(play-audio [ctx buffer]
-            (js/console.log "BLOB DECODED, PLAY AUDIO" "\n"
-                            "length" (.-length buffer) "\n"
-                            "duration" (.-duration buffer) "\n"
-                            "channels" (.-numberOfChannels buffer) "\n"
-                            "sample rate" (.-sampleRate buffer) "\n"
-                            "channel 0" (.getChannelData buffer 0))
-            (let [source (a/create-buffer-source ctx)]
-              (doto source
-                (aset "buffer" buffer)
-                (aset "onended"
-                      (fn []
-                        (js/console.log "PLAY AUDIO ENDED")
-                        (.disconnect source)
-                        (.close ctx)))
-                (.connect (.-destination ctx))
-                (.start))))
-          (log-error [err]
-            (js/console.warn "ERROR" err))]
-    (let [ctx  (a/audio-context)
-          blob (mp3-blob data)]
-      (doto (js/FileReader.)
-        (aset "onload"
-              (fn []
-                (js/console.log "BLOB LOADED")
-                (this-as this
-                  (let [array-buffer (.-result this)]
-                    (.decodeAudioData ctx array-buffer
-                                      (partial play-audio ctx)
-                                      log-error)))))
-        (.readAsArrayBuffer blob)))))
+  (let [ctx       (a/audio-context)
+        blob      (mp3-blob data)
+        play      (fn [buffer] (play-audio ctx buffer))
+        error     (fn [err] (js/console.warn "ERROR" err))]
+    (load-file blob #(decode-buffer ctx % play error))))
+
+(defn load-files
+  [ctx files ready-fn]
+  (js/console.log "LOAD FILES" files)
+  (let [buffers (volatile! (vector (repeat (count files) nil)))]
+    (doseq [[n file] (map-indexed vector files)]
+      (load-file (mp3-blob file)
+                 (fn [buffer]
+                   (decode-buffer ctx buffer
+                                  (fn [buffer]
+                                    (vswap! buffers assoc n buffer)
+                                    (js/console.log "BUFFER DECODED"
+                                                    (type buffer)
+                                                    (count files)
+                                                    (count @buffers))
+                                    (when (= (count files)
+                                             (count @buffers))
+                                      (ready-fn @buffers)))
+                                  (fn [error]
+                                    (js/console.error error))))))))
+
+(defn concat-buffers
+  [ctx buffers]
+  (let [total-length (transduce (map #(.-length %)) + 0 buffers)
+        buffer (a/create-buffer ctx 2 total-length
+                                (.-sampleRate ctx))]
+    (reduce (fn [length-so-far buf]
+              (doseq [channel (range 0 (.-numberOfChannels buffer))]
+                (let [in-chan  (.getChannelData buf channel)
+                      out-chan (.getChannelData buffer channel)]
+                  (doseq [n (range 0 (.-length in-chan))]
+                    (aset out-chan (+ length-so-far n)
+                          (aget in-chan n)))))
+              (+ length-so-far (.-length buf)))
+            0 buffers)
+    buffer))
+
+(defn play-files
+  [files]
+  (js/console.log "PLAY FILES" files)
+  (let [ctx (a/audio-context)]
+    (load-files ctx files
+                (fn [buffers]
+                  (js/console.log "BUFFERS LOADED" buffers)
+                  (let [combined-buffer (concat-buffers ctx buffers)]
+                    (js/console.log "COMBINED BUFFER" combined-buffer)
+                    (play-audio ctx combined-buffer))))))

 (defn plot-files
   [files]
   (html
    `[:div
-    ~@(for [[i file] (map-indexed vector files)]
-        (do
-          (js/console.log "FILE" file (type file))
-          (let [id (str "audio-file-" i)]
-            [:button
-             {:key      id
-              :on-click #(play-file file)}
-             (str "Play file " i)])))]))
+     ~@(for [[i file] (map-indexed vector files)]
+         (do
+           (js/console.log "FILE" file (type file))
+           (let [id (str "audio-file-" i)]
+             [:button
+              {:key      id
+               :on-click #(play-file file)}
+              (str "Play file " i)])))
+     [:button ~{:key      "files"
+                :on-click #(play-files files)}
+      "Play concatenated"]]))

 (defn run-test
   [state]
   (swap! state assoc :processing? true)
   (let [{:keys [source worker samples-per-mp3]} @state]
     (letfn [(encode-audio-data [ctx buffer]
-              (js/console.log "ENCODE AUDIO DATA" ctx buffer)
               (let [n-channels (.-numberOfChannels buffer)
                     source     (doto (a/create-buffer-source ctx)
                                  (aset "buffer" buffer))
@@ -73,22 +122,16 @@
                     entry-node (w/main-entry-node worker ctx config)
                     mp3s       (atom [])
                     exit-node  (w/main-exit-node
-                                worker (fn [mp3]
-                                         (js/console.log "MP3"
-                                                         (count @mp3s)
-                                                         mp3)
-                                         (swap! mp3s conj mp3)))
+                                worker (fn [mp3] (swap! mp3s conj mp3)))
                     dest       (.createMediaStreamDestination ctx)]
                 (.connect source entry-node)
                 (.connect entry-node (.-destination ctx))
                 (set! (.-onended source)
                       (fn [e]
-                        (js/console.log "ENDED")
                         (.disconnect source)
                         (.disconnect dest)
                         (go
                           (<! (timeout 5000))
-                          (js/console.log "TERMINATE")
                           (.disconnect entry-node)
                           (.terminate worker)
                           (.close ctx)
@@ -105,7 +148,6 @@
                      :finished    true)
               (.close ctx))
             (load-file [data]
-              (js/console.log "LOAD FILE" data)
               (let [ctx (a/audio-context)]
                 (doto ctx
                   (.decodeAudioData data


Fix scroll position jumping on save after stripping whitespace

 #2097 restored cursor but forgot to restore scroll

--- src/lt/objs/editor/file.cljs
+++ src/lt/objs/editor/file.cljs
@@ -15,7 +15,9 @@
                       (let [{:keys [path]} (@editor :info)
                             final (object/raise-reduce editor :save+ (ed/->val editor))]
                         (when (not= final (ed/->val editor))
-                          (ed/set-val-and-keep-cursor editor final))
+                          (let [y-position (.-top (.getScrollInfo (ed/->cm-ed editor)))]
+                            (ed/set-val-and-keep-cursor editor final)
+                            (ed/scroll-to editor 0 y-position)))
                         (doc/save path final
                                   (fn []
                                     (object/merge! editor {:dirty false


goog.string/buildString deoptimized, switch to array join expression

--- src/main/cljs/cljs/core.cljs
+++ src/main/cljs/cljs/core.cljs
@@ -2570,7 +2570,7 @@
   ([] "")
   ([x] (if (nil? x)
          ""
-         (gstring/buildString x)))
+         (.join #js [x] "")))
   ([x & ys]
     (loop [sb (StringBuffer. (str x)) more ys]
       (if more


Namespace should only return value if var exists

--- src/main/cljs/cljs/core.cljs
+++ src/main/cljs/cljs/core.cljs
@@ -9839,11 +9839,14 @@
 (deftype Namespace [obj name mappings]
   Object
   (find [_ sym]
-    (Var. #(get @mappings sym)
-      (symbol (str name) (str sym)) nil))
+    (when (has? @mappings sym)
+      (Var. #(get @mappings sym)
+        (symbol (str name) (str sym)) nil)))
   (findInternedVar [_ sym]
-    (Var. #(goog.object/get obj (munge (str sym)))
-      (symbol (str name) (str sym)) nil))
+    (let [k (munge (str sym))]
+      (when (goog.object/contains obj k)
+        (Var. #(goog.object/get obj k)
+          (symbol (str name) (str sym)) nil))))
   (getMappings [_]
     @mappings)
   (getName [_] name)


Add better errors to RDF reader (raise them across the thread)

--- src/grafter/rdf/sesame.clj
+++ src/grafter/rdf/sesame.clj
@@ -621,9 +621,15 @@
             (try
               (.parse parser reader "http://example.org/base-uri")
               (catch Exception ex
-                (println (str "TODO better handle this exception and communicate it back to the calling thread.  " ex)))
-              )))
-        (map sesame-statement->IStatement statements)))))
+                (put! ex)))))
+        (let [read-rdf (fn read-rdf [msg]
+                         (if (instance? Exception msg)
+                           ;; if the other thread puts an Exception on
+                           ;; the pipe, raise it here.
+                           (throw (ex-info "Reading triples aborted."
+                                           {:type :reading-aborted} msg))
+                           (sesame-statement->IStatement msg)))]
+          (map read-rdf statements))))))

 (defn shutdown [repo]
   "Cleanly shutsdown the repository."


dox for /api/setting

dox for /api/setting

--- src/metabase/api/setting.clj
+++ src/metabase/api/setting.clj
@@ -4,25 +4,29 @@
             [metabase.api.common :refer :all]
             (metabase.models [setting :as setting])))

-;; ## Get all settings + values
-(defendpoint GET "/" []
+(defendpoint GET "/"
+  "Get all `Settings` and their values. You must be a superuser to do this."
+  []
   (check-superuser)
   (setting/all-with-descriptions))

-;; ## Get a single setting
-(defendpoint GET "/:key" [key]
+(defendpoint GET "/:key"
+  "Fetch a single `Setting`. You must be a superuser to do this."
+  [key]
   {key Required}
   (check-superuser)
   (setting/get (keyword key)))

-;; ## Create/update a setting
-(defendpoint PUT "/:key" [key  :as {{:keys [value]} :body}]
+(defendpoint PUT "/:key"
+  "Create/update a `Setting`. You must be a superuser to do this."
+  [key  :as {{:keys [value]} :body}]
   {key Required, value Required}
   (check-superuser)
   (setting/set (keyword key) value))

-;; ## Delete a setting
-(defendpoint DELETE "/:key" [key]
+(defendpoint DELETE "/:key"
+  "Delete a `Setting`. You must be a superuser to do this."
+  [key]
   {key Required}
   (check-superuser)
   (setting/delete (keyword key)))


More golang/core cleanup

More golang/core cleanup

Signed-off-by: Gregory Haskins <640d9fe47775e6723f0355b7315e38f7d98d3539@gmail.com>

--- src/chaintool/platforms/golang/core.clj
+++ src/chaintool/platforms/golang/core.clj
@@ -93,22 +93,22 @@
 ;; buildX - build our ST friendly objects
 ;;-----------------------------------------------------------------

-(defn- buildfunction [{:keys [rettype functionName param index]}]
+(defn- build-function [{:keys [rettype functionName param index]}]
   (vector functionName (->Function (when (not= rettype "void") rettype) functionName param index)))

-(defn- buildfunctions [functions]
+(defn- build-functions [functions]
   (into {} (for [[k v] functions]
-             (buildfunction v))))
-
-(defn- buildinterface [base name interface]
-  (let [transactions (buildfunctions (:transactions interface))
-        queries (buildfunctions (:queries interface))]
+             (build-function v))))
+
+(defn- build-interface [base name interface]
+  (let [transactions (build-functions (:transactions interface))
+        queries (build-functions (:queries interface))]
     (vector name (->Interface name (package-name name) (package-camel name) (package-path base name) transactions queries))))

 (defn- build [base interfaces]
-  (into {} (map (fn [[name interface]] (buildinterface base name interface)) interfaces)))
-
-(defn- buildcci [ipath name]
+  (into {} (map (fn [[name interface]] (build-interface base name interface)) interfaces)))
+
+(defn- build-cci [ipath name]
   (let [path (io/file ipath (str name ".cci"))
         os (ByteArrayOutputStream.)]

@@ -123,10 +123,10 @@
         ;; finally, construct a new CCI object
         (vector name (->CCI name data))))))

-(defn- buildccis [ipath interfaces]
-  (into {} (map (fn [interface] (buildcci ipath interface)) interfaces)))
-
-(defn- buildfacts [config]
+(defn- build-ccis [ipath interfaces]
+  (into {} (map (fn [interface] (build-cci ipath interface)) interfaces)))
+
+(defn- build-facts [config]
   (let [facts [["Application Name" (:Name config)]
                ["Application Version" (:Version config)]
                ["Platform" (str (-> config :Platform :Name) " version " (-> config :Platform :Version))]
@@ -162,8 +162,8 @@
 ;; org.hyperledger.chaintool.meta interface
 ;;-----------------------------------------------------------------
 (defn- render-metadata [config ipath]
-  (let [facts (buildfacts config)
-        provides (buildccis ipath (intf/getprovides config))]
+  (let [facts (build-facts config)
+        provides (build-ccis ipath (intf/getprovides config))]
     (render-golang "metadata" [["facts" facts]
                                ["provides" provides]])))

@@ -179,12 +179,15 @@
 ;; emit-stub
 ;;-----------------------------------------------------------------
 (defn- emit-stub [base name functions template srcdir filename]
-  (let [[_ interface] (buildinterface base name functions)
+  (let [[_ interface] (build-interface base name functions)
         content (render-golang template [["base" base]["intf" interface]])
         output (io/file srcdir (package-path base name) filename)]

     (emit-golang output content)))

+;;-----------------------------------------------------------------
+;; emit-server-stub
+;;-----------------------------------------------------------------
 (defn- emit-server-stub [base name functions srcdir]
   (emit-stub base name functions "server" srcdir "server-stub.go"))


Use app-state for active-face

Use app-state for active-face

--- src/cljs/koeeoadi/components/faces.cljs
+++ src/cljs/koeeoadi/components/faces.cljs
@@ -38,27 +38,23 @@
            :tabIndex  (when-not disabled? "0")})))

 (defn face-update [comp prop e]
-  (let [name    (:face/name comp)
+  (let [name    (:face/name (om/props comp))
         checked (util/target-checked e)]
     (om/transact! comp
       `[(face/update {:face/name ~name
-                      ~prop      ~checked}) :palette])))
+                      ~prop      ~checked}) :code])))

 (defn face-style [comp prop]
-  (let [{:keys [face/name] :as props} (om/props comp)]
-    (dom/li nil
-      (dom/input #js
-        {:type    "checkbox"
-         :checked (get props prop)
-         :onClick #(face-update comp prop %)})
-      (clojure.core/name prop))))
+  (dom/li nil
+    (dom/input #js
+      {:type    "checkbox"
+       :checked (get (om/props comp) prop)
+       :onClick #(face-update comp prop %)})
+    (clojure.core/name prop)))

 (defn face-styles [comp]
-  (let [{:keys [face/name
-                face/bold
-                face/italic
-                face/underline]} (om/props comp)
-        {:keys [active-face]} (om/get-state (faces-comp))]
+  (let [{:keys [face/active-face
+                face/name]} (om/props comp)]
     (dom/ul #js {:className "face-styles"
                  :style (util/display (= name active-face))}
       (face-style comp :face/bold)
@@ -78,23 +74,24 @@
       :face/italic
       :face/underline
       {:face/color-fg ~(om/get-query Color)}
-      {:face/color-bg ~(om/get-query Color)}])
+      {:face/color-bg ~(om/get-query Color)}
+      [:face/active-face ~'_]])

   Object
   (render [this]
-    (let [{id        :face/id
-           face-name :face/name
+    (let [{id          :face/id
+           name   :face/name
+           active-face :face/active-face
            :as props}           (om/props this)
-          {:keys [active-face]} (om/get-state (faces-comp))
-          active?               (= face-name active-face)
+          active?               (= name active-face)
           icon-classes          (str "fa fa-2x "
                                   (if active? "fa-angle-down" "fa-angle-right"))]
       (dom/div #js {:className "face"}
         (face-color this :face/color-bg)
         (face-color this :face/color-fg)
         (dom/div #js {:className "face-name"
-                      :onClick   #(om/update-state! (faces-comp) assoc :active-face face-name)}
-          (clojure.core/name face-name))
+                      :onClick   #(om/transact! (faces-comp) `[(state/merge {:face/active-face ~name})])}
+          name)
         (dom/i #js {:className icon-classes})
         (when active?
           (face-styles this))))))
@@ -107,8 +104,8 @@
     [{:faces/list (om/get-query Face)}])
   Object
   (render [this]
-    (let [{:keys [faces/list]}  (om/props this)
-          {:keys [active-face]} (om/get-state this)]
+    (println "rerendering faces")
+    (let [{:keys [faces/list]}  (om/props this)]
       (dom/div #js {:className  "widget"
                     :id         "faces"}
         (util/widget-title "Faces")


Fix wrong JWT property type

Fix wrong JWT property type

--- src/ctia/properties.clj
+++ src/ctia/properties.clj
@@ -67,7 +67,7 @@
    (st/optional-keys {"ctia.http.jwt.enabled" s/Bool
                       "ctia.http.jwt.public-key-path" s/Str
                       "ctia.http.jwt.local-storage-key" s/Str
-                      "ctia.http.jwt.lifetime-in-sec" s/Str})
+                      "ctia.http.jwt.lifetime-in-sec" s/Num})

    (st/optional-keys {"ctia.http.dev-reload" s/Bool
                       "ctia.http.show.protocol" s/Str


lex.clj cleanup

lex.clj cleanup

--- src/clojure/org/mobileink/antlr/lex.clj
+++ src/clojure/org/mobileink/antlr/lex.clj
@@ -42,17 +42,12 @@
       (.fill tokens)
 ;      (println "tokens: " (class tokens))
       (let
-          [tseq (iterator-seq (.iterator (.getTokens tokens)))]
+          [seqtoks (iterator-seq (.iterator (.getTokens tokens)))]
         (do
           (doall (map (fn [t] (print (format "%s\n" (.toString t))))
-                      tseq))
-          )))
-      ;;(doall (map #(println (.getTokenIndex %) (.getType %) (.toString %)) seqtoks))
-      nil))
-
-(defmulti lex-string
-
-  )
+                      seqtoks))
+          ))))
+  nil)

 (defn lex-string
   [^String grammar ;; e.g. "org.mobileink.antlr.sym"
@@ -67,16 +62,18 @@
         strinput (ANTLRInputStream. the-string)
         lxr (eval `(new ~(Class/forName lexname) nil))
         foo (.setInputStream lxr strinput)
-        tokens (do (.reset lxr) (.getAllTokens lxr))
+        ;; tokens (do (.reset lxr) (.getAllTokens lxr))
+        tokens (CommonTokenStream. lxr)
         ;; parsername (str grammar "Parser")
         ;; parsens (import-by-name parsername)
         ;;lex (.setInputStream (symbol (new (str grammar "Lexer"))) input)
         ]
     (do
-      (let [seqtoks (iterator-seq (.iterator tokens))]
+      (.fill tokens)
+      (let
+          [seqtoks (iterator-seq (.iterator (.getTokens tokens)))]
         (do
-          (doall (map #(println (.getTokenIndex %) (.toString %)) seqtoks))
-      ))))
-  ;;(println "end")
-;;  (println "ns" (find-ns (symbol lexname))) ;;'org.mobileink.antlr.Hello1Lexer))
-  )
+          (doall (map #(println (.getTokenIndex %) (.toString %))
+                      seqtoks))
+          ))))
+  nil)


Adding sprint 10 demo.

Adding sprint 10 demo.

--- src/cmr/demos/visual_spatial_search.clj
+++ src/cmr/demos/visual_spatial_search.clj
@@ -180,37 +180,38 @@

         ;search-area (assoc (p/point 0 0) :options {:id "point"})

-        search-area (assoc (l/ords->line-string :geodetic -0.37 -14.07 4.75 1.27 25.13 -15.51) :options {:id "line"})
+        search-area (assoc (l/ords->line-string :geodetic 0 0 10 10) :options {:id "line"})

         ]
     (visual-interactive-search [
-                                touches-sp
-                                across-am-br
-                                touches-np
-                                normal-br1
-                                normal-br2
+                                ; touches-sp
+                                ; across-am-br
+                                ; touches-np
+                                ; normal-br1
+                                ; normal-br2

                                 normal-geod-line
                                 normal-cart-line

-                                wide-north
-                                wide-south
-                                across-am-poly
-                                on-np
-                                on-sp
-                                normal-poly
-                                polygon-with-holes
+                                ; wide-north
+                                ; wide-south
+                                ; across-am-poly
+                                ; on-np
+                                ; on-sp
+                                ; normal-poly
+                                ; polygon-with-holes
                                 wide-north-cart
-                                wide-south-cart
-                                very-wide-cart
-                                very-tall-cart
-                                normal-poly-cart
+                                ; wide-south-cart
+                                ; very-wide-cart
+                                ; very-tall-cart
+                                ; normal-poly-cart
                                 polygon-with-holes-cart
-                                north-pole
-                                south-pole
-                                normal-point
-                                am-point
+
+                                ; north-pole
+                                ; south-pole
+                                ; normal-point
+                                ; am-point
                                 ] search-area))


compiles now

compiles now

--- src/databinder/core.clj
+++ src/databinder/core.clj
@@ -55,9 +55,14 @@
   {:projector
    {:resource (fn [uri binding active url meta vals]
                 (let [s (apply str vals)]
-                  (hic/html [:a {:href url :class (if active "active projector-binding" "projector-binding")
-                                 :data-binding binding
-                                 :data-uri uri} (if (re-matches #"^\s*$" s) "untitled" s)])))
+                  (hic/html [:li  {:class (if active "active" "")
+
+                                   :data-uri uri}
+                             [:a.projector-binding {
+                                                    :href url
+                                                    :data-uri uri
+                                      :data-binding binding
+                                      } (if (re-matches #"^\s*$" s) "untitled" s)]])))
     :value (fn [parent uri binding meta val]
              uri)
     :update nil
@@ -77,17 +82,20 @@

    :list
    {:resource (fn [uri binding meta vals]
-                (hic/html [:p (:title meta)]
-                          [:ol.list-binding {:data-uri uri
+                (hic/html
+                          [:ul {:class "list-binding nav nav-list"
+                                             :data-uri uri
                                 :data-binding binding
                                 :data-description (:description meta)}
+                           [:li.nav-header (:title meta)]
                            vals]
-                          [:a.list-add-binding
+                          [:a
                            {:href "#"
+                            :class "list-add-binding btn"
                             :data-uri uri
                             :data-binding binding} "Create"]))
     :value (fn [parent uri binding meta val]
-             (hic/html [:li {:data-uri uri} val]))
+             (hic/html val))

     :update (fn [uri pred data]
               {:type "create" :uri uri :predicate pred :value (uuid)})
@@ -250,6 +258,13 @@
 (defn relate-left [model predicate resource]
   (iterator-seq (.listResourcesWithProperty model predicate resource)))

+
+(defn parse-uri [uri]
+  (let [parts (filter (comp not (partial re-matches #"^\s*$")) (clojure.string/split uri #"/"))]
+    (println "'" uri"'\n\n\n!!!!!!!\n\n\n\n" parts)
+    (if (empty? parts)
+     {}
+     (apply assoc {} parts))))

 (defn s-rec [binding model url-parts]

@@ -464,8 +479,7 @@

     ))

-(defn parse-uri [uri]
-  (apply assoc {} (clojure.string/split uri #"/")))
+
 (defn q-map [[node & children]]
   (let [results (apply merge {} (map q-map children))]
     (if (:path node)
@@ -855,11 +869,11 @@
   (swap! channels (fn [old]

                     (let [all (reduce (fn [accum key]
-                                        (if (closed? (get old key))
+                                        (if (closed? (get accum key))
                                           (do
                                             (println "Getting rid of old connection for " key)
-                                           (dissoc old key))
-                                          old)) old (keys old))
+                                            (dissoc accum key))
+                                          accum)) old (keys old))
                           url-ch (or (get all url)
                                      (let [new-ch (channel)]
                                        (println "creating a channel for url " url)


Prettify the expand/collapse all buttons

--- src/datafrisk/core.cljs
+++ src/datafrisk/core.cljs
@@ -26,18 +26,25 @@

 (defn CollapseAllButton [emit-fn]
   [:button {:onClick #(emit-fn :collapse-all)
-            :style {:padding "7px"
+            :style {:padding "3px"
+                    :borderTopLeftRadius "2px"
+                    :borderBottomLeftRadius "2px"
                     :cursor "pointer"
-                    :border 1
-                    :backgroundColor "lightgray"}}
+                    :border "1px solid darkgray"
+                    :backgroundColor "white"}}
    "Collapse all"])

 (defn ExpandAllButton [emit-fn data]
   [:button {:onClick #(emit-fn :expand-all data)
-            :style {:padding "7px"
+            :style {:padding "3px"
                     :cursor "pointer"
-                    :border 1
-                    :backgroundColor "lightgray"}}
+                    :borderTopRightRadius "2px"
+                    :borderBottomRightRadius "2px"
+                    :borderTop "1px solid darkgray"
+                    :borderBottom "1px solid darkgray"
+                    :borderRight "1px solid darkgray"
+                    :borderLeft "0"
+                    :backgroundColor "white"}}
    "Expand all"])

 (defn NilText []
@@ -222,8 +229,9 @@
                     data)
         emit-fn (emit-fn-factory state-atom id swappable)]
     [:div
-     [CollapseAllButton emit-fn]
-     [ExpandAllButton emit-fn data]
+     [:div {:style {:padding "4px 2px"}}
+      [ExpandAllButton emit-fn data]
+      [CollapseAllButton emit-fn]]
      [DataFrisk {:data data
                  :swappable swappable
                  :path []


Fix filter of posts when asking with before limit.

--- src/oc/storage/db/common.clj
+++ src/oc/storage/db/common.clj
@@ -123,7 +123,7 @@
                                                    sort-value-base))]
                 {;; Date of the last added comment on this entry
                  :last-activity-at last-activity-at
-                 :publish-time sort-value-base
+                 :sort-base sort-value-base
                  :sort-value sort-value
                  :unseen unseen-with-cap?})))
             ;; Filter out:
@@ -132,10 +132,14 @@
               (r/and ;; Filter out seen entries if unseen flag is on
                      (r/or (r/not unseen)
                            (r/default (r/get-field row :unseen) false))
+                     ;; When sorting from most recent and using before limit
+                     ;; it's necessary to use the sort-base value to avoid cutting out posts sorted at the top
                      (r/or (r/and (= direction :before)
-                                  (r/gt start (r/get-field row :publish-time)))
+                                  (r/gt start (r/get-field row :sort-base)))
+                           ;; for after instead we can use the sort-value since
+                           ;; there is no top limit
                            (r/and (= direction :after)
-                                  (r/le start (r/get-field row :publish-time)))))))
+                                  (r/le start (r/get-field row :sort-value)))))))
             ;; Merge in all the interactions
             (if-not count
               (r/merge query (r/fn [post-row]


Refactor aeron code for new pubs / subs lifecycle

--- src/onyx/messaging/aeron.clj
+++ src/onyx/messaging/aeron.clj
@@ -55,6 +55,7 @@
                                                    10
                                                    (.toNanos TimeUnit/MICROSECONDS 1)
                                                    (.toNanos TimeUnit/MICROSECONDS 100)))]
+        (timbre/info "Started reading")
         (while (not (Thread/interrupted))
           (let [fragments-read (.poll ^uk.co.real_logic.aeron.Subscription subscription limit)]
             (.idle idle-strategy fragments-read)))))))
@@ -72,105 +73,110 @@
   (start [component]
     (taoensso.timbre/info "Starting Aeron")

-    (let [inbound-ch (:inbound-ch (:messenger-buffer component))
-          daemon (:acking-daemon component)
-          release-ch (chan (clojure.core.async/dropping-buffer 100000))
-
-          ;; TODO, correct port allocation
-          port (+ 40000 (rand-int 10000))
-          channel (format "udp://%s:%s" (choose-ip opts) port)
-          ip (choose-ip opts)
-
-          rand-stream-id (fn [] (rand-int 1000000))
-          send-stream-id (rand-stream-id)
-          acker-stream-id (rand-stream-id)
-          completion-stream-id (rand-stream-id)
-
-          ctx (.errorHandler (Aeron$Context.) no-op-error-handler)
-          aeron (Aeron/connect ctx)
-
-          send-handler (data-handler (partial handle-sent-message inbound-ch))
-          acker-handler (data-handler (partial handle-acker-message daemon))
-          completion-handler (data-handler (partial handle-completion-message release-ch))
-
-          send-subscriber (.addSubscription aeron channel send-stream-id send-handler)
-          acker-subscriber (.addSubscription aeron channel acker-stream-id acker-handler)
-          completion-subscriber (.addSubscription aeron channel completion-stream-id completion-handler)
-          accept-send-fut (future (try (.accept ^Consumer (consumer 10) send-subscriber)
-                                       (catch Exception e (fatal e))))
-          accept-acker-fut (future (try (.accept ^Consumer (consumer 10) acker-subscriber)
-                                        (catch Exception e (fatal e))))
-          accept-completion-fut (future (try (.accept ^Consumer (consumer 10) completion-subscriber)
-                                             (catch Exception e (fatal e))))]
+    (let [release-ch (chan (clojure.core.async/dropping-buffer 100000))
+          ip (choose-ip opts)]
       (assoc component
-             :channel channel
              :ip ip
-             :send-stream-id send-stream-id
-             :acker-stream-id acker-stream-id
-             :completion-stream-id completion-stream-id
+             :site-resources (atom nil)
+             :release-ch release-ch)))
+
+  (stop [{:keys [aeron site-resources release-ch] :as component}]
+    (taoensso.timbre/info "Stopping Aeron")
+    (try
+      (when-let [resources @site-resources]
+        (let [{:keys [conn
+                      send-subscriber
+                      acker-subscriber
+                      completion-subscriber
+                      accept-send-fut
+                      accept-acker-fut
+                      accept-completion-fut]} resources]
+          (future-cancel accept-send-fut)
+          (future-cancel accept-acker-fut)
+          (future-cancel accept-completion-fut)
+          (when send-subscriber (.close send-subscriber))
+          (when acker-subscriber (.close acker-subscriber))
+          (when completion-subscriber (.close completion-subscriber))
+          (when conn (.close conn)))
+        (reset! site-resources nil))
+      (close! (:release-ch component))
+
+      ;; FIXME, need to startup and shutdown aeron resources properly
+      ;; however, this can't be done per connection
+      ;(CloseHelper/quietClose (:driver component))
+
+      (catch Exception e
+        (fatal e)))
+
+    (assoc component
+           :ip nil
+           :site-resources nil
+           :release-ch nil)))
+
+(defn aeron [opts]
+  (map->AeronConnection {:opts opts}))
+
+(defmethod extensions/peer-site AeronConnection
+  [messenger]
+  {:aeron/ip (:ip messenger)})
+
+(def allc (atom 40200))
+
+(defmethod extensions/assign-site-resources AeronConnection
+  [messenger peer-sites]
+  {:aeron/port (swap! allc inc)})
+
+(def send-stream-id 1)
+(def acker-stream-id 2)
+(def completion-stream-id 3)
+
+(defn aeron-channel [ip port]
+  (format "udp://%s:%s" ip port))
+
+(defmethod extensions/open-peer-site AeronConnection
+  [messenger assigned]
+  (timbre/info "Open peer site " messenger assigned)
+  (let [inbound-ch (:inbound-ch (:messenger-buffer messenger))
+        release-ch (:release-ch messenger)
+        daemon (:acking-daemon messenger)
+
+        ctx (.errorHandler (Aeron$Context.) no-op-error-handler)
+        aeron (Aeron/connect ctx)
+
+        channel (aeron-channel (:ip messenger) (:aeron/port assigned))
+
+        send-handler (data-handler (partial handle-sent-message inbound-ch))
+        acker-handler (data-handler (partial handle-acker-message daemon))
+        completion-handler (data-handler (partial handle-completion-message release-ch))
+
+        send-subscriber (.addSubscription aeron channel send-stream-id send-handler)
+        acker-subscriber (.addSubscription aeron channel acker-stream-id acker-handler)
+        completion-subscriber (.addSubscription aeron channel completion-stream-id completion-handler)
+        accept-send-fut (future (try (.accept ^Consumer (consumer 10) send-subscriber)
+                                     (catch Exception e (fatal e))))
+        accept-acker-fut (future (try (.accept ^Consumer (consumer 10) acker-subscriber)
+                                      (catch Exception e (fatal e))))
+        accept-completion-fut (future (try (.accept ^Consumer (consumer 10) completion-subscriber)
+                                           (catch Exception e (fatal e))))]
+    (reset! (:site-resources messenger)
+            {:conn aeron
              :accept-send-fut accept-send-fut
              :accept-acker-fut accept-acker-fut
              :accept-completion-fut accept-completion-fut
              :send-subscriber send-subscriber
              :acker-subscriber acker-subscriber
-             :completion-subscriber completion-subscriber
-             :release-ch release-ch
-             :context ctx
-             :aeron aeron)))
-
-  (stop [{:keys [aeron send-subscriber acker-subscriber
-                 completion-subscriber accept-send-fut accept-acker-fut
-                 accept-completion-fut release-ch] :as component}]
-    (taoensso.timbre/info "Stopping Aeron")
-
-    (try
-      (future-cancel accept-send-fut)
-      (future-cancel accept-acker-fut)
-      (future-cancel accept-completion-fut)
-      (when send-subscriber (.close send-subscriber))
-      (when acker-subscriber (.close acker-subscriber))
-      (when completion-subscriber (.close completion-subscriber))
-      (when aeron (.close aeron))
-      (close! (:release-ch component))
-      ;; FIXME, need to startup and shutdown aeron resources properly
-      ;; however, this can't be done per connection
-      ;(CloseHelper/quietClose (:driver component))
-
-      (catch Exception e
-        (fatal e)))
-
-    (assoc component :driver nil :ip nil :channel nil :release-ch nil :aeron nil
-           :accept-send-fut nil :accept-acker-fut nil :accept-completion-fut nil
-           :send-subscriber nil :acker-subscriber nil :completion-subscriber nil)))
-
-(defn aeron [opts]
-  (map->AeronConnection {:opts opts}))
-
-(defmethod extensions/peer-site AeronConnection
-  [messenger]
-  {:ip (:ip messenger)})
-
-(defmethod extensions/send-peer-site AeronConnection
-  [messenger]
-  {:channel (:channel messenger)
-   :stream-id (:send-stream-id messenger)})
-
-(defmethod extensions/acker-peer-site AeronConnection
-  [messenger]
-  {:channel (:channel messenger)
-   :stream-id (:acker-stream-id messenger)})
-
-(defmethod extensions/completion-peer-site AeronConnection
-  [messenger]
-  {:channel (:channel messenger)
-   :stream-id (:completion-stream-id messenger)})
+             :completion-subscriber completion-subscriber})))

 (defmethod extensions/connect-to-peer AeronConnection
-  [messenger event {:keys [channel stream-id]}]
+  [messenger event {:keys [aeron/ip]} {:keys [aeron/port]}]
+  (timbre/info "Connect to peer " ip port)
   (let [ctx (.errorHandler (Aeron$Context.) no-op-error-handler)
         aeron (Aeron/connect ctx)
-        pub (.addPublication aeron channel stream-id)]
-    {:ctx ctx :conn aeron :pub pub}))
+        channel (aeron-channel ip port)
+        send-pub (.addPublication aeron channel send-stream-id)
+        acker-pub (.addPublication aeron channel acker-stream-id)
+        completion-pub (.addPublication aeron channel completion-stream-id)]
+    {:conn aeron :send-pub send-pub :acker-pub acker-pub :completion-pub completion-pub}))

 (defmethod extensions/receive-messages AeronConnection
   [messenger {:keys [onyx.core/task-map] :as event}]
@@ -187,25 +193,28 @@
 (defmethod extensions/send-messages AeronConnection
   [messenger event peer-link batch]
   (let [[len unsafe-buffer] (protocol/build-messages-msg-buf batch)
-        pub ^uk.co.real_logic.aeron.Publication (:pub peer-link)
+        pub ^uk.co.real_logic.aeron.Publication (:send-pub peer-link)
         offer-f (fn [] (.offer pub unsafe-buffer 0 len))]
     (while (not (offer-f)))))

 (defmethod extensions/internal-ack-message AeronConnection
   [messenger event peer-link message-id completion-id ack-val]
   (let [unsafe-buffer (protocol/build-acker-message message-id completion-id ack-val)
-        pub ^uk.co.real_logic.aeron.Publication (:pub peer-link)
+        pub ^uk.co.real_logic.aeron.Publication (:acker-pub peer-link)
         offer-f (fn [] (.offer pub unsafe-buffer 0 protocol/ack-msg-length))]
     (while (not (offer-f)))))

 (defmethod extensions/internal-complete-message AeronConnection
   [messenger event id peer-link]
   (let [unsafe-buffer (protocol/build-completion-msg-buf id)
-        pub ^uk.co.real_logic.aeron.Publication (:pub peer-link)
+        pub ^uk.co.real_logic.aeron.Publication (:completion-pub peer-link)
         offer-f (fn [] (.offer pub unsafe-buffer 0 protocol/completion-msg-length))]
     (while (not (offer-f)))))

 (defmethod extensions/close-peer-connection AeronConnection
   [messenger event peer-link]
-  (.close (:pub peer-link))
-  (.close (:conn peer-link)) {})
+  (.close (:send-pub peer-link))
+  (.close (:acker-pub peer-link))
+  (.close (:completion-pub peer-link))
+  (.close (:conn peer-link))
+  {})


Tweaks to snapshot version logic

Tweaks to snapshot version logic

--- src/leiningen/amp/impl.clj
+++ src/leiningen/amp/impl.clj
@@ -59,13 +59,11 @@
     (let [non-snapshot-version      (.substring ^String version 0 (- (.length ^String version) (.length "-SNAPSHOT")))
           version-number-components (map #(Integer/parseInt %) (s/split non-snapshot-version #"\."))
           version-number-components (drop-while zero? (reverse version-number-components))
-          _                         (if (empty? version-number-components) (throw (RuntimeException. (str "Invalid version number: " version))))
+          _                         (if (empty? version-number-components) (main/abort (str "Invalid project version number: " version)))
           version-number-components (reverse (concat [999 (dec (first version-number-components))] (rest version-number-components)))
-          version-number-components (if (= (count version-number-components) 1)
-                                      (concat version-number-components [999 999])
-                                      (if (= (count version-number-components) 2)
-                                        (concat version-number-components [999])
-                                        version-number-components))]
+          version-number-components (if (= (count version-number-components) 2)
+                                      (concat version-number-components [999])
+                                      version-number-components)]
       (s/join "." version-number-components))
     version))


Add comments to explain the use of fields with 2 appended to the name

--- indexer-app/src/cmr/indexer/data/index_set.clj
+++ indexer-app/src/cmr/indexer/data/index_set.clj
@@ -298,6 +298,16 @@
                    :provider-id.lowercase string-field-mapping

                    :granule-ur            (stored string-field-mapping)
+
+                   ;; Modified mappings for the lowercase fields for granule-ur, producer-gran-id,
+                   ;; and readable-granule-name-sort in order to prevent these values from being
+                   ;; stored in the elasticsearch field data cache (by specifying to use doc-values
+                   ;; for these fields). These 3 fields were taking more than 40% of the cache and
+                   ;; are rarely used to sort on.
+                   ;;
+                   ;; The convention used is to append a 2 to the name of the fields. Note that
+                   ;; for the search application to use the special lowercase2 fields, the fields
+                   ;; need to be mapped in cmr.search.data.query-to-elastic/field->lowercase-field.
                    :granule-ur.lowercase2 (doc-values string-field-mapping)
                    :producer-gran-id (stored string-field-mapping)
                    :producer-gran-id.lowercase2 (doc-values string-field-mapping)


use progress trace macros

use progress trace macros

--- src/distillery/core.clj
+++ src/distillery/core.clj
@@ -7,30 +7,32 @@

 (defn run-complete
   [job-descr]
-  (let [job (-> job-descr
-                dt/load-speech-recognition-results
-                dt/analyze-speech-recognition-results
-                dt/load-categories
-                dt/analyze-categories
-                dt/match-videos
-                dt/lookup-categories-matches
-                dt/matching-stats)]
+  (let [job (dt/process-pipeline
+             "Preparation"
+             job-descr
+             dt/load-speech-recognition-results
+             dt/analyze-speech-recognition-results
+             dt/load-categories
+             dt/analyze-categories
+             dt/match-videos
+             dt/lookup-categories-matches
+             dt/matching-stats)]
     (trace-block
      "Output generation"
      (dt/prepare-output-dir job)
-     (doall ((dt/map-fn) #(% job)
-             [dt/create-index-page
-              dt/create-categories-page
-              dt/create-category-pages
-              dt/create-videos-page
-              dt/create-video-pages]))))
-  (System/exit 0)
+     (dt/process-task-group
+      "Output" #(% job)
+      [dt/create-index-page
+       dt/create-categories-page
+       dt/create-category-pages
+       dt/create-videos-page
+       dt/create-video-pages])))
   nil)

 (defn -main
   [job-file]
   (-> job-file
       load-data
-      run-complete))
-
+      run-complete)
+  (System/exit 0))


Refactored import declarations.

Refactored import declarations.

--- lambda-blog/src/lambda_blog/templates/page.clj
+++ lambda-blog/src/lambda_blog/templates/page.clj
@@ -3,7 +3,9 @@
   (:refer-clojure :exclude [meta])
   (:require [lambda-blog.templates.bits :refer [container javascript row text-centered]]
             [lambda-blog.utils :refer [pathcat]]
-            [s-html.tags :refer [a article body button div doctype head hr html img li link meta nav p script span ul] :as t]))
+            [s-html.tags :refer [a article body button div doctype head hr html
+                                 img li link meta nav p script span ul]
+             :as t]))

 (defn- link-or-pathcat [path-to-root link]
   (or (re-matches #"^https?://.*$" link)


fix image url

fix image url

--- src/pc/http/integrations.clj
+++ src/pc/http/integrations.clj
@@ -45,7 +45,7 @@
                                 :attachments [(merge {:fallback title
                                                       :title title
                                                       :title_link (urls/from-doc doc)
-                                                      :image_url (urls/svg-from-doc doc
+                                                      :image_url (urls/png-from-doc doc
                                                                                :query {:auth-token (-> slack-hook
                                                                                :slack-hook/permission
                                                                                :permission/token)})}


remove unit views, consolidate unit finding function

--- src/dodgeball/core.cljs
+++ src/dodgeball/core.cljs
@@ -43,59 +43,26 @@
 (defn coords [m]
   (dissoc m :move))

-(defn red-unit? [x y]
-  (let [{:keys [:red-team]} (:cells (om/root-cursor app-state))]
-    (first (filter #(and
-             (= x (:x %))
-             (= y (:y %)))
-           red-team))))
-
-(defn blue-unit? [x y]
-  (let [{:keys [:blue-team]} (:cells (om/root-cursor app-state))]
-    (first (filter #(and
-             (= x (:x %))
-             (= y (:y %)))
-           blue-team))))
-
-(defn ball? [x y]
-  (let [{:keys [:balls]} (:cells (om/root-cursor app-state))]
-    (first (filter #(and
-             (= x (:x %))
-             (= y (:y %)))
-           balls))))
+(defn unit? [kind x y]
+  (first (filter #(and
+           (= x (:x %))
+           (= y (:y %)))
+         (kind (:cells (om/root-cursor app-state))))))

 (defn highlight-tile [e]
  (set! (.. e -target -style -background) "gray"))
-
-(defn player-view [cursor owner]
-  (reify
-    om/IRenderState
-    (render-state [this {:keys [move]}]
-      (dom/div #js {:onClick #(highlight-tile %) :className "red-team"}))))
-
-(defn opponent-view [cursor owner]
-  (reify
-    om/IRender
-    (render [_]
-      (dom/div #js {:className "blue-team"}))))
-
-(defn ball-view [cursor owner]
-  (reify
-    om/IRender
-    (render [_]
-      (dom/div #js {:className "ball"}))))

 (defn tile-view [cursor owner]
   (reify
     om/IRenderState
     (render-state [this {:keys [x y move] :as position}]
       (dom/td #js {:onClick #(put! move position)}
-        (if-let [ball (ball? x y)]
-          (om/build ball-view ball {:state {:move move}}))
-        (if-let [red-player (red-unit? x y)]
-          (om/build player-view red-player))
-        (if-let [blue-player (blue-unit? x y)]
-          (om/build opponent-view blue-player))))))
+        (if-let [ball (unit? :balls x y)]
+          (dom/div #js {:className "ball"}))
+        (if-let [red-player (unit? :red-team x y)]
+          (dom/div #js {:onClick #(highlight-tile %) :className "red-team"}))
+        (if-let [blue-player (unit? :blue-team x y)]
+          (dom/div #js {:className "blue-team"}))))))

 (defn board-view [app owner]
   (reify
@@ -109,7 +76,7 @@
        (go (loop []
           (let [selected (coords (<! move))
                 target (coords (<! move))]
-            (if (red-unit? apply target)
+            (if (unit? :red-team apply target)
               (println "CAN'T MOVE THERE")
               (om/transact! app [:cells :red-team]
                 (fn [units]