DRY updating app-state

DRY updating app-state

--- src/hatti/views/dataview.cljs
+++ src/hatti/views/dataview.cljs
@@ -1,7 +1,7 @@
 (ns hatti.views.dataview
   (:require-macros [cljs.core.async.macros :refer [go]])
   (:require [chimera.js-interop :refer [format]]
-            [chimera.om.state :refer [merge-into-app-state!]]
+            [chimera.om.state :refer [transact! merge-into-app-state!]]
             [cljs.core.async :refer [put!]]
             [om.core :as om :include-macros true]
             [sablono.core :as html :refer-macros [html]]
@@ -109,15 +109,11 @@
         views (-> @shared/app-state :views :all)
         settings-views (-> @shared/app-state :views :settings :all)]
     (when (contains? (set settings-views) settings-section)
-      (merge-into-app-state! shared/app-state
-                             [:views]
-                             {:selected view})
-      (merge-into-app-state! shared/app-state
-                             [:views :settings]
-                             {:active-tab settings-section})
-      (merge-into-app-state! shared/app-state
-                             [:views :settings :integrated-apps]
-                             {:active-section active-section})
+      (transact! shared/app-state (fn [app-state]
+                             (-> app-state
+                               (assoc-in [:views] {:selected view})
+                               (assoc-in [:views :settings] {:active-tab settings-section})
+                               (assoc-in [:views :settings :integrated-apps] {:active-section active-section}))))
       (if (= app-type "google_sheets")
         (merge-into-app-state! shared/app-state
                                [:views :settings :integrated-apps]


Add project.clj

Add project.clj

--- src/leiningen/new/cljskel.clj
+++ src/leiningen/new/cljskel.clj
@@ -14,6 +14,8 @@
               :sanitized (name-to-path name)
               :year (year)}]
     (->files data
+             ["project.clj" (render "project.clj" data)]
+
              ["src/{{sanitized}}/setup.clj" (render "setup.clj" data)]
              ["src/{{sanitized}}/persistence.clj" (render "persistence.clj" data)]
              ["src/{{sanitized}}/core.clj" (render "core.clj" data)]


updated dependencies

updated dependencies

--- src/leiningen/new/reagent.clj
+++ src/leiningen/new/reagent.clj
@@ -30,24 +30,24 @@

 (def lib-or-app-dependencies
   "Dependencies for development or as part of an app."
-  '[[org.clojure/clojurescript "0.0-2496" :scope "provided"]
+  '[[org.clojure/clojurescript "0.0-2665" :scope "provided"]
     [com.cemerick/piggieback "0.1.3"]
     [weasel "0.4.2"]
     [ring "1.3.2"]
-    [ring/ring-defaults "0.1.2"]
+    [ring/ring-defaults "0.1.3"]
     [prone "0.8.0"]
     [compojure "1.3.1"]
-    [selmer "0.7.7"]
+    [selmer "0.7.9"]
     [environ "1.0.0"]
     [leiningen "2.5.0"]
-    [figwheel "0.1.5-SNAPSHOT"]])
+    [figwheel "0.1.6-SNAPSHOT"]])

 (def lib-or-app-plugins
   "Plugins for development or as part of an app."
-  '[[lein-cljsbuild "1.0.3"]
+  '[[lein-cljsbuild "1.0.4"]
     [lein-environ "1.0.0"]
     [lein-ring "0.8.13"]
-    [lein-asset-minifier "0.2.0"]])
+    [lein-asset-minifier "0.2.2"]])

 (defn app-dependencies [opts]
   (when-not (lib? opts)
@@ -74,7 +74,7 @@
   (some #{"+cljx"} opts))

 (def cljx-plugin
-  "com.keminglabs/cljx \"0.4.0\" :exclusions [org.clojure/clojure]")
+  "com.keminglabs/cljx \"0.5.0\" :exclusions [org.clojure/clojure]")

 (def cljx-source-paths
   " \"target/generated/clj\" \"target/generated/cljx\"")


Add separate +dirac option

Add separate +dirac option

Use boot-cljs-devtools SNAPSHOT


Add config documentation

Add config documentation

--- config.clj
+++ config.clj
@@ -3,6 +3,7 @@
   :hecuba/refstore
   {:jig/component kixi.hecuba.dev/RefStore
    :jig/project "../kixi.hecuba/project.clj"
+   :doc "An in-memory store for testing, this binds Commander and Querier in the system at :querier and :commander respectively"
    }

   :hecuba/kafka
@@ -22,7 +23,8 @@
   {:jig/component kixi.hecuba.web/Website
    :jig/project "../kixi.hecuba/project.clj"
    :jig/dependencies [:hecuba/refstore]
-   }
+   :doc "This depends on types that satisfy Commander and Querier being
+   bound in the system at :querier and :commander respectively" }

   :hecuba/cljs-builder
   {:jig/component jig.cljs-builder/Builder


login ja logout

login ja logout

--- mtg-pairings-server/src/mtg_pairings_server/server.clj
+++ mtg-pairings-server/src/mtg_pairings_server/server.clj
@@ -26,11 +26,27 @@
            db))
        db)))

+(defn login [req]
+  (if-let [dci (get-in req [:body :dci])]
+    (do
+      (println "dci:" dci)
+      {:status 200
+       :session (assoc (:session req {}) :dci dci)})
+    {:status 400}))
+
+(defn logout []
+  {:status 200
+   :session nil})
+
 (defn routes [db]
   (let [tournament-routes (tournament-api/routes db)]
     (c/routes
       (r/resources "/")
       (c/GET "/" [] "Hello World")
+      (c/POST "/login" [:as req]
+        (login req))
+      (c/POST "/logout" []
+        (logout))
       (c/context "/tournament" [] tournament-routes))))

 (defn run! []


Better name

Better name

--- src/structural_typing/guts/mechanics/compiling_types.clj
+++ src/structural_typing/guts/mechanics/compiling_types.clj
@@ -85,9 +85,9 @@
                    :whole-value whole-value
                    :path original-path}))))))

-(defn compile-type [t]
+(defn compile-type [type-map]
   ;; Note that the path-checks are compiled once, returning a function to be run often.
-  (let [compiled-path-checks (map compile-path-check t)]
+  (let [compiled-path-checks (map compile-path-check type-map)]
     (fn [whole-value]
       (reduce (fn [all-errors path-check]
                 (into all-errors (path-check whole-value)))


replace boot-stem1 with boot-stem; remove boot-stem2

--- src/babel/espanol/lexicon.clj
+++ src/babel/espanol/lexicon.clj
@@ -65,8 +65,7 @@
    "cambiar" {:synsem {:cat :verb
                        :sem {:pred :cambiare}}}

-   "cerrar" {:espanol {:boot-stem1 "cierr"
-                        :boot-stem2 "cerr"}
+   "cerrar" {:espanol {:boot-stem "cierr"}
              :synsem {:cat :verb
                       :sem {:pred :close}}}

@@ -248,8 +247,7 @@
                    :pred :loro}
              :subcat '()}}

-   "empezar" {:espanol {:boot-stem1 "empiez"
-                        :boot-stem2 "empez"}
+   "empezar" {:espanol {:boot-stem "empiez"}
               :synsem {:cat :verb
                        :sem {:pred :begin}}}

@@ -263,8 +261,7 @@
               {:synsem {:cat :verb
                         :sem {:pred :teach}}}]

-   "entender" {:espanol {:boot-stem1 "entiend"
-                         :boot-stem2 "entend"}
+   "entender" {:espanol {:boot-stem "entiend"}
                :synsem {:cat :verb
                         :sem {:pred :understand-simply}}}

@@ -453,8 +450,7 @@
                                  :number :sing
                                  :def :def}}}})

-   "pensar" {:espanol {:boot-stem1 "piens"
-                       :boot-stem2 "pens"}
+   "pensar" {:espanol {:boot-stem "piens"}
              :synsem {:cat :verb
                       :sem {:pred :think}}}

@@ -463,8 +459,7 @@

    "poder"
    (let [shared-part-of-poder
-                   {:espanol {:boot-stem1 "pued"
-                              :boot-stem2 "pod"}
+                   {:espanol {:boot-stem "pued"}
                     :synsem {:cat :verb}}]
      [(merge shared-part-of-poder
              {:synsem {:pred :can}})
@@ -605,6 +600,10 @@
               (if-then {:synsem {:cat :verb
                                  :synsem {:aux false}}}
                        {:synsem {:aux false}})
+
+              (if-then {:synsem {:cat :verb
+                                 :subcat {:2 {:reflexive false}}}}
+                       {:synsem {:subcat {:2 {:reflexive false}}}})

               ;; Cleanup functions can go here. Number them for ease of reading.
               ;; 1. this filters out any verbs without an inflection: infinitive verbs should have inflection ':infinitive',


fix typo

fix typo

--- src/babel/espanol/lexicon.clj
+++ src/babel/espanol/lexicon.clj
@@ -600,7 +600,7 @@

               ;; if verb has no :aux, it's {:aux false}
               (if-then {:synsem {:cat :verb
-                                 :synsem {:aux false}}}
+                                 :aux false}}
                        {:synsem {:aux false}})

               (if-then {:synsem {:cat :verb


Actions added

Actions added

--- src/clj/funstructor/cards.clj
+++ src/clj/funstructor/cards.clj
@@ -14,6 +14,13 @@
     :mutator-right-gap
     :mutator-position-gap
     ;:mutator-shot
+
+    :action-thief-1
+    :action-discard-1
+    :action-equality-1
+    :action-equality-2
+    :action-equality-3
+
     })

 (def cards
@@ -132,7 +139,7 @@
    {:name "Thief v1.0"
     :description
     "steal random card from opponent's hand"
-    :target :opponent
+    :target :self
     :type :action
     :weight 40
     :img "action_thief_1.svg"}
@@ -141,7 +148,7 @@
    {:name "Discard v1.0"
     :description
     "opponent discards random card"
-    :target :opponent
+    :target :self
     :type :action
     :weight 40
     :img "action_discard_1.svg"}
@@ -151,7 +158,7 @@
     :description
     "you and your opponent discard all cards from hand
 and take 5 from deck"
-    :target :opponent
+    :target :self
     :type :action
     :weight 20
     :img "action_equality_1.svg"}
@@ -160,7 +167,7 @@
    {:name "Equality v2"
     :description
     "you take cards from deck until you have as many as your opponent"
-    :target :opponent
+    :target :self
     :type :action
     :weight 20
     :img "action_equality_2.svg"}
@@ -169,7 +176,7 @@
    {:name "Equality v3"
     :description
     "you and your opponent discard all cards"
-    :target :opponent
+    :target :self
     :type :action
     :weight 10
     :img "action_equality_3.svg"}


Use safe read-string in Clojure.

Use safe read-string in Clojure.

--- src/clj/konserve/platform.clj
+++ src/clj/konserve/platform.clj
@@ -8,6 +8,10 @@

 (def log println)

+(defn read-string-safe [s]
+  (binding [*read-eval* false]
+    (read-string s)))
+
 (defrecord CouchKeyValueStore [db]
   IAsyncKeyValueStore
   (-get-in [this key-vec]
@@ -16,7 +20,7 @@
                        pr-str
                        (cl/get-document db)
                        :edn-value
-                       read-string)
+                       read-string-safe)
                   rkey))))
   ;; TODO, cleanup and unify with update-in
   (-assoc-in [this key-vec value]
@@ -38,7 +42,7 @@
                                             (fn [{v :edn-value :as old}]
                                               (assoc old
                                                 :edn-value (pr-str (if-not (empty? rkey)
-                                                                     (assoc-in (read-string v) rkey value)
+                                                                     (assoc-in (read-string-safe v) rkey value)
                                                                      value)))))
                         (catch clojure.lang.ExceptionInfo e
                           (if (< attempt 10)
@@ -51,7 +55,7 @@
   (-update-in [this key-vec up-fn]
     (go (let [[fkey & rkey] key-vec
               doc (cl/get-document db (pr-str fkey))
-              old (when doc (-> doc :edn-value read-string))
+              old (when doc (-> doc :edn-value read-string-safe))
               new (if-not (empty? rkey)
                     (update-in old rkey up-fn)
                     (up-fn old))]
@@ -59,7 +63,7 @@
                 [nil (-> (cl/put-document db {:_id (pr-str fkey) ;; TODO might throw on race condition to creation
                                               :edn-value (pr-str new)})
                          :edn-value
-                         read-string
+                         read-string-safe
                          (get-in rkey))]

                 (not new)
@@ -67,14 +71,14 @@

                 :else
                 ((fn trans [doc attempt]
-                   (let [old (-> doc :edn-value read-string (get-in rkey))
+                   (let [old (-> doc :edn-value read-string-safe (get-in rkey))
                          new* (try (cl/update-document db
                                                        doc
                                                        (fn [{v :edn-value :as old}]
                                                          (assoc old
                                                            :edn-value (pr-str (if-not (empty? rkey)
-                                                                                (update-in (read-string v) rkey up-fn)
-                                                                                (up-fn (read-string v)))))))
+                                                                                (update-in (read-string-safe v) rkey up-fn)
+                                                                                (up-fn (read-string-safe v)))))))
                                    (catch clojure.lang.ExceptionInfo e
                                      (if (< attempt 10)
                                        (trans (cl/get-document db (pr-str fkey)) (inc attempt))
@@ -82,7 +86,7 @@
                                          (log e)
                                          (.printStackTrace e)
                                          (throw e)))))
-                         new (-> new* :edn-value read-string (get-in rkey))]
+                         new (-> new* :edn-value read-string-safe (get-in rkey))]
                      [old new])) doc 0))))))


