Refactor handling of nested sequences.

Refactor handling of nested sequences.

--- src/dsbdp/data_processing_dsl.clj
+++ src/dsbdp/data_processing_dsl.clj
@@ -89,17 +89,17 @@
                                                       nested-expr-ret-tmp (last nested-expr-tmp)
                                                       nested-expr-ret [nested-expr-ret-tmp (prefix-rule-name '__offset-increment (inc nesting-level))]
                                                       nested-expr (into '() (reverse (assoc (vec nested-expr-tmp) (- (count nested-expr-tmp) 1) nested-expr-ret)))
-                                                      loop-expr ['loop ['offset (seq-params :initial-offset) 'result-vec []]
-                                                                 `(clojure.core/let [~'tmp-result ~nested-expr
-                                                                                ~'new-offset (+ ~'offset (second ~'tmp-result))
-                                                                                ~'new-result-vec (conj ~'result-vec (first ~'tmp-result))]
+                                                      loop-expr `(loop [~'offset (~seq-params :initial-offset) ~'result-vec []]
+                                                                  (let [~'tmp-result ~nested-expr
+                                                                        ~'new-offset (+ ~'offset (second ~'tmp-result))
+                                                                        ~'new-result-vec (conj ~'result-vec (first ~'tmp-result))]
 ;                                                                    (println "Nested seq step:" ~'new-offset "--" (count ~'input))
                                                                     (if (< ~'new-offset (count ~'input))
                                                                       (recur ~'new-offset ~'new-result-vec)
-                                                                      ~'new-result-vec))]]
+                                                                      ~'new-result-vec)))]
 												(conj v
 													  (prefix-rule-name rule-name nesting-level)
-													  (into '() (reverse loop-expr)))))
+													  loop-expr)))
           (list? rule-expression) (conj v
 										(prefix-rule-name rule-name nesting-level)
 										(create-proc-sub-fn rule-expression input))


day20 still not working

day20 still not working

--- src/adventofcode/day20.clj
+++ src/adventofcode/day20.clj
@@ -1,9 +1,35 @@
-(ns adventofcode.day20)
+(ns adventofcode.day20
+  (:require [clojure.math.combinatorics :as combo]))

-(defn dividers [n]
+(defn get-dividers [n]
   (filter #(zero? (mod n %)) (range 1 (inc n))))

-(def part-one (->> (range)
-                   (map #(vector % (* 10 (apply + (dividers %)))))
-                   (filter #(= 29000000 (second %)))
-                   first))
+(comment (combo/subsets (reverse (dividers 10))))
+
+(def dividers (get-dividers 2900000))
+
+(def valid? (memoize (fn [subset] (= 2900000 (apply + subset)))))
+
+(defn home-number [n]
+  (let [part (take n dividers)]
+    (println n)
+    (some->> part
+             combo/subsets
+             (drop 1) ;; empty subset
+             (filter #(.contains % (last part)))
+             (filter valid?)
+             first
+             (apply max))))
+
+(comment (def part-one (->> (dividers 2900000)
+                            reverse
+                            combo/subsets
+                            (drop 1)
+                            (map (juxt #(apply max %) #(apply + %)))
+                            (filter #(= 2900000 (second %)))
+                            first)))
+
+(comment (->> (range 1 (count dividers))
+              (map home-number)
+              (drop-while nil?)
+              first))


Shrink the (already large) street segment universe

--- src/vip/data_processor/validation/v5/street_segment.clj
+++ src/vip/data_processor/validation/v5/street_segment.clj
@@ -38,7 +38,7 @@
                ss.odd_even_both = 'both' OR
                ss2.odd_even_both = 'both')
    INNER JOIN xml_tree_values xtv
-           ON xtv.value = ss.id
+           ON xtv.value = ss.id AND xtv.results_id = ss.results_id
    WHERE ss.results_id = ? AND xtv.simple_path = 'VipObject.StreetSegment.id';")

 (defn validate-no-street-segment-overlaps


Adapt sse-chat examples to sse handler changes.

--- examples/sse-chat/src/compchat/core.clj
+++ examples/sse-chat/src/compchat/core.clj
@@ -57,28 +57,26 @@
   "A server-sent envents endpoint for send
   the messages to the client."
   {:handler-type :catacumba/sse}
-  [context output close]
+  [{:keys [out ctrl] :as context}]
   (let [sub (a/tap bus (a/chan))
         id (str (gensym "ev"))]
     (a/go-loop []
       ;; (log ">>>" id "go-loop:start")
-      (let [[msg port] (a/alts! [sub close])]
+      (let [[msg port] (a/alts! [sub ctrl])]
         ;; (log ">>>" id "go-loop:received close? =" (= port close))
-
         (if (= port sub)
-          (let [[msg port] (a/alts! [(a/timeout 200) [output msg]])]
+          (let [[msg port] (a/alts! [(a/timeout 200) [out msg]])]
             ;; (log ">>>" id "go-loop:sent timeout? =" (not= port output))
-
-            (if (= port output)
+            (if (= port out)
               (when msg (recur))
               (do
                 (log ">>>" id "go-loop:close because timeout")
                 (a/close! sub)
-                (a/close! output))))
+                (a/close! out))))
           (do
             (log ">>>" id "go-loop:close because client")
             (a/close! sub)
-            (a/close! output)))))))
+            (a/close! out)))))))

 (defn routes
   []


Allow flexible line ending in netcat output

--- main/src/dda/pallet/dda_serverspec_crate/infra/fact/netcat.clj
+++ main/src/dda/pallet/dda_serverspec_crate/infra/fact/netcat.clj
@@ -33,7 +33,7 @@

 (def NetcatFactResults {s/Keyword NetcatFactResult})

-(def output-separator "----- dda-pallet netcat output separator -----\n")
+(def output-separator "----- dda-pallet netcat output separator -----")

 ; -----------------------  functions  -------------------------------
 (s/defn replace-comma :- s/Str [input :- s/Str]
@@ -75,7 +75,7 @@
 (defn parse-netcat
   [script-result]
   (apply merge
-    (map parse-result
+    (map (comp parse-result clojure.string/trim)
       (clojure.string/split script-result (re-pattern output-separator)))))

 (s/defn collect-netcat-fact


Add name to cache update-state fn.

Add name to cache update-state fn.

--- src/blocks/store/cache.clj
+++ src/blocks/store/cache.clj
@@ -75,7 +75,8 @@
       ; Store the block and update cache state.
       (when-let [cached (block/put! cache block)]
         (swap! (:state store)
-               (fn [{:keys [priorities total-size tick]}]
+               (fn update-state
+                 [{:keys [priorities total-size tick]}]
                  {:priorities (assoc priorities (:id cached) [tick (:size cached)])
                   :total-size (+ total-size (:size cached))
                   :tick (inc tick)}))


Add test that put! retains extra attributes and metadata.

--- src/blocks/store/tests.clj
+++ src/blocks/store/tests.clj
@@ -36,6 +36,27 @@
        (take n)
        (map (juxt (comp :id (partial block/store! store)) identity))
        (into (sorted-map))))
+
+
+(defn- test-put-attributes
+  "The put! method in a store should return a block with an updated content or
+  reader, but keep the same id, extra attributes, and any non-stat metadata."
+  [store]
+  (let [original (-> (block/read! (random-bytes 512))
+                     (assoc :foo "bar")
+                     (vary-meta assoc ::thing :baz))
+        stored (block/put! store original)]
+    (is (= (:id original) (:id stored))
+        "Stored block id should match original")
+    (is (= (:size original) (:size stored))
+        "Stored block size should match original")
+    (is (= "bar" (:foo stored))
+        "Stored block should retain extra attributes")
+    (is (= :baz (::thing (meta stored)))
+        "Stored block should retain extra metadata")
+    (is (= original stored)
+        "Stored block should test equal to original")
+    (is (true? (block/delete! store (:id stored))))))

 (defn- test-block
@@ -93,6 +114,8 @@
   (println "  *" label)
   (is (empty? (block/list store)) "starts empty")
   (testing (.getSimpleName (class store))
+    (testing "put attributes"
+      (test-put-attributes store))
     (let [stored-content (populate-blocks! store blocks max-size)]
       (testing "list stats"
         (let [stats (block/list store)]


Add an event listener to fop

Add an event listener to fop

--- src/catalog/layout/fop.clj
+++ src/catalog/layout/fop.clj
@@ -12,7 +12,8 @@
            javax.xml.transform.sax.SAXResult
            javax.xml.transform.stream.StreamSource
            javax.xml.transform.TransformerFactory
-           [org.apache.fop.apps FopFactory MimeConstants]))
+           [org.apache.fop.apps FopFactory MimeConstants]
+           [org.apache.fop.events EventListener EventFormatter]))

 (def ^:private region-body-margin-top 15)

@@ -683,8 +684,17 @@
   (with-open [out (io/output-stream out)]
     (let [;; Construct a FopFactory by specifying a reference to the configuration file
           factory (FopFactory/newInstance (io/file (io/resource "fop.xconf")))
+          ;; get a user agent and add a listener to it that logs events
+          user-agent (.newFOUserAgent factory)
+          broadcaster (.getEventBroadcaster user-agent)
+          _ (.addEventListener broadcaster
+                               (reify EventListener
+                                 (processEvent [this event]
+                                   (let [id (.getEventID event)]
+                                     (when (not= id "org.apache.fop.render.RendererEventProducer.endPage")
+                                       (println (EventFormatter/format event)))))))
           ;; Construct fop with desired output format
-          fop (.newFop factory MimeConstants/MIME_PDF out)
+          fop (.newFop factory MimeConstants/MIME_PDF user-agent out)
           ;; Setup JAXP using identity transformer
           transformer (.newTransformer (TransformerFactory/newInstance))
           ;; Setup input and output for XSLT transformation


Comment test code.

Comment test code.

--- frontend/uxbox/ui/workspace/canvas.cljs
+++ frontend/uxbox/ui/workspace/canvas.cljs
@@ -48,26 +48,31 @@

 (defn- shape-render
   [own shape]
-  (let [local (:rum/local own)
-        x 30
-        y 30
-        width 100
-        height 100]
-    (html
-     [:g
-      (shapes/render shape {:x x :y y :width width :height height})
-      [:g {:class "controls"}
-       [:rect {:x x :y y :width width :height height
-               :style {:stroke "black" :fill "transparent"
-                       :stroke-opacity "0.5"}}]
-       [:circle (merge default-selection-props
-                       {:cx x :cy y})]
-       [:circle (merge default-selection-props
-                       {:cx (+ x width) :cy y})]
-       [:circle (merge default-selection-props
-                       {:cx x :cy (+ y height)})]
-       [:circle (merge default-selection-props
-                       {:cx (+ x width) :cy (+ y height)})]]])))
+  (let [local (:rum/local own)]
+    (shapes/render shape)))
+
+;; (defn- shape-render
+;;   [own shape]
+;;   (let [local (:rum/local own)
+;;         x 30
+;;         y 30
+;;         width 100
+;;         height 100]
+;;     (html
+;;      [:g
+;;       (shapes/render shape {:x x :y y :width width :height height})
+;;       [:g {:class "controls"}
+;;        [:rect {:x x :y y :width width :height height
+;;                :style {:stroke "black" :fill "transparent"
+;;                        :stroke-opacity "0.5"}}]
+;;        [:circle (merge default-selection-props
+;;                        {:cx x :cy y})]
+;;        [:circle (merge default-selection-props
+;;                        {:cx (+ x width) :cy y})]
+;;        [:circle (merge default-selection-props
+;;                        {:cx x :cy (+ y height)})]
+;;        [:circle (merge default-selection-props
+;;                        {:cx (+ x width) :cy (+ y height)})]]])))

 (def shape
   (util/component


Add description metatag for docsite. Close #107.

--- dev-resources/utils/docsite.clj
+++ dev-resources/utils/docsite.clj
@@ -27,7 +27,6 @@
    [[:body {:color "#333"}]
     [:a {:color "#333"}]
     [:p {:margin "0px"}]
-
     [:.category-div :#toc
      [:.category {:margin "0px 0px 7px 0px"}
       [:a {:color "#D53E07"}]]
@@ -77,9 +76,14 @@
              :top "0px"}]]]))

 (defn- get-page
-  "Converts hiccup-style body to full-blown page and returns it as string. class is string that will be used as class of body element in the page."
-  [class body]
+  "Converts hiccup-style body to full-blown page and returns it as string.
+class is string that will be used as class of body element in the page."
+  [class title body]
  (let [head [:head
+             [:meta {:name "description"
+                     :content (str "Quil is a clojure animation library for "
+                                   "creating interactive sketches. Quil is based on Processing.")}]
+             [:title title]
              [:style css]]]
    (p/html5 (list head [:body {:class class}
                         body]))))
@@ -180,9 +184,9 @@
           (column->html [column]
             [:div.column (map (comp category->html find-category) column)])]
     [:div.wrapper
-     [:h1#title "Quil 2.0 API"]
+     [:h1#title "Quil 2.0.0 API"]
      [:div#description
-      [:p "Quil is clojure animation library for creating interactive sketches. "]
+      [:p "Quil is a clojure animation library for creating interactive sketches. "]
       [:p
        "Quil is based on " (e/link-to "http://processing.org" "Processing")
        ". Check " (e/link-to "https://github.com/quil/quil" "Github repo") "."]]
@@ -191,11 +195,12 @@
 (defn- generate-all [fn-metas folder]
   (let [category-map (sorted-category-map fn-metas)]
     (doseq [category (vals category-map)]
-      (let [html (get-page "fn-page" (category->html category fn-metas))
+      (let [html (get-page "fn-page" (str "Quil - " (:name category))
+                           (category->html category fn-metas))
             file (as-filename-ext folder (:name category))]
         (spit file html)))
     (->> (generate-index-page category-map)
-         (get-page "index-page")
+         (get-page "index-page" "Quil API")
          (spit (as-filename-ext folder "index")))))

 (generate-all @(resolve 'quil.core/fn-metas) "out")


Port mem store to manifold

Port mem store to manifold

--- src/icecap/store/mem.clj
+++ src/icecap/store/mem.clj
@@ -1,7 +1,7 @@
 (ns icecap.store.mem
   "An in-memory store."
-  (:require [clojure.core.async :as a]
-            [icecap.store.api :refer :all]
+  (:require [manifold.deferred :as md]
+            [icecap.store.api :as api]
             [icecap.codec :refer [safebase64-encode]]))

 (defn mem-store
@@ -11,17 +11,12 @@
   Java byte arrays don't have equality semantics."
   []
   (let [store (atom {})]
-    (reify Store
+    (reify api/Store
       (create! [_ index blob]
-        (let [index (safebase64-encode index)]
-          (swap! store assoc index blob)
-          (a/to-chan [])))
+        (swap! store assoc (safebase64-encode index) blob)
+        (md/success-deferred nil))
       (retrieve [_ index]
-        (let [index (safebase64-encode index)
-              v (@store index)
-              vs (if (nil? v) [] [v])]
-          (a/to-chan vs)))
+        (md/success-deferred (@store (safebase64-encode index))))
       (delete! [_ index]
-        (let [index (safebase64-encode index)]
-          (swap! store dissoc index)
-          (a/to-chan []))))))
+        (swap! store dissoc (safebase64-encode index))
+        (md/success-deferred nil)))))


formatting/style

formatting/style

--- src/chat/client/views.cljs
+++ src/chat/client/views.cljs
@@ -169,8 +169,8 @@
           (apply dom/div #js {:className "threads"}
             (concat (om/build-all thread-view
                                   (->> (vals (data :threads))
-                                       (sort-by (fn [t]
-                                                  (apply min (map :created-at (t :messages))))))
+                                       (sort-by
+                                         (comp (partial apply min) (partial map :created-at) :messages)))
                                   {:key :id})
                     [(om/build thread-view
                                {:id (uuid/make-random-squuid)


Handle a race in EC2

Handle a race in EC2

--- src/circle/backend/ec2.clj
+++ src/circle/backend/ec2.clj
@@ -148,10 +148,17 @@
 (defn block-until-running
   "Blocks until AWS claims the instance is running"
   [instance-id & {:keys [timeout]
-                  :or {timeout 60}}]
+                  :or {timeout 120}}]
     (println "waiting for instance to start")
   (loop [timeout timeout]
-    (let [inst (instance instance-id)
+    (let [inst (try
+                 (instance instance-id)
+                 (catch com.amazonaws.AmazonServiceException e
+                   ;; this is an eventual consistency 'race'. Sometimes AWS
+                   ;; reports the instance is not there right after it's
+                   ;; started.
+                   (when (not= "InvalidInstanceID.NotFound" (.getErrorCode e))
+                     (throw e))))
           state (-> inst :state (bean) :name (keyword))
           ip (-> inst :publicIpAddress)
           sleep-interval 5]
@@ -177,7 +184,6 @@
               resp (circle.backend.ssh/remote-exec node "echo 'hello'")]
           (when (= 0 (-> resp :exit))
             (swap! success (constantly true))))
-
         (catch java.net.ConnectException e
           (println "caught" (class e) (.getMessage e)))
         (catch com.jcraft.jsch.JSchException e


:zzz:

:zzz:

25 = 25m *not* 2500m

--- src/main/clj/agency/irl/instagrammer/core.clj
+++ src/main/clj/agency/irl/instagrammer/core.clj
@@ -71,9 +71,10 @@
             subscribe/*client-secret* (:client-secret client-options)
             subscribe/*callback-url*  (:callback-url client-options)]

-    (let [sub-geo (subscribe/tag :tag "yolo")]
+    (let [sub-geo (subscribe/tag :lat 40.7903 :lng 73.9597 :radius 5000)
+          sub-tag (subscribe/tag :tag "yolo")]
       (println "<<<<<")
-      (println @sub-geo)
+      (println @sub-geo @sub-tag)
       (println ">>>>>")
       ))


Formatting

Formatting

--- src/clj/cglossa/server.clj
+++ src/clj/cglossa/server.clj
@@ -16,21 +16,21 @@
   (:gen-class))

 (deftemplate page
-  (io/resource "index.html") [] [:body] (if is-dev? inject-devmode-html identity))
+             (io/resource "index.html") [] [:body] (if is-dev? inject-devmode-html identity))

 (defroutes api-routes
            )

 (defroutes app-routes
-  (resources "/")
+           (resources "/")
   (GET "/request" [] handle-dump)
   (GET "/" req (page)))

 (defroutes db-routes
-           (GET "/db" []
-                {:status  200
-                 :headers {}
-                 :body    "dummy"}))
+           (GET "/corpus" [code]
+             {:status  200
+              :headers {}
+              :body    (db/get-corpus code)}))

 (def http-handler
   (let [r (routes (wrap-restful-format #'db-routes :formats [:transit-json :json])
@@ -42,11 +42,11 @@

 (defn run [& [port]]
   (defonce ^:private server
-    (do
-      (let [port (Integer. (or port (env :port) 10555))]
-        (print "Starting web server on port" port ".\n")
-        (run-server http-handler {:port port
-                                  :join? false}))))
+           (do
+             (let [port (Integer. (or port (env :port) 10555))]
+               (print "Starting web server on port" port ".\n")
+               (run-server http-handler {:port  port
+                                         :join? false}))))
   server)

 (defn -main [& [port]]


adjust datomic url

adjust datomic url

--- src/clj/lesezeichen/db.clj
+++ src/clj/lesezeichen/db.clj
@@ -6,7 +6,7 @@
             [lesezeichen.io :refer [transact-all]]))

-(def db-uri-base "datomic:free://localhost:4334")
+(def db-uri-base "datomic:free://bookie.polyc0l0r.net:4334")

 (defn- scratch-conn


excluding origin polygon from intersection by _id; testing on a wider area

--- src/clj/trotte/handler.clj
+++ src/clj/trotte/handler.clj
@@ -55,13 +55,14 @@
                 :coordinates coordinates}})

 (defn dump-dups [seq]
-  (for [[id freq] (frequencies seq)  ;; get the frequencies, destructure
-        :when (= freq 1)]            ;; this is the filter condition
-   id))
+  (for [[group els] (group-by :coords seq)  ;; get the frequencies, destructure
+        :when (= (count els) 1)]            ;; this is the filter condition
+   (first els)))
+

 ;; perform a mongodb aggregation of $geoNear (just to get the document distances, increasing) and $geoIntersects
 ;; take the closest result of two requests, since shapes were separated in two collections
-(defn closest-shape [perp radius]
+(defn closest-shape [perp id radius]
   (let [ q
          (fn [coll]
            (mc/aggregate
@@ -73,9 +74,13 @@
                           :spherical true
                           :maxDistance radius
                           :distanceField "calculated_distance"
-                          :query { :geometry { "$geoIntersects" { "$geometry" (:geometry (perp-lineString perp)) } }}
+                          :query {:_id {"$ne" id }
+                                  :geometry { "$geoIntersects" { "$geometry" (:geometry (perp-lineString perp)) } }}
                           }}]))]
-    (apply min-key #(if (nil? %) 10000 (:calculated_distance %)) (map (comp first q) ["t" "v"]))
+    (apply min-key
+           #(if (nil? %) 10000 ;; this because I don't know how to code
+             (:calculated_distance %))
+           (map (comp first q) ["v" "t"]))
     ))

 (apply min-key identity (remove nil? [ nil 1]))
@@ -85,37 +90,39 @@
   (let [nearQuery { :geometry { $near
                              { "$geometry" {
                                 :type "Point"
-                                :coordinates [2.3795807361602783 48.84644395021793]
+                                :coordinates [2.378979921340942 48.84630097640122]
                                 }
-                               "$maxDistance" 100} } }
+                               "$maxDistance" 200} } }
         ;; get some bati geojson
         results (mc/find-maps db "v" nearQuery)
         ;; get their coordinates
-        polygons (map (fn [{{coordinates :coordinates} :geometry}] coordinates) results)
+        polygons (map (fn [{id :_id {coordinates :coordinates} :geometry}] {:coords coordinates :id id}) results)
         ;; collect all the polygon segments
         all-segments (mapcat
-                       (fn [polygon]
+                       (fn [{:keys [id coords]}]
                          (mapcat
                            (fn [ring]
-                             (partition 2 1 ring))
-                           polygon))
+                             (map #(assoc {:_id id} :coords %) (partition 2 1 ring)))
+                           coords))
                        polygons)
         ;; remove shared (duplicate) segments, since they can't be near a trottoir
         lonely-segments (dump-dups all-segments)
         ;; remove short segments, they usually are corners of bati. This is a problem with round structures TODO
-        filtered-segments (filter (fn [s] (> (segment-length s) 5)) lonely-segments)
-        ;; compute perpendicular segments
-        perps (map (fn [lseg] [lseg (compute-perp lseg 20)]) filtered-segments)
+        filtered-segments (filter (fn [seg] (> (segment-length (:coords seg)) 5)) lonely-segments)
+        ;; compute [origin-segment corresponding-perpendicular-segment]
+        perps (map (fn [seg] [seg (compute-perp (:coords seg) 20)]) filtered-segments)
         ;; check whether this perpendicular's first intersection is a bordure trottoir
-        hits (mapcat (fn [[lseg perp]]
-                       (let [closest (closest-shape perp 60)
+        hits (mapcat (fn [[seg perp]]
+                       (let [closest (closest-shape perp (:_id seg) 60)
                              valid (= "BOR" (get-in closest [:properties :info]))]
-                         [valid]
-                         (if valid [(compute-perp lseg (:calculated_distance closest))] [])
+                         (if valid [(compute-perp (:coords seg) (:calculated_distance closest))] [])
+                         ;;[closest]
                          ))
                   perps)
         ]
-    ;(json/write-str hits :value-fn objectId-reader)
+    ;;(json/write-str (map (comp perp-lineString second) perps) :value-fn objectId-reader)
+    ;;(json/write-str (remove nil? hits) :value-fn objectId-reader)
+    ;;(json/write-str filtered-segments :value-fn objectId-reader)
     (json/write-str (map perp-lineString hits) :value-fn objectId-reader)
     ))


Extracted a method to getElementById

Extracted a method to getElementById

--- src/cljs/chatapp/core.cljs
+++ src/cljs/chatapp/core.cljs
@@ -1,7 +1,10 @@
 (ns chatapp.core)

+(defn- element [name]
+  (.getElementById js/document name))
+
 (defn output [style text]
-  (let [messages         (.getElementById js/document "messages")
+  (let [messages         (element "messages")
         current-messages (.-innerHTML messages)
         current-message  (str "
" text "")]
     (set! (.-innerHTML messages) (str current-messages current-message))))
@@ -22,8 +25,6 @@
 (def socket (atom nil))

 (defn oonclick [event]
-  (output "click" "Button Clicked")
-
   (.preventDefault event)

   (let [uri       (str "ws://" (.-host js/location) "/ws")
@@ -36,7 +37,7 @@
     (reset! socket websocket)))

 (defn sonclick [event]
-  (let [input (.getElementById js/document "input")
+  (let [input (element "input")
         text  (.-value input)]
     (.send @socket text)
     (output "sent" (str ">>> " text))))
@@ -45,9 +46,9 @@
   (.close @socket 1000 "Close button clicked"))

 (defn onload []
-  (let [openBtn  (.getElementById js/document "open")
-        sendBtn  (.getElementById js/document "send")
-        closeBtn (.getElementById js/document "close")]
+  (let [openBtn  (element "open")
+        sendBtn  (element "send")
+        closeBtn (element "close")]
     (set! (.-onclick openBtn) oonclick)
     (set! (.-onclick sendBtn) sonclick)
     (set! (.-onclick closeBtn) conclick)))


Add multiple columns for event persons, to fix #6

--- src/cljs/herder/event.cljs
+++ src/cljs/herder/event.cljs
@@ -41,13 +41,21 @@
          [:h2 "Event: " (:name event)]
          [:hr]
          [:h4 "People"]
-         (into [:ul]
-               (for [{:keys [id name]} (sort-by :name (map get-person (:persons event)))]
-                 ^{:key id} [:li [:a {:href (str "#/person/" id)} name " "]
-                             [:button {:type "button"
-                                       :class "btn btn-danger"
-                                       :on-click #(DELETE (str (event-url (:id @state) (:event_id @state)) "/person/" id))}
-                              (str "Remove " name)]]))
+         [:div.row
+          (into [:ul]
+                (for [{:keys [id name]} (sort-by :name (map get-person (:persons event)))]
+                  ^{:key id} [:div
+                              [:div.col-md-2
+                               [:a {:class "pull-xs-right"
+                                    :style {:line-height "38px"}
+                                    :href (str "#/person/" id)}
+                                name " "]]
+                              [:div.col-md-2
+                               [:button {:type "button"
+                                         :class "btn btn-danger"
+                                         :on-click #(DELETE (str (event-url (:id @state) (:event_id @state)) "/person/" id))}
+                                (str "Remove " name)]]]))]
+         [:hr]
          [:form {:class "form-inline"
                  :on-submit #(do
                                (.preventDefault %)


Only keep 20 most frequent hashtags for chart

--- src/cljs/skytwit/core.cljs
+++ src/cljs/skytwit/core.cljs
@@ -52,7 +52,7 @@
 ;; Originally taken from https://github.com/omcljs/om-cookbook/tree/master/recipes/dimple-bar-chart
 (defn- draw-chart
   [{:keys [data width height id]}]
-  (let [svg (.newSvg js/dimple (str "#" id) "100%" 600)
+  (let [svg (.newSvg js/dimple (str "#" id) "100%" 400)
         Chart (.-chart js/dimple)
         dimple-chart (Chart. svg data)
         _ (.addMeasureAxis dimple-chart "x" "y")
@@ -65,7 +65,8 @@
   (let [opts {:data (->> (:tweets app)
                          (mapcat :tags)
                          frequencies
-                         (sort-by val)
+                         (sort-by (comp - val))
+                         (take 20)
                          (mapv (fn [[x y]] {"x" x "y" y}))
                          clj->js)
               :id "report-chart"
@@ -82,9 +83,9 @@
       (draw-chart opts))
     om/IRender
     (render [_]
-        (dom/div #js {:width (:width opts)
-                      :height (:height opts)
-                      :id (:id opts)})))))
+      (dom/div #js {:width (:width opts)
+                    :height (:height opts)
+                    :id (:id opts)})))))

 (defn root-component [app owner]
   (reify


add extra about importance of order in cljs.core parsing

--- src/cljs_api_gen/parse.clj
+++ src/cljs_api_gen/parse.clj
@@ -374,7 +374,9 @@
   ;; And the imported macros from "clojure.core" should be overwritten
   ;; by cljs.core's macros.
   (concat (parse-extra-macros-from-clj)
-          (parse-ns* ns- "clojurescript" [:compiler :library])))
+          (parse-ns* ns- "clojurescript" [:compiler     ;; <-- again, order is important!
+                                          :library])))  ;; :library should come after :compiler
+                                                        ;; so the library functions overwrite compiler macros

 ;; pseudo-namespace since special forms don't have a namespace
 (defmethod parse-ns "special" [ns-]


Temporary fix to make search results readable

--- src/clojars/web/search.clj
+++ src/clojars/web/search.clj
@@ -36,17 +36,18 @@
            [:div
             (if (some jar-fork? results)
               collection-fork-notice)
-            [:ul
+            [:ul.row
              (for [jar results]
                [:li.search-results
-                (jar-link {:jar_name (:artifact-id jar)
-                           :group_name (:group-id jar)}) " " (:version jar)
-                [:br]
-                (when (seq (:description jar))
-                  [:span.desc (:description jar)
-                   [:br]])
-                [:span.details (if-let [created (:created jar)]
-                                 [:td (format-date created)])]])]]))
+                [:div.result
+                 (jar-link {:jar_name (:artifact-id jar)
+                            :group_name (:group-id jar)}) " " (:version jar)
+                 [:br]
+                 (when (seq (:description jar))
+                   [:span.desc (:description jar)
+                    [:br]])
+                 [:span.details (if-let [created (:created jar)]
+                                  [:td (format-date created)])]]])]]))
        (catch Exception _
          (.printStackTrace _)
          [:p "Could not search; please check your query syntax."]))]))


Ensure CORS conformity on /search endpoints

--- src/clojars/web/search.clj
+++ src/clojars/web/search.clj
@@ -17,7 +17,8 @@

 (defn json-search [search query]
   (let [response {:status 200
-                  :headers {"Content-Type" "application/json; charset=UTF-8"}}]
+                  :headers {"Content-Type" "application/json; charset=UTF-8"
+                            "Access-Control-Allow-Origin" "*"}}]
     (try
       (assoc response
         :body (let [results (search/search search query 1)]


small spacing change

small spacing change

--- src/co/nclk/linen/node.clj
+++ src/co/nclk/linen/node.clj
@@ -323,7 +323,8 @@
                 ;;_ (println ctor context node)
                 n (-> (ctor context) (create node (full-node-name self node)))
                 agent (ssh/ssh-agent {})]
-            (ssh/add-identity agent {:name (:name @(:data @n)) :private-key (-> @(:data @n) :private-key)})
+            (ssh/add-identity agent {:name (:name @(:data @n))
+                                     :private-key (-> @(:data @n) :private-key)})
             (swap! (:data @n) #(assoc % :ssh-agent agent
                                         :short-name (short-name node)))
             ;; The `node` returned from the constructor is a promise.


Add printing server version

Add printing server version

--- src/export_server/core.clj
+++ src/export_server/core.clj
@@ -1,4 +1,5 @@
 (ns export-server.core
+  (:import (java.util Properties))
   (:use [compojure.route :only [not-found]]
         org.httpkit.server
         compojure.core)
@@ -15,12 +16,22 @@
             [clojure.java.io :as io])
   (:gen-class))

+(defn get-project-version
+  ([] (get-project-version "export-server" "export-server"))
+  ([groupid artifact] (-> (doto (Properties.)
+         (.load (-> "META-INF/maven/%s/%s/pom.properties"
+                    (format groupid artifact)
+                    (io/resource)
+                    (io/reader))))
+       (.get "version"))))
+
+(def server-name (str "AnyChart Export Server " (get-project-version)))

 ;====================================================================================
 ; Server Usage
 ;====================================================================================
 (defn server-usage [options-summary]
-  (->> ["AnyChart Export Server"
+  (->> [server-name
         ""
         "Action: server"
         "Usage: java -jar anychart-export.jar server [options]"
@@ -39,7 +50,7 @@
 ;====================================================================================

 (defn cmd-usage [options-summary]
-  (->> ["AnyChart Export Server"
+  (->> [server-name
         ""
         "Action: cmd"
         "Usage: java -jar anychart-export.jar cmd [options]"
@@ -161,11 +172,12 @@
     ]

    ;Export PDF Args--------------------------------------------------------------------------------------------------
+   ["-v" "--version" "Print version, can be used without action"]
    ["-h" "--help"]
    ])

 (defn usage []
-  (->> ["AnyChart Export Server"
+  (->> [server-name
         ""
         "Usage: java -jar anychart-export.jar action [options]"
         "Actions:"
@@ -226,8 +238,10 @@
 ;====================================================================================
 (defn -main [& args]
   (let [{:keys [options arguments errors summary]} (parse-opts args common-options)]
-    (cond (not= (count arguments) 1) (exit 1 (usage))
-          errors (exit 1 (error-msg errors)))
+    (cond
+      (:version options) (exit 0 server-name)
+      (not= (count arguments) 1) (exit 1 (usage))
+      errors (exit 1 (error-msg errors)))
     (reset! web/allow-script-executing (:allow-scripts-executing options))
     (case (first arguments)
       "server" (start-server options summary)


Include problem name in the gist so it's clearer what they've solved

--- src/foreclojure/social.clj
+++ src/foreclojure/social.clj
@@ -1,7 +1,8 @@
 (ns foreclojure.social
   (:use foreclojure.utils
         compojure.core
-        hiccup.page-helpers)
+        hiccup.page-helpers
+        somnium.congomongo)
   (:require [clj-github.gists :as gist]
             [sandbar.stateful-session :as session])
   (:import java.net.URLEncoder))
@@ -17,9 +18,11 @@
   return its url."
   [user-name problem-num solution]
   (let [user-name (or user-name "anonymous")
+        {name :title} (fetch-one :problems
+                                 :where {:_id problem-num})
         filename (str user-name "-4clojure-solution" problem-num ".clj")
-        text (str ";; " user-name
-                  "'s solution to http://4clojure.com/problem/" problem-num
+        text (str ";; " user-name "'s solution to " name "\n"
+                  ";; http://4clojure.com/problem/" problem-num
                   "\n\n"
                   solution)]
     (try


Emacs fixed some whitespace while I was working

--- src/foreclojure/social.clj
+++ src/foreclojure/social.clj
@@ -31,7 +31,7 @@
   (str "<a href=\"http://twitter.com/share?"
        "text=" (URLEncoder/encode status)
        "&url=" (URLEncoder/encode
-	        (str "https://4clojure.com/problem/" id))
+                (str "https://4clojure.com/problem/" id))
        "&related=4clojure"
        "\">"
        (or anchor-text "Twitter")
@@ -40,8 +40,8 @@
 (defn get-problem-title [id]
   (:title
    (fetch-one :problems
-	      :only [:title]
-	      :where {:_id id})))
+              :only [:title]
+              :where {:_id id})))

 (defn gist!
   "Create a new gist containing a user's solution to a problem and
@@ -50,7 +50,7 @@
   (let [[user-name possessive] (if user-name
                                  [user-name "'s"]
                                  ["anonymous" nil])
-	name (get-problem-title problem-num)
+        name (get-problem-title problem-num)
         filename (str user-name "-4clojure-solution" problem-num ".clj")
         text (str ";; " user-name possessive " solution to " name "\n"
                   ";; https://4clojure.com/problem/" problem-num
@@ -65,10 +65,10 @@
 (defn tweet-solution [id gist-url & [link-text]]
   (let [status-msg (str "Check out how I solved "
                         (let [title (get-problem-title id)]
-			  (if (> (count title) 35)
-			    (str "problem " id)
-			    (str "\"" title "\"")))
-			" on #4clojure " (clojure-hashtag) gist-url)]
+                          (if (> (count title) 35)
+                            (str "problem " id)
+                            (str "\"" title "\"")))
+                        " on #4clojure " (clojure-hashtag) gist-url)]
     (tweet-link id status-msg link-text)))

 (def-page share-page []


added hover over text to track view

added hover over text to track view

--- src/frontend/renderer.cljs
+++ src/frontend/renderer.cljs
@@ -170,10 +170,17 @@
             username (.-username data)]
         (dom/div #js {:className "track-view"}
           (list
-            (dom/span #js {:className "track-title"} title)
-            (dom/span #js {:className "track-album"} album)
-            (dom/span #js {:className "track-artist"} artist)
-            (dom/span #js {:className "track-uploader"} "Added by " username)))))))
+            (dom/span #js {:className "track-title"
+                           :title title}
+                      title)
+            (dom/span #js {:className "track-album"
+                           :title album}
+                      album)
+            (dom/span #js {:className "track-artist"
+                           :title artist}
+                      artist)
+            (dom/span #js {:className "track-uploader"
+                           :title (str "Added by " username)} "Added by " username)))))))

 (defn track-queue [data owner]
   (reify


fix usage string

fix usage string

--- src/revdiff/core.clj
+++ src/revdiff/core.clj
@@ -122,7 +122,7 @@
       (diffrevpairs (rest (rest revpairs))))))

 (defn usage []
-  (println (str "\nUsage: " prog " item [term]\n"))
+  (println (str "\nUsage: revdiff item [term]\n"))
   (println "  item : svn uri or name of versioned working-copy object")
   (println "  term : only show diffs with term present on a changed line\n"))


Remove unneeded line in REPL comment.

Remove unneeded line in REPL comment.

--- src/oc/email/content.clj
+++ src/oc/email/content.clj
@@ -460,8 +460,6 @@
   (def data (clean-html (slurp "./resources/invite/cta-button.html")))
   (-> (hickory/parse data) hickory/as-hiccup first (nth 3) (nth 2))

-  (spit "./hiccup.html" (email/html {}))
-
   ;; Generate test email HTML content from various snapshots

   (def note "Hi all, here’s the latest info. Recruiting efforts paid off! Retention is down though, we’ll fix it. Let me know if you want to discuss before we meet next week.")


Add further ensure-connected! declarations. Also, remove an experimental slippage on line 193.

--- src/overtone/sc/node.clj
+++ src/overtone/sc/node.clj
@@ -185,37 +185,37 @@
   ([] (group :tail (root-group)))
   ([position target] (group (alloc-id :node) position target))
   ([id position target]
+     (ensure-connected!)
      (let [pos    (if (keyword? position) (get NODE-POSITION position) position)
            target (to-synth-id target)
            pos    (or pos 1)
            snode  (SynthGroup. id target position (atom :loading))]
-       (if (server-connected?)
-         (snd "/g_new" id pos target))
+       (snd "/g_new" id pos target)
        (swap! active-synth-nodes* assoc id snode)
        snode)))

 (defn- group-free*
   "Free synth groups, releasing their resources."
   [& group-ids]
-  {:pre [(server-connected?)]}
+  (ensure-connected!)
   (apply node-free group-ids))

 (defn node-pause*
   "Pause a running synth node."
-  {:pre [(server-connected?)]}
   [node]
+  (ensure-connected!)
   (snd "/n_run" (to-synth-id node) 0))

 (defn node-start*
   "Start a paused synth node."
   [node]
-  {:pre [(server-connected?)]}
+  (ensure-connected!)
   (snd "/n_run" (to-synth-id node) 1))

 (defn node-place*
   "Place a node :before or :after another node."
   [node position target]
-  {:pre [(server-connected?)]}
+  (ensure-connected!)
   (let [node-id (to-synth-id node)
         target-id (to-synth-id target)]
     (cond
@@ -225,7 +225,7 @@
 (defn node-control*
   "Set control values for a node."
   [node name-values]
-  {:pre [(server-connected?)]}
+  (ensure-connected!)
   (let [node-id (to-synth-id node)]
               (apply snd "/n_set" node-id (floatify (stringify (bus->id name-values))))
               node-id))
@@ -236,6 +236,7 @@

   {:freq 440.0 :attack 0.2}"
   [node names]
+  (ensure-connected!)
   (let [res (recv "/n_set")
         _ (apply snd "/s_get" (to-synth-id node) (stringify names))
         cvals (:args (deref! res))]
@@ -246,7 +247,7 @@
   "Set a range of controls all at once, or if node is a group control
   all nodes in the group."
   [node ctl-start ctl-vals]
-  {:pre [(server-connected?)]}
+  (ensure-connected!)
   (let [node-id (to-synth-id node)]
     (apply snd "/n_setn" node-id ctl-start (count ctl-vals) ctl-vals)))

@@ -254,6 +255,7 @@
   "Get a range of n controls starting at a given name or index.
   Returns a vector of values."
   [node name-index n]
+  (ensure-connected!)
   (let [res (recv "/n_setn")
         _ (snd "/s_getn" (to-synth-id node) (to-str name-index) n)
         cvals (:args (deref! res))]
@@ -270,7 +272,7 @@
 (defn node-map-controls*
   "Connect a node's controls to a control bus."
   [node names-busses]
-  {:pre [(server-connected?)]}
+  (ensure-connected!)
   (let [node-id (to-synth-id node)
         names-busses (bussify (stringify names-busses))]
     (apply snd "/n_map" node-id names-busses)))
@@ -279,7 +281,7 @@
   "Connect N controls of a node to a set of sequential control busses,
   starting at the given control name."
   [node start-control start-bus n]
-  {:pre [(server-connected?)]}
+  (ensure-connected!)
   (assert (bus? start-bus) "Invalid start-bus")
   (let [node-id (to-synth-id node)]
     (snd "/n_mapn" node-id (first (stringify [start-control])) (bus-id start-bus) n)))
@@ -289,12 +291,13 @@
   groups and synths contained within it, optionally including the
   current control values for synths."
   [id with-args?]
-  {:pre [(server-connected?)]}
+  (ensure-connected!)
   (snd "/g_dumpTree" id with-args?))

 (defn- group-prepend-node*
   "Add a synth node to the end of a group list."
   [group node]
+  (ensure-connected!)
   (let [group-id (to-synth-id group)
         node-id (to-synth-id node)]
     (snd "/g_head" group-id node-id)))
@@ -302,6 +305,7 @@
 (defn- group-append-node*
   "Add a synth node to the end of a group list."
   [group node]
+  (ensure-connected!)
   (let [group-id (to-synth-id group)
         node-id (to-synth-id node)]
   (snd "/g_tail" group-id node-id)))
@@ -309,6 +313,7 @@
 (defn- group-clear*
   "Free all child synth nodes in a group."
   [group]
+  (ensure-connected!)
   (snd "/g_freeAll" (to-synth-id group))
   :clear)

@@ -316,6 +321,7 @@
   "Free all child synth nodes in and below this group in other child
   groups."
   [group]
+  (ensure-connected!)
   (snd "/g_deepFree" (to-synth-id group))
   :clear)

@@ -359,6 +365,7 @@
   (ctl 34 :freq 440 :vol 0.2)
   (ctl [34 37] :freq 440 :vol 0.2)"
   [node & args]
+  (ensure-connected!)
   (if (sequential? node)
     (doseq [n node]
       (node-control n args))
@@ -384,6 +391,7 @@
   (kill [(hit) (hit) (hit)])
   "
   [& nodes]
+  (ensure-connected!)
   (doseq [node (flatten nodes)]
     (kill* node)))

@@ -464,12 +472,13 @@
   groups and synthesizer instances residing on the audio server."
   ([] (group-node-tree* 0))
   ([id & [ctls?]]
-   (let [ctls? (if (or (= 1 ctls?) (= true ctls?)) 1 0)]
-     (let [reply-p (recv "/g_queryTree.reply")
-           _ (snd "/g_queryTree" id ctls?)
-          tree (:args (deref! reply-p))]
-       (with-meta (parse-node-tree tree)
-         {:type ::node-tree})))))
+     (ensure-connected!)
+     (let [ctls? (if (or (= 1 ctls?) (= true ctls?)) 1 0)]
+       (let [reply-p (recv "/g_queryTree.reply")
+             _ (snd "/g_queryTree" id ctls?)
+             tree (:args (deref! reply-p))]
+         (with-meta (parse-node-tree tree)
+           {:type ::node-tree})))))

 (defprotocol ISynthGroup
   (group-prepend-node [group node])
@@ -505,6 +514,7 @@
   "Returns a data representation of the synth node tree starting at
   the root group."
   []
+  (ensure-connected!)
   (group-node-tree 0))

 (defn node-tree-zipper


Teach node-destroyed to delay freeing the node-id of the destroyed node for 1 second. This reduces the chance of a race condition occurring in the case where the id has been recycled and used before the node status has been set to :destroyed.

--- src/overtone/sc/node.clj
+++ src/overtone/sc/node.clj
@@ -6,9 +6,10 @@
         [overtone.sc.machinery allocator]
         [overtone.sc.machinery.server comms]
         [overtone.sc.util :only [id-mapper]]
-        [overtone.sc.defaults :only [foundation-groups*]])
+        [overtone.sc.defaults :only [foundation-groups* INTERNAL-POOL]])
   (:require [clojure.zip :as zip]
-            [overtone.config.log :as log]))
+            [overtone.config.log :as log]
+            [overtone.at-at :as at-at]))

 (defonce ^{:dynamic true} *non-active-node-modification-exceptions* true)

@@ -196,13 +197,17 @@
   node)

 (defn- node-destroyed
-  "Frees up a synth node to keep in sync with the server."
+  "Frees up a synth node to keep in sync with the server. Delays the
+  freeing of the node-id for 1 second to avoid race conditions in the
+  case where the id has been recycled and used before the node status
+  has been set to :destroyed."
   [id]
   (let [snode (get @active-synth-nodes* id)]
-    (free-id :node id 1 #(log/debug (format "node-destroyed: %d - synth-node: %s" id snode)))
+    (log/debug (format "node-destroyed: %d - synth-node: %s" id snode))
     (if snode
       (reset! (:status snode) :destroyed)
       (log/warn (format "ERROR: The fn node-destroyed can't find synth node: %d" id)))
+    (at-at/after 1000 #(free-id :node id 1) INTERNAL-POOL)
     (swap! active-synth-nodes* dissoc id)))

 (defn- node-created


show recording controls below each animated editor for dev use

--- src/parinfer/editor.cljs
+++ src/parinfer/editor.cljs
@@ -210,14 +210,82 @@
      (set! (.-id wrapper) (str "cm-" element-id))
      cm)))

+(defn freeze-editor!
+  [cm-or-key]
+  (let [cm (if (keyword? cm-or-key) (get-in @state [cm-or-key :cm]) cm-or-key)
+        element (.getWrapperElement cm)
+        cursor (gdom/getElementByClass "CodeMirror-cursors" element)]
+    (.setOption cm "readOnly" "nocursor")
+    (classlist/add element "CodeMirror-focused")
+    (set! (.. cursor -style -visibility) "visible")))
+
+(defn thaw-editor!
+  [cm-or-key]
+  (let [cm (if (keyword? cm-or-key) (get-in @state [cm-or-key :cm]) cm-or-key)
+        element (.getWrapperElement cm)
+        cursor (gdom/getElementByClass "CodeMirror-cursors" element)]
+    (.setOption cm "readOnly" false)))
+
+(defn start-recording!
+  [key-]
+  (let [{:keys [text cm] :as editor} (get @state key-)]
+    (swap! vcr update-in [key-]
+           assoc
+           :changes []
+           :init-value text
+           :recording? true
+           :last-time nil)))
+
+(defn stop-recording!
+  [key-]
+  (swap! vcr assoc-in [key- :recording?] false))
+
+
+(defn play-recording!
+  [key-]
+  (let [cm (get-in @state [key- :cm])
+        recording (get @vcr key-)
+        timescale (get recording :timescale 1)
+        element (.getWrapperElement cm)]
+    (freeze-editor! cm)
+    (go
+      (swap! state assoc-in [key- :text] (:init-value recording))
+      (doseq [{:keys [change selections dt] :as data} (:changes recording)]
+        (<! (timeout (/ dt timescale)))
+        (cond
+          change (apply-change cm change)
+          selections (apply-selections cm selections)
+          :else nil))
+      (thaw-editor! cm))))
+
+(def show-record-controls? true)
+
 (defn create-editor!
   ([element-id key-] (create-editor! element-id key- {}))
   ([element-id key- opts]
    (let [element (js/document.getElementById element-id)
          cm (js/CodeMirror.fromTextArea element (clj->js (merge editor-opts opts)))
-         wrapper (.getWrapperElement cm)]
+         wrapper (.getWrapperElement cm)
+         ]

      (set! (.-id wrapper) (str "cm-" element-id))
+
+     (when show-record-controls?
+       (let [btn-record (gdom/createElement "button")
+             btn-stop (gdom/createElement "button")
+             btn-play (gdom/createElement "button")]
+
+         (gdom/insertSiblingAfter btn-record wrapper)
+         (gdom/insertSiblingAfter btn-stop btn-record)
+         (gdom/insertSiblingAfter btn-play btn-stop)
+
+         (gdom/setTextContent btn-record "Start Recording")
+         (gdom/setTextContent btn-stop "Done Recording")
+         (gdom/setTextContent btn-play "Play Recording")
+
+         (set! (.-onclick btn-record) #(start-recording! key-))
+         (set! (.-onclick btn-stop) #(stop-recording! key-))
+         (set! (.-onclick btn-play) #(play-recording! key-))))

      (when-not (get @state key-)
        (swap! frame-updates assoc key- {}))
@@ -259,50 +327,3 @@
   (add-watch state :editor-updater on-state-change)
   (force-editor-sync!))

-(defn start-recording!
-  [key-]
-  (let [{:keys [text cm] :as editor} (get @state key-)]
-    (swap! vcr update-in [key-]
-           assoc
-           :changes []
-           :init-value text
-           :recording? true
-           :last-time nil)))
-
-(defn stop-recording!
-  [key-]
-  (swap! vcr assoc-in [key- :recording?] false))
-
-(defn freeze-editor!
-  [cm-or-key]
-  (let [cm (if (keyword? cm-or-key) (get-in @state [cm-or-key :cm]) cm-or-key)
-        element (.getWrapperElement cm)
-        cursor (gdom/getElementByClass "CodeMirror-cursors" element)]
-    (.setOption cm "readOnly" "nocursor")
-    (classlist/add element "CodeMirror-focused")
-    (set! (.. cursor -style -visibility) "visible")))
-
-(defn thaw-editor!
-  [cm-or-key]
-  (let [cm (if (keyword? cm-or-key) (get-in @state [cm-or-key :cm]) cm-or-key)
-        element (.getWrapperElement cm)
-        cursor (gdom/getElementByClass "CodeMirror-cursors" element)]
-    (.setOption cm "readOnly" false)))
-
-(defn play-recording!
-  [key-]
-  (let [cm (get-in @state [key- :cm])
-        recording (get @vcr key-)
-        timescale (get recording :timescale 1)
-        element (.getWrapperElement cm)]
-    (freeze-editor! cm)
-    (go
-      (swap! state assoc-in [key- :text] (:init-value recording))
-      (doseq [{:keys [change selections dt] :as data} (:changes recording)]
-        (<! (timeout (/ dt timescale)))
-        (cond
-          change (apply-change cm change)
-          selections (apply-selections cm selections)
-          :else nil))
-      (thaw-editor! cm))))
-


fix title

fix title

--- src/pc/views/content.clj
+++ src/pc/views/content.clj
@@ -46,8 +46,9 @@
 (defn layout [view-data & content]
   [:html
    [:head
-    [:title (or (str (:meta-title view-data) " | Precursor")
-                "Precursor—fast prototyping web app, makes collaboration easy.")]
+    [:title (if-let [meta-title (:meta-title view-data)]
+              (str meta-title " | Precursor")
+              "Precursor—fast prototyping web app, makes collaboration easy.")]
     [:meta {:charset    "utf-8"}]
     [:meta {:http-equiv "X-UA-Compatible" :content "IE=edge"}]


remove stray p

remove stray p

--- src/replme/cljs/repl.cljs
+++ src/replme/cljs/repl.cljs
@@ -1,4 +1,4 @@
-p(ns replme.cljs.repl
+(ns replme.cljs.repl
   (:require [cljs.core.async :refer [<! >! sub chan]]
             [replme.cljs.websocket :as ws])
   (:use [jayq.core :only [$]])


Fix trailing whitespace in usage output

Fix trailing whitespace in usage output

--- boot/core/src/boot/task/built_in.clj
+++ boot/core/src/boot/task/built_in.clj
@@ -45,14 +45,17 @@
               (-> [["" ""] ["Usage:" "boot OPTS <task> TASK_OPTS <task> TASK_OPTS ..."]]
                   (table/table :style :none)
                   with-out-str))
-      (printf "%s\nDo `boot <task> -h` to see usage info and TASK_OPTS for <task>.\n"
-              (-> [["" "" ""]]
-                  (into (#'helpers/set-title opts "OPTS:")) (br)
-                  (into (#'helpers/set-title (#'helpers/tasks-table tasks) "Tasks:")) (br)
-                  (into (#'helpers/set-title envs "Env:")) (br)
-                  (into (#'helpers/set-title files "Files:"))
-                  (table/table :style :none)
-                  with-out-str))
+      (printf "%s\n\nDo `boot <task> -h` to see usage info and TASK_OPTS for <task>.\n"
+              (->> (-> [["" "" ""]]
+                       (into (#'helpers/set-title opts "OPTS:")) (br)
+                       (into (#'helpers/set-title (#'helpers/tasks-table tasks) "Tasks:")) (br)
+                       (into (#'helpers/set-title envs "Env:")) (br)
+                       (into (#'helpers/set-title files "Files:"))
+                       (table/table :style :none)
+                       with-out-str
+                       (string/split #"\n"))
+                   (map string/trimr)
+                   (string/join "\n")))
       fileset)))

 (core/deftask checkout
@@ -188,7 +191,7 @@
     (core/with-pre-wrap fileset (Thread/sleep time) fileset)))

 (core/deftask watch
-  "Call the next handler whenever source and/or resource files change.
+  "Call the next handler when source files change.

   Debouncing time is 10ms by default."


address comments

address comments

--- src/metabase/driver/druid/query_processor.clj
+++ src/metabase/driver/druid/query_processor.clj
@@ -443,8 +443,8 @@
                                                      {:dimension (->rvalue field)
                                                       :direction direction}))))

-(defn sort-by-timestamp [field direction druid-query]
-  (assoc druid-query :descending (and (= (->rvalue field) "timestamp")
+(defn- sort-by-timestamp [field direction druid-query]
+  (assoc druid-query :descending (and (instance? DateTimeField field)
                                       (= direction :descending))))

 (defmethod handle-order-by ::grouped-timeseries [_ {[{field :field, direction :direction}] :order-by} druid-query]


Extend ToConnection protocol to Repository interface

--- src/rdf-repository/grafter/rdf/repository.clj
+++ src/rdf-repository/grafter/rdf/repository.clj
@@ -373,12 +373,7 @@
       (let [c (.getConnection repo)]
         c)))

-  SailRepository
-  (->connection
-    [^Repository repo]
-    (.getConnection repo))
-
-  SPARQLRepository
+  Repository
   (->connection
     [^Repository repo]
     (.getConnection repo)))


use :js-options directly as compiler opts for js conversion

allows accessing more closure-knobs like :pseudo-names

--- src/main/shadow/build/closure.clj
+++ src/main/shadow/build/closure.clj
@@ -1543,21 +1543,20 @@
         cc
         (make-closure-compiler)

-        ;; FIXME: are there more options we should take from the user?
         co-opts
-        {:source-map (:source-maps js-options true)
-         ;; FIXME: is there any reason to not always use :simple?
-         ;; source maps are pretty good so debugging should not be an issue
-         ;; :whitespace is about an order of magnitude faster though
-         ;; could use that in :dev but given that npm deps won't change that often
-         ;; that might not matter, should cache anyways
-         :optimizations (:optimizations js-options :simple) ;; FIXME: validate whitespace or simple
-         :pretty-print (:pretty-print js-options false)
-         ;; es6+ is transformed by babel first
-         ;; but closure got real picky and complains about some things being es6 that aren't
-         ;; doesn't really impact much here anyways
-         :language-in :ecmascript-next
-         :language-out :ecmascript5}
+        (merge
+          {:source-map true
+           ;; :whitespace or :simple work but some patterns really require the DCE done by :simple
+           ;; eg some conditional imports done by react&friends
+           :optimizations :simple
+           :pretty-print false
+           :pseudo-names false
+           ;; es6+ is transformed by babel first
+           ;; but closure got real picky and complains about some things being es6 that aren't
+           ;; doesn't really impact much here anyways
+           :language-in :ecmascript-next
+           :language-out :ecmascript5}
+          (dissoc js-options :resolve))

         property-collector
         (PropertyCollector. cc)


remove node-jre support, installing java is more reliable

--- src/main/shadow/cljs/npm/cli.cljs
+++ src/main/shadow/cljs/npm/cli.cljs
@@ -61,18 +61,9 @@
       (throw (ex-info "java process exit with non-zero exit code" {:tag :java-exit :status status :result result}))

       (and (.-error result) (= "ENOENT" (.. result -error -errno)))
-      (do (js/console.log "shadow-cljs - java not found, trying node-jre")
-          (prn result)
-          (let [jre
-                (js/require "node-jre")
-
-                result
-                (run project-root (.driver jre) args opts)]
-
-            (when-not (zero? (.-status result))
-              (js/console.log "failed to run java", result)
-              (js/process.exit 1)
-              ))))))
+      (do (js/console.log "shadow-cljs - java not found, please install a Java8 SDK. (OpenJDK or Oracle)")
+          (js/process.exit 1)
+          ))))

 (defn run-lein [project-root {:keys [lein] :as config} args]
   (let [{:keys [profile] :as lein-config}


Add additional viewport fns

Add additional viewport fns

--- src/robinson/viewport.clj
+++ src/robinson/viewport.clj
@@ -20,6 +20,16 @@
         (get-in state [:world :viewport])]
     [v-width v-height]))

+(defn xy-in-viewport?
+  [state x y]
+  (let [{v-width     :width
+         v-height    :height
+         {v-x :x v-y :y} :pos}
+        (get-in state [:world :viewport])]
+
+    (xy-in-rect? x y v-x v-y)
+                     v-width v-height))
+
 (defn xy-in-safe-zone?
   "Is `(x,y)` in the viewport bounds defined in the viewport in `state`?"
   [state x y]
@@ -37,7 +47,12 @@
   (let [{v-width     :width
          v-height    :height}
         (get-in state [:world :viewport])]
-    (keyword (format "%d_%d" (int (/ x v-width)) (int (/ y v-height))))))
+    ;(info "xy->place-id")
+    ;(info x)
+    ;(info v-width)
+    ;(info y)
+    ;(info v-height)
+    [(int (/ x v-width)) (int (/ y v-height))]))

 (defn get-place
   [state x y]
@@ -52,7 +67,7 @@
   (let [{v-width     :width
          v-height    :height}
         (get-in state [:world :viewport])
-        [px py]      (map read-string (clojure.string/split (name place-id) #"_"))]
+        [px py]      place-id]
     [(* px v-width) (* py v-height)]))

 (defn +xy
@@ -72,11 +87,11 @@
         (get-in state [:world :viewport])
         ;; upper left place
         ul-place-id (xy->place-id state v-x v-y)
-        [px py]      (map read-string (clojure.string/split (name ul-place-id) #"_"))]
+        [px py]     ul-place-id]
     [ul-place-id
-     (keyword (format "%d_%d" (inc px) py))
-     (keyword (format "%d_%d" px       (inc py)))
-     (keyword (format "%d_%d" (inc px) (inc py)))]))
+     [(inc px) py]
+     [px       (inc py)]
+     [(inc px) (inc py)]]))

 (defn viewport-xys
   [state]


Adapt code to PR review

Adapt code to PR review

--- backend/src/akvo/lumen/lib/visualisation/map_config.clj
+++ backend/src/akvo/lumen/lib/visualisation/map_config.clj
@@ -117,10 +117,8 @@
   "Should convert hex string to hue for hsl color."
   [hex-string]
   (try
-    (let [c (Color/decode hex-string)
-          hue (->> (Color/RGBtoHSB (.getRed c) (.getGreen c) (.getBlue c) (float-array 3))
-                   (into [])
-                   first)]
+    (let [c   (Color/decode hex-string)
+          hue (first (Color/RGBtoHSB (.getRed c) (.getGreen c) (.getBlue c) (float-array 3)))]
       (str (int (* 360 hue))))
     (catch Exception e "0")))


Improved naming

Improved naming

--- streamable.clj
+++ streamable.clj
@@ -18,7 +18,7 @@
 (kdb/defdb db sqll)
 (kcore/defentity movies)

-(def episode-ids
+(def movie-ids
   (reduce
     (fn [ids record]
       (assoc
@@ -99,15 +99,15 @@
 (def throttled-id (throttle-fn get-cisi-id 1 :second))

 (defn assoc-cisi-id [ep]
-  (let [ep-ids (-> ep :episode-id episode-ids)]
+  (let [ids (-> ep :episode-id movie-ids)]
     (cond
-      (:cisi ep-ids) (assoc ep :cisi-id (:cisi ep-ids))
-      (:imdb ep-ids) (throttled-id ep (:imdb ep-ids))
-      ep-ids (println "*** No IMDB ID found for" (:title ep) "***")
+      (:cisi ids) (assoc ep :cisi-id (:cisi ids))
+      (:imdb ids) (throttled-id ep (:imdb ids))
+      ids (println "*** No IMDB ID found for" (:title ep) "***")
       (:episode-id ep) (do
                          (kcore/insert movies
                            (kcore/values {:episode_id (:episode-id ep)
-                                          :title (:title ep)}))
+                                          :title (:media-title ep)}))
                          (println "Adding empty entry for" (:title ep)))
       :else (println "Skipping" (:title ep)))))

@@ -156,4 +156,4 @@
                    (map throttled-options)
                    (remove (comp empty? :streaming-options)))]
   (println "----------------")
-  (print (format-results results)))
+  (print (format-results (reverse results))))


handle email errors and log responses

handle email errors and log responses

--- src/polismath/server.clj
+++ src/polismath/server.clj
@@ -255,12 +255,17 @@

 (defn send-email-notification-via-polis-api!
   [filename {:keys [zinvite email]}]
-  (client/post "https://pol.is/api/v3/sendEmailExportReady"
-               {:query-params {:webserver_username (:webserver-username env/env)
-                               :webserver_pass (:webserver-pass env/env)
-                               :email email
-                               :filename filename
-                               :conversation_id zinvite}}))
+  (try
+    (let [response
+          (client/post "https://pol.is/api/v3/sendEmailExportReady"
+                       {:query-params {:webserver_username (:webserver-username env/env)
+                                       :webserver_pass (:webserver-pass env/env)
+                                       :email email
+                                       :filename filename
+                                       :conversation_id zinvite}})]
+      (log/info "send email notification response:\n" (with-out-str (clojure.pprint/pprint response))))
+    (catch Exception e
+      (log/error e "failed to send email:\n"))))

 (defn handle-completion!
   [aws-cred filename params]


Don't initialise blank state - the way we were doing it was wrong anyway as it was missing a lot of code panes.

--- src/klangmeister/core.cljs
+++ src/klangmeister/core.cljs
@@ -11,19 +11,11 @@
   (:require-macros
     [klangmeister.compile.macros :as macro]))

-(def nothing
-  {:looping? false
-   :error nil
-   :text ""
-   :value []})
-
 (defn empty-state []
   (reagent/atom
     {:audiocontext (if js/window.AudioContext.
                      (js/window.AudioContext.)
-                     (js/window.webkitAudioContext.))
-     :main nothing
-     :synth nothing}))
+                     (js/window.webkitAudioContext.))}))

 (defonce state-atom (empty-state))


Added prxml for generating web.xml

Added prxml for generating web.xml

--- src/leiningen/ring/war.clj
+++ src/leiningen/ring/war.clj
@@ -1,6 +1,7 @@
 (ns leiningen.ring.war
   (:require [leiningen.compile :as compile]
             [clojure.java.io :as io])
+  (:use [clojure.contrib.prxml :only (prxml)])
   (:import [java.util.jar Manifest
                           JarEntry
                           JarOutputStream]
@@ -35,12 +36,21 @@
      "Built-By: " (System/getProperty "user.name") "\n"
      "Build-Jdk: " (System/getProperty "java.version") "\n\n"))))

+(defn make-web-xml [project]
+  (with-out-str
+    (prxml
+      [:web-app
+        [:servlet
+          [:servlet-name "TODO"]
+          [:servlet-class "TODO"]]
+        [:servlet-mapping
+          [:servlet-name "TODO"]
+          [:url-pattern "/*"]]])))
+
 (defn create-war [project file-path]
   (-> (FileOutputStream. file-path)
       (BufferedOutputStream.)
       (JarOutputStream. (make-manifest))))
-
-(defn make-web-xml [project] "<xml/>")

 (defn write-entry [war war-path entry]
   (.putNextEntry war (JarEntry. war-path))


Use leinjacker for servlet war dependency

--- src/leiningen/ring/war.clj
+++ src/leiningen/ring/war.clj
@@ -2,7 +2,8 @@
   (:require leiningen.deps
             [leiningen.compile :as compile]
             [clojure.java.io :as io]
-            [clojure.string :as string])
+            [clojure.string :as string]
+            [leinjacker.deps :as deps])
   (:use [leinjacker.eval :only (eval-in-project)]
         [clojure.data.xml :only [sexp-as-element indent-str]]
         leiningen.ring.util)
@@ -222,8 +223,7 @@
     war-stream))

 (defn add-servlet-dep [project]
-  (update-in project [:dependencies]
-             conj ['ring/ring-servlet "1.1.0"]))
+  (deps/add-if-missing project '[ring/ring-servlet "1.1.6"]))

 (defn war
   "Create a $PROJECT-$VERSION.war file."


UverseBuf persistent queue implementation.

--- src/rewindable/agos.cljs
+++ src/rewindable/agos.cljs
@@ -7,67 +7,44 @@
             [cljs.core.async.impl.dispatch :as dispatch]
             [cljs.core.async.impl.protocols :as protocols]))

-(deftype RingBuffer [^:mutable head ^:mutable tail ^:mutable length ^:mutable arr]
+(defn make-uverse []
+  (let [last-id (atom 0)]
+    (atom {:gen-id #(swap! last-id inc)
+           :bufs {}})))
+
+; Persistent buffer implementation as an alternative to
+; CLJS/core.async's default mutable RingBuffer.
+(deftype UverseBuf [uverse buf-id ^:mutable length]
   Object
   (pop [_]
-    (when-not (zero? length)
-      (let [x (aget arr tail)]
-        (aset arr tail nil)
-        (set! tail (js-mod (inc tail) (alength arr)))
-        (set! length (dec length))
-        x)))
+    (when-let [x (last (get-in @uverse [:bufs buf-id]))]
+      (swap! uverse #(update-in % [:bufs buf-id] drop-last))
+      (set! length (dec length))
+      x))

   (unshift [_ x]
-    (aset arr head x)
-    (set! head (js-mod (inc head) (alength arr)))
+    (swap! uverse #(update-in % [:bufs buf-id] conj x))
     (set! length (inc length))
     nil)

-  (unbounded-unshift [this x]
-    (if (== (inc length) (alength arr))
-      (.resize this))
+  (unbounded-unshift [this x] ; From RingBuffer 'interface'.
     (.unshift this x))

-  ;; Doubles the size of the buffer while retaining all the existing values
-  (resize
-    [_]
-    (let [new-arr-size (* (alength arr) 2)
-          new-arr (make-array new-arr-size)]
-      (cond
-       (< tail head)
-       (do (buffers/acopy arr tail new-arr 0 length)
-           (set! tail 0)
-           (set! head length)
-           (set! arr new-arr))
+  (resize [_] nil) ; From RingBuffer 'interface'.

-       (> tail head)
-       (do (buffers/acopy arr tail new-arr 0 (- (alength arr) tail))
-           (buffers/acopy arr 0 new-arr (- (alength arr) tail) head)
-           (set! tail 0)
-           (set! head length)
-           (set! arr new-arr))
+  (cleanup [_ keep?]
+    (swap! uverse #(update-in % [:bufs buf-id] (fn [xs] (filter keep? xs))))
+    (set! length (count (get-in @uverse [:bufs buf-id])))))

-       (== tail head)
-       (do (set! tail 0)
-           (set! head 0)
-           (set! arr new-arr)))))
-
-  (cleanup [this keep?]
-    (dotimes [x length]
-      (let [v (.pop this)]
-        (when ^boolean (keep? v)
-          (.unshift this v))))))
-
-(defn ring-buffer [n]
-  (assert (> n 0) "Can't create a ring buffer of size 0")
-  (RingBuffer. 0 0 0 (make-array n)))
+(defn uverse-buf [uverse]
+  (UverseBuf. uverse ((:gen-id @uverse)) 0))

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

 (defn chan-buf [buf]
   (println :chan-buf buf)
-  (channels/ManyToManyChannel. (ring-buffer 32) 0
-                               (ring-buffer 32) 0
+  (channels/ManyToManyChannel. (uverse-buf (make-uverse)) 0
+                               (uverse-buf (make-uverse)) 0
                                buf false))

 (defn chan
@@ -105,7 +82,7 @@

 (defn agos-chan [buf]
   (println :agos-chan buf)
-  (channels/ManyToManyChannel. (ring-buffer 32) 0
-                               (ring-buffer 32) 0
+  (channels/ManyToManyChannel. (uverse-buf (make-uverse)) 0
+                               (uverse-buf (make-uverse)) 0
                                buf false))


The remote macro should correctly handle failure/error events

--- src/shoreleave/remotes/macros.clj
+++ src/shoreleave/remotes/macros.clj
@@ -3,7 +3,10 @@
 (defmacro rpc
   [[sym & params] & [destruct & body]]
   (let [func (if destruct
-               `(fn ~destruct ~@body)
+               (if (some #{:on-success :on-error} body)
+                 (reduce (fn [callback-map [k v-form]] (assoc callback-map k `(fn ~destruct ~v-form)))
+                         {} (apply hash-map body))
+                 `(fn ~destruct ~@body))
                nil)]
     `(shoreleave.remotes.http-rpc/remote-callback ~(str sym)
                                                   ~(vec params)


fix perf tests

fix perf tests

--- perf-test/clj/reitit/prefix_tree_perf_test.clj
+++ perf-test/clj/reitit/prefix_tree_perf_test.clj
@@ -70,11 +70,12 @@
     nil routes))

 (def trie-matcher
-  (trie/compile
-    (reduce
-      (fn [acc [p d]]
-        (trie/insert acc p d))
-      nil routes)))
+  (trie/matcher
+    (trie/compile
+      (reduce
+        (fn [acc [p d]]
+          (trie/insert acc p d))
+        nil routes))))

 (defn bench! []

@@ -108,13 +109,13 @@
   ;; 0.51µs (Cleanup)
   ;; 0.30µs (Java)
   #_(cc/quick-bench
-    (segment/lookup segment-matcher "/v1/orgs/1/topics"))
+      (segment/lookup segment-matcher "/v1/orgs/1/topics"))

   ;; 0.32µs (initial)
   ;; 0.30µs (iterate arrays)
   ;; 0.28µs (list-params)
   (cc/quick-bench
-    (trie/matcher trie-matcher "/v1/orgs/1/topics")))
+    (trie-matcher "/v1/orgs/1/topics")))

 (comment
   (bench!))
@@ -123,6 +124,6 @@

 (comment
   (p/lookup pedestal-tree "/v1/orgs/1/topics")
-  (trie/matcher trie-matcher "/v1/orgs/1/topics")
+  (trie-matcher "/v1/orgs/1/topics")
   #_(segment/lookup segment-matcher "/v1/orgs/1/topics"))


Add test for nested sequences and cond expressions.

--- test/dsbdp/test/data_processing_dsl_tests.clj
+++ test/dsbdp/test/data_processing_dsl_tests.clj
@@ -560,3 +560,48 @@
     (is (map? result))
     (is (= expected result))))

+(deftest pcap-file-nested-packet-sequence-processing-with-cond-test-1
+  (let [pcap-raw-data (Files/readAllBytes (Paths/get "test/data/pcap_three_packets_icmp_dns_http.pcap" (into-array [""])))
+        expected {"magic-number" 2712847316,
+                  "snapshot-len" 262144,
+                  "packets" [{"capture-length" 98, "packet-length" 98, "__offset-increment" 114,
+                              "data" {"eth-dst" "E8:DE:27:59:0E:AD", "eth-src" "0E:AD:B4:74:9F:FA",
+                                      "data" {"proto-id" 1, "ip-dst" "10.0.0.230", "ip-src" "149.20.4.69",
+                                              "data" {"type" "Echo Request"}}}}
+                             {"capture-length" 70, "packet-length" 70, "__offset-increment" 86,
+                              "data" {"eth-dst" "E8:DE:27:59:0E:AD", "eth-src" "0E:AD:B4:74:9F:FA",
+                                      "data" {"proto-id" 17, "ip-dst" "10.0.0.230", "ip-src" "10.0.0.1",
+                                              "data" {"dst" 53, "src" 43471}}}}
+                             {"capture-length" 74, "packet-length" 74, "__offset-increment" 90,
+                              "data" {"eth-dst" "E8:DE:27:59:0E:AD", "eth-src" "0E:AD:B4:74:9F:FA",
+                                      "data" {"proto-id" 6, "ip-dst" "10.0.0.230", "ip-src" "199.204.44.194",
+                                              "data" {"dst" 80, "src" 49526, "flags" 74, "ack-no" 0, "seq-no" 1034137073}}}}]}
+        dsl-expression {:output-type :clj-map
+                        :rules [['magic-number '(int32be 0)]
+                                ['snapshot-len '(int32be 16)]
+                                ['packets
+                                 '([capture-length (int32be (+ offset 8))]
+                                   [packet-length (int32be (+ offset 12))]
+                                   [__offset-increment (+ 16 __1_capture-length)]
+                                   [data [[eth-dst (eth-mac-addr-str (+ offset 16))]
+                                          [eth-src (eth-mac-addr-str (+ offset 20))]
+                                          [data [[proto-id (int8 (+ offset 39))]
+                                                 [ip-dst (ipv4-addr-str (+ offset 42))]
+                                                 [ip-src (ipv4-addr-str (+ offset 46))]
+                                                 [data [(= __3_proto-id 1) [[type (condp = (int8 (+ offset 50))
+                                                                                0 "Echo Reply"
+                                                                                3 "Destination Unreachable"
+                                                                                8 "Echo Request")]]
+                                                        (= __3_proto-id 6) [[dst (int16 (+ offset 52))]
+                                                                            [src (int16 (+ offset 50))]
+                                                                            [flags (int8 (+ offset 8))]
+                                                                            [ack-no (int32 (+ offset 58))]
+                                                                            [seq-no (int32 (+ offset 54))]]
+                                                        (= __3_proto-id 17) [[dst (int16 (+ offset 52))]
+                                                                            [src (int16 (+ offset 50))]]]]]]]])
+                                 {:initial-offset 24}]]}
+        data-processing-fn (create-proc-fn dsl-expression)
+        result (data-processing-fn pcap-raw-data)]
+    (is (map? result))
+    (is (= expected result))))
+


Add perfect game test

Add perfect game test

--- clojure/kata/test/kata/game_test.clj
+++ clojure/kata/test/kata/game_test.clj
@@ -17,3 +17,7 @@
 (deftest test-one-strike
 	(is (= 24 (get-score (concat [10 3 4] (repeat 16 0)))))
 )
+
+(deftest test-perfect-game
+	(is (= 300 (get-score (repeat 12 10))))
+)


Fix import in kstreams.clj to prevent tools from barfing

clj-refactor and Eastwood seem to affected by the issue, even though
the software could be loaded and run without any other issues.

--- clstreams/src/clstreams/kstreams.clj
+++ clstreams/src/clstreams/kstreams.clj
@@ -1,5 +1,5 @@
 (ns clstreams.kstreams
-  (:refer-clojure :only [])
+  (:refer-clojure :only [import])
   (:require [clstreams.kstreams.impl :refer [define-multimethods]]))

 (define-multimethods)


New adjudicator gui

New adjudicator gui

--- src/tango/cljs/main.cljs
+++ src/tango/cljs/main.cljs
@@ -206,6 +206,9 @@
               :competitor/number 21}]
             :class/results []}]}}))

+
+
+
 (defn on-file-read [e file-reader]
   (let [result (.-result file-reader)]
     (log "On file read: send :file/import")
@@ -318,6 +321,59 @@
        x))
    0
    class-result))
+
+(def new-adj-data
+  {:competition/name "TurboMegatävling"
+   :competition/date "2014 11 22"
+   :competition/location "THUNDERDOME"
+   :competition/panels
+   [{:adjudicator-panel/name "1"
+     :adjudicator-panel/adjudicators
+     [{:adjudicator/name "Anders"
+       :adjudicator/id 1
+       :adjudicator/country "Sweden"}
+      {:adjudicator/name "Bertil"
+       :adjudicator/id 2
+       :adjudicator/country ""}]
+     :adjudicator-panel/id 4}
+    {:adjudicator-panel/name "2"
+     :adjudicator-panel/adjudicators
+     [{:adjudicator/name "Bertil"
+       :adjudicator/id 2
+       :adjudicator/country ""}
+      {:adjudicator/name "Cesar"
+       :adjudicator/id 3
+       :adjudicator/country ""}]
+     :adjudicator-panel/id 5}]
+   :competition/adjudicators
+   [{:adjudicator/name "Anders"
+     :adjudicator/id 1
+     :adjudicator/country "Sweden"}
+    {:adjudicator/name "Bertil"
+     :adjudicator/id 2
+     :adjudicator/country "Uganda"}
+    {:adjudicator/name "Cesar"
+     :adjudicator/id 3
+     :adjudicator/country "Tibet"}]
+   :competitor/activities []
+   :competition/classes []})
+
+(defn new-adjudictors-component []
+  [:div
+   [:h3 "Domare"]
+   [:table.table
+    [:thead
+     [:tr
+      [:th {:with "20"} "#"]
+      [:th {:with "200"} "Name"]
+      [:th {:with "20"} "Country"]]]
+    [:tbody
+     (for [adjudicator (sort-by :adjudicator/id (:competition/adjudicators new-adj-data))]
+       ^{:key adjudicator}
+       [:tr
+        [:td (:adjudicator/id adjudicator)]
+        [:td (:adjudicator/name adjudicator)]
+        [:td (:adjudicator/country adjudicator)]])]]])

 (defn adjudictors-component []
   [:div
@@ -336,10 +392,24 @@
         [:td (:adjudicator/name adjudicator)]
         [:td (:adjudicator/country adjudicator)]])]]])

+(defn new-adjudictor-panels-component []
+  [:div
+   [:h3 "Domarpaneler"]
+   [:table.table
+    [:thead
+     [:tr
+      [:th {:with "20"} "#"]
+      [:th {:with "200"} "Domare"]]]
+    [:tbody
+     (for [adjudicator-panel (sort-by :adjudicator-panel/id (:competition/panels new-adj-data))]
+       ^{:key adjudicator-panel}
+       [:tr
+        [:td (:adjudicator-panel/id adjudicator-panel)]
+        [:td (clojure.string/join ", " (map :adjudicator/name (:adjudicator-panel/adjudicators adjudicator-panel)))]])]]])

 (defn adjudictor-panels-component []
   [:div
-   [:h3 "Domare"]
+   [:h3 "Domarpaneler"]
    [:table.table
     [:thead
      [:tr
@@ -391,10 +461,15 @@
                             :on-click #(dispatch [:select-page :classes])}]
    [:input.btn.btn-default {:type "button" :value "Time Schedule"
                             :on-click #(dispatch [:select-page :events])}]
+   [:input.btn.btn-default {:type "button" :value "NewAdjudicators"
+                            :on-click #(dispatch [:select-page :new-adjudicators])}]
+   [:input.btn.btn-default {:type "button" :value "NewAdjudicator panels"
+                            :on-click #(dispatch [:select-page :new-adjudicator-panels])}]
    [:input.btn.btn-default {:type "button" :value "Adjudicators"
                             :on-click #(dispatch [:select-page :adjudicators])}]
    [:input.btn.btn-default {:type "button" :value "Adjudicator panels"
-                            :on-click #(dispatch [:select-page :adjudicator-panels])}]])
+                            :on-click #(dispatch [:select-page :adjudicator-panels])}]
+   ])

 (defn events-component []
   [:div
@@ -492,6 +567,8 @@
        :classes [dp-classes-component]
        :events [events-component]
        :adjudicators [adjudictors-component]
+       :new-adjudicators [new-adjudictors-component]
+       :new-adjudicator-panels [new-adjudictor-panels-component]
        :adjudicator-panels [adjudictor-panels-component]
        )]))


Update to DynamoDB APIv2 (Rotary PR: edpaget)

--- src/taoensso/faraday.clj
+++ src/taoensso/faraday.clj
@@ -6,14 +6,15 @@
             [taoensso.timbre        :as timbre]
             [taoensso.nippy         :as nippy]
             [taoensso.faraday.utils :as utils])
-  (:import  [com.amazonaws.services.dynamodb.model
+  (:import  [com.amazonaws.services.dynamodbv2.model
              AttributeValue
+             AttributeDefinition
              BatchGetItemRequest
              BatchGetItemResult
-             BatchResponse
+             ;; BatchResponse
              BatchWriteItemRequest
              BatchWriteItemResult
-             BatchWriteResponse
+             ;; BatchWriteResponse
              Condition
              CreateTableRequest
              UpdateTableRequest
@@ -25,8 +26,8 @@
              ExpectedAttributeValue
              GetItemRequest
              GetItemResult
-             Key
-             KeySchema
+             ;; Key
+             ;; KeySchema
              KeySchemaElement
              KeysAndAttributes
              ProvisionedThroughput
@@ -39,7 +40,7 @@
              WriteRequest]
             com.amazonaws.ClientConfiguration
             com.amazonaws.auth.BasicAWSCredentials
-            com.amazonaws.services.dynamodb.AmazonDynamoDBClient
+            com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient
             java.nio.ByteBuffer))

 ;;;; TODO Rotary PRs
@@ -77,23 +78,33 @@
 (def db-client (memoize db-client*))

 (defn- key-schema-element "Returns a new KeySchemaElement object."
-  [{key-name :name key-type :type}]
+  ;; [{key-name :name key-type :type}]
+  [key-name key-type]
   (doto (KeySchemaElement.)
     (.setAttributeName (str key-name))
-    (.setAttributeType (str/upper-case (name key-type)))))
+    (.setKeyType (str/upper-case (name key-type)))))

 (defn- key-schema "Returns a new KeySchema object."
   [hash-key & [range-key]]
-  (let [schema (KeySchema. (key-schema-element hash-key))]
-    (when range-key
-      (.setRangeKeyElement schema (key-schema-element range-key)))
-    schema))
+  (let [schema (key-schema-element (:name hash-key) :hash)]
+    (if range-key
+      (conj schema (key-schema-element (:name range-key) :range))
+      schema)))

 (defn- provisioned-throughput "Returns a new ProvisionedThroughput object."
   [{read-units :read write-units :write}]
   (doto (ProvisionedThroughput.)
     (.setReadCapacityUnits  (long read-units))
     (.setWriteCapacityUnits (long write-units))))
+
+(defn- attribute-definition "Returns a new AttributeDefinition objects."
+  [{key-name :name key-type :type :as def}] ; TODO Why not [key-name key-type]?
+  (doto (AttributeDefinition.)
+    (.setAttributeName key-name)
+    (.setAttributeType (str/upper-case (name key-type)))))
+
+(defn- attribute-definitions "Returns a new vector of AttributeDefinition objects."
+  [defs] (mapv attribute-definition defs))

 ;;;; Coercion - values

@@ -148,18 +159,11 @@
 (defprotocol AsMap (as-map [x]))

 (extend-protocol AsMap
-  KeySchemaElement
-  (as-map [element]
-    {:name (.getAttributeName element)
-     :type (-> (.getAttributeType element)
-               (str/lower-case)
-               (keyword))})
-
-  KeySchema
-  (as-map [schema]
-    (merge
-     (when-let [e (.getHashKeyElement schema)]  {:hash-key  (as-map e)})
-     (when-let [e (.getRangeKeyElement schema)] {:range-key (as-map e)})))
+
+  java.util.ArrayList (as-map [alist] (into [] (map as-map alist)))
+  java.util.HashMap   (as-map [hmap] (utils/fmap as-map (into {} hmap)))
+  AttributeValue      (as-map [aval] (db-val->clj-val aval))
+  KeySchemaElement    (as-map [element] {:name (.getAttributeName element)})

   ProvisionedThroughputDescription
   (as-map [throughput]
@@ -180,21 +184,9 @@
                           (str/lower-case)
                           (keyword))}))

-  BatchWriteResponse
-  (as-map [result]
-    {:consumed-capacity-units (.getConsumedCapacityUnits result)})
-
   BatchWriteItemResult
   (as-map [result]
-    {:responses         (utils/fmap as-map (into {} (.getResponses result)))
-     :unprocessed-items (.getUnprocessedItems result)})
-
-  BatchResponse
-  (as-map [result]
-    {:consumed-capacity-units (.getConsumedCapacityUnits result)
-     :items (some->> (.getItems result)
-                     (into [])
-                     (utils/fmap #(utils/fmap db-val->clj-val (into {} %))))})
+    {:unprocessed-items (into {} (.getUnprocessedItems result))})

   KeysAndAttributes
   (as-map [result]
@@ -209,11 +201,6 @@
      :unprocessed-keys (utils/fmap as-map (into {} (.getUnprocessedKeys result)))})

   GetItemResult (as-map [result] (db-map->clj-map (.getItem result)))
-
-  Key
-  (as-map [k]
-    {:hash-key  (db-val->clj-val (.getHashKeyElement k))
-     :range-key (db-val->clj-val (.getRangeKeyElement k))})

   nil (as-map [_] nil))

@@ -236,14 +223,29 @@

   The throughput is a map with two keys:
     :read  - the provisioned number of reads per second
-    :write - the provisioned number of writes per second"
-  [creds {:keys [name hash-key range-key throughput]}]
+    :write - the provisioned number of writes per second
+
+  ;; TODO +
+  The indexes vector is a vector of maps with keys:
+    :name           - the name of the Local Secondary Index (required)
+    :range-key      - a map that defines the range key name and type (required)
+    :projection     - keyword that defines the projection may be:
+      :all, :keys_only, :include (optional - default is :keys-only)
+    :included-attrs - a vector of attribute names when :projection is :include
+                      (optional)"
+  [creds {:keys [name hash-key range-key throughput]}] ;; TODO +indexes
   (.createTable
    (db-client creds)
-   (doto (CreateTableRequest.)
-     (.setTableName (str name))
-     (.setKeySchema (key-schema hash-key range-key))
-     (.setProvisionedThroughput (provisioned-throughput throughput)))))
+   (let [defined-attrs (->> (conj [] hash-key range-key)
+                              ;; (concat (map #(:range-key %) indexes))
+                            (filter identity))]
+     (doto (CreateTableRequest.)
+       (.setTableName (str name))
+       (.setKeySchema (key-schema hash-key range-key))
+       (.setAttributeDefinitions (attribute-definitions defined-attrs))
+       (.setProvisionedThroughput (provisioned-throughput throughput))
+       ;; (.setLocalSecondaryIndexes (local-indexes hash-key indexes))
+       ))))

 (defn update-table
   "Update a table in DynamoDB with the given name. Only the throughput may be
@@ -323,40 +325,49 @@
               [(name k) (clj-val->db-val v)])))
      (set-expected-value! expected))))

-(defn- item-key
-  "Create a Key object from a value."
-  [{:keys [hash-key range-key]}]
-  (let [key (Key.)]
-    (when hash-key
-      (.setHashKeyElement key (clj-val->db-val hash-key)))
-    (when range-key
-      (.setRangeKeyElement key (clj-val->db-val range-key)))
-    key))
+;; (defn- item-key
+;;   "Create a Key object from a value."
+;;   [{:keys [hash-key range-key]}]
+;;   (let [key (Key.)]
+;;     (when hash-key
+;;       (.setHashKeyElement key (clj-val->db-val hash-key)))
+;;     (when range-key
+;;       (.setRangeKeyElement key (clj-val->db-val range-key)))
+;;     key))
+
+(defn- item-key "Returns a new Key map." ; TODO Key?
+  [key] ; TODO key?
+  (into {} (map (fn [[k v]] {(name k) (clj-val->db-val v)}) key)))

 (defn get-item
   "Retrieve an item from a DynamoDB table by its hash key."
+  ;; TODO hash-key should be specified as a map of {:attr-name value}. Huh??
   [creds table hash-key]
   (as-map
    (.getItem
     (db-client creds)
     (doto (GetItemRequest.)
       (.setTableName table)
-      (.setKey (item-key {:hash-key hash-key}))))))
+      (.setKey (item-key hash-key))))))

 (defn delete-item
   "Delete an item from a DynamoDB table by its hash key."
   [creds table hash-key]
   (.deleteItem
    (db-client creds)
-   (DeleteItemRequest. table (item-key {:hash-key hash-key}))))
+   (DeleteItemRequest. table (item-key hash-key))))

 ;;;; API - batch ops
+
+;; (defn- batch-item-keys [request-or-keys]
+;;   (for [key (:keys request-or-keys request-or-keys)]
+;;     (if (map? key)
+;;       (item-key key)
+;;       (item-key {:hash-key key}))))

 (defn- batch-item-keys [request-or-keys]
   (for [key (:keys request-or-keys request-or-keys)]
-    (if (map? key)
-      (item-key key)
-      (item-key {:hash-key key}))))
+    (item-key {(:key-name request-or-keys) key})))

 (defn- keys-and-attrs [{:keys [attrs consistent] :as request}]
   (let [kaa (KeysAndAttributes.)]
@@ -378,12 +389,14 @@
    which were elided by Amazon are available in the returned map
    key :unprocessed-keys.

-   Examples:
-   (batch-get-item creds
-     {:users [\"alice\" \"bob\"]
-      :posts {:keys [1 2 3]
-              :attrs [\"timestamp\" \"subject\"]
-              :consistent true}})"
+  Example:
+  (batch-get-item cred
+    {:users {:key-name \"names\"
+             :keys [\"alice\" \"bob\"]}
+     :posts {:key-name \"id\"
+             :keys [1 2 3]
+             :attrs [\"timestamp\" \"subject\"]
+             :consistent true}})"
   [creds requests]
   (as-map
     (.batchGetItem
@@ -467,14 +480,30 @@
     (db-client creds)
     (scan-request table options))))

+(defn- set-hash-condition
+  "Create a map of specifying the hash-key condition for query"
+  [hash-key]
+  (utils/fmap #(doto (Condition.)
+                 (.setComparisonOperator "EQ")
+                 (.setAttributeValueList [(clj-val->db-val %)]))
+              hash-key))
+
+;; (defn- set-range-condition
+;;   "Add the range key condition to a QueryRequest object"
+;;   [query-request operator & [range-key range-end]]
+;;   (let [attribute-list (->> [range-key range-end] (remove nil?) (map clj-val->db-val))]
+;;     (.setRangeKeyCondition query-request
+;;                            (doto (Condition.)
+;;                              (.withComparisonOperator operator)
+;;                              (.withAttributeValueList attribute-list)))))
+
 (defn- set-range-condition
   "Add the range key condition to a QueryRequest object"
-  [query-request operator & [range-key range-end]]
-  (let [attribute-list (->> [range-key range-end] (remove nil?) (map clj-val->db-val))]
-    (.setRangeKeyCondition query-request
-                           (doto (Condition.)
-                             (.withComparisonOperator operator)
-                             (.withAttributeValueList attribute-list)))))
+  [range-key operator & [range-value range-end]]
+  (let [attribute-list (->> [range-value range-end] (filter identity) (map clj-val->db-val))]
+    {range-key (doto (Condition.)
+                 (.setComparisonOperator operator)
+                 (.setAttributeValueList attribute-list))}))

 (defn- normalize-operator
   "Maps Clojure operators to DynamoDB operators"
@@ -483,45 +512,91 @@
         op (->> operator name str/upper-case)]
     (operator-map (keyword op) op)))

+;; (defn- query-request
+;;   "Create a QueryRequest object."
+;;   [table hash-key range-clause {:keys [order limit after count consistent attrs]}]
+;;   (let [qr (QueryRequest. table (clj-val->db-val hash-key))
+;;         [operator range-key range-end] range-clause]
+;;     (when operator
+;;       (set-range-condition qr (normalize-operator operator) range-key range-end))
+;;     (when attrs
+;;       (.setAttributesToGet qr (map name attrs)))
+;;     (when order
+;;       (.setScanIndexForward qr (not= order :desc)))
+;;     (when limit
+;;       (.setLimit qr (int limit)))
+;;     (when count
+;;       (.setCount qr count))
+;;     (when consistent
+;;       (.setConsistentRead qr consistent))
+;;     (when after
+;;       (.setExclusiveStartKey qr (item-key after)))
+;;     qr))
+
 (defn- query-request
   "Create a QueryRequest object."
-  [table hash-key range-clause {:keys [order limit after count consistent attrs]}]
-  (let [qr (QueryRequest. table (clj-val->db-val hash-key))
-        [operator range-key range-end] range-clause]
-    (when operator
-      (set-range-condition qr (normalize-operator operator) range-key range-end))
-    (when attrs
-      (.setAttributesToGet qr (map name attrs)))
-    (when order
-      (.setScanIndexForward qr (not= order :desc)))
-    (when limit
-      (.setLimit qr (int limit)))
-    (when count
-      (.setCount qr count))
-    (when consistent
-      (.setConsistentRead qr consistent))
-    (when after
-      (.setExclusiveStartKey qr (item-key after)))
+  [table hash-key range-clause {:keys [order limit after count consistent attrs]}] ;; TODO +index
+  (let [qr (QueryRequest.)
+        hash-clause (set-hash-condition hash-key)
+        [range-key operator range-value range-end] range-clause
+        query-conditions (if-not operator
+                           hash-clause
+                           (merge hash-clause (set-range-condition range-key
+                                                                   (normalize-operator operator)
+                                                                   range-value
+                                                                   range-end)))]
+    (.setTableName qr table)
+    (.setKeyConditions qr query-conditions)
+    (when attrs      (.setAttributesToGet qr (map name attrs)))
+    (when order      (.setScanIndexForward qr (not= order :desc)))
+    (when limit      (.setLimit qr (int limit)))
+    (when count      (.setCount qr count))
+    (when consistent (.setConsistentRead qr consistent))
+    (when after      (.setExclusiveStartKey qr (item-key after)))
+    ;; (when index      (.setIndexName qr index)) ; TODO
     qr))

 (defn- extract-range [[range options]]
-  (if (and (map? range) (nil? options))
+  (if (and (map? range) (not options))
     [nil range]
     [range options]))

+;; (defn query
+;;   "Return the items in a DynamoDB table matching the supplied hash key.
+;;   Can specify a range clause if the table has a range-key ie. `(>= 234)
+;;   Takes the following options:
+;;     :order - may be :asc or :desc (defaults to :asc)
+;;     :attrs - limit the values returned to the following attribute names
+;;     :limit - the maximum number of items to return
+;;     :after - only return results after this key
+;;     :consistent - return a consistent read if logical true
+
+;;   The items are returned as a map with the following keys:
+;;     :items    - the list of items returned
+;;     :count    - the count of items matching the query
+;;     :last-key - the last evaluated key (useful for paging)"
+;;   [creds table hash-key & range-and-options]
+;;   (let [[range options] (extract-range range-and-options)]
+;;     (result-map
+;;      (.query
+;;       (db-client creds)
+;;       (query-request table hash-key range options)))))
+
 (defn query
-  "Return the items in a DynamoDB table matching the supplied hash key.
-  Can specify a range clause if the table has a range-key ie. `(>= 234)
+  "Return the items in a DynamoDB table matching the supplied hash key,
+  defined in the form {\"hash-attr\" hash-value}.
+  Can specify a range clause if the table has a range-key ie. `(\"range-attr\" >= 234)
   Takes the following options:
     :order - may be :asc or :desc (defaults to :asc)
     :attrs - limit the values returned to the following attribute names
     :limit - the maximum number of items to return
     :after - only return results after this key
     :consistent - return a consistent read if logical true
+;;    :index - the secondary index to query ; TODO

   The items are returned as a map with the following keys:
-    :items    - the list of items returned
-    :count    - the count of items matching the query
+    :items - the list of items returned
+    :count - the count of items matching the query
     :last-key - the last evaluated key (useful for paging)"
   [creds table hash-key & range-and-options]
   (let [[range options] (extract-range range-and-options)]


reformat

reformat

--- src/otp_api_proxy/util.clj
+++ src/otp_api_proxy/util.clj
@@ -39,8 +39,7 @@
     (for [l lines]
       (let [fields (split l #"\\")]
         {:route_short_name (nth fields 0)
-         :frequency        (nth fields 5)}
-        ))))
+         :frequency        (nth fields 5)}))))

 (defn anaheim-frequency-for-route-short-name [n]
   (-> (filter (comp #{n} :route_short_name) (anaheim-route-lines))


Add a simple torus stepper function

Add a simple torus stepper function

--- src/petulant_life/life.clj
+++ src/petulant_life/life.clj
@@ -66,6 +66,8 @@

 (def hex-step  (stepper hex-neighbours   #{2} #{3 4}))

+(def torus-step (stepper (mk-torus-neighbours [6 6]) #{3} #{2 3}))
+
 (defn run [step-n]
   (->> (iterate rect-step #{[2 0] [2 1] [2 2] [1 2] [0 1]})
        (drop (dec step-n))


Update domain_model.clj

Update domain_model.clj

--- src/poeaa/domain_model.clj
+++ src/poeaa/domain_model.clj
@@ -55,7 +55,7 @@
 (defn make-product [name recognition-strategy]
   (fn [action]
     (case action
-      :calculate-revenue-recognitions
+      :calculate-revenue-recognitions ;; duck typing duck typing polymorphism
       (fn [contract]
         ((recognition-strategy :calculate-revenue-recognitions)) contract))))