fix broken table in invoices list

fix broken table in invoices list

--- src-cljs/frontend/components/plan.cljs
+++ src-cljs/frontend/components/plan.cljs
@@ -128,8 +128,8 @@
       (let [invoice (d/touch (d/entity @(om/get-shared owner :team-db) invoice-id))]
         (html
           [:tr.invoice.make
-           [:td.invoice-date
-            (datetime/medium-consistent-date (:invoice/date invoice))]
+           [:td.invoice-date {:title (datetime/medium-date (:invoice/date invoice))}
+            (datetime/month-day (:invoice/date invoice))]
            [:td.invoice-id
             [:a {:href (urls/invoice-url team-uuid invoice-id)
                  :target "_blank"}
@@ -140,7 +140,7 @@
             (cond (:invoice/paid? invoice)
                   "Paid"
                   (:invoice/next-payment-attempt invoice)
-                  (str "Charging " (datetime/medium-consistent-date (:invoice/next-payment-attempt invoice)))
+                  (str "Charging " (datetime/month-day (:invoice/next-payment-attempt invoice)))
                   :else "Unpaid")]])))))

 (defn invoices [{:keys [plan team-uuid]} owner]
@@ -156,7 +156,7 @@
                               reverse)]
         (html
           [:div.menu-view
-           (if (= 2 (count sorted-invoices))
+           (if (< 0 (count sorted-invoices))

              [:table.invoices-table
               [:thead.invoices-head


Worker should retry later instead of dying on failure to send heartbeats to ZK/Pacemaker

--- storm-core/src/clj/org/apache/storm/daemon/worker.clj
+++ storm-core/src/clj/org/apache/storm/daemon/worker.clj
@@ -72,8 +72,10 @@
                :time-secs (current-time-secs)
                }]
     ;; do the zookeeper heartbeat
-    (.worker-heartbeat! (:storm-cluster-state worker) (:storm-id worker) (:assignment-id worker) (:port worker) zk-hb)
-    ))
+    (try
+      (.worker-heartbeat! (:storm-cluster-state worker) (:storm-id worker) (:assignment-id worker) (:port worker) zk-hb)
+      (catch Exception exc
+        (log-error exc "Worker failed to write heatbeats to ZK or Pacemaker...will retry")))))

 (defn do-heartbeat [worker]
   (let [conf (:conf worker)


Cleans up :require and :import in cook.mesos.api (#275)

--- scheduler/src/cook/mesos/api.clj
+++ scheduler/src/cook/mesos/api.clj
@@ -41,12 +41,13 @@
             [mesomatic.scheduler]
             [metatransaction.core :refer (db)]
             [metrics.timers :as timers]
-            [plumbing.core :refer (map-vals map-from-vals)]
-            [plumbing.core :refer [map-keys mapply]]
+            [plumbing.core :refer [map-from-vals map-keys map-vals mapply]]
             [ring.middleware.json]
             [schema.core :as s]
             [swiss.arrows :refer :all])
-  (:import java.util.UUID))
+  (:import java.net.URLEncoder
+           (java.util Date UUID)
+           schema.core.OptionalKey))

 ;; This is necessary to prevent a user from requesting a uid:gid
 ;; pair other than their own (for example, root)
@@ -87,7 +88,7 @@
    1. changes keys to snake_case"
   [schema]
   (map-keys (fn [k]
-              (if (instance? schema.core.OptionalKey k)
+              (if (instance? OptionalKey k)
                 (update k :k ->snake_case)
                 (->snake_case k)))
             schema))
@@ -404,12 +405,12 @@
                                       :resource/amount (double gpus)}]))])
         commit-latch-id (d/tempid :db.part/user)
         commit-latch {:db/id commit-latch-id
-                      :commit-latch/uuid (java.util.UUID/randomUUID)
+                      :commit-latch/uuid (UUID/randomUUID)
                       :commit-latch/committed? true}
         txn {:db/id db-id
              :job/commit-latch commit-latch-id
              :job/uuid uuid
-             :job/submit-time (java.util.Date.)
+             :job/submit-time (Date.)
              :job/name (or name "cookjob") ; set the default job name if not provided.
              :job/command command
              :job/custom-executor false
@@ -643,7 +644,7 @@
   [host executor-state]
   (str "http://" host ":5051"
        "/files/read.json?path="
-       (java.net.URLEncoder/encode (get executor-state "directory") "UTF-8")))
+       (URLEncoder/encode (get executor-state "directory") "UTF-8")))

 (defn fetch-job-map
   [db fid job-uuid]
@@ -1090,6 +1091,7 @@

 (def ReadRetriesRequest
   {:job [s/Uuid]})
+
 (def UpdateRetriesRequest
   {(s/optional-key :jobs) [s/Uuid]
    (s/optional-key :retries) PosNum
@@ -1370,9 +1372,9 @@
                               since-hours-ago ::since-hours-ago
                               limit ::limit} ctx
                              start (if start-ms
-                                     (java.util.Date. start-ms)
-                                     (java.util.Date. (- end-ms (-> since-hours-ago t/hours t/in-millis))))
-                             end (java.util.Date. end-ms)
+                                     (Date. start-ms)
+                                     (Date. (- end-ms (-> since-hours-ago t/hours t/in-millis))))
+                             end (Date. end-ms)
                              job-uuids (->> (timers/time!
                                               fetch-jobs
                                               ;; Get valid timings


Do not generate empty Icepick$$Bundlers

Do not generate empty Icepick$$Bundlers

--- icepick-processor/src/clojure/icepick/processor.clj
+++ icepick-processor/src/clojure/icepick/processor.clj
@@ -317,7 +317,7 @@
     (doseq [ann annotations]
       (let [analyzed-fields (map analyze-field (.getElementsAnnotatedWith env ann))
             bundlers (apply hash-set (remove nil? (map :bundler analyzed-fields)))]
-        (emit-bundlers-class! bundlers)
+        (when (seq bundlers) (emit-bundlers-class! bundlers))
         (->> analyzed-fields
              (group-by :enclosing-class)
              (map emit-class!)


Remove response body from analytics

Remove response body from analytics

--- systems/ring-analytics/src/containium/systems/ring_analytics.clj
+++ systems/ring-analytics/src/containium/systems/ring_analytics.clj
@@ -46,16 +46,17 @@
         (let [started (System/currentTimeMillis)
               response (try (handler request)
                             (catch Throwable t (ex/exit-when-fatal t) t))
+              took (- (System/currentTimeMillis) started)
               processed (+> request
                             (dissoc :body :async-channel)
                             (assoc :started (time/format (time/datetime started)
                                                          :date-hour-minute-second-ms)
-                                   :took (- (System/currentTimeMillis) started)
                                    ;; Maybe move the request parameters to a :request key as well?
-                                   :response response)
-                            (if (instance? Throwable response)
-                              (assoc :failed (.getMessage ^Throwable response))
-                              (assoc :status (:status response))))]
+                                   :response (-> body
+                                                 (dissoc :body)
+                                                 (assoc :took took)))
+                            (when (instance? Throwable response)
+                              (assoc :failed (.getMessage ^Throwable response))))]
           (future (try (store-request client app-name processed)
                        (catch Throwable t
                          (ex/exit-when-fatal t)


Fixed bug in domain cleanup.

Fixed bug in domain cleanup.

--- src/clj/elephantdb/common/domain.clj
+++ src/clj/elephantdb/common/domain.clj
@@ -402,7 +402,7 @@
         (status/to-loading)
         (transfer-version! version)
         (load-version! version)
-        (cleanup-domain! domain)))))
+        (cleanup-domain!)))))

 (defn attempt-update!
   "If the supplied domain isn't currently updating, returns a future


Fix one issue related to the encoding format of strokes Note: Due to unknown reason if encode strokes as vectors one the server side load-string will throw :Method code too large error" I don't have knowledge to dig in now. But after some error and try if I use list instead of vectors load-string can parse the clojure string perfectly.

--- src/cljs/handwrite_strokes/core.cljs
+++ src/cljs/handwrite_strokes/core.cljs
@@ -33,12 +33,12 @@
       (swap! curr-stroke (fn [arr] (conj arr [(.-offsetX evt) (.-offsetY evt)]))))))

 (defn format-strokes []
-  (defn format-stroke [arr] (str "["
+  (defn format-stroke [arr] (str "(list "
                                  (string/join " " (map (fn [[x y]] (str "'(" x " " y ")")) arr))
-                                 "]"))
+                                 ")"))
   (str "{"
        :scale " " (.-width (.getElementById js/document "canvas")) " "
-       :strokes " [" (string/join " " (map format-stroke @strokes)) "]}"))
+       :strokes " (list " (string/join " " (map format-stroke @strokes)) ")}"))

 (defn call-set-strokes []
   (POST "/write-character" {:format :url :params {:strokes (format-strokes)}}))


basic clean up

basic clean up

--- src/cljs/phonecat_re_frame/core.cljs
+++ src/cljs/phonecat_re_frame/core.cljs
@@ -60,14 +60,32 @@
     (fn []

       [:ul {:class= "phones"}
-       (for [phone (filter (partial matches-query? @search-input) @phones)]
+       (for [phone (->> @phones
+                        (filter (partial matches-query? @search-input))
+                        (sort-by (keyword @order-prop)))]
          ^{:key (:name phone)} [phone-component phone])])))

 (defn search-component
   []
   (let [search-input (re-frame/subscribe [:search-input])])
   (fn []
-    [:input {:on-change #(re-frame/dispatch [:search-input-entered (-> % .-target .-value)])}]))
+    [:div "Search"
+     [:input {:on-change #(re-frame/dispatch [:search-input-entered (-> % .-target .-value)])}]]))
+
+(defn mark-selected
+  [props order-prop current-prop-value]
+  (if (= order-prop current-prop-value)
+    (reagent/merge-props props {:selected "selected"})
+    props))
+
+(defn order-by-component
+  []
+  (let [order-prop (re-frame/subscribe [:order-prop])]
+    (fn []
+      [:div "Sort by: "
+       [:select {:on-change #(re-frame/dispatch [:order-prop-changed (-> % .-target .-value)])}
+        [:option (mark-selected {:value "name"} @order-prop "name") "Alphabetical"]
+        [:option (mark-selected {:value "age"} @order-prop "age") "Newest"]]])))

 (defn home-page []
   [:div {:class "container-fluid"}


add endorsement modal to badge route

add endorsement modal to badge route

--- src/cljs/salava/badge/ui/routes.cljs
+++ src/cljs/salava/badge/ui/routes.cljs
@@ -13,7 +13,8 @@
             [salava.badge.ui.stats :as stats]
             [reagent.session :as session]
             [salava.badge.ui.modal :as badgemodal]
-            [salava.core.i18n :as i18n :refer [t]]))
+            [salava.core.i18n :as i18n :refer [t]]
+            [salava.badge.ui.endorsement :as e]))

 (defn placeholder [content]
   (fn [site-navi params]
@@ -27,11 +28,13 @@
                                        [["/info/" :badge-id "/embed"] embed/handler]
                                        [["/info/" :badge-id "/pic/embed"] embed-pic/handler]
                                        ["/import" imp/handler]
-                                       [["/receive/" :badge-id] rec/handler]]})
+                                       [["/receive/" :badge-id] rec/handler]
+                                       [["/user/endorsements"] e/handler]]})

 (defn ^:export navi [context]
   {(str (base-path context) "/badge") {:weight 20 :title (t :badge/Badges)   :top-navi true  :breadcrumb (t :badge/Badges " / " :badge/Mybadges)}
    (str (base-path context) "/badge/mybadges") {:weight 20 :title (t :badge/Mybadges) :site-navi true :breadcrumb (t :badge/Badges " / "  :badge/Mybadges)}
    (str (base-path context) "/badge/import") {:weight 22 :title (t :badge/Import) :site-navi false :breadcrumb (t :badge/Badges " / " :badge/Import)}
-   (str (base-path context) "/badge/info/\\d+") {:breadcrumb   (t :badge/Badges " / " :badge/Badgeinfo)}})
+   (str (base-path context) "/badge/info/\\d+") {:breadcrumb   (t :badge/Badges " / " :badge/Badgeinfo)}
+   (str (base-path context) "/badge/user/endorsements") {:weight 50 :title (t :badge/Endorsements) :breadcrumb (t :badge/Badges " / " :badge/Endorsements) :site-navi true}})


Fix classapth

Fix classapth

--- src/edu/berkeley/ai/util/cluster.clj
+++ src/edu/berkeley/ai/util/cluster.clj
@@ -29,7 +29,7 @@
 		  "-o" (str (util/file-stem f) ".out")
 		  "-e" (str (util/file-stem f) ".err")]
 		*default-qsub-options*