some testing

some testing

--- src/clj/salava/gallery/db.clj
+++ src/clj/salava/gallery/db.clj
@@ -7,9 +7,120 @@
             [salava.core.countries :refer [all-countries sort-countries]]
             [salava.page.main :as p]
             [salava.social.db :as so]
+            [clojure.set :refer [subset?]]
+            [clojure.string :as string]
             [salava.badge.main :as b]))

 (defqueries "sql/gallery/queries.sql")
+
+
+(defn contains-tag? [query-tags tags]
+  (subset? (set query-tags) (set tags)))
+
+(defn tag-parser [tags]
+  (if tags
+    (string/split tags #",")))
+
+(defn filter-tags [search tags]
+  (remove (fn [advert] (not (contains-tag? tags  (tag-parser (:tags advert))))) search))
+
+
+(defn map-collection
+  ([where value]
+   (map-collection where value true))
+  ([where value fn]
+   (if (and where value fn)
+     {(str where)  value})))
+
+
+
+(defn badge-adverts-where-params [country name issuer-name id recipient-name]
+  (let [where-params {}]
+
+    (-> where-params
+                                        ;(conj (map-collection " and ba.id = ? " id ))
+        #_(conj (map-collection  " AND CONCAT(u.first_name,' ',u.last_name) LIKE ?" (if recipient-name (str "%" recipient-name "%")) ))
+        (conj (map-collection " and ba.country = ? " country (not= country "all")))
+        (conj (map-collection " AND bc.name LIKE ? " (if name (str "%" name "%"))))
+        (conj (map-collection " AND ic.name LIKE ? " (if issuer-name (str "%" issuer-name "%"))))
+        )))
+
+
+(def ctx {:config {:core {:site-name "Perus salava"
+
+                          :share {:site-name "jeejjoee"
+                                  :hashtag "KovisKisko"}
+
+                          :site-url "http://localhost:3000"
+
+                          :base-path "/app"
+
+                          :asset-version 2
+
+                          :languages [:en :fi]
+
+                          :plugins [:badge :page :gallery :file :user :oauth :admin :social :registerlink :mail]
+
+                          :http {:host "localhost" :port 3000 :max-body 100000000}
+                          :mail-sender "sender@example.com"}
+                   :user {:email-notifications true}}
+          :db (hikari-cp.core/make-datasource {:adapter "mysql",
+                                               :username "root",
+                                               :password "isokala",
+                                               :database-name "salava_extra1",
+                                               :server-name "localhost"})})
+
+
+(def most-messages
+  "SELECT bc.id, bc.name, bc.image_file, bc.description, ic.name AS issuer_content_name, ic.url AS issuer_content_url, MAX(b.ctime) AS ctime, badge_content_id  FROM social_event AS se
+  JOIN badge AS b ON se.object = b.badge_content_id
+                    JOIN badge_content AS bc ON b.badge_content_id = bc.id
+                    JOIN issuer_content AS ic ON b.issuer_content_id = ic.id
+                    LEFT JOIN user AS u ON b.user_id = u.id
+                    WHERE b.status = 'accepted' AND b.deleted = 0 AND b.revoked = 0 AND (b.expires_on IS NULL OR b.expires_on > UNIX_TIMESTAMP())
+
+  GROUP BY bc.id, bc.name, bc.image_file, bc.description, ic.name, ic.url, b.badge_content_id")
+
+(def lo
+  "select distinct bc.id, count(se.id) as messagecount, count(b.id) as ownercount,  bc.name, bc.image_file, bc.description, ic.name AS issuer_content_name, ic.url AS issuer_content_url, MAX(b.ctime) AS ctime from badge_content as bc
+  left join badge as b on bc.id = b.badge_content_id AND  b.status = 'accepted' AND b.deleted = 0 AND b.revoked = 0
+  left join social_event as se on bc.id = se.object and se.verb = 'message'
+  JOIN issuer_content AS ic ON b.issuer_content_id = ic.id
+  group by bc.id;")
+
+(defn get-badge-adverts [ctx country tags badge-name issuer-name order id user-id show-followed-only recipient-name]
+  (let [;where-params (badge-adverts-where-params country badge-name issuer-name id recipient-name)
+        ;user-id (or user-id "NULL") ;set null if nil
+       ; where   (str (apply str (keys where-params))  (if show-followed-only  " AND scba.user_id IS NOT NULL ")) ;add IS NOT NULL when user want only followed adverts
+        params [] ;(cons user-id (vec (vals where-params)))  ;add user-id to params
+        ;tags (vec (vals tags))
+        order (cond
+                ;(= order "mtime") "ORDER BY ba.mtime DESC"
+                (= order "name") "ORDER BY bc.name"
+                (= order "issuer_content_name") "ORDER BY ic.name"
+                :else "ORDER BY ctime DESC")
+        query (str "SELECT bc.id, bc.name, bc.image_file, bc.description, ic.name AS issuer_content_name, ic.url AS issuer_content_url, MAX(b.ctime) AS ctime, badge_content_id  FROM badge AS b
+                    JOIN badge_content AS bc ON b.badge_content_id = bc.id
+                    JOIN issuer_content AS ic ON b.issuer_content_id = ic.id
+                    LEFT JOIN user AS u ON b.user_id = u.id
+                    WHERE b.status = 'accepted' AND b.deleted = 0 AND b.revoked = 0 AND (b.expires_on IS NULL OR b.expires_on > UNIX_TIMESTAMP()) "
+
+                  ; where
+
+                   "GROUP BY bc.id, bc.name, bc.image_file, bc.description, ic.name, ic.url, b.badge_content_id "
+                   order
+                   )
+        search (jdbc/with-db-connection
+                 [conn (:connection (get-db ctx))]
+                 (jdbc/query conn (into [query] params)))]
+    search
+    #_(if (not-empty tags)
+      (filter-tags search tags)
+      search)))
+
+(dump )
+(count (get-badge-adverts ctx nil nil nil nil nil nil nil nil nil))
+(:name (first (get-badge-adverts ctx nil nil nil nil "mtime" nil nil nil nil)))

 (defn public-badges-by-user
   "Return user's public badges"


Add a note on how to improve test once we switch to new event-bus

--- test/clj/lambdacd/event_bus_test.clj
+++ test/clj/lambdacd/event_bus_test.clj
@@ -9,6 +9,7 @@
             [lambdacd.util :as util]))

 (defn- make-sure-subscriber-has-started []
+  ; TODO: check if this is still necessary once we switch to the new event bus
   (Thread/sleep 100))

 (defn- append-to! [a msg]


remove click cost from Tallie Perrault

remove click cost from Tallie Perrault

Tallie's ability doesn't cost a click, it happens by trashing her at paid ability speed.

--- src/clj/game/cards.clj
+++ src/clj/game/cards.clj
@@ -3398,7 +3398,7 @@
    {:req (req (:made-run runner-reg))}

    "Tallie Perrault"
-   {:abilities [{:cost [:click 1] :effect (effect (trash card) (draw (:bad-publicity corp)))
+   {:abilities [{:label "Draw 1 card for each Corp bad publicity" :effect (effect (trash card) (draw (:bad-publicity corp)))
                  :msg (msg "draw " (:bad-publicity corp) " cards")}]
     :events {:play-operation {:msg "give the Corp 1 bad publicity and take 1 tag"
                               :effect (effect (gain :bad-publicity 1) (gain :runner :tag 1))


Return 503 on rate limit hit

Return 503 on rate limit hit

--- src/clj/inky/entry.clj
+++ src/clj/inky/entry.clj
@@ -166,25 +166,20 @@
 (defn compiling? [hash]
   (get @in-progress hash))

-(defn html-response [body]
-  {:headers {"Content-Type" "text/html; utf-8"}
-   :body body})
+(defn html-response [body & [opts]]
+  (merge
+    opts
+    {:headers {"Content-Type" "text/html; utf-8"}
+     :body body}))

 (defn gist-data [gist-id]
-  (let [resp (try+
-               (assoc (hcl/get (str "https://api.github.com/gists/" gist-id))
-                 :success true)
-               (catch [:status 403] _
-                 ;; rate limit error
-                 (println "Rate limit hit fetching gist id:" gist-id)
-                 {:success false}))]
-    (if-not (:success resp)
-      resp
+  (try+
+    (let [resp (hcl/get (str "https://api.github.com/gists/" gist-id))]
       (let [body (->> resp
                       :body
                       util/from-json)
-            {:keys [login avatar_url html_url]} (:user resp)]
-        {:source (->> resp
+            {:keys [login avatar_url html_url]} (:user body)]
+        {:source (->> body
                       :files
                       (filter #(or (.endsWith (str (first %)) ".cljs")
                                    (.endsWith (str (first %)) ".clj")))
@@ -194,8 +189,11 @@
          :user {:login login
                 :avatar-url avatar_url
                 :html-url html_url}
-         :success true}))))
-
+         :success true}))
+    (catch [:status 403] _
+      ;; rate limit error
+      (println "Rate limit hit fetching gist id:" gist-id)
+      {:success false})))

 (def cljs-libs
   [["dommy" "0.1.2" "https://github.com/Prismatic/dommy"]
@@ -402,7 +400,8 @@
                           (html-response
                             (render-error
                               [:h2 "GitHub Rate Limit Hit"]
-                              [:p "Whoops, looks like we hit the rate limit. GitHub allows us to call their API a limited number of times per hour. Please try again next hour."])))
+                              [:p "Whoops, looks like we hit the rate limit. GitHub allows us to call their API a limited number of times per hour. Please try again next hour."])
+                            {:status 503}))
                         (let [source (:source gist-data)
                               hash gist-id
                               dir (str "/tmp/inky/" hash)


Pull out reply.main/launch for tool use

Pull out reply.main/launch for tool use

--- src/clj/reply/main.clj
+++ src/clj/reply/main.clj
@@ -90,6 +90,28 @@
         :prompt (constantly false)
         :need-prompt (constantly false)))

+(declare -main) ; for --help
+(defn launch
+  "Entry point for tools which may prefer to send a map of options rather than a
+varargs list of arguments.
+Available options: [:help :custom-init :skip-default-init :nrepl :attach :port :color]
+See -main for descriptions."
+  [options]
+  (print "options: ") (prn options)
+  (try
+    (concurrency/set-signal-handler! "CONT" handle-resume)
+    (with-redefs [clojure.core/print-sequential hacks.printing/print-sequential
+                  complete/resolve-class hacks.complete/resolve-class
+                  clojure.repl/pst clj-stacktrace.repl/pst]
+      (cond (:help options) (println (clojure.repl/doc -main))
+            (:nrepl options) (launch-nrepl options)
+            :else (launch-standalone options)))
+  (catch Throwable e
+    (when (not= (.getMessage e) "EOF while reading")
+      (println "Oh noez!")
+      (clj-stacktrace.repl/pst e)))
+  (finally
+    (exit))))

 (defn -main
   "Launches a REPL. Customizations available:
@@ -97,19 +119,9 @@
   -i/--init:           Provide a Clojure file to evaluate in the user ns
   -e/--eval:           Provide custom code to evaluate in the user ns
   --skip-default-init: Skip the default initialization code
-  --nrepl:             Launch nREPL (clojure.tools.nrepl) in interactive mode"
+  --nrepl:             Launch nREPL (clojure.tools.nrepl) in interactive mode
+  --attach:            Attach to an existing nrepl session on this port, when used with --nrepl
+  --port:              Start a new nrepl session on this port, when used with --nrepl
+  --color:             Use color; currently only available with --nrepl"
   [& args]
-  (try
-    (concurrency/set-signal-handler! "CONT" handle-resume)
-    (let [arg-map (parse-args args)]
-      (with-redefs [clojure.core/print-sequential hacks.printing/print-sequential
-                    complete/resolve-class hacks.complete/resolve-class
-                    clojure.repl/pst clj-stacktrace.repl/pst]
-        (cond (:help arg-map) (println (clojure.repl/doc -main))
-              (:nrepl arg-map) (launch-nrepl arg-map)
-              :else (launch-standalone arg-map))))
-    (catch Throwable e
-      (when (not= (.getMessage e) "EOF while reading")
-        (println "Oh noez!")
-        (clj-stacktrace.repl/pst e))))
-  (exit))
+  (launch (parse-args args)))


schema neutral

schema neutral

--- src/cljs/app/core.cljs
+++ src/cljs/app/core.cljs
@@ -11,7 +11,7 @@
 (enable-console-print!)

 (defn fetch-joke-async [cb]
-  (let [req (Jsonp. (Uri. "https://api.icndb.com/jokes/random"))]
+  (let [req (Jsonp. (Uri. "://api.icndb.com/jokes/random"))]
     (.send req nil
            (fn [res]
              (cb (get-in (js->clj res) ["value" "joke"]))))))


limit recent views to 10 and activity to 40 for now.

--- src/metabase/api/activity.clj
+++ src/metabase/api/activity.clj
@@ -13,7 +13,7 @@
 (defendpoint GET "/"
   "Get recent activity."
   []
-  (-> (db/sel :many Activity (k/order :timestamp :DESC))
+  (-> (db/sel :many Activity (k/order :timestamp :DESC) (k/limit 40))
       (hydrate :user :table :database :model_exists)))

 (defendpoint GET "/recent_views"
@@ -30,7 +30,7 @@
              (k/where (= :user_id *current-user-id*))
              (k/group :user_id :model :model_id)
              (k/order :max_ts :desc)
-             (k/limit 15))
+             (k/limit 10))
            (map #(assoc % :model_object (delay (case (:model %)
                                          "card" (-> (Card (:model_id %))
                                                     (select-keys [:id :name :description :display]))


Add more setup for alembic

Add more setup for alembic

--- clojure/profiles.clj
+++ clojure/profiles.clj
@@ -1,7 +1,6 @@
 ;; See: https://github.com/kumarshantanu/lein-localrepo
 {:user {:plugins [;; Try new api quickly using the repl
                   [lein-try "0.4.3"]
-
                   ;;[lein-localrepo "0.5.4"]

                   ;; Convert pom.xml to project.clj
@@ -15,8 +14,13 @@

                   ;; Pretty-print a representation of the project map
                   [lein-pprint "1.2.0"]
-                  ;; Keep adding more stuff here
-                  ]
+
+                  ;; For quick typing
+                  [com.palletops/lein-shorthand "0.4.0"]]
+
+        ;; See: https://github.com/pallet/alembic
+        :shorthand {. [alembic.still/distill alembic.still/lein]}
+
         ;; Experimental
         :dependencies [[pjstadig/humane-test-output "0.8.3"]
                        ;; See: https://github.com/pallet/alembic


Chris - closes #121

Chris - closes #121

--- src/nevergreen/api/routes.clj
+++ src/nevergreen/api/routes.clj
@@ -25,7 +25,9 @@
     (OPTIONS "/api/encrypt" [] preflight-response)
     (POST "/api/encrypt" {body :body} {:body (security/encrypt-password body)})

-    (GET "/api/register" [] sse/handler)))
+    (GET "/api/register" [] sse/handler)
+
+    (GET "/api/ping" [] {:status 204})))

 (defn- wrap-logging [handler]
   (-> handler


Added class option

Added class option

--- src/om_semantic/dropdown.cljs
+++ src/om_semantic/dropdown.cljs
@@ -51,6 +51,7 @@
    menu: kork to the menu items
    idkey: which key in the menu items that should be used as value
    tabidx: tabIndex
+   class: a class to add to element ui select dropdown
    disabled: if the dropdown is disabled or not
    default-text: What shows if nothing is selected
    lkey: which key in the menu items that should be used as label (text)
@@ -69,10 +70,11 @@
        :open false})
     om/IRenderState
     (render-state [_ {:keys [name lkey idkey open disabled
-                             tabidx default-text] :as state}]
+                             tabidx default-text class] :as state}]
       (let [items (get-in data (:menu state))
             selected (get-in data (:selected state))
-            class (str "ui selection dropdown"
+            class (str "ui selection dropdown "
+                       (when class class)
                        (cond open " active visible"
                              disabled " disabled"))
             tclass (str "text" (when-not selected " default"))


Reply 401 on unauth access to secure urls

The default configuration is to redirected to the login url, but since
we're going to be calling from a SPA we won't be displaying the page
that the redirect points to. By returning a 401 we can catch that, mark
the user as logged out and return them to the login screen.

--- src/expensapp/routes/home.clj
+++ src/expensapp/routes/home.clj
@@ -50,10 +50,10 @@
                    {:status 204})
                {:status 409 :body (str "Username: " username " is already taken")}))))))

-
 (defn make-all-routes [db]
   (-> (ring.middleware.session/wrap-session
        (friend/authenticate (routes app-routes (make-account-routes db))
                             {:login-uri "/"
                              :default-landing-uri "/session"
-                             :workflows [(make-auth-routes db)]}))))
+                             :workflows [(make-auth-routes db)]
+                             :unauthenticated-handler (fn [req] {:status 401})}))))


clean up docstrings

clean up docstrings

--- src/overtone/studio/mixer.clj
+++ src/overtone/studio/mixer.clj
@@ -31,12 +31,14 @@
   (deps-satisfied? MIXER-BOOT-DEPS))

 (defn wait-until-mixer-booted
-  "Makes the current thread sleep until the mixer completed its boot process."
+  "Makes the current thread sleep until the mixer completed its boot
+  process."
   []
   (wait-until-deps-satisfied MIXER-BOOT-DEPS))

 (defn boot-mixer
-  "Boots the server and waits until the studio mixer has complete set up"
+  "Boots the server and waits until the studio mixer has complete set
+  up"
   []
   (when-not (mixer-booted?)
     (boot-server)


Use conditional instead of both

Use conditional instead of both

--- src/icecap/handlers/delay.clj
+++ src/icecap/handlers/delay.clj
@@ -4,6 +4,6 @@
             [schema.core :as sc]))

 (defstep :delay
-  {:amount (sc/both sc/Int (sc/pred #(< 0 % 60)'(< 0 delay 60)))}
+  {:amount (sc/conditional #(< 0 % 60) sc/Int)}
   [step]
   (timeout (:amount step)))


Replace call to deprecated Long. constructor

--- ring-core/src/ring/util/request.clj
+++ ring-core/src/ring/util/request.clj
@@ -26,7 +26,7 @@
   {:added "1.3"}
   [request]
   (if-let [^String length (get-in request [:headers "content-length"])]
-    (Long. length)))
+    (Long/valueOf length)))

 (defn character-encoding
   "Return the character encoding for the request, or nil if it is not set."


minor doctsring edits

minor doctsring edits

--- src/push/interpreter/core.clj
+++ src/push/interpreter/core.clj
@@ -46,12 +46,7 @@

 (defn register-type
-  "Takes an Interpreter record, and a PushType record, and adds the
-  PushType to the :types collection in the Interpeter; adds the
-  type's :name as a new stack (if not already present); appends the
-  type's :recognizer to the :router vector; adds
-  the type's internally defined instructions to the Interpreter's
-  registry automatically."
+  "Takes an Interpreter record, and a PushType record, and adds the PushType to the :types collection in the Interpeter; adds the type's :name as a new stack (if not already present); appends the type's :recognizer to the :router vector; adds the type's internally defined instructions to the Interpreter's registry automatically."
   [interpreter type]
   (let [old-types (:types interpreter)
         old-stacks (:stacks interpreter)
@@ -65,9 +60,7 @@

 (defn register-module
-  "Takes an Interpreter record, and a module; adds
-  the module's internally defined instructions to the Interpreter's
-  registry automatically."
+  "Takes an Interpreter record, and a module; adds the module's internally defined instructions to the Interpreter's registry automatically."
   [interpreter module]
   (let [old-instructions (:instructions interpreter)]
     (-> interpreter
@@ -75,22 +68,19 @@

 (defn register-types
-  "Takes an Interpreter record, and a list of PushType records. Calls
-  `register-type` on each of the types in turn."
+  "Takes an Interpreter record, and a list of PushType records. Calls `register-type` on each of the types in turn."
   [interpreter types]
   (reduce #(register-type %1 %2) interpreter types))

 (defn register-modules
-  "Takes an Interpreter record, and a list of modules. Calls
-  `register-module` on each of those in turn."
+  "Takes an Interpreter record, and a list of modules. Calls `register-module` on each of those in turn."
   [interpreter modules]
   (reduce #(register-module %1 %2) interpreter modules))

 (defn register-input
-  "Takes an Interpreter record, a keyword and any item, and adds the
-  item as a value stored under the keyword in the :inputs hashmap."
+  "Takes an Interpreter record, a keyword and any item, and adds the item as a value stored under the keyword in the :inputs hashmap."
   ([interpreter value]
     (let [next-index (inc (count (:inputs interpreter)))
           next-input (keyword (str "input!" next-index))]
@@ -100,8 +90,7 @@

 (defn register-inputs
-  "Takes an Interpreter record, and a hashmap of key-value items;
-  merges them into the :inputs map if the Interpreter."
+  "Takes an Interpreter record, and a hashmap of key-value items; merges them into the :inputs map if the Interpreter."
   [interpreter values]
   (cond (vector? values)
     (reduce (partial register-input) interpreter values)
@@ -110,16 +99,13 @@

 (defn input?
-  "Takes an interpreter, and a keyword, and returns true if the
-  keyword is a key in the :inputs hashmap"
+  "Takes an interpreter, and a keyword, and returns true if the keyword is a key in the :inputs hashmap"
   [interpreter kwd]
   (contains? (:inputs interpreter) kwd))

 (defn- add-instruction
-  "Takes an Interpreter and an Instruction (record), and adds the
-  instruction to the :instructions registry of the interpreter,
-  without checking for prior definitions."
+  "Takes an Interpreter and an Instruction (record), and adds the instruction to the :instructions registry of the interpreter, without checking for prior definitions."
   [interpreter instruction]
   (assoc-in
     interpreter
@@ -128,9 +114,7 @@

 (defn register-instruction
-  "Takes an Interpreter and an Instruction, and attempts to add the
-  Instruction to the :instructions map of the Interpreter, keyed by
-  its :token."
+  "Takes an Interpreter and an Instruction, and attempts to add the Instruction to the :instructions map of the Interpreter, keyed by its `:token`."
   [interpreter instruction]
   (let [token (:token instruction)
         registry (:instructions interpreter)]
@@ -146,8 +130,7 @@

 (defn basic-interpreter
-  "creates a new Interpreter record
-  With no arguments, it has an empty :program, the :stacks include
+  "With no arguments, it has an empty :program, the :stacks include
   core types and are empty, no :instructions are registered, and the
   counter is 0.


update precondition to work with new input macro

--- src/example/rooms.cljc
+++ src/example/rooms.cljc
@@ -8,8 +8,10 @@
             [advenjure.ui.input :refer [prompt-value]]
             #?(:cljs [advenjure.dialogs]
                :clj [advenjure.dialogs :refer [dialog]])
+            #?(:clj [advenjure.async :refer [alet]])
             [example.dialogs :refer [npc-dialog]])
-  #?(:cljs (:require-macros [advenjure.dialogs :refer [dialog]])))
+  #?(:cljs (:require-macros [advenjure.dialogs :refer [dialog]]
+                            [advenjure.async :refer [alet]])))

 ;;; DEFINE ROOMS AND ITEMS

@@ -118,9 +120,9 @@

 (defn enter-combination
   [game-state]
-  (let [combo (prompt-value "Enter combination: ")
-        combo (string/trim combo)
-        responses ["No luck." "That wasn't it." "Nope."]]
+  (alet [combo (prompt-value "Enter combination: ")
+         combo (string/trim combo)
+         responses ["No luck." "That wasn't it." "Nope."]]
     (if (= combo safe-combination)
         (do (utils/say "Gotcha!") true)
         (get responses (rand-int (count responses))))))


BUGFIX: Matches from the last day of month are included in the stats.

--- src/fist/models/db.clj
+++ src/fist/models/db.clj
@@ -27,7 +27,7 @@
     (where (or (= :home_player_id player-id)
              (= :away_player_id player-id)))
     (where {:occured_at [>= (time-coerce/to-sql-time start-date)]})
-    (where {:occured_at [<= (time-coerce/to-sql-time end-date)]})
+    (where {:occured_at [< (time-coerce/to-sql-time end-date)]})
     (order :occured_at)))

 (defn normalize-match [match player-id]
@@ -91,7 +91,7 @@
                    :stats (stats-fn
                             (:id %)
                             (time/first-day-of-the-month (time/now))
-                            (time/last-day-of-the-month (time/now)))})
+                            (time/plus (time/last-day-of-the-month (time/now)) (time/days 1)))})
       (get-players))))

 (defn get-all-between-players-stats []


rf core.cljs routing

rf core.cljs routing

--- src/frontend/core.cljs
+++ src/frontend/core.cljs
@@ -29,14 +29,10 @@
                               (-> todos/reconcile
                                   (persistence/wrap-reconcile storage :model nil))
                               storage)]
-    (letfn [(dispatch-navigate
-              [token]
-              ((:dispatch-signal app) [:component [:on-navigate token]]))]
-      ; clear listeners in case of hotloading
-      (goog.events/removeAll history)
-
-      ; start listening
-      (goog.events/listen history EventType/NAVIGATE #(dispatch-navigate (.-token %))))
+    ; clear previous listeners which can be there after hot reload
+    (goog.events/removeAll history)
+    (goog.events/listen history EventType/NAVIGATE
+                        #((:dispatch-signal app) [:component [:on-navigate (.-token %)]]))

     (r/render-component [(:view app)] (. js/document (getElementById "root")))
     app))


Fix typo

Fix typo

--- server/src/patavi/server/server.clj
+++ server/src/patavi/server/server.clj
@@ -39,6 +39,6 @@
       (println banner)
       (System/exit 0))
     (let [handler (if in-dev? (reload/wrap-reload app) app)]
-      (log/info "Running server on:" (:port options))
+      (log/info "running server on:" (:port options))
       (service/initialize)
       (run-server handler {:port (:port options)}))))


set qualified? to false

set qualified? to false

--- src/jarkeeper/core.clj
+++ src/jarkeeper/core.clj
@@ -23,7 +23,7 @@

 (defn check-deps [deps]
   (map (fn [dep]
-         (conj dep (anc/artifact-outdated? {:snapshots? false :qualified? true} dep))
+         (conj dep (anc/artifact-outdated? {:snapshots? false :qualified? false} dep))
          ) deps))


--- src/tenantadvisor/handler.clj
+++ src/tenantadvisor/handler.clj
@@ -33,6 +33,9 @@
   (GET "/api/contracts" []
      (json-response
       [] ))
+  (GET "/api/leases" []
+     (json-response
+      [] ))
   (route/resources "/")
   (route/not-found "Not Found"))


Avoid using full async in locking.

Avoid using full async in locking.

It seems to hang the peer in konserve operations from time to time.

--- src/konserve/core.cljc
+++ src/konserve/core.cljc
@@ -2,13 +2,27 @@
   (:refer-clojure :exclude [get-in update-in assoc-in exists?])
   (:require [konserve.protocols :refer [-exists? -get-in -update-in -bget -bassoc]]
             [hasch.core :refer [uuid]]
-            #?(:clj [clojure.core.async :refer [chan poll!]]
-               :cljs [cljs.core.async :refer [chan poll!]])
+            #?(:clj [clojure.core.async :refer [chan poll! put! <!]]
+               :cljs [cljs.core.async :refer [chan poll! put! <!]])
             #?(:clj [full.async :refer [go-try <? put?]]
                :cljs [full.async :refer [put?]]))
   #?(:cljs (:require-macros [full.async :refer [go-try <?]]
                             [konserve.core :refer [go-try-locked]])))