-		[:in (str "java -server -Xmx1024m -cp " *classpath* " clojure.main " f) :dir (util/dirname f)])))))))
+		[:in (str "java -server -Xmx1024m -cp " user/*classpath* " clojure.main " f) :dir (util/dirname f)])))))))

 (defn run-experiment-set-subprocesses [es]
   (run-files-subprocesses


core tests fixed

core tests fixed

--- test/clojure2d/core_test.clj
+++ test/clojure2d/core_test.clj
@@ -15,9 +15,8 @@
   (set-state! window (assoc (get-state window) :fps fps))
   (-> canvas
       (set-background :black)
-      (set-color :white)
+      (set-color :maroon)
       (line 0 (inc (mod fps 100)) 100 (inc (mod fps 100)))
-      (set-color :maroon)
       (ellipse 50 50 10 10)))

 (def window (atom nil))


moar idiomatic

moar idiomatic

--- solutions/day12/solution.clj
+++ solutions/day12/solution.clj
@@ -1,41 +1,36 @@
 (require '[clojure.data.json :as json])

-(defn seqsum
-  "Returns the sum of all numbers in a sequence"
-  [s]
-  {:test (defn f [] (assert (= 6 (seqsum [1 2 "a" 3]))))}
-  (let [numbers (filter number? s)
-        seqs (filter sequential? s)
-        maps (filter map? s)
-        numsum (reduce + numbers)
-        ssum (reduce + (map seqsum seqs))
-        msum (reduce + (map mapsum maps))]
-    (+ numsum ssum msum)))
+(defn json-sum
+  "Returns the sum of all numbers in a json object"
+  {:test (defn f[] (assert (= (10 json-sum [1 2 {3 4}]))))}
+  [j]
+  (cond
+    (map? j)
+      (reduce + (map json-sum [(keys j) (vals j)]))
+    (sequential? j)
+      (reduce + (map json-sum j))
+    :else
+      (if (number? j) j 0)))

-(defn mapsum
-  "Returns the sum of all numbers in a map's keys and values"
-  [m]
-  {:test (defn f[] (assert (= (6 mapsum {1 2 2 1}))))}
-  (+ (seqsum (keys m))
-     (seqsum (vals m))))
-
-(defn filter-by-val
+(defn filter-json-by-val
   "Recursively filters any json serialized object - which can be any arbitrary
    nested combination of lists, maps, and literals - removing any maps that
    contain the specified value"
-  [v m]
-  {:test (defn f[] (assert (= {1 2 3 nil} (filter-by-val {1 2 3 {4 "red"}}))))}
+  [v j]
+  {:test (defn f[] (assert (= {1 2 3 nil} (filter-json-by-val {1 2 3 {4 "red"}}))))}
   (cond
-    (sequential? m) (map #(filter-by-val v %) m)
-    (map? m)
-      (when (not (some #{v} (vals m)))
+    (map? j)
+      (when (not (some #{v} (vals j)))
         (into {}
            (map
              (fn [[k, vv]]
-               [k, (filter-by-val v vv)])
-             m)))
-    :else m))
+               [k, (filter-json-by-val v vv)])
+             j)))
+    (sequential? j)
+      (map #(filter-json-by-val v %) j)
+    :else
+      j))

 (def input (json/read-str (slurp "input.txt")))
-(println "part 1: " (mapsum input))
-(println "part 2: " (mapsum (filter-by-val "red" input)))
+(println "part 1: " (json-sum input))
+(println "part 2: " (json-sum (filter-json-by-val "red" input)))


Added additional test

Added additional test

--- test/fake_http/fake_test.clj
+++ test/fake_http/fake_test.clj
@@ -21,4 +21,10 @@
       (fake-route! @server "/something" {:status 200 :content-type "application/json" :body (json/generate-string {:hello "world"})})
       (let [response (client/get (str (uri @server) "/something"))
             json-response (json/parse-string (:body response) true)]
+        (should= (:hello json-response) "world")))
+
+  (it "Matches path with specific single query param"
+      (fake-route! @server {:path "/something" :first "value1"} {:status 200 :content-type "application/json" :body (json/generate-string {:hello "world"})})
+      (let [response (client/get (str (uri @server) "/something?first=value1"))
+            json-response (json/parse-string (:body response) true)]
         (should= (:hello json-response) "world"))))


cjl - Spelling

cjl - Spelling

--- test/icfp2015/board_test.clj
+++ test/icfp2015/board_test.clj
@@ -3,5 +3,5 @@
             [icfp2015.board :refer :all]))

 (deftest make-board-test
-  (testing "Tnitial state"
+  (testing "Initial state"
     (is (= 1 1))))


Minor changes on tests.

Minor changes on tests.

--- test/promesa/core_tests.cljc
+++ test/promesa/core_tests.cljc
@@ -52,14 +52,14 @@
   #?(:cljs
      (t/async done
        (let [p1 (p/promise (fn [resolve reject]
-                             (p/schedule 100 #(resolve 1))))]
+                             (p/schedule 50 #(resolve 1))))]
          (t/is (p/pending? p1))
          (p/then p1 (fn [v]
                       (t/is (= v 1))
                       (done)))))
      :clj
      (let [p1 (p/promise (fn [resolve reject]
-                           (p/schedule 100 #(resolve 1))))]
+                           (p/schedule 50 #(resolve 1))))]
        (t/is (p/pending? p1))
        (t/is (= @p1 1)))))

@@ -107,12 +107,12 @@
 (t/deftest arbitrary-choice-with-any
   #?(:cljs
      (t/async done
-       (let [p1 (p/any [(p/delay 300 1) (p/delay 200 2)])]
+       (let [p1 (p/any [(p/delay 300 1) (p/delay 100 2)])]
          (p/then p1 (fn [v]
                       (t/is (= v 2))
                       (done)))))
      :clj
-     (let [p1 (p/any [(p/delay 300 1) (p/delay 200 2)])]
+     (let [p1 (p/any [(p/delay 300 1) (p/delay 100 2)])]
        (t/is (= @p1 2)))))

 (t/deftest reject-promise-in-chain
@@ -137,14 +137,14 @@
 (t/deftest chaining-using-then
   #?(:cljs
      (t/async done
-       (let [p1 (future-ok 200 2)
+       (let [p1 (future-ok 100 2)
              p2 (p/then p1 inc)
              p3 (p/then p2 inc)]
          (p/then p3 (fn [v]
                       (t/is (= v 4))
                       (done)))))
      :clj
-     (let [p1 (future-ok 200 2)
+     (let [p1 (future-ok 100 2)
            p2 (p/then p1 inc)
            p3 (p/then p2 inc)]
        (t/is (= @p3 4)))))
@@ -152,14 +152,14 @@
 (t/deftest chaining-using-map
   #?(:cljs
      (t/async done
-       (let [p1 (future-ok 200 2)
+       (let [p1 (future-ok 100 2)
              p2 (p/map inc p1)
              p3 (p/map inc p2)]
          (p/then p3 (fn [v]
                       (t/is (= v 4))
                       (done)))))
      :clj
-     (let [p1 (future-ok 200 2)
+     (let [p1 (future-ok 100 2)
            p2 (p/map inc p1)
            p3 (p/map inc p2)]
        (t/is (= @p3 4)))))
@@ -167,7 +167,7 @@
 (t/deftest chaining-using-mapcat
   #?(:cljs
      (t/async done
-       (let [p1 (future-ok 200 2)
+       (let [p1 (future-ok 100 2)
              inc #(p/resolved (inc %))
              p2 (p/mapcat inc p1)
              p3 (p/mapcat inc p2)]
@@ -175,7 +175,7 @@
                       (t/is (= v 4))
                       (done)))))
      :clj
-     (let [p1 (future-ok 200 2)
+     (let [p1 (future-ok 100 2)
            inc #(p/resolved (inc %))
            p2 (p/mapcat inc p1)
            p3 (p/mapcat inc p2)]
@@ -185,10 +185,10 @@
   #?(:cljs
      (t/async done
        (let [value (volatile! nil)
-             c1 (p/schedule 1000 #(vreset! value 1))
-             c2 (p/schedule 1000 #(vreset! value 2))]
+             c1 (p/schedule 100 #(vreset! value 1))
+             c2 (p/schedule 100 #(vreset! value 2))]
          (p/cancel! c1)
-         (p/schedule 1200
+         (p/schedule 300
                      (fn []
                        (t/is (= @value 2))
                        (t/is (realized? c2))
@@ -197,10 +197,10 @@
                        (done)))))
      :clj
      (let [value (volatile! nil)
-           c1 (p/schedule 1000 #(vreset! value 1))
-           c2 (p/schedule 1000 #(vreset! value 2))]
+           c1 (p/schedule 500 #(vreset! value 1))
+           c2 (p/schedule 500 #(vreset! value 2))]
        (p/cancel! c1)
-       @(p/schedule 1200 (constantly nil))
+       @(p/schedule 1100 (constantly nil))
        (t/is (realized? c2))
        (t/is (not (realized? c1)))
        (t/is (p/cancelled? c1))
@@ -209,26 +209,26 @@
 (t/deftest chaining-using-chain
   #?(:cljs
      (t/async done
-       (let [p1 (future-ok 200 2)
+       (let [p1 (future-ok 100 2)
              p2 (p/chain p1 inc inc inc)]
          (p/then p2 (fn [v]
                       (t/is (= v 5))
                       (done)))))
      :clj
-     (let [p1 (future-ok 200 2)
+     (let [p1 (future-ok 100 2)
            p2 (p/chain p1 inc inc inc)]
        (t/is (= @p2 5)))))

 (t/deftest branching-using-branch-1
   #?(:cljs
      (t/async done
-       (let [p1 (future-ok 200 2)
+       (let [p1 (future-ok 100 2)
              p2 (p/branch p1 #(inc %) (constantly nil))]
          (p/then p2 #(do
                        (t/is (= % 3))
                        (done)))))
      :clj
-     (let [p1 (future-ok 200 2)
+     (let [p1 (future-ok 100 2)
            p2 (p/branch p1 #(inc %) (constantly nil))]
        (t/is (= @p2 3)))))

@@ -236,14 +236,14 @@
   #?(:cljs
      (t/async done
        (let [e (ex-info "foobar" {})
-             p1 (future-fail 200 e)
+             p1 (future-fail 100 e)
              p2 (p/branch p1 (constantly nil) identity)]
          (p/then p2 #(do
                        (t/is (= % e))
                        (done)))))
      :clj
      (let [e (ex-info "foobar" {})
-           p1 (future-fail 200 e)
+           p1 (future-fail 100 e)
            p2 (p/branch p1 (constantly nil) (constantly 1))]
        (t/is (= @p2 1)))))

@@ -293,45 +293,45 @@

 #?(:clj
    (t/deftest async-let
-     (let [result (p/alet [a (p/await (future-ok 100 1))
+     (let [result (p/alet [a (p/await (future-ok 50 1))
                            b 2
                            c 3
-                           d (p/await (future-ok 200 4))]
+                           d (p/await (future-ok 100 4))]
                     (+ a b c d))]
        (t/is (= @result 10)))))

 #?(:cljs
    (t/deftest async-let
      (t/async done
-       (let [result (p/alet [a (p/await (future-ok 100 1))
+       (let [result (p/alet [a (p/await (future-ok 50 1))
                              b 2
                              c 3
-                             d (p/await (future-ok 200 4))]
+                             d (p/await (future-ok 100 4))]
                       (+ a b c d))]
          (p/then result (fn [result]
                           (t/is (= result 10))
                           (done)))))))

-;; --- Do Expression tests
-
-(t/deftest do-expression
-  #?(:cljs
-     (t/async done
-       (let [error (ex-info "foo" {})
-             result (p/do* (throw error))]
-         (p/catch result (fn [e]
-                           (t/is (= e error))
-                           (done)))))
-     :clj
-     (let [error (ex-info "foo" {})
-           result (p/do* (throw error))
-           result @(p/catch result (fn [e]
-                                     (assert (= e error))
-                                     nil))]
-       (t/is (= nil result)))))
-
-
-;; --- `async` macro tests
+;; ;; --- Do Expression tests
+
+;; (t/deftest do-expression
+;;   #?(:cljs
+;;      (t/async done
+;;        (let [error (ex-info "foo" {})
+;;              result (p/do* (throw error))]
+;;          (p/catch result (fn [e]
+;;                            (t/is (= e error))
+;;                            (done)))))
+;;      :clj
+;;      (let [error (ex-info "foo" {})
+;;            result (p/do* (throw error))
+;;            result @(p/catch result (fn [e]
+;;                                      (assert (= e error))
+;;                                      nil))]
+;;        (t/is (= nil result)))))
+
+
+;; ;; --- `async` macro tests

 (defn my-func
   [i]


Add more tests.

Add more tests.

--- test/promesa/core_tests.cljs
+++ test/promesa/core_tests.cljs
@@ -40,15 +40,24 @@
     (t/is (identical? p1 p2))))

 (t/deftest syncrhonize-two-promises
-  (let [p1 (-> (p/all [(p/promise 1) (p/promise 2)])
-               (p/then (fn [[x y]]
-                         (t/is (= x 1))
-                         (t/is (= y 2))
-                         (+ x y))))]
-    (p/then p1 (fn [v]
-                 (t/is (= v 3))))))
+  (t/async done
+    (let [p1 (p/all [(p/promise 1) (p/promise 2)])]
+      (p/then p1 (fn [[x y]]
+                   (t/is (= x 1))
+                   (t/is (= y 2))
+                   (done))))))

-(t/deftest arbitrary-choice
+(t/deftest arbitrary-choice-with-some
+  (t/async done
+    (let [p1 (p/some 2 [(future 200 1)
+                        (future 200 2)
+                        (future 300 3)])]
+      (p/then p1 (fn [[x y]]
+                   (t/is (= x 1))
+                   (t/is (= y 2))
+                   (done))))))
+
+(t/deftest arbitrary-choice-with-any
   (t/async done
     (let [p1 (p/any [(p/delay 300 1) (p/delay 200 2)])]
       (p/then p1 (fn [v]
@@ -75,6 +84,36 @@
                    (t/is (= v "foo"))
                    (done))))))

+
+(defn future
+  [sleep value]
+  (p/promise (fn [resolve]
+               (js/setTimeout #(resolve value) sleep))))
+
+(t/deftest chaining-using-then
+  (t/async done
+    (let [p1 (future 200 2)
+          p2 (p/then p1 inc)
+          p3 (p/then p2 inc)]
+      (p/then p3 (fn [v]
+                   (t/is (= v 4))
+                   (done))))))
+
+(t/deftest chaining-using-chain
+  (t/async done
+    (let [p1 (future 200 2)
+          p2 (p/chain p1 inc inc inc)]
+      (p/then p2 (fn [v]
+                   (t/is (= v 5))
+                   (done))))))
+
+(t/deftest chaining-using->>=
+  (t/async done
+    (let [p1 (future 200 2)
+          p2 (m/>>= p1 inc inc inc)]
+      (p/then p2 (fn [v]
+                   (t/is (= v 5))
+                   (done))))))

 (t/deftest promise-as-functor
   (t/async done


tweaking heatmap

tweaking heatmap

--- src/cljs/gointermod/heatmap/views.cljs
+++ src/cljs/gointermod/heatmap/views.cljs
@@ -21,7 +21,7 @@
 ;    (.log js/console "%c@expanded" "color:goldenrod;font-weight:bold;" (clj->js @expanded))
   [:thead
    [:tr
-    [:th.axis {:col-span 3}
+    [:th.axis {:col-span 2}
       [:div
         [:h3
           [:svg.icon [:use {:xlinkHref (:icon filter-info)}]] " "
@@ -67,29 +67,31 @@
     [:td
       ;;output differently depending on the status of the
       ;;expanded/expandable) row
-      (if
+      (cond
         is-expanded-but-summary-row? organism-name
-        organism-name)
-     ]
-      (if
+        is-expanded? [:svg.icon [:use {:xlinkHref "#expanded-row"}]]
+        true organism-name)
+
+     (cond
         ;;so if it's a number, it's a multi-result row. We want number rows to be expandable.
       (number? ortholog)
-        [:td
+        [:span
           (if is-expanded?
             [:span.expand {:on-click #(re-frame/dispatch [:collapse-heatmap organism-id])} [:svg.icon [:use {:xlinkHref "#icon-circle-down"}]]]
             [:span.expand {:on-click #(re-frame/dispatch [:expand-heatmap organism-id])} [:svg.icon [:use {:xlinkHref "#icon-circle-right"}]]]
         )]
-        [:td]
      )
+
+     ]
     (if (number? ortholog)
       ;;handle aggregate result counts
-      [:td.ortholog
+      [:td
         (if (= org-count 1)
           ;;don't say "1 gene", just output the gene itself.
           ortholog
           [:span org-count " genes " ])]
       ;;if the results aren't aggregate (e.g. the user expanded them) we just output its name
-      [:td.ortholog ortholog]
+      [:td ortholog]
      )]))

 (defn make-cell-title


set-x and set-y in vec2 to return new vec2 with altered param

--- src/cljs/infinitelives/utils/vec2.cljs
+++ src/cljs/infinitelives/utils/vec2.cljs
@@ -200,6 +200,16 @@
 (defn get-y [v]
   (aget v 1))

+(defn set-x
+  "return a new vector with a different x"
+  [v x]
+  (vec2 x (aget v 1)))
+
+(defn set-y
+  "return a new vector with a different y"
+  [v y]
+  (vec2 (aget v 0) y))
+
 (defn angle-between
   "Placing the tails of the two vectors together,
 return the angle between them in radians"


Initialisation, logging to websocket ns

Initialisation, logging to websocket ns

--- src/cljs/train_race/communication.cljs
+++ src/cljs/train_race/communication.cljs
@@ -1,19 +1,20 @@
 (ns train-race.communication
   (:require-macros
-    [cljs.core.async.macros :as asyncm :refer [go go-loop]])
+    [cljs.core.async.macros :as asyncm :refer [go go-loop]]
+    [alter-cljs.core :refer [alter-var-root]])
   (:require
     [cljs.core.async :as async :refer [<! >! put! chan]]
-    [taoensso.sente  :as sente :refer [cb-success?]]))
+    [taoensso.sente :as sente :refer [cb-success?]]

-(let [{:keys [chsk ch-recv send-fn state]}
-      (sente/make-channel-socket! "/api/chsk" ; Note the same path as before
-                                  {:type :auto ; e/o #{:auto :ajax :ws}
-                                   })]
-  (def chsk       chsk)
-  (def ch-chsk    ch-recv) ; ChannelSocket's receive channel
-  (def chsk-send! send-fn) ; ChannelSocket's send API fn
-  (def chsk-state state)   ; Watchable, read-only atom
-  )
+    [train-race.log :as log :refer [logger]]))
+
+(defonce ^{:private true} +no-receive-channel+ (chan (async/dropping-buffer 1)))
+(defonce ^{:private true} +no-send-fn+ (constantly nil))
+(defonce ^{:private true} +no-chsk-state+ (atom nil))
+
+(defonce receive-channel +no-receive-channel+)
+(defonce sente-send! +no-send-fn+)
+(defonce sente-state +no-chsk-state+)

 (defonce listeners (atom {}))
 (defonce router_ (atom nil))
@@ -37,30 +38,66 @@
 (defmethod -event-msg-handler
   :default ; Default/fallback case (no other matching handler)
   [{:as ev-msg :keys [event]}]
-  (println "Unhandled event: %s" event))
+  (log/warn logger ::communication.sente {:msg (str "Unhandled event: %s" event)
+                                          :data ev-msg}))

 (defmethod -event-msg-handler :chsk/state
   [{:as ev-msg :keys [?data]}]
   (if (:first-open? ?data)
-    (println "Channel socket successfully established!: %s" ?data)
-    (println "Channel socket state change: %s" ?data)))
+    (log/info logger ::communication.sente {:msg (str "Channel socket successfully established!: " ?data)
+                                             :data ev-msg})
+    (log/info logger ::communication.sente {:msg (str "Channel socket state change: " ?data)
+                                             :data ev-msg})))

 (defmethod -event-msg-handler :chsk/recv
   [{:as ev-msg :keys [?data]}]
   (let [[event & payload] ?data]
-    #_(println "New event from server: " event)
+    (log/trace logger ::communication.sente {:msg (str "New event from server: " ?data)
+                                             :data ev-msg})
     (doseq [fn (@listeners event)]
       (apply fn payload))))

 (defmethod -event-msg-handler :chsk/handshake
   [{:as ev-msg :keys [?data]}]
   (let [[?uid ?csrf-token ?handshake-data] ?data]
-    (println "Handshake: %s" ?data)))
+    (log/info logger ::communication.sente {:msg (str "Handshake: " ?data)
+                                             :data ev-msg})))

-(defn  stop-router! [] (when-let [stop-f @router_] (stop-f)))
+(defn- initialise-socket! []
+  (let [{:keys [chsk ch-recv send-fn state]}
+        (sente/make-channel-socket! "/websocket/conn"
+                                    {:type :auto})]
+    (alter-var-root #'receive-channel (constantly ch-recv))
+    (alter-var-root #'sente-send! (constantly send-fn))
+    (alter-var-root #'sente-state (constantly state))))

-(defn start-router! []
+(defn- stop-socket! []
+  (alter-var-root #'receive-channel (constantly +no-receive-channel+))
+  (alter-var-root #'sente-send! (constantly +no-send-fn+))
+  (alter-var-root #'sente-state (constantly +no-chsk-state+)))
+
+(defn- stop-router! []
+  (when-let [stop-f @router_]
+    (log/info logger ::system.shutdown {:msg "Stopping sente router"})
+    (stop-f)))
+
+(defn- start-router! []
   (stop-router!)
+  (log/info logger ::system.startup {:msg "Starting sente router"})
   (reset! router_
           (sente/start-client-chsk-router!
-            ch-chsk event-msg-handler)))
+            receive-channel event-msg-handler)))
+
+(defn start-websocket-connection! []
+  (initialise-socket!)
+  (add-watch sente-state ::sente-state
+             (fn [_ _ old new]
+               (log/trace logger ::communication.sente
+                          {:msg (str "Sente state: " (pr-str new))
+                           :data {:old old :new new}})))
+  (start-router!))
+
+(defn stop-websocket-connection! []
+  (stop-router!)
+  (remove-watch sente-state ::sente-state)
+  (stop-socket!))


Fix issue #69 to provide helpful compilation messages on the RHS.

--- src/main/clojure/clara/rules/dsl.clj
+++ src/main/clojure/clara/rules/dsl.clj
@@ -178,10 +178,11 @@
         rule {:lhs (list 'quote
                          (mapv #(resolve-vars % (destructure-syms %))
                                conditions))
-              :rhs (with-meta
-                     (resolve-vars (list 'quote rhs)
-                                   (map :fact-binding conditions))
-                     (assoc (meta rhs) :file *file*))}
+              :rhs (list 'quote
+                         (with-meta (resolve-vars rhs
+                                                  (map :fact-binding conditions))
+
+                           (assoc (meta rhs) :file *file*)))}

         symbols (set (filter symbol? (flatten (concat lhs rhs))))
         matching-env (into {} (for [sym (keys env)


Added kml visualization

Added kml visualization

--- system-int-test/test/cmr/system_int_test/search/granule_orbit_search_test.clj
+++ system-int-test/test/cmr/system_int_test/search/granule_orbit_search_test.clj
@@ -124,7 +124,10 @@
   (ge-helper/display-shapes "start_circ_neg_50.kml" @matching-mbrs)
   (ge-helper/display-shapes "start_circ_0.kml" @matching-mbrs)

-  ;;TODO visualize kml returned by granule and commit this
+  ;; visualize the kml representation
+  (do (spit "granule_kml.kml"
+            (:out (clojure.java.shell/sh "curl" "--silent" "http://localhost:3003/granules.kml")))
+    (clojure.java.shell/sh "open" "granule_kml.kml"))


WIP on new cursor implementation.

WIP on new cursor implementation.

--- src-cljs/freactive/core.cljs
+++ src-cljs/freactive/core.cljs
@@ -427,5 +427,147 @@
   ([ref korks-or-getter] (cursor* ref korks-or-getter nil true))
   ([ref getter setter] (cursor* ref getter setter true)))

-
 (defn lens-cursor [ref getter setter] (cursor ref getter setter))
+
+
+;; WIP on new cursor implementation
+(comment
+
+  (defprotocol IHasCursors
+    (-get-cursor [this sub-key]))
+
+  (defprotocol ICursor
+    (-cursor-key [this])
+    (-child-cursor [this key])
+    (-parent-cursor [this]))
+
+  (defn cursor-key [^clj cursor]
+    (-cursor-key cursor))
+
+  (defn child-cursor [^clj cursor key]
+    (-child-cursor cursor))
+
+  (defn descendant-cursor [^clj cursor path]
+    (loop [[key & more] path
+           res cursor]
+      (if key
+        (recur more (child-cursor res key))
+        res)))
+
+  (defn parent-cursor [^clj cursor]
+    (-parent-cursor cursor))
+
+  (defn get-root-cursor [cursor]
+    (loop [cursor cursor]
+      (if-let [parent (parent-cursor cursor)]
+        (recur parent)
+        cursor)))
+
+  (defn cursor-path [cursor]
+    (loop [cursor cursor
+           path []]
+      (let [parent (parent-cursor cursor)
+            key (cursor-key cursor)]
+        (if (and parent key)
+          (recur parent (conj path key))
+          path))))
+
+  (defn cursor [cursor korks]
+    (if (sequential? korks)
+      (descendant-cursor cursor korks)
+      (child-cursor cursor korks)))
+
+  (deftype Cursor [id parent tkey children
+                   getter setter dirty state meta
+                   watches fwatches watchers invalidation-watches iwatchers
+                   lazy add-watch-fn remove-watch-fn]
+    Object
+    (equiv [this other]
+      (-equiv this other))
+    (compute [cursor]
+      (set! (.-dirty cursor) false)
+      (add-watch-fn cursor)
+      (let [new-value ((.-getter cursor) @ref)
+            old-value (.-state cursor)]
+        (when-not (identical? old-value new-value)
+          (set! (.-state cursor) new-value)
+          (when (> watchers 0)
+            (.notifyFWatches cursor old-value new-value))
+          (when (> iwatchers 0)
+            (.notifyInvalidationWatches cursor))
+          new-value)))
+    (clean [this]
+      (when (identical? 0 (.-watchers this)) (identical? 0 (.-iwatchers this))
+            (remove-watch-fn ref id)
+            (set! (.-dirty this) true)))
+
+    cljs.core/IAtom
+
+    IReactive
+    (-get-binding-fns [this]
+      (if lazy invalidates-binding-info fwatch-binding-info))
+
+    cljs.core/IEquiv
+    (-equiv [o other] (identical? o other))
+
+    cljs.core/IDeref
+    (-deref [this] (.reactiveDeref this))
+
+    IMeta
+    (-meta [_] meta)
+
+    IPrintWithWriter
+    (-pr-writer [a writer opts]
+      (-write writer "#<Cursor: ")
+      (pr-writer state writer opts)
+      (-write writer ">"))
+
+    IWatchable
+    (-notify-watches [this oldval newval]
+      (.notifyFWatches this oldval newval))
+
+    (-add-watch [this key f]
+      (when-not (contains? watches key)
+        (set! (.-watchers this) (inc watchers))
+        (set! (.-watches this) (assoc watches key f)))
+      this)
+    (-remove-watch [this key]
+      (when (contains? watches key)
+        (set! (.-watchers this) (dec watchers))
+        (set! (.-watches this) (dissoc watches key)))
+      this)
+
+    IHash
+    (-hash [this] (goog/getUid this))
+
+    IReset
+    (-reset! [this new-value]
+      (swap! ref (fn [cur] (setter cur new-value)))
+      (.rawDeref this))
+
+    ISwap
+    (-swap! [this f] (cursor-swap! this ref getter setter f))
+    (-swap! [this f x] (cursor-swap! this ref getter setter #(f % x)))
+    (-swap! [this f x y] (cursor-swap! this ref getter setter #(f % x y)))
+    (-swap! [this f x y more] (cursor-swap! this ref getter setter #(apply f %  x y  more)))
+
+    ICursor
+    (-cursor-key [this] tkey)
+    (-child-cursor [this ckey]
+      (if-let [child-cursor (first (get children ckey))]
+        (first child-cursors)
+        (let [child-cursor (Cursor. )]
+          (set! (.-children this) (update children conj child-cursor))
+          child-cursor)))
+    (-parent-cursor [this]
+      (when tkey
+        parent)))
+
+  (defn root-cursor [atom-like])
+
+  (defn atom [init]
+    (root-cursor (cljs.core/atom init)))
+
+  (apply-js-mixin ReactiveCursor fwatch-mixin)
+  (apply-js-mixin ReactiveCursor invalidates-mixin)
+  (apply-js-mixin ReactiveCursor rx-mixin))


ufold streams where: fix regexes

ufold streams where: fix regexes

--- ufold/src/ufold/streams.clj
+++ ufold/src/ufold/streams.clj
@@ -122,7 +122,7 @@
     (prn event)))

 ; Sends a map to a client, coerced to state
-(defn send-state [client]
+(defn fwd [client]
   (fn [statelike]
     (ufold.client/send-state client statelike)))

@@ -130,8 +130,8 @@
 (defn where [field pred & children]
     (fn [event]
       (let [value (field event)]
-        (when (case (class pred)
-                java.util.regex.Pattern (re-find pred value)
+        (when (if (= (class pred) java.util.regex.Pattern)
+                (re-find pred value)
                 (= pred value))
           (doseq [child children]
             (child event))))))


use an empty version of the map passed to select-in

Good idea in general, the particular benefit is that
this keeps Om cursors from turning into regular maps.

--- src-cljs/frontend/utils/seq.cljs
+++ src-cljs/frontend/utils/seq.cljs
@@ -11,7 +11,7 @@
   "Returns a map containing only those entries in map whose keypath is in keypaths
    (select-in {:a {:b 1 :c 2}} [[:a :b]]) => {:a {:b 1}} "
   [map keypathseq]
-    (loop [ret {} keypaths (seq keypathseq)]
+    (loop [ret (empty map) keypaths (seq keypathseq)]
       (if keypaths
         (let [entry (get-in map (first keypaths) sentinel)]
           (recur


cleanup

cleanup

--- src/metabase/api/common/throttle.clj
+++ src/metabase/api/common/throttle.clj
@@ -94,10 +94,8 @@
      (defendpoint POST [:as {{:keys [email]} :body}]
        (throttle/check email-throttler email)
        ...)"
-  [^Throttler {:keys [attempts exception-field-key], :as throttler} keyy]
-  {:pre [(or (= (type throttler) Throttler)
-             (println "THROTTLER IS: " (type throttler)))
-         keyy]}
+  [^Throttler {:keys [attempts exception-field-key], :as throttler} keyy] ; technically, keyy can be nil so you can record *all* attempts
+  {:pre [(= (type throttler) Throttler)]}
   (println "RECENT ATTEMPTS:\n" (metabase.util/pprint-to-str 'cyan @(:attempts throttler))) ;; TODO - remove debug logging
   (remove-old-attempts throttler)
   (when-let [delay-ms (calculate-delay throttler keyy)]


Use round to get better oscillation.

Use round to get better oscillation.

--- src/afterglow/effects/dimmer.clj
+++ src/afterglow/effects/dimmer.clj
@@ -38,7 +38,7 @@
      (fn [show snapshot]
        (pspy :dimmer-oscillator
              (let [phase (osc snapshot)
-                   new-level (+ min (long (* range phase)))]
+                   new-level (+ min (Math/round (* range phase)))]
                (map (partial assign-level new-level) chans)))))))

 (defn sawtooth-beat


remove duplicates

remove duplicates

--- src/leiningen/new/figwheel/project.clj
+++ src/leiningen/new/figwheel/project.clj
@@ -22,9 +22,7 @@
   :cljsbuild {
     :builds [{:id "dev"
               :source-paths ["src"]
-              :compiler {:main {{name}}.core
-                         :asset-path "js/compiled/out"
-                         :output-to "resources/public/js/compiled/{{sanitized}}.js"
+              :compiler {:output-to "resources/public/js/compiled/{{sanitized}}.js"
                          :output-dir "resources/public/js/compiled/out"
                          :optimizations :none
                          :main {{name}}.core


Fix doc

Fix doc

--- services/tnseq-phase2.clj
+++ services/tnseq-phase2.clj
@@ -13,7 +13,7 @@
                         "Finished"]}      ; subject, body intro
          :tnag  {:type "func"
                  :name "tnseq-aggregate"
-                 :args ["#1" "#2"]} ; eid, compfile, gtf/gbk, norm
+                 :args ["#1" "#2"]} ; eid, compfile
          :mail2 {:type "func"
                  :name "mailp2"
                  :args ["#3"        ; recipient


Refactor register-*-schema!

Refactor register-*-schema!

--- src/main/cljc/mikron/runtime/core.cljc
+++ src/main/cljc/mikron/runtime/core.cljc
@@ -19,19 +19,19 @@

 (defonce ^:private registry-ref (atom {}))

-(defn register-schema!
+(defn registered-schema!
   "Registers a reified schema with the given name."
   [schema-name ^Schema schema]
   (swap! registry-ref assoc schema-name schema)
-  schema-name)
+  schema)

 (defonce ^:private local-registry-ref (atom {}))

-(defn register-local-schema!
+(defn registered-local-schema!
   "Registers a local, reified schema with the given name."
   [schema-name ^Schema schema]
   (swap! local-registry-ref assoc schema-name schema)
-  schema-name)
+  schema)

 (defn resolve-schema
   "Returns a reified schema for the given argument."
@@ -71,15 +71,13 @@
           (schema* schema global-options)
           (let [schema-name' (keyword (str (namespace schema-name))
                                       (str (gensym (name schema-name))))]
-            `(let [~rschema ~(schema* schema global-options {schema-name schema-name'})]
-               (register-local-schema! ~schema-name' ~rschema)
-               ~rschema))))))
+            `(registered-local-schema! ~schema-name' ~(schema* schema global-options {schema-name schema-name'})))))))

   (defmacro defschema
     "Globally registers a reified schema for the given schema definition, with the given name."
     [& args]
     (let [{:keys [schema-name schema global-options]} (util/enforce-spec ::runtime.core-spec/defschema-args args)]
-      `(register-schema! ~schema-name ~(schema* schema global-options)))))
+      `(registered-schema! ~schema-name ~(schema* schema global-options)))))

 (def ^:dynamic ^:private *buffer*
   "The default buffer with a 10Kb size."


[PDOK-1872] definitie POST-request templates toegevoegd

--- src/main/clojure/pdok/featured/api.clj
+++ src/main/clojure/pdok/featured/api.clj
@@ -50,6 +50,14 @@
    :extractType s/Str
    :extractVersion s/Str
    (s/optional-key :callback) URI})
+
+(def TemplateRequest
+  "A schema for a JSON template request"
+  {:dataset s/Str
+   :collection s/Str
+   :extractType s/Str
+   :template s/Str
+    (s/optional-key :partial) s/Bool})

 (defn- callbacker [uri run-stats]


Move secretbox to new API

Move secretbox to new API

--- src/caesium/crypto/secretbox.clj
+++ src/caesium/crypto/secretbox.clj
@@ -2,7 +2,7 @@
   "Bindings to the secretbox secret-key authenticated encryption scheme."
   (:require [caesium.binding :as b]
             [caesium.util :as u]
-            [caesium.byte-bufs :refer [buflen]])
+            [caesium.byte-bufs :as bb])
   (:import [java.nio ByteBuffer]))

 (b/defconsts [keybytes noncebytes macbytes primitive])
@@ -15,7 +15,7 @@
   You only want this to manage the output byte buffer yourself. Otherwise,
   you want [[secretbox-easy]]."
   [c m n k]
-  (b/✨ easy m n k))
+  (b/✨ easy c m n k))

 (defn secretbox-easy
   "Encrypt with `crypto_secretbox_easy`.
@@ -28,41 +28,26 @@
   automatically prepend the required `ZERO_BYTES` NUL bytes, verify
   that the encryption succeeded, and strip them from the returned
   ciphertext."
-  [msg nonce key]
-  (let [out (byte-array (+ macbytes (buflen msg)))]
-    (secretbox-easy-to-buf! out msg nonce key)
-    out))
+  [m n k]
+  (let [c (bb/alloc (+ macbytes (bb/buflen m)))]
+    (secretbox-easy-to-buf!
+     c
+     (bb/->indirect-byte-buf m)
+     (bb/->indirect-byte-buf n)
+     (bb/->indirect-byte-buf k))
+    (bb/->bytes c)))

 (defn secretbox-open-easy-to-buf!
   "Decrypt with `crypto_secretbox_open_easy` into the given byte array.

+  All arguments must be `java.nio.ByteBuffer`.
+
   You only want this to manage the output byte array yourself. Otherwise,
   you want [[secretbox-open-easy]]."
-  [^bytes out ^bytes ctext ^bytes nonce ^bytes key]
-  (let [clen (long (buflen ctext))
-        res (.crypto_secretbox_open_easy b/sodium out ctext clen nonce key)]
+  [m c n k]
+  (let [res (b/✨ open-easy m c n k)]
     (if (= res 0)
-      out
-      (throw (RuntimeException. "Ciphertext verification failed")))))
-
-(defn secretbox-open-easy-from-byte-bufs!
-  "**WARNING** low-level API, specialized use!
-
-  This function is probably only useful if you're using ByteBuffers to manage
-  the layout of a byte array that contains both the nonce and the
-  secretbox-easy ciphertext. If you're not sure, this is not the API you want;
-  check out [[secretbox-open-easy]] instead."
-  [out ctext ctextlen nonce key]
-  ;; This takes an ctextlen argument because you can't tell the appropriate
-  ;; length from the ctext ByteBuffer and the caller knows anyway.
-  (let [res (.crypto_secretbox_open_easy b/sodium
-                                         ^bytes out
-                                         ^java.nio.ByteBuffer ctext
-                                         ^long ctextlen
-                                         ^java.nio.ByteBuffer nonce
-                                         ^bytes key)]
-    (if (= res 0)
-      out
+      m
       (throw (RuntimeException. "Ciphertext verification failed")))))

 (defn secretbox-open-easy
@@ -76,23 +61,28 @@
   automatically prepend the required `BOXZERO_BYTES` NUL bytes, verify
   that the decryption succeeded, and strip them from the returned
   plaintext."
-  [ctext nonce key]
-  (let [out (byte-array (- (buflen ctext) macbytes))]
-    (secretbox-open-easy-to-buf! out ctext nonce key)))
+  [c n k]
+  (let [m (bb/alloc (- (bb/buflen c) macbytes))]
+    (secretbox-open-easy-to-buf!
+     m
+     (bb/->indirect-byte-buf c)
+     (bb/->indirect-byte-buf n)
+     (bb/->indirect-byte-buf k))
+    (bb/->bytes m)))

 (defn encrypt
   "Backwards-compatible alias for [[secretbox-easy]].

   Please note that this uses a different argument order."
-  [key nonce msg]
-  (secretbox-easy msg nonce key))
+  [k n m]
+  (secretbox-easy m n k))

 (defn decrypt
   "Backwards-compatible alias for [[secretbox-open-easy]].

   Please note that this uses a different argument order."
-  [key nonce ciphertext]
-  (secretbox-open-easy ciphertext nonce key))
+  [k n c]
+  (secretbox-open-easy c n k))

 (def int->nonce
   "Turns an integer into a byte array, suitable as a nonce.


[fix 6052] check empty filters

[fix 6052] check empty filters

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

--- src/status_im/transport/filters.cljs
+++ src/status_im/transport/filters.cljs
@@ -65,4 +65,4 @@
  :shh/remove-filters
  (fn [filters]
    (doseq [filter filters]
-     (remove-filter! filter))))
+     (when filter (remove-filter! filter)))))


Lift symbol resolution into a standalone function (#283)

--- waiter/src/waiter/utils.clj
+++ waiter/src/waiter/utils.clj
@@ -472,6 +472,11 @@
     (when (and host origin scheme)
       (= origin (str (name scheme) "://" host)))))

+(defn resolve-symbol
+  "Resolve the given symbol to the corresponding Var."
+  [sym]
+  (resolve (some-> sym namespace symbol use) sym))
+
 (defn create-component
   "Creates a component based on the specified :kind"
   [{:keys [kind] :as component-config} & {:keys [context]}]
@@ -479,12 +484,9 @@
   (let [kind-config (get component-config kind)
         factory-fn (:factory-fn kind-config)]
     (if factory-fn
-      (let [ns (namespace factory-fn)
-            lookup-env (when ns (use (symbol ns)))
-            resolved-fn (resolve lookup-env factory-fn)]
-        (if resolved-fn
-          (resolved-fn (merge context kind-config))
-          (throw (ex-info "Unable to resolve factory function" (assoc component-config :ns ns)))))
+      (if-let [resolved-fn (resolve-symbol factory-fn)]
+        (resolved-fn (merge context kind-config))
+        (throw (ex-info "Unable to resolve factory function" (assoc component-config :ns (namespace factory-fn)))))
       (throw (ex-info "No :factory-fn specified" component-config)))))

 (defn pos-int?


clean up

clean up

--- src/clj/searchbot/server.clj
+++ src/clj/searchbot/server.clj
@@ -21,19 +21,13 @@

 (defroutes routes
   (resources "/react" {:root "react"})
-;;   (GET "/*" req (page))
   (GET "/" req (apply str (page)))
   (GET "/test" req
        (response {:foo "bar"}))
   (GET "/es/:idx/:idxType/_count" [idx idxType]
-;;        (jresp/json-response (es/es-count @es-host idx idxType)))
        (response (es/es-count @es-host idx idxType)))
   (POST "/es/:idx/:idxType/_search" [idx idxType :as req]
-;;         (jresp/json-response (es/es-search @es-host idx idxType (:body req))))
         (do
-          (println "req")
-          (println req)
-;;           (jresp/json-response (es/es-search @es-host idx idxType (:body req)))))
           (response (es/es-search @es-host idx idxType (:body req)))))
   (resources "/")
   (not-found "Not Found"))


Added Artist Colony

Added Artist Colony

First stab at contributing, added artist colony, tested locally.
Only potential issue - this does no cost checks, so picking a card you can't afford
results in forfeiting an agenda and nothing happening.

--- src/clj/game/cards-resources.clj
+++ src/clj/game/cards-resources.clj
@@ -49,6 +49,13 @@
     :abilities [{:cost [:click 1] :counter-cost 2 :msg "gain 2 [Credits]"
                  :effect (req (gain state :runner :credit 2)
                               (when (zero? (:counter card)) (trash state :runner card {:unpreventable true})))}]}
+
+   "Artist Colony"
+   {:abilities [{:prompt "Choose a card to install"
+                 :msg (msg "install " (:title target))
+                 :cost [:forfeit]
+                 :choices (req (cancellable (filter #(not (is-type? % "Event")) (:deck runner)) :sorted))
+                 :effect (effect (runner-install target) (shuffle! :deck))}]}

    "Bank Job"
    {:data {:counter 8}


tweak Councilman toast again

tweak Councilman toast again

--- src/clj/game/cards-resources.clj
+++ src/clj/game/cards-resources.clj
@@ -108,8 +108,8 @@
    "Councilman"
    {:events {:rez {:req (req (and (#{"Asset" "Upgrade"} (:type target))
                                   (can-pay? state :runner nil [:credit (rez-cost state :corp target)])))
-                   :effect (req (toast state :runner (str "Click Councilman to derez " (:title target)
-                                                          " just rezzed in " (zone->name (second (:zone target)))) "info"))}}
+                   :effect (req (toast state :runner (str "Click Councilman to derez " (card-str state target {:visible true})
+                                                          " that was just rezzed") "info"))}}
     :abilities [{:prompt "Choose an asset or upgrade that was just rezzed"
                  :choices {:req #(and (rezzed? %)
                                       (or (is-type? % "Asset") (is-type? % "Upgrade")))}


Minor ns path fix on http.route ns

Minor ns path fix on http.route ns

--- src/clj/hellhound/http/route.clj
+++ src/clj/hellhound/http/route.clj
@@ -4,7 +4,7 @@
   (:require
    [clojure.spec.alpha                      :as spec]
    [io.pedestal.http.route                  :as route]
-   [hellhound.components.core               :as system]
+   [hellhound.system                        :as system]
    [hellhound.core                          :as hellhound]))

 ;; Specs ---------------------------------------------------


Update naming for apropos replacement

Update naming for apropos replacement

Use "apropos-better" to nudge people via auto-complete, and alias as
find-name since it seems more descriptive. Removes the pprint to be more
similar to apropos.

refs #107

--- src/clj/reply/initialization.clj
+++ src/clj/reply/initialization.clj
@@ -6,15 +6,16 @@
 (defn help
   "Prints a list of helpful commands."
   []
-  (println "    Exit: Control+D or (exit) or (quit)")
-  (println "Commands: (user/help)")
-  (println "    Docs: (doc function-name-here)")
-  (println "          (find-doc \"part-of-name-here\")")
-  (println "  Source: (source function-name-here)")
-  (println " Javadoc: (javadoc java-object-or-class-here)")
-  (println "Examples from clojuredocs.org: [clojuredocs or cdoc]")
-  (println "          (user/clojuredocs name-here)")
-  (println "          (user/clojuredocs \"ns-here\" \"name-here\")"))
+  (println "        Exit: Control+D or (exit) or (quit)")
+  (println "    Commands: (user/help)")
+  (println "        Docs: (doc function-name-here)")
+  (println "              (find-doc \"part-of-name-here\")")
+  (println "Find by Name: (find-name \"part-of-name-here\")")
+  (println "      Source: (source function-name-here)")
+  (println "     Javadoc: (javadoc java-object-or-class-here)")
+  (println "    Examples from clojuredocs.org: [clojuredocs or cdoc]")
+  (println "              (user/clojuredocs name-here)")
+  (println "              (user/clojuredocs \"ns-here\" \"name-here\")"))

 (defn intern-with-meta [ns sym value-var]
   (intern ns
@@ -60,8 +61,12 @@
            (map (fn [ns-alias-symbol]
                   (symbol (str ns-alias-symbol) sym-name-str))))))))

-(defn better-apropos
-  "Given a regular expression or stringable thing, calculate a
+(defn apropos-better
+  "Similar to clojure.repl/apropos, but provides enough context (in the form of
+  namespaces where the vars live, when necessary) to actually use the results
+  in a REPL.
+
+  Given a regular expression or stringable thing, calculate a
   sequence of all symbols in all currently-loaded namespaces such that
   it matches the str-or-pattern, with at most one such symbol per Var.
   The sequence returned contains symbols that map to those Vars, and are
@@ -70,28 +75,23 @@
   the Var.  Note that it is possible the symbol returned does not match
   the str-or-pattern itself, e.g. if the symbol-to-var mapping was
   created with :rename.
-
+
   Searches through all non-Java symbols in the current namespace, but
   only public symbols of other namespaces."
-  [str-or-pattern & opts]
+  [str-or-pattern]
   (let [matches? (if (instance? java.util.regex.Pattern str-or-pattern)
                    #(re-find str-or-pattern (str %))
                    #(.contains (str %) (str str-or-pattern)))]
-    (map #(first (reply.initialization/unresolve %))
-         (set
-          (mapcat (fn [ns]
-                    (map second
-                         (filter (fn [[s v]] (matches? s))
-                                 (if (= ns *ns*)
-                                   (concat (ns-interns ns) (ns-refers ns))
-                                   (ns-publics ns)))))
-                  (all-ns))))))
-
-(defn apro
-  "Shorter-name version of apropos that also sorts and pretty-prints
-  the results."
-  [str-or-pattern & opts]
-  (clojure.pprint/pprint (sort (apply reply.initialization/better-apropos str-or-pattern opts))))
+    (sort
+      (map #(first ((ns-resolve 'reply.exports 'unresolve) %))
+           (set
+             (mapcat (fn [ns]
+                       (map second
+                            (filter (fn [[s v]] (matches? s))
+                                    (if (= ns *ns*)
+                                      (concat (ns-interns ns) (ns-refers ns))
+                                      (ns-publics ns)))))
+                     (all-ns)))))))

 (def clojuredocs-available?
   (delay
@@ -139,9 +139,7 @@
 (defn formify-file [f]
   (read-string (str "(do " (slurp f) ")")))

-(defn default-init-code
-  "Assumes cd-client will be on the classpath when this is evaluated."
-  []
+(defn default-init-code []
   `(do
      (println "REPL-y" ~(version/get-version "reply" "reply"))
      (println "Clojure" (clojure-version))
@@ -164,10 +162,10 @@
      ~(export-definition 'reply.initialization/help)
      (~'intern-with-meta '~'user '~'help ~'#'help)

-     ~(export-definition 'reply.initialization/apro)
-     ~(export-definition 'reply.initialization/better-apropos)
-     (~'intern-with-meta '~'user '~'apro ~'#'apro)
-     (~'intern-with-meta '~'user '~'better-apropos ~'#'better-apropos)
+     ~(export-definition 'reply.initialization/unresolve)
+     ~(export-definition 'reply.initialization/apropos-better)
+     (~'intern-with-meta '~'user '~'apropos-better ~'#'apropos-better)
+     (~'intern-with-meta '~'user '~'find-name ~'#'apropos-better)

      ~(export-definition 'reply.initialization/clojuredocs-available?)
      ~(export-definition 'reply.initialization/call-with-ns-and-name)


Yet another db check

Yet another db check

--- src/clj_crud/system/database.clj
+++ src/clj_crud/system/database.clj
@@ -95,9 +95,11 @@
                      :connection-uri db-connect-string}]
            ;; Return an updated version of the component with the
            ;; run-time state assoc'd in.
-           (try (jdbc/query conn ["SELECT *"])
+           (try (jdbc/query conn ["VALUES 1"]) ;; derbydb
                 (catch Exception e
-                  (debug "DB connection failed:" e (with-out-str (.printStackTrace e)))))
+                  (try (jdbc/query conn ["SELECT NOW()"]) ;; postgres
+                       (catch Exception e
+                         (debug "DB connection failed:" e (with-out-str (.printStackTrace e)))))))
            (assoc component :connection conn)))

   (stop [component]


Fix save command

Fix save command

--- src/cljs/dbquery/db_console.cljs
+++ src/cljs/dbquery/db_console.cljs
@@ -145,8 +145,8 @@
         query-assocs (subscribe [:state :query-assocs])
         model (atom {})
         save-fn #(if (nil? @query)
-                   (dispatch [:change :modal [query-form id {:sql (.getValue @editor)}]])
-                   (dispatch [:save-query (assoc @query :sql (.getValue @editor))]))
+                   (dispatch [:change :modal [query-form id {:sql (text @editor)}]])
+                   (dispatch [:save-query (assoc @query :sql (text @editor))]))
         query-filter (fn[text]
                        (let [re (re-pattern text)]
                          (filter #(re-find re (or (:name %) "")) @suggestions)))


1. Change reduceByWindow to 4-arity version (to use Java functions) 2. Add other stream functions (count, mapToPair, textFileStream, saveAsTextFiles)

--- src/clojure/flambo/streaming.clj
+++ src/clojure/flambo/streaming.clj
@@ -4,7 +4,7 @@
 ;; Spark Streaming; consider it a work in progress.
 ;;
 (ns flambo.streaming
-  (:refer-clojure :exclude [map time print union])
+  (:refer-clojure :exclude [map time print union count])
   (:require [flambo.api :as f]
             [flambo.conf :as conf]
             [flambo.function :refer [flat-map-function
@@ -22,7 +22,9 @@
 (defn time [ms]
   (Time. ms))

-(defn streaming-context [conf batch-duration]
+(defn streaming-context
+  "conf can be a SparkConf or JavaSparkContext"
+  [conf batch-duration]
   (JavaStreamingContext. conf (duration batch-duration)))

 (defn local-streaming-context [app-name duration]
@@ -34,6 +36,9 @@
 (defmulti checkpoint (fn [context arg] (class arg)))
 (defmethod checkpoint java.lang.String [streaming-context path] (.checkpoint streaming-context path))
 (defmethod checkpoint java.lang.Long [dstream interval] (.checkpoint dstream (duration interval)))
+
+(defn text-file-stream [context file-path]
+  (.textFileStream context file-path))

 (defn socket-text-stream [context ip port]
   (.socketTextStream context ip port))
@@ -53,6 +58,9 @@
       (.reduceByKey (function2 f))
       (.map (function f/untuple))))

+(defn map-to-pair [dstream f]
+  (.mapToPair dstream (pair-function f)))
+

 ;; ## Transformations
 ;;
@@ -71,6 +79,9 @@
 (defn window [dstream window-length slide-interval]
   (.window dstream (duration window-length) (duration slide-interval)))

+(defn count [dstream]
+  (.count dstream))
+
 (defn count-by-window [dstream window-length slide-interval]
   (.countByWindow dstream (duration window-length) (duration slide-interval)))

@@ -80,8 +91,8 @@
       (.groupByKeyAndWindow (duration window-length) (duration slide-interval))
       (.map (function f/untuple))))

-(defn reduce-by-window [dstream f window-length slide-interval]
-  (.reduceByWindow dstream (function2 f) (duration window-length) (duration slide-interval)))
+(defn reduce-by-window [dstream f f-inv window-length slide-interval]
+  (.reduceByWindow dstream (function2 f) (function2 f-inv) (duration window-length) (duration slide-interval)))

 (defn reduce-by-key-and-window [dstream f window-length slide-interval]
   (-> dstream
@@ -96,3 +107,14 @@

 (defn foreach-rdd [dstream f]
   (.foreachRDD dstream (function2 f)))
+
+
+;; ## Output
+;;
+(defn save-as-text-files
+  ;;TODO: check whether first param is of type
+  ;;DStream or just let an exception be thrown?
+  ([dstream prefix suffix]
+    (.saveAsTextFiles dstream prefix suffix))
+  ([dstream prefix]
+   (.saveAsTextFiles dstream prefix)))


Use common threadpool in the 'remove-empty-paths'

--- src/cyanite_remover/core.clj
+++ src/cyanite_remover/core.clj
@@ -644,13 +644,14 @@
       (log/info starting-str)
       (log-cli-cmd options)
       (dry-mode-warn options)
-      (let [pstore (pstore/elasticsearch-path-store es-url options)
+      (let [tpool (get-thread-pool options)
+            pstore (pstore/elasticsearch-path-store es-url options)
             sort (get-sort-or-dummy-fn (:sort options))
             empty-paths (->> (tree-walker tenant paths pstore options
-                                          empty-paths-remover)
+                                          empty-paths-remover tpool)
                              (sort))]
         (process-paths tenant empty-paths pstore options
-                       remove-empty-paths-processor)))
+                       remove-empty-paths-processor tpool)))
     (catch Exception e
       (clog/unhandled-error e))))


Tidy up blackrain examples

Tidy up blackrain examples

--- src/overtone/sc/examples/blackrain.clj
+++ src/overtone/sc/examples/blackrain.clj
@@ -5,36 +5,108 @@
 (defexamples iir-filter
   (:low-pass
    "Create a low pass filter"
-   "Here we use blackrain's iir-filter to create a low pass filter.  The iir-filter has a 24db/oct rolloff.  That means the frequency one octave past the cutoff frequency is attenuated by 24dB.  Two octaves past the cutoff, the attenuation is 48dB, and so on.  However, near the frequency cutoff the frequency response is determined by rq.  Depending on your rq some frequencies near the cutoff may even be boosted while others may decrease more than the rolloff.  As you get farther from the cutoff frequency, you'll return to the 24dB/oct rolloff.
-
+   "Here we use blackrain's iir-filter to create a low pass filter.  The
+    iir-filter has a 24db/oct rolloff.  That means the frequency one
+    octave past the cutoff frequency is attenuated by 24dB.  Two octaves
+    past the cutoff, the attenuation is 48dB, and so on.  However, near
+    the frequency cutoff the frequency response is determined by rq.
+    Depending on your rq some frequencies near the cutoff may even be
+    boosted while others may decrease more than the rolloff.  As you get
+    farther from the cutoff frequency, you'll return to the 24dB/oct
+    rolloff.

-For input signal, we'll use a saw wave because it has lots of harmonics.  For the cutoff frequency we'll use frequencies ranging from 20 to 20000 Hz exponentially, depending on the mouse-x coordinate.  The rq ranges from 0.1 to 1 linearly depending on the mouse-y coordinate so that moving the mouse up and down selects and boosts or attenuates frequencies differently."
+
+    For our input signal, we'll use a saw wave because it has lots of
+    harmonics.  For the cutoff frequency we'll use frequencies ranging
+    from 20 to 20000 Hz exponentially, depending on the mouse-x
+    coordinate.  The rq ranges from 0.1 to 1 linearly depending on the
+    mouse-y coordinate so that moving the mouse up and down selects and
+    boosts or attenuates frequencies differently."
    rate :ar
-   [signal-in {:default (saw 440) :doc "Input signal to the filter.  The default here is a saw wave at 440Hz since that has nifty harmoics."}]
-   "(iir-filter signal-in (mouse-x 20 20000 EXP) (mouse-y 0.1 1))"
+   [signal-in {:default (saw 440)
+               :doc "Input signal to the filter.  The default here is a
+                     saw wave at 440Hz since that has nifty harmoics." }]
+   "(iir-filter signal-in
+                (mouse-x 20 20000 EXP)
+                (mouse-y 0.1 1))"
    contributor "Colleen T"))

 (defexamples b-moog
    (:compare-filters
    "Compare low, high, and bandpass"
-   "This example demonstrates how three different filters with a variable cutoff frequency change the same input signal.  The y mouse coordinate will control which filter you are using by breaking the screen into three regions.  The top third is bandpass, the middle third is high pass, and the lower third is low pass.  The x-coordinate is controlling q, which is bandwidth/cutoff frequency.  Although bandwidth doesn't mean much for low and high pass filters, changing this parameter will change the filter characteristics.  Move the mouse around to explore and compare the filter properties."
+   "This example demonstrates how three different filters with a
+    variable cutoff frequency change the same input signal.
+
+    The y mouse coordinate will control which filter you are using by
+    breaking the screen into three regions.  The top third is bandpass,
+    the middle third is high pass, and the lower third is low pass.  The
+    x-coordinate is controlling q, which is bandwidth/cutoff frequency.
+
+    Although bandwidth doesn't mean much for low and high pass filters,
+    changing this parameter will change the filter characteristics.
+    Move the mouse around to explore and compare the filter properties."
    rate :ar
-   [signal-in {:default (saw 265) :doc "The default is a saw wave with a frequency of 265 Hz.  Maybe you have a sound handy you'd like to try to filter?"}
-    cutoff-frequency {:default 440 :doc "Try changing the cutoff frequency to see how that affects the input."}]
-   "(b-moog signal-in cutoff-frequency (mouse-x 0 1) (mouse-y 0.01 2.99))"
+   [signal-in        {:default (saw 265)
+                      :doc "The default is a saw wave with a frequency
+                            of 265 Hz.  Maybe you have a sound handy
+                            you'd like to try to filter?" }
+
+    cutoff-frequency {:default 440
+                      :doc "Try changing the cutoff frequency to see how
+                            that affects the input."}]
+   "(b-moog signal-in
+            cutoff-frequency
+            (mouse-x 0 1)
+            (mouse-y 0.01 2.99))"
    contributor "Colleen T"))

 (defexamples svf
     (:state-filter
     "Create a state variable filter"
-    "A state variable filter is many filters combined in one - low, high, band, notch.  In this example, we'll use a saw wave with the frequency ranging from 260 to 700 with the mouse-x coordinate.  A saw wave has many harmonics so it is ideal for this kind of filter.  We'll put the cutoff frequency at 440 and use the mouse-y, ranging from 0 to 1 to control the resonance.  Consider how you can use your current home setup (keyboard or other controller) to vary some of the parameters in time.  A state variable filter is ideal for modifying the filter properties on the fly to change the characteristics of the sound."
+    "A state variable filter is many filters combined in one - low,
+     high, band, notch.
+
+     In this example, we'll use a saw wave with the frequency ranging
+     from 260 to 700 with the mouse-x coordinate.  A saw wave has many
+     harmonics so it is ideal for this kind of filter.  We'll put the
+     cutoff frequency at 440 and use the mouse-y, ranging from 0 to 1 to
+     control the resonance.  Consider how you can use your current home
+     setup (keyboard or other controller) to vary some of the parameters
+     in time.
+
+     A state variable filter is ideal for modifying the filter
+     properties on the fly to change the characteristics of the sound."
     rate :ar
-    [signal-in {:default (saw (mouse-x 260 700)) :doc "The input signal to filter.  The example default here is a saw wave because a saw wave has interesting harmonics you can select with the filter."}
-     cutoff {:default 440 :doc "The cutoff frequency the filter is centered on, try adjusting this to see how your selection from the input signal changes."}
-     low-pass {:default 0.1 :doc "The amount of the low pass output to select, from 0 (none) to 1 (all)"}
-     band-pass {:default 0.3 :doc "The amount of the band pass output to select."}
-     high-pass {:default 0 :doc "The amount of the highpass output to use."}
-     notch {:default 0.4 :doc "A notch filter is the opposite of a band-pass filter."}
-    ]
-    "(svf signal-in cutoff (mouse-y 0 1) low-pass band-pass high-pass notch)"
+    [signal-in {:default (saw (mouse-x 260 700))
+                :doc "The input signal to filter.  The example default
+                      here is a saw wave because a saw wave has
+                      interesting harmonics you can select with the
+                      filter."}
+
+     cutoff    {:default 440
+                :doc "The cutoff frequency the filter is centered on,
+                      try adjusting this to see how your selection from
+                      the input signal changes."}
+
+     low-pass  {:default 0.1
+                :doc "The amount of the low pass output to select, from
+                      0 (none) to 1 (all)"}
+
+     band-pass {:default 0.3
+                :doc "The amount of the band pass output to select."}
+
+     high-pass {:default 0
+                :doc "The amount of the highpass output to use."}
+
+     notch     {:default 0.4
+                :doc "A notch filter is the opposite of a band-pass
+                      filter."}]
+
+    "(svf signal-in
+          cutoff
+          (mouse-y 0 1)
+          low-pass
+          band-pass
+          high-pass
+          notch)"
     contributor "Colleen T"))


Added simple doc string.

Added simple doc string.

--- src/plugboard/webfunction/response.clj
+++ src/plugboard/webfunction/response.clj
@@ -22,7 +22,9 @@
             )
   )

-(defn get-content-type [webfn]
+
+(defn ^{:doc "Get the content type from the web function metadata"}
+  get-content-type [webfn]
   (if-let [ct (get (meta webfn) web/content-type)]
     {"Content-Type" ct}
     {})


Little refactor

Little refactor

--- src/golden_kestrel/core.cljs
+++ src/golden_kestrel/core.cljs
@@ -35,16 +35,14 @@

 (defn attributes-for-embed
   [data]
-  (into
-    {}
-    (remove
-      (comp string/blank? second)
-      {:className "altmetric-embed"
-       :data-badge-popover (:popover data)
-       :data-badge-details (:badge-details data)
-       :data-badge-type (:badge-type data)
-       :data-doi (:doi data)
-       :data-hide-no-mentions (:hide-no-mentions data)})))
+  (->> {:className "altmetric-embed"
+        :data-badge-popover (:popover data)
+        :data-badge-details (:badge-details data)
+        :data-badge-type (:badge-type data)
+        :data-doi (:doi data)
+        :data-hide-no-mentions (:hide-no-mentions data)}
+       (remove (comp string/blank? second))
+       (into {})))

 (defn pair-as-attribute
   [[k v]]


use lazy parsing

use lazy parsing

--- corpusmaker.clj
+++ corpusmaker.clj
@@ -11,16 +11,16 @@

 (ns corpusmaker
     (:require [clojure.zip :as zip]
-              [clojure.xml :as xml]
-              [clojure.contrib.zip-filter.xml]))
+              [clojure.contrib.lazy-xml :as lxml]
+              [clojure.contrib.zip-filter.xml :as zfx]))

 (defn parse-xml
-  "seqable XML content from filename"
-  [filename] (zip/xml-zip (xml/parse (java.io.File. filename))))
+  "Zipable XML content from any common source"
+  [src] (zip/xml-zip (lxml/parse-trim src)))

 (defn collect-text
   "collect wikimarkup payload of a dump in seqable xml"
-  [xml] (xml-> xml :page :revision :text text))
+  [xml] (zfx/xml-> xml :page :revision :text zfx/text))

 ; sample timed run
 ; (time (dorun (collect-text (parse-xml "chunk-0001.xml"))))


Diff returns second fileset when first is nil

--- boot/core/src/boot/core.clj
+++ boot/core/src/boot/core.clj
@@ -205,7 +205,7 @@
 (defn fileset-diff
   "FIXME: document this"
   [before after]
-  (tmpd/diff before after))
+  (if-not before after (tmpd/diff before after)))

 ;; TmpFileSet API


only ask one time for commit msg

only ask one time for commit msg

--- src/leiningen/namespaces.clj
+++ src/leiningen/namespaces.clj
@@ -144,13 +144,12 @@
       (m/info "* No update has been applied on the project" project "\n")
       (m/info "* Changes on project" project "\n\n" changes))))

-(defn commit-project! [project]
+(defn commit-project! [project commit-msg]
   (if (not (empty? (get-changed-files)))
-    (let [commit-result (->> (str "\nPlease enter the commit message for " project)
-                             (u/ask-user)
-                             (sh/sh "git" "commit" "-am"))]
+    (let [commit-result (sh/sh "git" "commit" "-am" commit-msg)]
       (if (not (u/is-success? commit-result))
-        (m/info "===> Could not commit because" (u/error-of commit-result))))
+        (m/info "===> Could not commit because" (u/error-of commit-result))
+        (m/info "Commited")))
     (m/info "\n* No change to be committed on" project)))

 (defn pull-rebase! [project]
@@ -195,8 +194,12 @@
     (u/run-command-on (->target-project-path p) reset-project! p)))

 (defn commit-all! [projects _ _]
-  (doseq [p projects]
-    (u/run-command-on (->target-project-path p) commit-project! p)))
+  (let [commit-msg (->> projects
+                        (str/join ",")
+                        (str "\nPlease enter the commit message for projects: ")
+                        (u/ask-user))]
+    (doseq [p projects]
+      (u/run-command-on (->target-project-path p) commit-project! p commit-msg))))

 (defn pull-rebase-all! [projects _ _]
   (doseq [p projects]


CLJS-1200: compare behaves differently from Clojure

drop type check from cljs.core/compare and move into IComparable
implementations.

fast path in cljs.core/compare for numbers

--- src/main/cljs/cljs/core.cljs
+++ src/main/cljs/cljs/core.cljs
@@ -1103,7 +1103,9 @@

   IComparable
   (-compare [this other]
-    (garray/defaultCompare (.valueOf this) (.valueOf other))))
+    (if (instance? js/Date other)
+      (garray/defaultCompare (.valueOf this) (.valueOf other))
+      (throw (js/Error. (str "Cannot compare " this " to " other))))))

 (extend-type number
   IEquiv
@@ -1935,13 +1937,18 @@

    (nil? y) 1

-   (identical? (type x) (type y))
-   (if (implements? IComparable x)
-     (-compare ^not-native x y)
-     (garray/defaultCompare x y))
+   (number? x) (if (number? y)
+                 (garray/defaultCompare x y)
+                 (throw (js/Error. (str "Cannot compare " x " to " y))))
+
+   (satisfies? IComparable x)
+   (-compare x y)

    :else
-   (throw (js/Error. "compare on non-nil objects of different types"))))
+   (if (and (or (string? x) (array? x) (true? x) (false? x))
+            (identical? (type x) (type y)))
+     (garray/defaultCompare x y)
+     (throw (js/Error. (str "Cannot compare " x " to " y))))))

 (defn ^:private compare-indexed
   "Compare indexed collection."
@@ -8783,16 +8790,28 @@
 ;; IComparable
 (extend-protocol IComparable
   Symbol
-  (-compare [x y] (compare-symbols x y))
+  (-compare [x y]
+    (if (symbol? y)
+      (compare-symbols x y)
+      (throw (js/Error. (str "Cannot compare " x " to " y)))))

   Keyword
-  (-compare [x y] (compare-keywords x y))
+  (-compare [x y]
+    (if (keyword? y)
+      (compare-keywords x y)
+      (throw (js/Error. (str "Cannot compare " x " to " y)))))

   Subvec
-  (-compare [x y] (compare-indexed x y))
+  (-compare [x y]
+    (if (vector? y)
+      (compare-indexed x y)
+      (throw (js/Error. (str "Cannot compare " x " to " y)))))

   PersistentVector
-  (-compare [x y] (compare-indexed x y)))
+  (-compare [x y]
+    (if (vector? y)
+      (compare-indexed x y)
+      (throw (js/Error. (str "Cannot compare " x " to " y))))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Reference Types ;;;;;;;;;;;;;;;;


tweak count, tweak nth

tweak count, tweak nth

--- src/main/cljs/cljs/core.cljs
+++ src/main/cljs/cljs/core.cljs
@@ -1562,10 +1562,10 @@
       (string? coll)
       (alength coll)

-      (native-satisfies? ICounted coll)
-      (-count coll)
-
-      :else (accumulating-seq-count coll))
+      (implements? ISeqable coll)
+      (accumulating-seq-count coll)
+
+      :else (-count coll))
     0))

 (defn- linear-traversal-nth
@@ -1610,7 +1610,7 @@

       (string? coll)
       (when (< n (.-length coll))
-        (aget coll n))
+        (.charAt coll n))

       (implements? ISeq coll)
       (linear-traversal-nth coll n)
@@ -1639,7 +1639,7 @@

       (string? coll)
       (if (< n (.-length coll))
-        (aget coll n)
+        (.charAt coll n)
         not-found)

       (implements? ISeq coll)
@@ -2144,7 +2144,7 @@

        (string? coll)
        (array-reduce coll f)
-
+
        (native-satisfies? IReduce coll)
        (-reduce coll f)

@@ -2160,7 +2160,7 @@

        (string? coll)
        (array-reduce coll f val)
-
+
        (native-satisfies? IReduce coll)
        (-reduce coll f val)


Hotfix. twitter-uri -> (twitter-uri)

Hotfix. twitter-uri -> (twitter-uri)

--- src/word_keeper/frontend.clj
+++ src/word_keeper/frontend.clj
@@ -7,7 +7,7 @@
    :headers {"Content-Type" "text/html"}
    :body (render-resource
             "views/index.html.mustache"
-            {:twitter-auth-uri twitter-auth-uri})})
+            {:twitter-auth-uri (twitter-auth-uri)})})

 (defn action-signin [req]
   (let [user-data (authorize (-> req :params :oauth_verifier))]


remove cruft

remove cruft

--- src/metabase/api/meta/db.clj
+++ src/metabase/api/meta/db.clj
@@ -30,14 +30,6 @@
 (defendpoint GET "/form_input" []
   {:timezones metabase.models.common/timezones
    :engines driver/available-drivers})
-
-
-
-
-
-
-
-{{:body {}} :body}

 ;Stub function that will eventually validate a connection string
 (defendpoint POST "/validate" [:as {{:keys [host port]} :body}]


clearer comments

clearer comments

--- src/metabase/api/session.clj
+++ src/metabase/api/session.clj
@@ -38,10 +38,10 @@
 ;;
 ;; Once a User has some number of failed login attempts over the past hour (e.g. 4), calculate some delay before
 ;; they're allowed to try to login again (e.g., 15 seconds). This number will increase exponentially as the number of
-;; recent failures increases (e.g., 40 seconds for 5 failed attempts, 80 for 6 failed attempts, etc).
+;; recent failures increases (e.g., 40 seconds for 5 failed attempts, 90 for 6 failed attempts, etc).
 ;;
-;; Calucate the time since the last failed attempt, and throw an exception telling the user the number of seconds they
-;; must wait before trying again if applicable.
+;; If applicable, Calucate the time since the last failed attempt, and throw an exception telling the user the number of seconds they
+;; must wait before trying again.

 (def ^:private ^:const failed-login-attempts-initial-delay-seconds
   "If a user makes the number of failed login attempts specified by `failed-login-attempts-throttling-threshold` in the


WIP create test for budget monitor

WIP create test for budget monitor

--- test/clj_money/models/reports_test.clj
+++ test/clj_money/models/reports_test.clj
@@ -559,3 +559,9 @@
 ; Entertainment/Movies  80  75   5
 ; it would be:
 ; Entertainment        180 185  -5
+
+(deftest create-a-budget-monitor
+  (let [context (serialization/realize storage-spec budget-report-context)
+        groceries (-> context :accounts (get 6))
+        actual (budgets/monitor storage-spec (:id groceries)) ]
+    ))


Additional tests: test-send-plain-response-existence, test-info-handler-existence, and test-configuration-handler-existence

--- test/emender_jenkins/rest_api_test.clj
+++ test/emender_jenkins/rest_api_test.clj
@@ -60,3 +60,21 @@
         (is (callable? 'emender-jenkins.rest-api/send-response))))

+(deftest test-send-plain-response-existence
+    "Check that the emender-jenkins.rest-api/send-plain-response definition exists."
+    (testing "if the emender-jenkins.rest-api/send-plain-response definition exists."
+        (is (callable? 'emender-jenkins.rest-api/send-plain-response))))
+
+
+(deftest test-info-handler-existence
+    "Check that the emender-jenkins.rest-api/info-handler definition exists."
+    (testing "if the emender-jenkins.rest-api/info-handler definition exists."
+        (is (callable? 'emender-jenkins.rest-api/info-handler))))
+
+
+(deftest test-configuration-handler-existence
+    "Check that the emender-jenkins.rest-api/configuration-handler definition exists."
+    (testing "if the emender-jenkins.rest-api/configuration-handler definition exists."
+        (is (callable? 'emender-jenkins.rest-api/configuration-handler))))
+
+


Set clojure project version

Set clojure project version

--- clojure/project.clj
+++ clojure/project.clj
@@ -1,4 +1,4 @@
-(defproject clojure_sample "0.2.1"
+(defproject clojure_sample "0.2.2"
   :description "Clojure Funcatron sample"
   :url "http://funcatron.org"
   :license {:name "Apache 2.0"}


Solving 3.13, 3.14 and 3.15 - plus fixes which led to solving 3.13 (check out fold left and comment that follows - (f acc x)) :)

--- src/fpinscala/datastructures.clj
+++ src/fpinscala/datastructures.clj
@@ -100,10 +100,12 @@
 ;3.10
 ;mine
 (defn fold-left [xs z f]
-  (loop [[x & others] xs acc z]
-    (if (nil? others)
-      (f x acc)
-      (recur others (f x acc)))))
+  (loop [[x & others :as original] xs acc z]
+    (if (nil? original)
+      acc
+      (recur others (f acc x)))))                           ;here it was (f x acc) thus
+;my fold-r-via-fold-l-1 didn't work :)
+;after swapping to (f acc x) it worked :)
 ;
 ;fpins
 ;relies on @tailrec scala annotation
@@ -115,6 +117,13 @@
 ; case Nil => z
 ; case Cons (h, t) => foldLeft (t, f (z, h)) (f)
 ; }
+; Actually - nope mine is not really equiv because below fold-r-via-fold-l-1 fails
+;this should be better:
+(defn fold-left-fpins [l z f]
+  (let [[h & t :as original] l]
+    (if (nil? original)
+      z
+      (fold-left-fpins t (f z h) f))))
 ;-----------------------------------------------------------------------

 ;3.11
@@ -124,7 +133,7 @@
 (defn product-fl [xs]
   (fold-left xs 1 *))
 (defn len-fl [xs]
-  (fold-left xs  0 (fn [_ x] (+ 1 x))))
+  (fold-left xs 0 (fn [_ x] (+ 1 x))))
 ;fpins
 ;All are basically same :)
 ;-----------------------------------------------------------------------
@@ -134,8 +143,52 @@
 (defn my-reverse [xs]
   (fold-left xs '() cons))
 (defn my-reverse2 [xs]
-  (fold-right xs [] #(conj %2 %)))                           ;This is
+  (fold-right xs [] #(conj %2 %)))                          ;This is
 ;way to do it with fold-right as list does not support adding at the end
 ;fpins
 ;It is done via f-l as in my first attempt
+;-----------------------------------------------------------------------
+
+;3.13
+;mine (I have cheated here and looked into answer but just for accumulator function :) )
+(defn fold-r-via-fold-l [xs z f]
+  (fold-left (my-reverse xs) z (fn [b a] (f a b))))
+(defn fold-r-via-fold-l-1 [xs z f]                          ; with my fold-left
+  ((fold-left xs (fn [b] b) (fn [g a]
+                              (fn [b]
+                                (g (f a b))))) z))
+;Check answer-rewrite below as I simply used answer :|
+;fpins
+;this is by the book literal translation as fold-left-fpins is literal translation as well (see above)
+(defn fold-r-via-fold-l-1-fpins [xs z f]
+  ((fold-left-fpins xs (fn [b] b) (fn [g a]
+                                    (fn [b]
+                                      (g (f a b))))) z))
+(defn fold-l-via-fold-r [xs z f]
+  ((fold-right xs (fn [b] b) (fn [a g]
+                               (fn [b]
+                                 (g (f b a))))) z))
+;-----------------------------------------------------------------------
+
+;3.14
+;mine
+(defn append [xs ys]
+  (fold-right xs ys cons))
+;fpins
+;basically - the same :)
+;-----------------------------------------------------------------------
+
+;3.15
+;mine
+;(defn list-concat [ls]
+;  (let [[h & t] ls]
+;    (fold-left t h #(append %2 %)))) ; before fixing append (swapped args xs ys)
+; there was ys xs before
+(defn list-concat [ls]
+  (let [[h & t] ls]
+    (fold-left t h append)))
+;fpins
+;they did it via fold right what is even better (more concise that is)
+(defn list-concat-fpins [ls]
+  (fold-right ls nil append))
 ;-----------------------------------------------------------------------


Add missing properties to create a post link.

--- src/oc/storage/async/bot.clj
+++ src/oc/storage/async/bot.clj
@@ -29,6 +29,8 @@
     :org-name (schema/maybe schema/Str)
     :org-logo-url (schema/maybe schema/Str)
     :board-name (schema/maybe schema/Str)
+    :board-slug lib-schema/NonBlankStr
+    :entry-uuid lib-schema/UniqueID
     :headline (schema/maybe schema/Str)
     :body (schema/maybe schema/Str)
     :must-see (schema/maybe schema/Bool)
@@ -70,7 +72,9 @@
       :org-slug (:slug org)
       :org-name (:name org)
       :board-name (:name board)
+      :board-slug (:slug board)
       :org-logo-url (:logo-url org)
+      :entry-uuid (:uuid entry)
       :headline (:headline entry)
       :body (:body entry)
       :must-see (:must-see entry)


java.home is the jre, so try to go up one directory

--- src/leiningen/compile_native.clj
+++ src/leiningen/compile_native.clj
@@ -57,7 +57,7 @@
   (let [src    (file target "tokyocabinet")
         cflags (format " %s -I%s/include -L%s/lib " arch-flag target target)]
     (configure src target {"JAVA_HOME" (or (System/getenv "JAVA_HOME")
-                                           (System/getProperty "java.home"))
+                                           (str (System/getProperty "java.home") "/.."))
                            "CFLAGS" cflags})
     (let [token "\nCFLAGS ="] ; hack because configure doesn't set CFLAGS correctly in Makefile
       (replace-text (file src "Makefile") token (str token " " cflags)))


Fix ClassCastException in conn_mgr_test for shutdown

This gets the tests past the exception (probably introduced by migration to the
newer Apache client APIs), but the tests still fail because shutdown doesn't
seem to get called.

--- test/clj_http/test/conn_mgr_test.clj
+++ test/clj_http/test/conn_mgr_test.clj
@@ -6,7 +6,7 @@
             [ring.adapter.jetty :as ring])
   (:import (java.security KeyStore)
            (org.apache.http.conn.ssl SSLSocketFactory)
-           (org.apache.http.impl.conn BasicClientConnectionManager)))
+           (org.apache.http.impl.conn BasicHttpClientConnectionManager)))

 (def client-ks "test-resources/client-keystore")
 (def client-ks-pass "keykey")
@@ -64,7 +64,7 @@
 (deftest ^:integration t-closed-conn-mgr-for-as-stream
   (run-server)
   (let [shutdown? (atom false)
-        cm (proxy [BasicClientConnectionManager] []
+        cm (proxy [BasicHttpClientConnectionManager] []
              (shutdown []
                (reset! shutdown? true)))]
     (try
@@ -83,7 +83,7 @@
 (deftest ^:integration t-closed-conn-mgr-for-empty-body
   (run-server)
   (let [shutdown? (atom false)
-        cm (proxy [BasicClientConnectionManager] []
+        cm (proxy [BasicHttpClientConnectionManager] []
              (shutdown []
                (reset! shutdown? true)))
         response (core/request {:request-method :get :uri "/unmodified-resource"


Add support of pixels test to ClojureScript.

--- test/cljx/snippets/image/pixels.cljx
+++ test/cljx/snippets/image/pixels.cljx
@@ -5,7 +5,6 @@
   #+cljs
   (:use-macros [quil.snippet :only [defsnippet]]))

-#+clj
 (defsnippet blend {}
   (q/background 255 100 20 50)

@@ -33,7 +32,6 @@
           ; blend graphics to graphics
           (q/blend gr (q/current-graphics) 0 0 50 50 (* col 55) (+ 340 (* row 55)) 50 50 mode))))))

-#+clj
 (defsnippet copy {}
   (q/background 255)
   (let [gr (q/create-graphics 100 100)]
@@ -87,7 +85,6 @@
           (apply q/image-filter clone mode)
           (q/image clone (* col 120) (* 120 (inc row))))))))

-#+clj
 (defsnippet display-filter {}
   (q/background 255)
   (let [orig (q/create-graphics 100 100)
@@ -141,7 +138,6 @@
     (q/filter-shader shd)
     (q/image orig 100 100)))

-#+clj
 (defsnippet get-pixel {}
   (q/background 255)
   (let [gr (q/create-graphics 100 100)]
@@ -186,7 +182,6 @@
         (aset-int px (+ i half) (aget px i))))
     (q/update-pixels)))

-#+clj
 (defsnippet set-image {}
   (q/background 255)
   (let [gr (q/create-graphics 100 100)]


improve (initialize)

improve (initialize)

--- src/babel/francais/workbook.clj
+++ src/babel/francais/workbook.clj
@@ -232,10 +232,17 @@
   ))

 (def initialize
-  (do (fo (parse "je parle"))
-      (generate {:synsem {:sem {:pred :drink
-                                :tense :present}
-                          :infl :present}})))
-
-
-
+  (take 1 (generate
+           ;; assemble a structure and (generate) from..
+           {:synsem {:sem
+
+                     ;; .. taking a parse of a simple sentence..
+                     (-> (parse "je parle")
+                         first
+                         strip-refs
+                         ;; and then extracting its semantics.
+                         :synsem :sem)}})))
+
+
+
+


remove unused parse-lexicon

remove unused parse-lexicon

--- src/babel/italiano/grammar.cljc
+++ src/babel/italiano/grammar.cljc
@@ -707,22 +707,8 @@

 (defn medium []
   (deliver-lexicon)
-  ;; TODO: remove parse-lexicon.
-  ;; Should not need a separate parse-lexicon here: for debugging,
-  ;; instead add to the lexicon and entry like "_" (as with english/lexicon.clj).
   (let [debug (log/info "  loading lexicon..")
         lexicon (babel.italiano.lexicon/edn2lexicon (clojure.java.io/resource "babel/italiano/lexicon.edn"))
-        debug (log/info "  loading parse lexicon..")
-        parse-lexicon
-        ;; TODO: remove this do-nothing filtering and
-        ;; replace with comment like "if you want to filter, then do: `(into {}..)`".
-        (into {}
-              (for [[k vals] lexicon]
-                (let [filtered-vals
-                      (filter (fn [x] true)
-                              vals)]
-                  (if (not (empty? filtered-vals))
-                    [k filtered-vals]))))
         debug (log/info "  filtering lexicon..")
         lexicon
         (into {}
@@ -752,7 +738,7 @@
          :lexical-cache (atom (cache/fifo-cache-factory {} :threshold 1024))
          :lexicon lexicon
          :lookup (fn [arg]
-                   (analyze arg parse-lexicon))
+                   (analyze arg lexicon))
          :morph (fn [expression & {:keys [from-language show-notes]}] (fo expression))
          :morph-ps fo-ps


fix syntax error

fix syntax error

--- src/babel/italiano/lexicon.cljc
+++ src/babel/italiano/lexicon.cljc
@@ -101,7 +101,7 @@
       (default  ;; pronouns are non-reflexive by default...
        {:synsem {:cat :noun
                  :pronoun true
-                 :reflexive false})
+                 :reflexive false}})

       (default  ;; ..but reflexive pronouns are case=acc
        {:synsem {:case :acc


~(defn edn2lexicon): (noun-pred-defaults)

--- src/babel/italiano/lexicon.cljc
+++ src/babel/italiano/lexicon.cljc
@@ -7,7 +7,8 @@
     :as lexfn
     :refer [apply-unify-key default evaluate
             filter-vals listify map-function-on-map-vals
-            new-entries rewrite-keys verb-pred-defaults]]
+            new-entries rewrite-keys noun-pred-defaults
+            verb-pred-defaults]]

    #?(:clj [clojure.tools.logging :as log])
    #?(:cljs [babel.logjs :as log])
@@ -165,7 +166,10 @@
       (default
        {:synsem {:cat :noun
                  :sem {:null false}}})
-
+
+      ;; TODO: simplify to just (noun-pred-defaults)
+      (noun-pred-defaults)
+
       ;; </noun default rules>

       ;; <verb default rules>


Updated routes.

Updated routes.

--- src/clj/clojang/blog/routes.clj
+++ src/clj/clojang/blog/routes.clj
@@ -9,24 +9,52 @@
      routes should be generated dynamically as URI path / slurp call pairs.
   "
   (:require [clojang.blog.web.content.page :as page]
-            [dragon.blog :as blog]))
+            [clojusc.twig :refer [pprint]]
+            [dragon.blog :as blog]
+            [taoensso.timbre :as log]))
+
+(defn static-routes
+  []
+  (log/info "Generating pages for static pages ...")
+  {"/about.html" (page/about)
+   "/community.html" (page/community)})
+
+(defn design-routes
+  []
+  (log/info "Generating pages for design pages ...")
+  {"/design/index.html" (page/design)
+   "/design/bootstrap-theme.html" (page/bootstrap-theme)
+   "/design/example-blog.html" (page/blog-example)})
+
+(defn post-routes
+  [uri-base data]
+  (log/info "Generating pages for blog posts ...")
+  (blog/get-archive-routes
+    data
+    :gen-func page/post
+    :uri-base uri-base))
+
+(defn index-routes
+  [data]
+  (log/info "Generating pages for front page, archives, categories, etc. ...")
+  {"/index.html" (page/front-page data)
+   "/archives/index.html" (page/archives data)
+   "/categories/index.html" (page/categories data)
+   "/tags/index.html" (page/tags data)
+   "/authors/index.html" (page/authors data)})
+
+(defn reader-routes
+  [data]
+  ;; XXX TBD
+  {"/atom.xml" ""})

 (defn routes
-  []
-  (let [uri-base "/archives"
-        data (blog/process uri-base)]
+  [uri-base]
+  (let [data (blog/process uri-base)]
+    (log/trace "Got data:" (pprint (blog/data-minus-body data)))
     (merge
-      (blog/get-archive-routes
-        data
-        :gen-func page/post
-        :uri-base uri-base)
-      {"/index.html" (page/front-page data)
-       "/about.html" (page/about)
-       "/archives/index.html" (page/archives (blog/data-for-archives data))
-       "/categories/index.html" (page/categories (blog/data-for-categories data))
-       "/tags/index.html" (page/tags (blog/data-for-tags data))
-       "/authors/index.html" (page/authors (blog/data-for-authors data))
-       ;; The remaining pages are for design purposes only; no access to data needed
-       "/design/index.html" (page/design)
-       "/design/bootstrap-theme.html" (page/bootstrap-theme)
-       "/design/example-blog.html" (page/blog-example)})))
+      (static-routes)
+      (design-routes)
+      (post-routes uri-base data)
+      (index-routes data)
+      (reader-routes data))))


Extract some configuration into variables

--- src/clj/freestuffly/scraper.clj
+++ src/clj/freestuffly/scraper.clj
@@ -8,6 +8,9 @@
 (def ^:private interesting-keywords
   #"(?i)paint|playstation|camping|emulsion|lamp|ladder|roller|xbox|mac|fish|marine|kitchen")

+(def ^:private freecycle-group "southwark-freecycle")
+(def ^:private freecycle-results-per-page 50)
+
 (defn- interesting-finds
   [results]
   (cset/select
@@ -15,7 +18,12 @@
       (re-find (re-matcher interesting-keywords (first (:content (into {} result))))))
     (set results)))

-(def ^:private my-group-urls "https://groups.freecycle.org/group/southwark-freecycle/posts/offer?page=1&resultsperpage=50&showall=off&include_offers=off&include_wanteds=off&include_receiveds=off&include_takens=off")
+(def ^:private my-group-urls
+  (str "https://groups.freecycle.org/group/"
+       freecycle-group
+       "/posts/offer?page=1&resultsperpage="
+       freecycle-results-per-page
+       "&showall=off&include_offers=off&include_wanteds=off&include_receiveds=off&include_takens=off"))

 (def ^:private site-tree
   (-> (client/get my-group-urls) :body h/parse h/as-hickory))