+
+;; support logging also in clj macroexpansion for cljs
+#?(:clj
+   (defn- cljs-env?
+     "Take the &env from a macro, and tell whether we are expanding into cljs."
+     [env]
+     (boolean (:ns env))))
+
+#?(:clj
+   (defmacro if-cljs
+     "Return then if we are generating cljs code and else for Clojure code.
+     https://groups.google.com/d/msg/clojurescript/iBY5HaQda4A/w1lAQi9_AwsJ"
+     [then else]
+     (if (cljs-env? &env) then else)))

 ;; TODO we keep one chan for each key in memory
 ;; as async ops seem to infer with the atom state changes
@@ -16,22 +30,31 @@
 (defn get-lock [{:keys [locks] :as store} key]
   (or (get @locks key)
       (let [c (chan)]
-        (put? c :unlocked)
+        (put! c :unlocked)
         (get (swap! locks assoc key c) key))))

 #?(:clj
    (defmacro go-try-locked [store key & code]
-     `(go-try
-       (let [l# (get-lock ~store ~key)]
-         (try
-           (<? l#)
-           ~@code
-           (finally
-             (put? l# :unlocked)))))))
-
-(defn exists? [store key]
+     (if-cljs
+      `(go-try
+         (let [l# (get-lock ~store ~key)]
+           (try
+             (cljs.core.async/<! l#)
+             ~@code
+             (finally
+               (cljs.core.async/put! l# :unlocked)))))
+      `(go-try
+        (let [l# (get-lock ~store ~key)]
+          (try
+            (<! l#)
+            ~@code
+            (finally
+              (put! l# :unlocked))))))))
+
+(defn exists?
   "Checks whether value is in the store."
+  [store key]
   (go-try-locked
    store key
    (<? (-exists? store key))))


Fix infinite loop in core/-main when called w/o args.

--- src/leiningen/core.clj
+++ src/leiningen/core.clj
@@ -183,4 +183,4 @@
              (System/exit value))))))
   ([]
      (doseq [arg-group (make-groups *command-line-args*)]
-       (apply -main (or arg-group ["help"])))))
+       (apply -main (or (seq arg-group) ["help"])))))


Initial :box-add functionallity.

Initial :box-add functionallity.

--- src/leiningen/voom.clj
+++ src/leiningen/voom.clj
@@ -516,6 +516,18 @@
           :when (.contains ^String proj dep) ]
       proj)))

+(defn adj-path
+  ([f path] (adj-path false f path))
+  ([dir-flag f path]
+     (->
+      ;; TODO Should this be made an isDirectory check?
+      (if (and = dir-flag (.isFile ^File f))
+        (.getParentFile ^File f)
+        ^File f)
+      (.getCanonicalPath)
+      ^String (str "/" path)
+      (File.))))
+
 (defn find-box
   "Locates voom-box root starting from current working directory."
   [& args]
@@ -526,6 +538,31 @@
         (if (.exists pfile)
           path
           (recur (.getParentFile path)))))))
+
+(defn box-repo-add
+  [{:keys [gitdir branch sha proj path]}]
+  (if-let [bdir (find-box)]
+    (let [pname (-> (str proj)
+                    (s/replace #"/" "--"))
+          pdir (adj-path bdir pname)
+          checkout (adj-path bdir (str ".voom-box/" pname))]
+      (println "Found box at:" bdir pdir)
+      (if (.exists ^File checkout)
+        (git {:gitdir (adj-path checkout "/.git")}
+             "fetch")
+        (git {} "clone" gitdir
+             "--refer" gitdir
+             checkout))
+      (git {:gitdir (adj-path checkout "/.git")}
+           "checkout" sha) ; must detach head for update...
+      (git {:gitdir (adj-path checkout "/.git")}
+           "branch" "-f" branch sha)
+      (git {:gitdir (adj-path checkout "/.git")}
+           "checkout" branch)
+      (sh "rm" "-f" pdir)
+      ;; (SYMLINK WILL NEED TO BE UPDATED FOR EACH CHECKOUT)
+      (sh "ln" "-s" (adj-path checkout path) pdir))
+    (println "Can't find box")))

 (defn box-add
   [proj & deps]
@@ -538,7 +575,7 @@
           (println "Multiple projects / locations match" (str \" dep \"\:))
           (doseq [r repo-infos]
             (prn r)))
-        (prn "Found:" (first repo-infos))))))
+        (box-repo-add (first repo-infos))))))

 ;; === lein entrypoint ===

@@ -550,7 +587,6 @@
 (def sub-commands
   {"build-deps" build-deps
    "freshen" freshen
-   "box-add" box-add
    "retag" retag
    "new-task" nope})

@@ -577,6 +613,8 @@
     (cond
      (:print kargset) (println (:version @new-project))
      (:parse kargset) (prn (ver-parse (first sargs)))
+     (:find-box kargset) (prn (find-box))
+     (:box-add kargset) (apply box-add project sargs)
      :else (if-let [f (get sub-commands (first sargs))]
              (apply f @new-project (rest sargs))
              (if (and (dirty-wc? (:root @new-project))


remove logging

remove logging

--- src/thi/ng/luxor/compiler.clj
+++ src/thi/ng/luxor/compiler.clj
@@ -190,7 +190,6 @@
   [_ scene id {:keys [__mesh __basename __export-path filename] :as opts}]
   (when __mesh
     (let [path (or __export-path (second filename) (str __basename ".ply"))]
-      (prn "exporting ply mesh: " id path)
       (with-open [out (io/output-stream path)]
         (mio/write-ply out __mesh))))
   (luxentity scene "Shape" "plymesh" opts))
@@ -199,7 +198,6 @@
   [_ scene id {:keys [__mesh __basename __export-path filename] :as opts}]
   (when __mesh
     (let [path (or __export-path (second filename) (str __basename ".stl"))]
-      (prn "exporting stl mesh: " id path)
       (with-open [out (io/output-stream path)]
         (mio/write-stl out __mesh))))
   (luxentity scene "Shape" "stlmesh" opts))


Augment 'git to take optional ok-statuses set.

This allows us to avoid throwing an exception for statuses the caller
expects.

--- src/leiningen/voom.clj
+++ src/leiningen/voom.clj
@@ -15,15 +15,16 @@
 (set! *warn-on-reflection* true)

 (defn git
-  [{:keys [^File gitdir]} & subcmd]
+  [{:keys [^File gitdir ok-statuses]
+    :or {ok-statuses #{0}}} & subcmd]
   ;; We won't handle bare repos or displaced worktrees
   (let [dir-args (if (nil? gitdir)
                    []
                    [(str "--git-dir=" (.getPath gitdir))
                     (str "--work-tree=" (.getParent gitdir))])
         all-args (concat dir-args subcmd)
-        rtn (apply sh "git" all-args)]
-    (when-not (zero? (:exit rtn))
+        {:keys [exit] :as rtn} (apply sh "git" all-args)]
+    (when-not (contains? ok-statuses exit)
       (throw (ex-info "git error" (assoc rtn :git all-args))))
     (assoc rtn :lines (when (not= "\n" (:out rtn))
                         (re-seq #"(?m)^.*$" (:out rtn))))))


contacts should be a vector

contacts should be a vector

--- src-cljs/reagent_tutorial/core.cljs
+++ src-cljs/reagent_tutorial/core.cljs
@@ -15,20 +15,16 @@
      {:first "Cy" :middle-initial "D" :last "Effect" :email "bugs@mit.edu"}
      {:first "Lem" :middle-initial "E" :last "Tweakit" :email "morebugs@mit.edu"}]}))

+(defn update-contacts! [f & args]
+  (apply swap! app-state update-in [:contacts] f args))
+
 (defn add-contact! [c]
-  (swap! app-state
-         update-in
-         [:contacts]
-         conj
-         c))
+  (update-contacts! conj c))

 (defn remove-contact! [c]
-  (swap! app-state
-         update-in
-         [:contacts]
-         (fn [cs]
-           (remove #(= % c) cs))
-         c))
+  (update-contacts! (fn [cs]
+                      (vec (remove #(= % c) cs)))
+                    c))

 ;; The next three fuctions are copy/pasted verbatim from the Om tutorial
 (defn middle-name [{:keys [middle middle-initial]}]


Better handling when shortening the label

I was shortening it only if the title was empty, but it's possible that
the title is the same as the URL for whatever reason (the page was
done to report that way). Changing comparison.

--- src/ui/relevance/display.cljs
+++ src/ui/relevance/display.cljs
@@ -212,7 +212,7 @@
                 label   (if (empty? title)
                           url
                           title)
-                display (if (and (empty? title)
+                display (if (and (= url label)
                                  (< 80 (count label)))
                           (apply str (concat (take 80 label) "..."))
                           label)


Handles 429 for all HTTP requests, fixes #5.

--- src/fr/tedoldi/lichess/game/retriever/lichess.clj
+++ src/fr/tedoldi/lichess/game/retriever/lichess.clj
@@ -21,11 +21,33 @@
 (def ^:private nice-downloader-waiting-time 1000)
 (def ^:private even-nicer-downloader-waiting-time 120000)

+
+(defn http-get [url options]
+  (try
+
+    (client/get url options)
+
+    (catch Exception e
+      (if (= 429 (:status (ex-data e)))
+        (do
+          (-> (str "Lichess is rate-limiting us, waiting "
+                   (/ even-nicer-downloader-waiting-time
+                      1000)
+                   "s...\n")
+              color/cyan
+              console/print-err)
+          (Thread/sleep even-nicer-downloader-waiting-time)
+          (http-get url options))
+
+        ; else
+        (throw e)))))
+
 (defn username->user [url username user-agent]
   (let [url (str url "/user/" username)]
     (try
       (-> url
-          (client/get {:client-params {"http.useragent" user-agent}})
+          (http-get
+            {:client-params {"http.useragent" user-agent}})

           :body

@@ -49,14 +71,15 @@

   (try
     (-> url
-        (client/get {:client-params {"http.useragent" user-agent}
-                     :query-params
-                     {:nb             max-per-page
-                      :page           (inc page)
-                      :with_moves     1
-                      :with_movetimes 1
-                      :with_opening   1
-                      :with_analysis  1}})
+        (http-get
+          {:client-params {"http.useragent" user-agent}
+           :query-params
+           {:nb             max-per-page
+            :page           (inc page)
+            :with_moves     1
+            :with_movetimes 1
+            :with_opening   1
+            :with_analysis  1}})

         :body

@@ -84,10 +107,11 @@
         url          (str url "/user/" username "/games")

         nb-results   (-> url
-                         (client/get {:client-params {"http.useragent" user-agent}
-                                      :query-params
-                                      {:nb   1
-                                       :page 1}})
+                         (http-get
+                           {:client-params {"http.useragent" user-agent}
+                            :query-params
+                            {:nb   1
+                             :page 1}})

                          :body


Fix tests broken after CMR-1134 commit

Fix tests broken after CMR-1134 commit

--- system-int-test/test/cmr/system_int_test/search/acls/collection_acl_search_test.clj
+++ system-int-test/test/cmr/system_int_test/search/acls/collection_acl_search_test.clj
@@ -164,16 +164,16 @@
     (testing "opendata ACL enforcement"
       (testing "all items"
         (let [coll-od (:results (od/collections->expected-opendata guest-permitted-collections))]
-          (is (= coll-od (set (:results (search/find-concepts-opendata :collection {:token guest-token
-                                                                                :page-size 100})))))))
+          (is (= coll-od (:results (search/find-concepts-opendata :collection {:token guest-token
+                                                                                :page-size 100}))))))

       (testing "by concept id"
         (let [concept-ids (map :concept-id all-colls)
               coll-od (:results (od/collections->expected-opendata guest-permitted-collections))]
-          (is (= coll-od (set (:results (search/find-concepts-opendata :collection
+          (is (= coll-od (:results (search/find-concepts-opendata :collection
                                                                        {:token guest-token
                                                                         :page-size 100
-                                                                        :concept-id concept-ids}))))))))))
+                                                                        :concept-id concept-ids})))))))))

 ;; This tests that when acls change after collections have been indexed that collections will be
 ;; reindexed when ingest detects the acl hash has change.


State.

State.

--- test/com/nomistech/clojure_the_language/c_400_state_and_concurrency/s_020_atoms.clj
+++ test/com/nomistech/clojure_the_language/c_400_state_and_concurrency/s_020_atoms.clj
@@ -52,7 +52,10 @@
 ;;;; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 ;;;; Storing maps in atoms

-;;;; Something about films
+;;;; When we have maps in atoms, we use functions like `assoc`, `assoc-in` and
+;;;; `update` for the data function.
+
+;;;; Something about films:

 (def jaws-atom (atom {}))


Add comment

Add comment

--- dev/src/yada/dev/template.clj
+++ dev/src/yada/dev/template.clj
@@ -35,6 +35,9 @@
                          ;; specify the encoding and yada's
                          ;; representation logic takes care of the
                          ;; encoding.
+
+                         ;; TODO: Is this necessary? Doesn't yada
+                         ;; default to this anyway?
                          :charset charset/default-platform-charset}]

       ;; We can work out last-modified, iff model is not a function


Print to provided output stream in deprecated 'write-json'

Originally reported by Benjamin Teuber in a GitHub pull request:
https://github.com/clojure/data.json/pull/9

--- src/main/clojure/clojure/data/json_compat_0_1.clj
+++ src/main/clojure/clojure/data/json_compat_0_1.clj
@@ -37,7 +37,7 @@

   Print object to PrintWriter out as JSON"
   [x out escape-unicode?]
-  (write x *out* :escape-unicode escape-unicode?))
+  (write x out :escape-unicode escape-unicode?))

 (defn json-str
   "DEPRECATED; replaced by 'write-str'.


Update interpreter.clj

Update interpreter.clj

--- src/simple_symbolic_regression_clojure/interpreter.clj
+++ src/simple_symbolic_regression_clojure/interpreter.clj
@@ -75,4 +75,4 @@
     score-penalty))

 (defn total-score-on [script rubrics]
-  (future (reduce + (map (partial score-on script) rubrics))) (deref rubrics))
+  (reduce + (map (partial score-on script) rubrics)))


Clean up macro

Clean up macro

--- benchmarks/caesium/crypto/secretbox_benchmark.clj
+++ benchmarks/caesium/crypto/secretbox_benchmark.clj
@@ -11,15 +11,14 @@

 (defmacro bench-secretnonce
   [fs converter]
-  `(doseq [[size msg] (map (juxt identity (comp converter randombytes)) sizes)
-           f ~fs]
-     (let [rand-buf (comp converter randombytes)
-           key (rand-buf s/keybytes)
-           nonce (randbuf s/noncebytes)
-           out (randbuf (+ s/macbytes size))]
-       (println f (fmt-bytes size))
-       (spy (mapv type [out msg nonce key]))
-       (bench (f out msg nonce key)))))
+  (let [rand-buf `(comp ~converter ~randombytes)]
+    `(doseq [[size# msg#] (map (juxt identity ~rand-buf) sizes)
+             f# ~fs]
+       (let [key# (~rand-buf s/keybytes)
+             nonce# (~rand-buf s/noncebytes)
+             out# (~rand-buf (+ s/macbytes size#))]
+         (println f# (fmt-bytes size#) (mapv type [out# msg# nonce# key#]))
+         (bench (f out# msg# nonce# key#))))))

 (deftest ^:benchmark to-buf!-benchmarks
   (println "secretbox to-buf! with direct bufs, pre-allocation")


Take advantage of sanitize-name function.

--- src/afterglow/fixtures/blizzard.clj
+++ src/afterglow/fixtures/blizzard.clj
@@ -3,7 +3,8 @@
   Lighting](http://www.blizzardlighting.com)."
   {:doc/format :markdown}
   (:require [afterglow.channels :as chan]
-            [afterglow.effects.channel :refer [function-value-scaler]]))
+            [afterglow.effects.channel :refer [function-value-scaler]]
+            [afterglow.fixtures.qxf :refer [sanitize-name]]))

 (defn- build-gobo-entries
   "Create a series of function map entries describing the gobos
@@ -18,9 +19,7 @@
   [moving? shake? names]
   (map (fn [entry]
          (let [prefix (str "gobo-" (if moving? "moving-" "fixed-"))
-               type-key (keyword
-                         (str prefix (clojure.string/lower-case (clojure.string/replace entry #"[^a-zA-Z0-9]" "-"))
-                              (when shake? "-shake")))
+               type-key (keyword (sanitize-name (str prefix entry (when shake? " shake"))))
                label (str "Gobo" (when moving? "M") " " entry (when shake? " shake"))]
            (merge {:type type-key
                    :label label


Shore up state-set

Shore up state-set

--- src/angelic/hierarchy/state_set.clj
+++ src/angelic/hierarchy/state_set.clj
@@ -29,7 +29,7 @@
 ;; TODO:Note: we have to be really careful about OOC-effects here.
 ;; for now, we can just require that these be unconditional.
 ;; If we add unions, etc later, worry about details.
-
+;; TODO: constraint is not the same as set-vars ?  ???

 ;(def no-effect ::no-effect)

@@ -110,6 +110,7 @@

 (defn make-logging-factored-state-set [lfss]
   (assert (apply = (map state/current-context lfss)))
+  (assert (apply = (map (comp keys state/ooc-effects) lfss)))
   (assert (apply = (map meta lfss)))
   (if (clojure.core/empty? lfss) empty-lfss
       (let [effect-vars (set (apply concat (map (comp keys state/extract-effects) lfss)))


Fix casing of constant

Fix casing of constant

--- src/asciinema/player/asciicast.cljs
+++ src/asciinema/player/asciicast.cljs
@@ -9,7 +9,7 @@
             [asciinema.vt.screen :as screen]
             [clojure.string :as str]))

-(def format_error "only asciicast v1 and v2 formats can be opened")
+(def format-error "only asciicast v1 and v2 formats can be opened")

 (defn parse-json [json]
   (-> json js/JSON.parse (js->clj :keywordize-keys true)))
@@ -47,7 +47,7 @@
         (sequential? thing) (load-from-seq thing vt-width vt-height)
         (map? thing) (load-from-map thing vt-width vt-height)
         :else nil)
-      (throw format_error)))
+      (throw format-error)))

 (defn- vt-lines [vt]
   (-> vt :screen screen/lines))


Add new router impl with ad-hoc error handler.

--- src/uxbox/frontend/routes.clj
+++ src/uxbox/frontend/routes.clj
@@ -9,10 +9,11 @@
             [catacumba.http :as http]
             [catacumba.serializers :as sz]
             [catacumba.handlers.auth :as cauth]
-            [catacumba.handlers.postal :as pc]
+            [catacumba.handlers.parse :as cparse]
+            [catacumba.handlers.misc :as cmisc]
             [uxbox.services.auth :as auth]
-            [uxbox.frontend.core :refer (-handler)]
-            [uxbox.frontend.auth]))
+            [uxbox.frontend.core :as ufc]
+            [uxbox.frontend.auth :as ufa]))

 (defn- welcome-api
   "A GET entry point for the api that shows
@@ -27,13 +28,28 @@
   [context]
   (http/see-other "/api"))

+(defn- error-handler
+  [context err]
+  (if (instance? clojure.lang.ExceptionInfo err)
+    (let [message (.getMessage err)
+          data (ex-data err)]
+      (-> (ufc/rsp {:message message
+                    :payload data})
+          (http/bad-request)))
+    (let [message (.getMessage err)]
+      (-> (ufc/rsp {:message message})
+          (http/internal-server-error)))))
+
 (defn app
   []
   (let [props {:secret auth/secret
                :options auth/+auth-opts+}
         backend (cauth/jwe-backend props)]
     (ct/routes [[:any (cauth/auth backend)]
-                [:get "api" welcome-api]
-                [:put "api" (pc/router -handler)]
-                [:get "" redirect-to-api]])))
-
+                [:any (cmisc/autoreloader)]
+                [:prefix "api"
+                 [:any (cparse/body-params)]
+                 [:error #'error-handler]
+                 [:post "auth/token" #'ufa/login]
+                 [:get "" #'welcome-api]]
+                [:get "" #'redirect-to-api]])))


change default language settings again

change default language settings again

closure produces very weird results when using the built-in
defaults. guess we'll need to switch to using output feature sets.

--- src/main/shadow/build/api.clj
+++ src/main/shadow/build/api.clj
@@ -64,7 +64,8 @@
    :elide-asserts false
    :closure-configurators []
    :infer-externs true
-   :language-in :ecmascript6
+   :language-in :ecmascript-next
+   :language-out :ecmascript5

    :closure-warnings
    {:check-types :off}


fix JS resolve to global support

fix JS resolve to global support

--- src/main/shadow/build/npm.clj
+++ src/main/shadow/build/npm.clj
@@ -401,7 +401,7 @@

    means require(\"react\") returns the global React instance"
   [require {:keys [global] :as pkg}]
-  (let [ns (ModuleNames/fileToModuleName require)]
+  (let [ns (symbol (ModuleNames/fileToModuleName require))]
     {:resource-id [::global require]
      :resource-name (str "global$" ns ".js")
      :output-name (str ns ".js")


fix REPL ns bug

fix REPL ns bug

--- src/main/shadow/cljs/repl.clj
+++ src/main/shadow/cljs/repl.clj
@@ -32,7 +32,6 @@
 (defn repl-state? [x]
   (and (map? x) (::repl-state x)))

-
 (defn make-repl-resource* [ns ns-form]
   (let [resource-name
         (util/ns->cljs-filename ns)
@@ -40,7 +39,7 @@
         output-name
         (util/flat-js-name resource-name)]

-    {:resource-id [::resource name]
+    {:resource-id [::resource resource-name]
      :resource-name resource-name
      :output-name output-name
      :type :cljs


include other_names in /integration/search-exact

--- src/wb_es/web/integration.clj
+++ src/wb_es/web/integration.clj
@@ -6,6 +6,7 @@
      :class (clojure.string/replace (get-in doc [:_source :page_type]) "-" "_")
      :label (or (:label doc-source)
                 (:wbid doc-source))
+     :other_names (:other_names doc-source)
      :taxonomy (get-in doc-source [:species :key])}))

 (defn- pack-species [species-name]


Added title and link for pulse cards with error

--- src/metabase/pulse/render.clj
+++ src/metabase/pulse/render.clj
@@ -396,48 +396,55 @@
            (number-field? col-2))                                  :bar
       :else                                                        :table)))

+(defn render-pulse-card-container
+  [card content]
+  [:a {:href   (card-href card)
+       :target "_blank"
+       :style  (style section-style
+                      {:margin          :16px
+                       :margin-bottom   :16px
+                       :display         :block
+                       :text-decoration :none})}
+   (when *include-title*
+     [:table {:style (style {:margin-bottom :8px
+                             :width         :100%})}
+      [:tbody
+       [:tr
+        [:td [:span {:style header-style}
+              (-> card :name h)]]
+        [:td {:style (style {:text-align :right})}
+         (when *include-buttons*
+           [:img {:style (style {:width :16px})
+                  :width 16
+                  :src   (render-image-with-filename "frontend_client/app/img/external_link.png")}])]]]])
+    content])
+
 (defn render-pulse-card
   "Render a single CARD for a `Pulse`. RESULT is the QP results."
   [card {:keys [data error]}]
   (try
     (when error
       (throw (Exception. (str "Card has errors: " error))))
-    [:a {:href   (card-href card)
-         :target "_blank"
-         :style  (style section-style
-                        {:margin          :16px
-                         :margin-bottom   :16px
-                         :display         :block
-                         :text-decoration :none})}
-     (when *include-title*
-       [:table {:style (style {:margin-bottom :8px
-                               :width         :100%})}
-        [:tbody
-         [:tr
-          [:td [:span {:style header-style}
-                (-> card :name h)]]
-          [:td {:style (style {:text-align :right})}
-           (when *include-buttons*
-             [:img {:style (style {:width :16px})
-                    :width 16
-                    :src   (render-image-with-filename "frontend_client/app/img/external_link.png")}])]]]])
-     (case (detect-pulse-card-type card data)
-       :empty     (render:empty     card data)
-       :scalar    (render:scalar    card data)
-       :sparkline (render:sparkline card data)
-       :bar       (render:bar       card data)
-       :table     (render:table     card data)
-       [:div {:style (style font-style
-                            {:color       "#F9D45C"
-                             :font-weight 700})}
-        "We were unable to display this card." [:br] "Please view this card in Metabase."])]
+    (let [content (case (detect-pulse-card-type card data)
+                    :empty     (render:empty     card data)
+                    :scalar    (render:scalar    card data)
+                    :sparkline (render:sparkline card data)
+                    :bar       (render:bar       card data)
+                    :table     (render:table     card data)
+                    [:div {:style (style font-style
+                                         {:color       "#F9D45C"
+                                          :font-weight 700})}
+                     "We were unable to display this card." [:br] "Please view this card in Metabase."])]
+      (render-pulse-card-container card content))
     (catch Throwable e
       (log/warn "Pulse card render error:" e)
-      [:div {:style (style font-style
-                           {:color       "#EF8C8C"
-                            :font-weight 700
-                            :padding     :16px})}
-       "An error occurred while displaying this card."])))
+      (let [content [:div {:style (style font-style
+                                         {:color       "#EF8C8C"
+                                          :font-weight 700
+                                          :padding     :16px})}
+                     "An error occurred while displaying this card."]]
+        (render-pulse-card-container card content)))))
+

 (defn render-pulse-section


Add atom link

Add atom link

--- src/odinodinstatic/layout.clj
+++ src/odinodinstatic/layout.clj
@@ -10,19 +10,21 @@
      [:meta {:name    "viewport"
              :content "width=device-width, initial-scale=1.0"}]
      [:title "Odin odin blog"]
-     [:link {:rel "stylesheet" :href "/css/responsive.css"}]]
+     [:link {:rel "stylesheet" :href "/css/responsive.css"}]
      [:link {:rel "shortcut icon" :type "image/png" :href "favicon.ico"}]
+     [:link {:rel "alternate" :type "application/atom+xml" :href "/atom.xml" :title "Odinodin blog"}]]
+
     [:body
      [:script (slurp (io/resource "public/scripts/analytics.js"))]
      [:div {:id "main" :class "vertical-list"}
       [:div {:class "navbar flex-item"}
        [:div {:class "title"} "Odin"]
        [:a {:class "nav-item"
-            :href "/"} "Posts"]
+            :href  "/"} "Posts"]
        [:a {:class "nav-item"
-            :href "/about/"} "About"]
+            :href  "/about/"} "About"]
        [:a {:class "nav-item ender"
-            :href "http://github.com/odinodin/odinodinstatic"} "Source"]]
+            :href  "http://github.com/odinodin/odinodinstatic"} "Source"]]
       [:div.content {:class "flex-item"} page]
       [:div {:id "bottom" :class "flex-item horizontal-list"}
        (link-to {:class "bottom-box"} "http://www.kodemaker.no/cv/odin/" "CV")


Don't return full store val when setting - as it floods the repo

--- src/overtone/config/store.clj
+++ src/overtone/config/store.clj
@@ -39,7 +39,8 @@
 (defn config-set!
   "Set config key to val"
   [key val]
-  (file-store-set! live-config key val))
+  (file-store-set! live-config key val)
+  (str "set " key))

 (defn store-get
   "Get config value. Returns default if specified and the config does
@@ -50,7 +51,8 @@
 (defn store-set!
   "Set store key to val"
   [key val]
-  (file-store-set! live-store key val))
+  (file-store-set! live-store key val)
+  (str "set " key))

 (defn config
   "Get the full config map"


Enforce order of SS children output to match sequence specification

--- src/vip/data_processor/output/street_segments.clj
+++ src/vip/data_processor/output/street_segments.clj
@@ -20,21 +20,24 @@
     (.add writer (.createCharacters event-factory el-content))
     (.add writer (.createEndElement event-factory "" nil el-name))))

+(def ss-ordered-fields
+  [[:address_direction "AddressDirection"]
+   [:city "City"]
+   [:includes_all_addresses "IncludesAllAddresses"]
+   [:includes_all_streets "IncludesAllStreets"]
+   [:odd_even_both "OddEvenBoth"]
+   [:precinct_id "PrecinctId"]
+   [:start_house_number "StartHouseNumber"]
+   [:end_house_number "EndHouseNumber"]
+   [:state "State"]
+   [:street_direction "StreetDirection"]
+   [:street_name "StreetName"]
+   [:street_suffix "StreetSuffix"]
+   [:unit_number "UnitNumber"]
+   [:zip "Zip"]])
+
 (def ss-fields
-  {:address_direction "AddressDirection"
-   :city "City"
-   :includes_all_addresses "IncludesAllAddresses"
-   :includes_all_streets "IncludesAllStreets"
-   :odd_even_both "OddEvenBoth"
-   :precinct_id "PrecinctId"
-   :start_house_number "StartHouseNumber"
-   :end_house_number "EndHouseNumber"
-   :state "State"
-   :street_direction "StreetDirection"
-   :street_name "StreetName"
-   :street_suffix "StreetSuffix"
-   :unit_number "UnitNumber"
-   :zip "Zip"})
+  (into {} ss-ordered-fields))

 (defn validate-required-field!
   [ctx {:keys [id] :as street-segment-entry} field-key]
@@ -103,7 +106,7 @@
           (validate-street-segment! ctx line' precinct-ids)
           (.add writer (.createStartElement event-factory "" nil "StreetSegment"))
           (.add writer (.createAttribute event-factory "id" (:id line')))
-          (doseq [[ss-key ss-name] ss-fields]
+          (doseq [[ss-key ss-name] ss-ordered-fields]
             (add-element event-factory writer ss-name (ss-key line')))
           (.add writer (.createEndElement event-factory "" nil "StreetSegment")))))))


Fingerprint css / js

Fingerprint css / js

--- src/clj/clojuredocs/site/common.clj
+++ src/clj/clojuredocs/site/common.clj
@@ -45,14 +45,32 @@
        [:div.col-md-10.col-md-offset-1
         [:div.ac-results-widget]]])]])

+(def clojuredocs-script
+  [:script {:src (str "/cljs/clojuredocs.js?"
+                      (util/md5 "resources/public/cljs/clojuredocs.js"))}])
+
+(def app-link
+  [:link {:rel :stylesheet
+          :href (str "/css/app.css?"
+                     (util/md5 "resources/public/css/app.css"))}])
+
+(def bootstrap-link
+  [:link {:rel :stylesheet
+          :href (str "/css/bootstrap.min.css?"
+                     (util/md5 "resources/public/css/bootstrap.min.css"))}])
+
+(def font-awesome-link
+  [:link {:rel :stylesheet :href (str "/css/font-awesome.min.css?"
+                                      (util/md5 "resources/public/css/font-awesome.min.css"))}])
+
 (defn $main [{:keys [content title body-class user page-data] :as opts}]
   [:html5
    [:head
     [:meta {:name "viewport" :content "width=device-width, maximum-scale=1.0"}]
     [:title (or title "Community-Powered Clojure Documentation and Examples | ClojureDocs")]
-    [:link {:rel :stylesheet :href "/css/font-awesome.min.css"}]
-    [:link {:rel :stylesheet :href "/css/bootstrap.min.css"}]
-    [:link {:rel :stylesheet :href "/css/app.css"}]
+    font-awesome-link
+    bootstrap-link
+    app-link
     [:script "window.PAGE_DATA=" (util/to-json (pr-str page-data)) ";"]]
    [:body
     (when body-class
@@ -69,7 +87,7 @@
      [:div.sticky-push]]
     [:footer
      [:div.divider
-      "⤜ ❦ ⤛"]
+      "- ❦ -"]
      [:div.ctas
       "Brought to you by "
       [:a {:href "https://twitter.com/heyzk"} "@heyzk"]
@@ -100,7 +118,7 @@
       [:script {:src "/js/react.js"}])
     (when (env/bool :cljs-dev)
       [:script {:src "/cljs/goog/base.js"}])
-    [:script {:src "/cljs/clojuredocs.js"}]
+    clojuredocs-script
     (when (env/bool :cljs-dev)
       [:script "goog.require(\"clojuredocs.main\");"])]])


Fix env config setting of server-port setting

--- src/clj/comic_reader/config/env.clj
+++ src/clj/comic_reader/config/env.clj
@@ -3,10 +3,16 @@
             [comic-reader.config :as config]
             [environ.core :refer [env]]))

+(defn- env-key-and-key [key-or-vec]
+  (if (vector? key-or-vec)
+    key-or-vec
+    [key-or-vec key-or-vec]))
+
 (defn- assoc-env [cfg key]
-  (if-let [val (env key)]
-    (assoc cfg key val)
-    cfg))
+  (let [[env-key key] (env-key-and-key key)]
+   (if-let [val (env env-key)]
+     (assoc cfg key val)
+     cfg)))

 (defrecord EnvConfig [database-uri norms-dir server-port]
   component/Lifecycle
@@ -15,7 +21,7 @@
     (println "Comic-Reader: Loading configuration...")
     (reduce assoc-env component [:database-uri
                                  :norms-dir
-                                 :server-port]))
+                                 [:port :server-port]]))

   (stop [component]
     component)


fixes off-by-one date discrepancy in edit schedule form

--- src/cljs/early_vote_site/utils.cljs
+++ src/cljs/early_vote_site/utils.cljs
@@ -10,20 +10,20 @@
   "Translates from a long date string format (ie 2017-10-10T13:23:34.00Z)
    to a short format (2017-10-10)."
   [date-str]
-  (let [parsed (format/parse full-format date-str)]
-    (format/unparse short-format parsed)))
+  (let [parsed (format/parse-local full-format date-str)]
+    (format/unparse-local short-format parsed)))

 (defn format-date
   "Translates from a js date object
    to a short format (2017-10-10)."
   [date]
   (let [coerced (coerce/from-date date)]
-    (format/unparse short-format coerced)))
+    (format/unparse-local short-format coerced)))

 (defn parse-date
-  "Translates a full state string into a js/Date"
+  "Translates a full date string into a js/Date"
   [date-str]
-  (let [parsed (format/parse full-format date-str)]
+  (let [parsed (format/parse-local full-format date-str)]
     (coerce/to-date parsed)))

 (defn flash-error-with-results
@@ -36,13 +36,13 @@
   [schedule]
   (str
     (->> (:start-date schedule)
-      (format/parse full-format)
-      (format/unparse (format/formatter "MM-dd")))
+      (format/parse-local full-format)
+      (format/unparse-local (format/formatter "MM-dd")))
     " - "
     (->> (:end-date schedule)
-      (format/parse full-format)
-      (format/unparse (format/formatter "MM-dd")))
-    " "
-    (:start-time schedule)
+      (format/parse-local full-format)
+      (format/unparse-local (format/formatter "MM-dd")))
+    ", "
+    (military-to-standard (:start-time schedule))
     " - "
     (:end-time schedule)))


Updated last instance of render-pulse-card

--- src/metabase/pulse.clj
+++ src/metabase/pulse.clj
@@ -45,8 +45,8 @@
   "Create an attachment in Slack for a given Card by rendering its result into an image and uploading it."
   [card-results]
   (when-let [{channel-id :id} (slack/get-or-create-files-channel!)]
-    (doall (for [{{card-id :id, card-name :name, :as card} :card, {:keys [data]} :result} card-results]
-             (let [image-byte-array (render/render-pulse-card-to-png card data)
+    (doall (for [{{card-id :id, card-name :name, :as card} :card, result :result} card-results]
+             (let [image-byte-array (render/render-pulse-card-to-png card result)
                    slack-file-url   (slack/upload-file! image-byte-array "image.png" channel-id)]
                {:title      card-name
                 :title_link (urls/card-url card-id)


Refactor visit map generation in database tests

--- test/clj/coffee_table/component/database_test.clj
+++ test/clj/coffee_table/component/database_test.clj
@@ -25,36 +25,16 @@

 (deftest test-create-visit
   (let [db (:db cts/*system*)
-        visit-params {:cafe_name "Test Café"
-                      :visit_date (java-time/sql-date)
-                      :beverage_ordered "Espresso"
-                      :beverage_rating 3}
+        visit-params (m/make-visit "Test Cafe" (java-time/sql-date) "Espresso" 5)
         visit-id (sut/insert-visit! db visit-params)]
-    (is (= {:id visit-id
-            :cafe_name (:cafe_name visit-params)
-            :visit_date (:visit_date visit-params)
-            :beverage_ordered (:beverage_ordered visit-params)
-            :beverage_rating (:beverage_rating visit-params)
-            :machine nil
-            :grinder nil
-            :roast nil
-            :beverage_notes nil
-            :service_rating nil
-            :service_notes nil
-            :ambience_rating nil
-            :ambience_notes nil
-            :other_notes nil}
+    (is (= (assoc visit-params :id visit-id)
            (sut/get-visit db visit-id)))))

 (deftest test-remove-visit
   (let [db (:db cts/*system*)
-        visit-params {:cafe_name "Test Cafe"
-                      :visit_date (java-time/sql-date)
-                      :beverage_ordered "Espresso"
-                      :beverage_rating 5}
+        visit-params (m/make-visit "Test Cafe" (java-time/sql-date) "Espresso" 5)
         visit-id (sut/insert-visit! db visit-params)
         rows-removed (sut/delete-visit-by-id! db visit-id)]
-    (is (= rows-removed 1))
     (is (nil? (sut/get-visit db visit-id)))))

 (deftest test-update-visit


fix typo

fix typo

--- test/clj/modern_cljs/shopping/validators_test.clj
+++ test/clj/modern_cljs/shopping/validators_test.clj
@@ -18,7 +18,7 @@
            "Price can't be empty"
            (first (:price (validate-shopping-form "1" "" "0" "0")))

-           "Tax can't be emmpty"
+           "Tax can't be empty"
            (first (:tax (validate-shopping-form "1" "0" "" "0")))

            "Discount can't be empty"
@@ -33,10 +33,10 @@
            (first (:quantity (validate-shopping-form "1.1" "0" "0" "0")))

            "Price has to be a number"
-           (first (:quantity (validate-shopping-form "1" "foo" "0" "0")))
+           (first (:price (validate-shopping-form "1" "foo" "0" "0")))

            "Tax has to be a number"
-           (first (:tax (validate-shopping-form "1" "0" "0" "foo" "0")))
+           (first (:tax (validate-shopping-form "1" "0" "foo" "0")))

            "Discount has to be a number"
            (first (:discount (validate-shopping-form "1" "0" "0" "foo")))))


Fix tests

Fix tests

--- test/clojure/clojurewerkz/cassaforte/cql_test.clj
+++ test/clojure/clojurewerkz/cassaforte/cql_test.clj
@@ -10,6 +10,7 @@
             [clj-time.core                       :refer [seconds ago before? date-time] :as tc]

             [clojurewerkz.cassaforte.cql         :refer :all]
+            [clojurewerkz.cassaforte.query       :as query]
             [clojure.test                        :refer :all]))

@@ -446,7 +447,7 @@
 (deftest test-insert-with-forced-prepared-statements
   (let [r        {:name "Alex" :city "Munich" :age (int 19)}
         prepared (client/prepare *session*
-                                 (insert :users
+                                 (query/insert :users
                                                {:name ?
                                                 :city ?
                                                 :age  ?}))]
@@ -486,11 +487,11 @@

 (deftest test-insert-with-atomic-batch-without-prepared-statements
   (client/execute *session*
-                  (unlogged-batch
-                   (queries
-                    (insert :users
+                  (query/unlogged-batch
+                   (query/queries
+                    (query/insert :users
                                   {:name "Alex" :city "Munich" :age (int 19)})
-                    (insert :users
+                    (query/insert :users
                                   {:name "Fritz" :city "Hamburg" :age (int 28)}))))
   (is (= [{:name "Alex" :city "Munich" :age (int 19)}
           {:name "Fritz" :city "Hamburg" :age (int 28)}]


tweaked the regexs so that they now are less greedy and more possessive


Eliminate reflection

Eliminate reflection

--- src/play_clj/utils.clj
+++ src/play_clj/utils.clj
@@ -25,4 +25,4 @@

 (defn gdx-into-array
   [a]
-  (-> a into-array Array.))
+  (Array. true (into-array a) 1 (count a)))


[scamp] Re-order args to 'send-msg-new-upstream-node for consistency

--- modules/scamp/src/scamp/core.clj
+++ modules/scamp/src/scamp/core.clj
@@ -246,8 +246,8 @@
   "Take a new 'upstream-node-contact-address and a 'node, and return
   an :new-upstream-node message envelope for
   'upstream-node-contact-address."
-  [node :- NetworkedNodeSchema
-   upstream-node-contact-address :- NodeContactAddressSchema]
+  [upstream-node-contact-address :- NodeContactAddressSchema
+   node :- NetworkedNodeSchema]
   [:message-envelope
    upstream-node-contact-address
    :new-upstream-node
@@ -275,7 +275,7 @@
            ;; so check the probability that we add it to this node.
            (do-probability (subscription-acceptance-probability downstream)))
     [(update-in node [:downstream] conj subscriber-contact-address)
-     [(send-msg-new-upstream-node node subscriber-contact-address)]]
+     [(send-msg-new-upstream-node subscriber-contact-address node)]]

     (let [forwarded-subscription-messages (forward-subscription downstream
                                                                 subscriber-contact-address


terraform_remote_state is not referred to as data

--- src/terraboot/core.clj
+++ src/terraboot/core.clj
@@ -24,6 +24,11 @@
 (defn arn-of [type name]
   (output-of type name "arn"))

+(defn data
+  [type name spec]
+  {:data
+   {type
+    {name spec}}})
 (defn resource
   ([type name spec]
    {:resource
@@ -419,14 +424,14 @@
    "sa-east-1"      "s3-sa-east-1.amazonaws.com"})

 (defn remote-state [region bucket profile name]
-  (resource "terraform_remote_state" name
-            {:backend "s3"
-             :config {:bucket bucket
-                      :profile profile
-                      :encrypt true
-                      :key (str name ".tfstate")
-                      :region region
-                      :endpoint (get s3-endpoints region)}}))
+  (data "terraform_remote_state" name
+        {:backend "s3"
+         :config {:bucket bucket
+                  :profile profile
+                  :encrypt true
+                  :key (str name ".tfstate")
+                  :region region
+                  :endpoint (get s3-endpoints region)}}))

 (defn remote-output-of [module name]
-  (output-of "terraform_remote_state" module name))
+  (clojure.string/join "." ["data"  "terraform_remote_state" module name]))


update phrases

update phrases

--- src/thingybot/core.clj
+++ src/thingybot/core.clj
@@ -35,8 +35,8 @@
    #"\bit\b" "'t"
    #"\b(it's|it is|this is)\b" "'tis"
    #"\bnot\b" "nay"
-   #"should\b" ["must" "shalt"]
-   #"shouldn't\b" ["mustn't" "shan't"]
+   #"\b(should|must)\b" "shalt"
+   #"\b(shouldn't|mustn't)\b" "shan't"
    #"\buntil\b" "'til"
    #"\bright\b" "true"
    #"\bbye\b" ["fare thee well" "be blessed"]


specific gender of subject needed for test

--- test/babel/test/fr.clj
+++ test/babel/test/fr.clj
@@ -78,6 +78,7 @@
               :français "nous"},
           :b {:b {:future-stem "ir",
                   :agr {:number :plur,
+                        :gender :fem
                         :person :1st},
                   :present {:3plur "vont",
                             :2plur "allez",


Fix out of bound index on batch

Fix out of bound index on batch

--- src/com/wsscode/pathom/connect.cljc
+++ src/com/wsscode/pathom/connect.cljc
@@ -617,7 +617,8 @@

                 linked-results (zipmap items (mapv vector channels batch-result))]

-            (if-not (= ::p/reader-error (first batch-result))
+            (if (and (not= ::p/reader-error (first batch-result))
+                     (>= (count path) 2))
               (swap! entity-path-cache
                 (fn entity-path-swap [cache]
                   (let [path (subvec path 0 (- (count path) 2))]


added stats back

added stats back

--- core/src/samsara_core/kernel2.clj
+++ core/src/samsara_core/kernel2.clj
@@ -1,16 +1,15 @@
 (ns samsara-core.kernel2
   (:refer-clojure :exclude [var-get var-set])
+  (:require [samsara.trackit :refer [track-time track-rate new-registry
+                                     count-tracker distribution-tracker
+                                     track-pass-count] :as trk])
   (:require [clojure.string :as str]
             [com.stuartsierra.component :as component]
             [moebius
-             [core :refer [where inject-if]]
+             [core :refer [inject-if where]]
              [kv :as kv]]
-            [samsara.utils :refer [from-json to-json]]
-            [taoensso.timbre :as log])
-  (:require [samsara.trackit :refer [track-time track-rate new-registry
-                                     count-tracker distribution-tracker
-                                     track-pass-count] :as trk]))
-
+            [samsara.utils :refer [from-json invariant to-json]]
+            [taoensso.timbre :as log]))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;                                                                            ;;
@@ -369,12 +368,36 @@
     (handler {:component component :stream-id stream-id :events values})))

+(defn pipeline-stats-wrapper [component stream-id pipeline]
+  (let [job-name (-> component :config :job :job-name)
+        prefix   (str "pipeline." job-name "." (name stream-id))
+        track-time-name2 (str prefix ".pipeline-processing.time")]
+    (fn [state events]
+      (track-time track-time-name2
+                  (pipeline state events)))))
+
+
+(defn stream-stats-wrapper [component stream-id handler]
+  (let [job-name (-> component :config :job :job-name)
+        prefix   (str "pipeline." job-name "." (name stream-id))
+        track-time-name (str prefix ".overall-processing.time")
+        total-size-in (count-tracker (str prefix ".in.total-size"))
+        dist-size-in (distribution-tracker (str prefix ".in.size"))
+        size-in-tracker (invariant #(let [sz (count %)]
+                                      (total-size-in sz)
+                                      (dist-size-in sz)))]
+    (fn [events]
+      (track-time track-time-name
+       (handler (map size-in-tracker events))))))
+
+
 (defn- standard-stream-wrappers
   [component stream-id handler]
   (let [{:keys [format input-partitions]} (stream-config component stream-id)]
     (->> handler
          (message-only-wrapper)
          (format-wrapper format)
+         (stream-stats-wrapper component stream-id)
          (partition-filter-wrapper input-partitions))))

@@ -434,8 +457,9 @@
        (component-stream-processor-wrapper component stream-id handler)

        :samsara-factory
-       (let [handler' (handler (:config component))]
-         (topic-process-wrapper component stream-id handler'))
+       (let [handler' (handler (:config component))
+             pipeline (pipeline-stats-wrapper component stream-id handler')]
+         (topic-process-wrapper component stream-id pipeline))

        :raw
        handler))))
@@ -530,7 +554,8 @@
            (trk/get-metric "events.all.counter"))
          :unknown)))))

-;; TODO: remove this
+
+;; TODO: remove this after kernel2 migration
 (defn events-counter-stats []
   (all-events-counter :current-value))

@@ -543,13 +568,33 @@
   (let [cmp (component/start (make-samsara-core config))]
     (alter-var-root #'*pipelines*
                     (constantly
-                     (fn [output-collector stream partition key message]
-                       (reset! (:output-collector cmp) output-collector)
-                       (process (:routes cmp) [{:topic stream
-                                                :partition partition
-                                                :key key
-                                                :message message}]))))
+                     (fn
+                       ([] cmp)
+                       ([output-collector stream partition key message]
+                        (reset! (:output-collector cmp) output-collector)
+                        (process (:routes cmp) [{:topic stream
+                                                 :partition partition
+                                                 :key key
+                                                 :message message}])))))
     cmp))
+
+
+
+;; TODO: this should use the stream-id instead
+(def output-collector-tracker
+  (memoize
+   (fn [job-name stream]
+     (let [prefix (str "pipeline." job-name "." stream)
+           total-size-out(count-tracker (str prefix ".out.total-size"))
+           dist-size-out (distribution-tracker (str prefix ".out.size"))
+
+           size-out-tracker (invariant #(let [sz (count (last %))]
+                                          (total-size-out sz)
+                                          (dist-size-out sz)))]
+       (fn [output-collector]
+         (fn [outputs]
+           (output-collector (map size-out-tracker outputs))))))))
+

 (defn process-dispatch
@@ -559,76 +604,20 @@
    is for the kv-store"
   [output-collector stream partition key message]

-  (all-events-counter)
-  (try
-    (*pipelines* output-collector stream partition key message)
-
-    ;;
-    ;; ERROR Handling
-    ;;
-    (catch Exception x
-      (log/warn x "Error processing message from [" stream "]:" message)
-      #_(track-rate (str "pipeline." (-> *config* :job :job-name) "." stream ".errors"))
-      (output-collector [[(str stream "-errors") key message]]))))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;                                                                            ;;
-;;                 ---==| * S C R A T C H   A R E A * |==----                 ;;
-;;                                                                            ;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-(comment
-  (def config (#'samsara-core.main/read-config "./config/config.edn"))
-  (def config (read-string (slurp "./config/config.edn")))
-
-
-  (normalize-streams-with-defaults config)
-
-  (def txlog
-    (doall
-     (->> (range 30)
-          (reduce (fn [kvs x]
-               (kv/set kvs
-                       (rand-nth ["d1" "d2" "d3"])
-                       (rand-nth [:k1 :k2 :k3])
-                       x))
-             (kv/make-in-memory-kvstore))
-          (kv/tx-log)
-          (map (fn [m] {:topic "vod-programme"
-                       :key   (first m)
-                       :partition 0
-                       :message (to-json m)})))))
-
-  (def ingest
-    (doall
-     (->> (repeatedly
-           (fn []
-             {:timestamp (System/currentTimeMillis)
-              :eventName "test"
-              :sourceId (rand-nth ["d1" "d2" "d3"])
-              :action (rand-int 100)}))
-          (take 10)
-          (map (fn [x]
-                 {:topic "ingestion"
-                  :key   (:sourceId x)
-                  :partition 0
-                  :message x}))
-          (map #(update % :message to-json)))))
-
-  (def events (concat txlog ingest))
-
-  (def cmp (component/start (make-samsara-core config)))
-  (reset! (:output-collector cmp) (fn [e] (doseq [x e] (prn "OUTPUT:" x)) ))
-
-  (build-routes cmp)
-
-  (build-routes-for-stream cmp :ingestion)
-
-  (-> cmp :global-stores)
-
-  (time ((dispatch-group-by
-          (build-routes cmp)) events))
-
-  )
+  (let [collector-tracker (output-collector-tracker
+                           (-> (*pipelines*) :config :job :job-name) stream)]
+
+    (all-events-counter)
+    (try
+
+      (*pipelines* (collector-tracker output-collector)
+                   stream partition key message)
+
+      ;;
+      ;; ERROR Handling
+      ;;
+      (catch Exception x
+        (log/warn x "Error processing message from [" stream "]:" message)
+        (track-rate (str "pipeline." (-> (*pipelines*) :config :job :job-name)
+                         "." stream ".errors"))
+        (output-collector [[(str stream "-errors") key message]])))))


fix timezone labels

fix timezone labels

--- priv/ui/src/holiday_ping_ui/channels/forms.cljs
+++ priv/ui/src/holiday_ping_ui/channels/forms.cljs
@@ -65,10 +65,10 @@
    {:value "-11:00" :text "(GMT -11:00) Midway Island, Samoa"}
    {:value "-10:00" :text "(GMT -10:00) Hawaii"}
    {:value "-09:00" :text "(GMT -9:00) Alaska"}
-   {:value "-08:00" :text "(GMT -8:00) Pacific Time (US & Canada)"}
-   {:value "-07:00" :text "(GMT -7:00) Mountain Time (US & Canada)"}
-   {:value "-06:00" :text "(GMT -6:00) Central Time (US & Canada), Mexico City"}
-   {:value "-05:00" :text "(GMT -5:00) Eastern Time (US & Canada), Bogota, Lima"}
+   {:value "-08:00" :text "(GMT -8:00) Pacific Time (US & Canada)"}
+   {:value "-07:00" :text "(GMT -7:00) Mountain Time (US & Canada)"}
+   {:value "-06:00" :text "(GMT -6:00) Central Time (US & Canada), Mexico City"}
+   {:value "-05:00" :text "(GMT -5:00) Eastern Time (US & Canada), Bogota, Lima"}
    {:value "-04:00" :text "(GMT -4:00) Atlantic Time (Canada), Caracas, La Paz"}
    {:value "-03:30" :text "(GMT -3:30) Newfoundland"}
    {:value "-03:00" :text "(GMT -3:00) Brazil, Buenos Aires, Georgetown"}


wow solution for gcd

wow solution for gcd

--- stuf/src/sandbox/4clojure.clj
+++ stuf/src/sandbox/4clojure.clj
@@ -258,6 +258,11 @@

 ;;66 Greatest Common Divisor
 (defn f[a b] (some #(if (every? integer? %) (first %)) (for [k (range (min a b) 0 -1)] [k (/ (min a b) k) (/ (max a b) k)])))
+;; wow solution
+;;#(loop [n % d %2]
+;;   (if (zero? d) n
+;;       (recur d (mod n d))))
+

 ;;67 Prime Numbers
 (defn f [k]


[Fix] fact -> facts

[Fix] fact -> facts

--- test/clj_elm/core_test.clj
+++ test/clj_elm/core_test.clj
@@ -42,7 +42,7 @@
     (count (make-ass 10 3)) => 3
     (count (first (make-ass 10 3))) => 10))

-(fact "test-make-bs"
+(facts "test-make-bs"
   (fact "(make-bs L)"
     (count (make-bs 3)) => 3))

@@ -52,11 +52,11 @@
     (filter #(> % 1.0) (map standard-sigmoid (take 10 (repeatedly #(rand 100)))))
     => []))

-(fact "test-a-hidden-layer-output"
+(facts "test-a-hidden-layer-output"
   (fact "(a-hidden-layer-output as_i b_i xs)"
     (a-hidden-layer-output [0 0 0] 0 [0 0 0]) => 0.5))

-(fact "test-hidden-layer-output-matrix"
+(facts "test-hidden-layer-output-matrix"
   (fact "(hidden-layer-output-matrix ass bs xss)"
     (hidden-layer-output-matrix
      [[0 0 0] [0 0 0] [0 0 0]]
@@ -74,11 +74,14 @@
         [0.5 0.5 0.5]
         [0.5 0.5 0.5]]))

+(facts "test-make-double-jarray"
+  (fact "(make-double-jarray array2h)"))
+
 (defn roundn [^Double x ^Integer n]
   (-> (BigDecimal. x)
       (.setScale n BigDecimal/ROUND_HALF_UP)))

-(fact "test-pseudo-inverse-matrix"
+(facts "test-pseudo-inverse-matrix"
   (fact "(pseudo-inverse-matrix mat)"
     (let [A [[2 0 0]
              [0 2 0]