Make place swapping on out of bounds moves faster

--- src/robinson/update.clj
+++ src/robinson/update.clj
@@ -179,7 +179,7 @@
        ;; manipulate state so that if there isn't a destination place, create one
        ;; save the current place to disk
        _                 (spit (format "save/%s.place.edn" orig-place-id)
-                               (with-out-str (pprint (-> state :world :places orig-place-id))))
+                               (prn-str (-> state :world :places orig-place-id)))

        dest-x             (case direction
                             (:left :up-left :down-left) (mod (dec x) width)


add service discovery middleware for /waiter-consent/* (#1621)

--- waiter/src/waiter/core.clj
+++ waiter/src/waiter/core.clj
@@ -2074,14 +2074,16 @@
                                               "x-waiter-auth-principal" (str principal)
                                               "x-waiter-auth-user" (str user)}
                                     :status http-200-ok}))))
-   :waiter-request-consent-handler-fn (pc/fnk [[:routines request->consent-service-id token->service-description-template]
+   :waiter-request-consent-handler-fn (pc/fnk [[:routines request->consent-service-id token->service-description-template wrap-service-discovery-fn]
                                                [:settings consent-expiry-days]
-                                               wrap-secure-request-fn]
-                                        (wrap-secure-request-fn
-                                          (fn waiter-request-consent-handler-fn [request]
-                                            (handler/request-consent-handler
-                                              token->service-description-template request->consent-service-id
-                                              consent-expiry-days request))))
+                                               wrap-ignore-disabled-auth-fn wrap-secure-request-fn]
+                                        (-> (fn waiter-request-consent-handler-fn [request]
+                                              (handler/request-consent-handler
+                                               token->service-description-template request->consent-service-id
+                                               consent-expiry-days request))
+                                            wrap-secure-request-fn
+                                            wrap-ignore-disabled-auth-fn
+                                            wrap-service-discovery-fn))
    :waiter-request-interstitial-handler-fn (pc/fnk [wrap-secure-request-fn]
                                              (wrap-secure-request-fn
                                                (fn waiter-request-interstitial-handler-fn [request]


fix renamed functions/variables post-refactoring

--- src/set_solver/core.clj
+++ src/set_solver/core.clj
@@ -110,12 +110,12 @@
           _ (Imgproc/drawContours mask card-contours -1 (Scalar. 0 0 0) -1)
           outside-color (Core/mean target mask)
           [outside-h outside-s outside-l] (scalar-to-hsl outside-color)
-          fill (cond (and (close-enough inside-l edge-l 5)
-                          (close-enough inside-h edge-h 5))
+          fill (cond (and (close-enough? inside-l edge-l 5)
+                          (close-enough? inside-h edge-h 5))
                      :filled
-                     (and (close-enough inside-l outside-l 5)
-                          (close-enough inside-h outside-h 30)
-                          (close-enough inside-s outside-s 5)) :empty
+                     (and (close-enough? inside-l outside-l 5)
+                          (close-enough? inside-h outside-h 30)
+                          (close-enough? inside-s outside-s 5)) :empty
                           :else :shaded)

           _ (let [m (-> (Core/mean target-gray) .val first (* 0.80))]
@@ -130,7 +130,7 @@
        :shape sname
        :color cname
        :fill fill
-       :contour c
+       :contour contour
        :bb br
        :image target})))

@@ -153,7 +153,7 @@
     (->> contours
          (filter #(< 250 (Imgproc/contourArea %)))
          (filter #(> 0.5 (match-shapes-i1 card-shape (contour-hu-invariants %))))
-         (filter is-rectangle)
+         (filter rectangle?)
          ;; eliminate overlapping contours
          (reduce (fn [cs c]
                    (if (some #(rect-close-enough? (Imgproc/boundingRect %) (Imgproc/boundingRect c)) cs)
@@ -241,7 +241,6 @@
   (q/fill 255)
   (q/text (str (select-keys (:mat-converter state) [:left :top :zoom])) 15 15)
   (q/text (str (round (q/current-frame-rate)) "/" (q/target-frame-rate)) 15 45)
-  (println "what")
   (doseq [c (:card-props state)
           :let [mc (:mat-converter state)]]

@@ -257,8 +256,7 @@
                (:left mc))
            (- (* (:zoom mc) (-> c :bb .tl .y))
                (:top mc))
-            ))
-  (q/fill (:color state) 255 255))
+            )))

 (q/defsketch hi
   :title "hi"


Modified database info

Modified database info

--- src-cljs/tea_time/core.cljs
+++ src-cljs/tea_time/core.cljs
@@ -30,7 +30,7 @@
           [:span.icon-bar]
           [:span.icon-bar]
           [:span.icon-bar]]
-         [:a.navbar-brand {:href "#/"} "tea-time"]]
+         [:a.navbar-brand {:href "#/"} "Tea Time"]]
         [:div.navbar-collapse.collapse
          (when-not @collapsed? {:class "in"})
          [:ul.nav.navbar-nav
@@ -41,12 +41,12 @@
   [:div.container
    [:div.row
     [:div.col-md-12
-     "this is the story of tea-time... work in progress"]]])
+     "this is the story of Tea Time... work in progress"]]])

 (defn home-page []
   [:div.container
    [:div.jumbotron
-    [:h1 "Welcome to tea-time"]
+    [:h1 "Welcome to Tea Time"]
     [:p "Time to start building your site!"]
     [:p [:a.btn.btn-primary.btn-lg {:href "http://luminusweb.net"} "Learn more »"]]]
    [:div.row


Add openings button to jumbotron too

Add openings button to jumbotron too

--- src-cljs/frontend/components/jobs.cljs
+++ src-cljs/frontend/components/jobs.cljs
@@ -22,15 +22,17 @@
         [:div.jumbotron
          common/language-background-jumbotron
          [:section.container
-          [:div.row
-           [:div.]
+          [:div.row.text-center
            [:article.hero-title.center-block
             [:div.text-center
              [:img.hero-logo {:src (utils/cdn-path "/img/outer/enterprise/logo-circleci.svg")}]]
             [:h1.text-center
              "Build amazing products"
              [:br]
-             "with a great team"]]]]]
+             "with a great team"]
+            [:a.btn.btn-cta
+             {:href ""}
+             "View openings"]]]]]
         [:div
          [:div.row.jobs-intro-wrapper
           [:div.col-sm-6.jobs-intro


Clean up desktop actions

Clean up desktop actions

--- desktop/src/nightweb_desktop/actions.clj
+++ desktop/src/nightweb_desktop/actions.clj
@@ -7,68 +7,105 @@
             [nightweb.users :as users]
             [nightweb-desktop.utils :as utils]))

+(defn save-profile
+  [params]
+  (-> (assoc params :pic-hash (-> (:pic-str params)
+                                  utils/decode-data-uri
+                                  io/write-pic-file))
+      actions/save-profile
+      deref)
+  nil)
+
+(defn import-user
+  [params]
+  (let [path (str @c/base-dir c/nw-dir c/slash c/user-zip-file)
+        file-barray (utils/decode-data-uri (:file-str params))]
+    (io/write-file path file-barray)
+    (-> (assoc params :source-str path)
+        actions/import-user
+        utils/get-string)))
+
+(defn export-user
+  [params]
+  (let [path (str @c/base-dir c/nw-dir c/slash c/user-zip-file)]
+    (actions/export-user (assoc params :dest-str path))))
+
+(defn new-post
+  [params]
+  (-> (assoc params
+             :pic-hashes (for [pic (edn/read-string (:pics-str params))]
+                           (-> (utils/decode-data-uri pic)
+                               io/write-pic-file))
+             :ptr-hash (f/base32-decode (:ptr-hash params))
+             :ptr-time (edn/read-string (:ptr-time params))
+             :status 1)
+      actions/new-post
+      deref)
+  nil)
+
+(defn edit-post
+  [params]
+  (-> (assoc params
+             :create-time (edn/read-string (:create-time params))
+             :ptr-hash (f/base32-decode (:ptr-hash params))
+             :ptr-time (edn/read-string (:ptr-time params))
+             :pic-hashes (for [pic (edn/read-string (:pic-hashes params))]
+                           (f/base32-decode pic))
+             :status 1)
+      actions/new-post
+      deref)
+  nil)
+
+(defn delete-post
+  [params]
+  (-> {:create-time (edn/read-string (:create-time params))
+       :status 0}
+      actions/new-post
+      deref)
+  nil)
+
+(defn switch-user
+  [params]
+  (-> (:userhash params)
+      f/base32-decode
+      users/load-user)
+  nil)
+
+(defn delete-user
+  [params]
+  (-> (:userhash params)
+      f/base32-decode
+      users/delete-user
+      deref)
+  nil)
+
+(defn create-user
+  [params]
+  (users/load-user (users/create-user))
+  (actions/fav-default-user)
+  nil)
+
+(defn toggle-fav
+  [params]
+  (-> (assoc params
+             :ptr-hash (f/base32-decode (:userhash params))
+             :ptr-time (edn/read-string (:time params)))
+      actions/toggle-fav
+      deref)
+  nil)
+
 (defn do-action
   [params]
-  (case (:type params)
-    "save-profile" (-> (assoc params :pic-hash (-> (:pic-str params)
-                                                   utils/decode-data-uri
-                                                   io/write-pic-file))
-                       actions/save-profile
-                       deref
-                       (do nil))
-    "import-user" (let [path (str @c/base-dir c/nw-dir c/slash c/user-zip-file)
-                        file-barray (utils/decode-data-uri (:file-str params))]
-                    (io/write-file path file-barray)
-                    (-> (assoc params :source-str path)
-                        actions/import-user
-                        utils/get-string))
-    "export-user" (let [path (str @c/base-dir c/nw-dir c/slash c/user-zip-file)]
-                    (actions/export-user (assoc params :dest-str path)))
-    "new-post" (-> (assoc params
-                          :pic-hashes (for [pic (-> (:pics-str params)
-                                                    edn/read-string)]
-                                        (-> pic
-                                            utils/decode-data-uri
-                                            io/write-pic-file))
-                          :ptr-hash (f/base32-decode (:ptr-hash params))
-                          :ptr-time (edn/read-string (:ptr-time params))
-                          :status 1)
-                   actions/new-post
-                   deref
-                   (do nil))
-    "edit-post" (-> (assoc params
-                           :create-time (-> (:create-time params)
-                                            edn/read-string)
-                           :ptr-hash (f/base32-decode (:ptr-hash params))
-                           :ptr-time (edn/read-string (:ptr-time params))
-                           :pic-hashes (for [pic (-> (:pic-hashes params)
-                                                     edn/read-string)]
-                                         (f/base32-decode pic))
-                           :status 1)
-                    actions/new-post
-                    deref
-                    (do nil))
-    "delete-post" (-> {:create-time (edn/read-string (:create-time params))
-                       :status 0}
-                    actions/new-post
-                    deref
-                    (do nil))
-    "switch-user" (-> (:userhash params)
-                      f/base32-decode
-                      users/load-user)
-    "delete-user" (-> (:userhash params)
-                      f/base32-decode
-                      users/delete-user
-                      deref
-                      (do nil))
-    "create-user" (do
-                    (users/load-user (users/create-user))
-                    (actions/fav-default-user)
-                    nil)
-    "toggle-fav" (-> (assoc params
-                            :ptr-hash (f/base32-decode (:userhash params))
-                            :ptr-time (edn/read-string (:time params)))
-                     actions/toggle-fav
-                     deref
-                     (do nil))
-    nil))
+  (when-let [action (case (:type params)
+                      "save-profile" save-profile
+                      "import-user" import-user
+                      "export-user" export-user
+                      "new-post" new-post
+                      "edit-post" edit-post
+                      "delete-post" delete-post
+                      "switch-user" switch-user
+                      "delete-user" delete-user
+                      "create-user" create-user
+                      "toggle-fav" toggle-fav
+                      nil)]
+    (action params)))


Fix favicon size

Fix favicon size

--- dev/src/yada/dev/manual.clj
+++ dev/src/yada/dev/manual.clj
@@ -44,7 +44,7 @@
 (defn generate-favicons []
   (html
    [:link {:rel "icon" :type "image/png" :href "/img/favicon/favicon.png"}]
-   (for [size [16 92 192 32]              ; firefox needs 32x32 last
+   (for [size [16 96 192 32]              ; firefox needs 32x32 last
          :let [s (format "%dx%d" size size)]]
      [:link {:rel "icon" :type "image/png" :href (format "/img/favicon/favicon-%s.png" s) :sizes s}])


great

great

--- src/bluebell/utils/lufn.clj
+++ src/bluebell/utils/lufn.clj
@@ -40,7 +40,6 @@
                              :name (::name m#)})
           (let [f# (get m# key#)]
             (assert (fn? f#))
-            (println "Evaluate it on " args#)
             (apply f# args#)))))))

 (defmacro def-lufn


Whitespace

Whitespace

--- src/braid/core/modules.cljc
+++ src/braid/core/modules.cljc
@@ -49,4 +49,4 @@
   (braid.video-embeds.core/init!)
   (braid.website-embeds.core/init!)
   (braid.youtube-embeds.core/init!)
-  (braid.map-embeds.core/init!))+  (braid.map-embeds.core/init!))


Improve styling of notices

Improve styling of notices

--- src/braid/notices/core.cljc
+++ src/braid/notices/core.cljc
@@ -3,15 +3,16 @@
     [braid.core.api :as core]
     #?@(:cljs
          [[clojure.spec.alpha :as s]
+          [garden.units :refer [rem em]]
           [re-frame.core :refer [subscribe dispatch]]
-          [garden.units :refer [rem em]]])))
+          [braid.core.client.ui.styles.mixins :as mixins]])))

 #?(:cljs
    (do
      (def ErrorSpec
        {:key keyword?
         :message string?
-        :class (s/spec #{:error :warn :info})})))
+        :class (s/spec #{:error :info})})))

 (defn init! []
   #?(:cljs
@@ -43,40 +44,58 @@

        (core/register-root-view!
          (fn []
-           [:div.error-banners
+           [:div.notices
             (doall
               (for [{:keys [key message class]} @(subscribe [::sub])]
                 ^{:key key}
-                [:div.error-banner
+                [:div.notice
                  {:class class}
                  message
+                 [:span.gap]
                  [:span.close
                   {:on-click (fn [_] (dispatch [:braid.notices/clear! key]))}
                   "×"]]))]))

        (core/register-styles!
          [:#app>.app>.main
-          [:>.error-banners
+          [:>.notices
            {:z-index 9999
             :position "fixed"
-            :top 0
-            :right 0
-            :width "100%"}
+            :top "4rem"
+            :right "1rem"}

-           [:>.error-banner
-            {:margin-bottom (rem 0.25)
-             :font-size (em 2)
-             :text-align "center"}
+           [:>.notice
+            {:display "flex"
+             :justify-content "space-between"
+             :min-width "10em"
+             :align-items "center"
+             :margin [[0 "auto" (rem 0.25)]]
+             :font-size (em 1.5)
+             :padding "0.25em"
+             :border-radius "3px"
+             :border [["0.5px" "solid" "#000000"]]}

             [:&.error
-             {:background-color "rgba(255, 5, 14, 0.6)"}]
+             {:background "#ffe4e4"
+              :border-color "#CA1414"
+              :color "#CA1414"}

-            [:&.warn
-             {:background-color "rgba(255, 190, 5, 0.6)"}]
+             [:&:before
+              (mixins/fontawesome \uf071)
+              {:margin "0 0.5rem 0 0.25rem"}]]

             [:&.info
-             {:background-color "rgba(5, 255, 70, 0.6)"}]
+             {:background "#cfe9ff"
+              :border-color "#236cab"
+              :color "#236cab"}
+
+             [:&:before
+              (mixins/fontawesome \uf06a)
+              {:margin "0 0.5rem 0 0.25rem"}]]
+
+            [:>.gap
+             {:flex-grow 1}]

             [:>.close
-             {:margin-left (em 1)
-              :cursor "pointer"}]]]]))))
+             {:cursor "pointer"
+              :margin "0 0.25rem"}]]]]))))


Parsing group, repository, and branch from the job name

--- src/branch_handler/core.clj
+++ src/branch_handler/core.clj
@@ -104,8 +104,13 @@

 (defn parse-job-name
     [branch-job-prefix job-name]
-    {:name job-name
-    })
+    (let [parsed (clojure.string/split job-name #"\+")]
+         (if (= (count parsed) 3)
+            {:name       job-name
+             :group      (subs (clojure.string/trim (first parsed)) (count branch-job-prefix))
+             :repository (clojure.string/trim (second parsed))
+             :branch     (clojure.string/trim (nth parsed 2))
+            })))

 (defn parse-job-names
     [branch-job-prefix job-names]
@@ -121,7 +126,6 @@
           jobs-info      (parse-job-names branch-job-prefix jobs-for-branches)
           branch-list-in-repo (read-branch-list-from-repo workdir group reponame)]
           jobs-info))
-

 (defn create-action-queue
     []


Using sorted-map for keys and changes.

Using sorted-map for keys and changes.

--- src/cbfg/world-storage.cljs
+++ src/cbfg/world-storage.cljs
@@ -42,6 +42,16 @@
     {:opaque opaque :status :ok
      :key key :sq (dec (:next-sq storage2))}))

+(defn storage-scan [storage opaque from to]
+  (let [s @storage
+        sq (get (:keys s) key)
+        change (get (:changes s) sq)]
+    (if (and change (not (:deletion change)))
+      {:opaque opaque :status :ok
+       :key key :sq sq :cas (:cas change) :val (:val change)}
+      {:opaque opaque :status :not-found
+       :key key})))
+
 (defn make-storage-cmd-handlers [storage]
   {"get" [["key"]
           (fn [c] {:rq #(ago storage-cmd-get %
@@ -80,7 +90,8 @@
                          (get-el-innerHTML (str el-prefix "-" log-kind "-log")))))

 (defn world-vis-init [el-prefix]
-  (let [storage (atom {:keys {} :changes {} :next-sq 1 :max-deleted-sq 1})
+  (let [storage (atom {:keys (sorted-map) :changes (sorted-map)
+                       :next-sq 1 :max-deleted-sq 1})
         storage-cmd-handlers (make-storage-cmd-handlers storage)
         cmd-ch (map< (fn [ev] {:op (.-id (.-target ev))})
                      (merge (map #(listen-el (gdom/getElement %) "click")


Typo in map-kv docstring (#58)

Typo in map-kv docstring (#58)

--- src/clj/datasplash/core.clj
+++ src/clj/datasplash/core.clj
@@ -560,7 +560,7 @@

 Example:
 ```
-(ds/map (fn [{:keys [month revenue]}] [month revenue]) foo)
+(ds/map-kv (fn [{:keys [month revenue]}] [month revenue]) foo)
 ```

 Note: Unlike clojure.core/map, datasplash.api/map-kv takes only one PCollection."


Brought chunk-samples back to what it was. Looking at the changes.

--- src/clj/forma/reproject.clj
+++ src/clj/forma/reproject.clj
@@ -248,8 +248,6 @@
   [mod-h mod-v]
   (let [edge (pixels-at-res m-res)
         numpix (#(* % %) edge)]
-    (for [chunk (range (/ numpix chunk-size))
-          pixel (range chunk-size)
-          :let [[sample line] (tile-position m-res chunk pixel chunk-size)]
+    (for [chunk (range (/ numpix chunk-size))]
       [chunk
-       (vec (resample m-res ll-res mod-h mod-v chunk chunk-size))]))))+       (vec (resample m-res ll-res mod-h mod-v chunk chunk-size))])))


Ensure we can't accidentally send to nil UID.

--- src/clj/om_sente/server.clj
+++ src/clj/om_sente/server.clj
@@ -97,10 +97,8 @@
 (defn session-status
   "Tell the server what state this user's session is in."
   [req]
-  (chsk-send! (session-uid req)
-              [:session/state (if (get-token (session-uid req))
-                                :secure
-                                :open)]))
+  (when-let [uid (session-uid req)]
+    (chsk-send! uid [:session/state (if (get-token uid) :secure :open)])))

 ;; Reply with the session state - either open or secure.

@@ -113,20 +111,19 @@

 (defmethod handle-event :session/auth
   [[_ [username password]] req]
-  (let [valid (and (= "admin" username)
-                   (= "secret" password))
-        uid (session-uid req)]
-    (when valid
-      (add-token uid (unique-id)))
-    (chsk-send! (session-uid req)
-                [(if valid :auth/success :auth/fail)])))
+  (when-let [uid (session-uid req)]
+    (let [valid (and (= "admin" username)
+                     (= "secret" password))]
+      (when valid
+        (add-token uid (unique-id)))
+      (chsk-send! uid [(if valid :auth/success :auth/fail)]))))

 ;; Reply with the message in angle brackets.
 ;; Also record activity to keep session alive.

 (defmethod handle-event :test/echo
   [[_ msg] req]
-  (let [uid (session-uid)]
+  (when-let [uid (session-uid req)]
     (keep-alive uid)
     (chsk-send! uid [:test/reply (str "<" msg ">")])))


Add shadow-cljs after-load hook to refresh the page

--- src/cljs/my_money/core.cljs
+++ src/cljs/my_money/core.cljs
@@ -54,3 +54,6 @@
   (load-interceptors!)
   (session/put! :identity js/identity)
   (mount-components))
+
+(defn ^:dev/after-load  refresh! []
+  (init!))


clean up sending initial sente messages

clean up sending initial sente messages

--- src/cljs/tictag/events.cljs
+++ src/cljs/tictag/events.cljs
@@ -169,20 +169,21 @@
    :db/authenticated-user (ref-to-user user)})

 (reg-event-fx
+ :sente-connected
+ [interceptors]
+ (fn [{:keys [db]} ]))
+
+(reg-event-fx
  :user-me-success
  [interceptors]
  (fn [{:keys [db]} [_ user]]
    {:db             (merge db (normalize-user-to-db user))
     :sente-connect  (:auth-token db)
-    :dispatch-later [{:ms 2 :dispatch [:pings/receive
-                                       (ref-to-user user)
-                                       true
-                                       []
-                                       (partition-all 100 (:pings user))]}
-                     {:ms 2 :dispatch [:macro/get]}
-                     {:ms 2 :dispatch [:beeminder/get]}
-                     {:ms 2 :dispatch [:goal/get]}
-                     {:ms 2 :dispatch [:slack/get]}]}))
+    :dispatch [:pings/receive
+               (ref-to-user user)
+               true
+               []
+               (partition-all 100 (:pings user))]}))

 (defn register-query! [n]
@@ -204,7 +205,6 @@
  :db/query-success
  [interceptors]
  (fn [db [_ v]]
-   (timbre/debug "merging " v)
    (deep-merge* db v)))

 (defn with-path [db path]
@@ -343,11 +343,15 @@
 (defonce !chsk-send! (atom nil))
 (defonce !chsk-state (atom nil))

-(reg-event-db
+(reg-event-fx
  :chsk/state
  [interceptors]
- (fn [db [_ v]]
-   db))
+ (fn [{:keys [db]} [_ [old new]]]
+   (when (:first-open? new)
+     {:dispatch-n [[:macro/get]
+                   [:beeminder/get]
+                   [:goal/get]
+                   [:slack/get]]})))

 (reg-event-fx
  :chsk/recv
@@ -592,3 +596,4 @@
         (fn [id]
           (js/clearTimeout (@timeouts id))
           (swap! timeouts dissoc id)))
+


Minor cleaning

Minor cleaning

--- src/cljs/triboard/core.cljs
+++ src/cljs/triboard/core.cljs
@@ -46,9 +46,8 @@
     (shuffle all-positions)))

 (defn new-board []
-  (reduce (fn [r [color [x y]]]
-            (prn [x y])
-            (assoc-in r [x y] color))
+  (reduce
+    (fn [r [color [x y]]] (assoc-in r [x y] color))
     empty-board (init-positions)))

 (defn new-game []
@@ -194,11 +193,8 @@
 (defn empty-cell
   [x y]
   (rect-cell x y "lightgray"
-    {:on-click
-     (fn []
-       (prn [x y])
-       (swap! app-state play-move [x y]))
-     }))
+    {:on-click #(swap! app-state play-move [x y])}
+    ))

 (defn show-scores
   [scores player]


Added workaround for problem with REPL not reloading code at times.

--- src/cmr/common/dev/util.clj
+++ src/cmr/common/dev/util.clj
@@ -1,15 +1,33 @@
 (ns cmr.common.dev.util
   "This contains utility functions for development"
-  (:require [clojure.java.shell :as sh]))
+  (:require [clojure.java.shell :as sh]
+            [clojure.java.io :as io]))
+
+(defn touch-file
+  [file]
+  (future
+    (try
+      (clojure.java.shell/sh "touch" file)
+      (catch Throwable e
+        (println "Error touch" file)
+        (.printStackTrace e))))
+  nil)
+

 (defn touch-user-clj
   "Touches dev/user.clj to help avoid cases where file changes are not caught by
   clojure.tools.namespace refresh."
   []
-  (future
-    (try
-      (clojure.java.shell/sh "touch" "dev/user.clj")
-      (catch Throwable e
-        (println "Error touch user.clj")
-        (.printStackTrace e))))
-  nil)+  (touch-file "dev/user.clj"))
+
+(defn touch-files-in-dir
+  "Touches all top level files in the folder."
+  [dir]
+  (let [d (io/file dir)
+        files (seq (.listFiles d))]
+    (dorun (map #(-> % str touch-file) (filter #(not (.isDirectory %)) files)))))
+
+(comment
+(touch-files-in-dir ".")
+
+)


Pre: clarify comments.

Pre: clarify comments.

--- src/common/datomish/db.cljc
+++ src/common/datomish/db.cljc
@@ -111,9 +111,12 @@

   (in-transaction!
     [db chan-fn]
-    "Evaluate the given pair-chan `chan-fn` in an exclusive transaction. If it returns non-nil,
-    commit the transaction; otherwise, rollback the transaction.  Returns a pair-chan resolving to
-    the pair-chan returned by `chan-fn`.")
+    "Evaluate the given `chan-fn` in an exclusive transaction. If it returns non-nil,
+    commit the transaction; otherwise, rollback the transaction.
+
+    `chan-fn` should be a function of no arguments returning a pair-chan.
+
+    Returns a pair-chan resolving to the same pair as the pair-chan returned by `chan-fn`.")

   (<bootstrapped? [db]
     "Return true if this database has no transactions yet committed.")
@@ -818,14 +821,14 @@
    (<?q db find {}))
   ([db find options]
    (let [unexpected (seq (clojure.set/difference (set (keys options)) #{:limit :order-by :inputs}))]
-    (when unexpected
-      (raise "Unexpected options: " unexpected {:bad-options unexpected})))
+     (when unexpected
+       (raise "Unexpected options: " unexpected {:bad-options unexpected})))
    (let [{:keys [limit order-by inputs]} options
          parsed (query/parse find)
          context (-> db
-                   query-context
-                   (query/options-into-context limit order-by)
-                   (query/find-into-context parsed))
+                     query-context
+                     (query/options-into-context limit order-by)
+                     (query/find-into-context parsed))

          ;; We turn each row into either an array of values or an unadorned
          ;; value. The row-pair-transducer does this work.


Added program-exists?

Added program-exists?

Signed-off-by: Daniel Borchmann <25857343a15bf1edafebc2912e82ecf775c585c1@mailbox.tu-dresden.de>

--- src/conexp/contrib/exec.clj
+++ src/conexp/contrib/exec.clj
@@ -9,9 +9,29 @@
 (ns conexp.contrib.exec
   (:use conexp.main
         [conexp.io.util :only (tmpfile with-out-writer)])
-  (:use [clojure.java.shell :only (sh)]))
+  (:use [clojure.java.shell :only (sh)]
+        [clojure.string :only (split)])
+  (:import [java.io File]
+           [java.util Map]))

 (ns-doc "Executing external programs with a common interface.")
+
+;;;
+
+(defn program-exists?
+  "Tests whether the given program-name is an executable program in
+  the current path."
+  [program-name]
+  (let [path     (split (.get ^Map (System/getenv) "PATH")
+                        (re-pattern File/pathSeparator)),
+        program  (first (for [dir path,
+                              program (.list ^File (File. ^String dir)),
+                              :when (= program program-name)]
+                          (str dir "/" program)))]
+    (boolean (and program
+                  (let [^File program-file (File. ^String program)]
+                    (and (.canExecute program-file)
+                         (.isFile program-file)))))))

 ;;;


Reimplemented arrow computation in terms of reducers

Tests succeed, and seem to take an equal amount of time.  It
remains to be checked how good these operations perform on
larger data sets, where parallelism can kick in.

Signed-off-by: Daniel Borchmann <25857343a15bf1edafebc2912e82ecf775c585c1@mailbox.tu-dresden.de>

--- src/conexp/fca/contexts.clj
+++ src/conexp/fca/contexts.clj
@@ -7,7 +7,8 @@
 ;; You must not remove this notice, or any other, from this software.

 (ns conexp.fca.contexts
-  (:use conexp.base))
+  (:use conexp.base)
+  (:require [clojure.core.reducers :as r]))

 (ns-doc
  "Provides the implementation of formal contexts and functions on
@@ -314,13 +315,17 @@
         att   (attributes ctx),
         inz   (incidence ctx),
         prime (map-by-fn #(object-derivation ctx #{%}) obj)]
-    (set-of [g m]
-            [g obj
-             m att
-             :when (and (not (inz [g m]))
-                        (forall [h obj]
-                          (or (inz [h m])
-                              (not (proper-subset? (prime g) (prime h))))))])))
+    (r/fold union
+            (fn [set g]
+              (into set
+                    (map #(vector g %)
+                         (reduce (fn [places h]
+                                   (if (proper-subset? (prime g) (prime h))
+                                     (intersection places (prime h))
+                                     places))
+                                 (difference (attributes ctx) (prime g))
+                                 (objects ctx)))))
+            (vec (objects ctx)))))

 (defn up-arrows
   "Computes the up arrow relation of ctx."
@@ -329,13 +334,17 @@
         att   (attributes ctx),
         inz   (incidence ctx),
         prime (map-by-fn #(attribute-derivation ctx #{%}) att)]
-    (set-of [g m]
-            [g obj,
-             m att
-             :when (and (not (inz [g m]))
-                        (forall [n att]
-                          (or (inz [g n])
-                              (not (proper-subset? (prime m) (prime n))))))])))
+    (r/fold union
+            (fn [set m]
+              (into set
+                    (map #(vector % m)
+                         (reduce (fn [places n]
+                                   (if (proper-subset? (prime m) (prime n))
+                                     (intersection places (prime n))
+                                     places))
+                                 (difference (objects ctx) (prime m))
+                                 (attributes ctx)))))
+            (vec (attributes ctx)))))

 (defn up-down-arrows
   "Returns up-down-arrow relation of ctx."


Scaling can now handle zero-{width,height}

Signed-off-by: Daniel Borchmann <25857343a15bf1edafebc2912e82ecf775c585c1@mailbox.tu-dresden.de>

--- src/conexp/layouts/util.clj
+++ src/conexp/layouts/util.clj
@@ -46,10 +46,14 @@
   rectangle given by [x1 y1] and [x2 y2]."
   [[x1 y1] [x2 y2] points]
   (let [[x_min y_min x_max y_max] (edges-of-points points),
-	a_x (/ (- x1 x2) (- x_min x_max 0.1)), ; -0.1 for (= x_min x_max)
-	b_x (- x1 (* a_x x_min)),
-	a_y (/ (- y1 y2) (- y_min y_max 0.1)),
-	b_y (- y1 (* a_y y_min))]
+	[a_x, b_x] (if (= x_min x_max)
+                     [0, (/ (+ x1 x2) 2)]
+                     (let [slope (/ (- x1 x2) (- x_min x_max))]
+                       [slope, (- x1 (* slope x_min))])),
+	[a_y, b_y] (if (= y_min y_max)
+                     [0, (/ (+ y1 y2) 2)]
+                     (let [slope (/ (- y1 y2) (- y_min y_max))]
+                       [slope, (- y1 (* slope y_min))]))]
     (map (fn [[x y]]
 	   [(+ (* a_x x) b_x), (+ (* a_y y) b_y)])
 	 points)))


output config

output config

--- src/statuses/server.clj
+++ src/statuses/server.clj
@@ -19,7 +19,9 @@
   (cfg/init! (or (first m) "config.clj"))
   (println "Configuration: " (config))
   (persistence/init! (config :database-path) (config :save-interval))
-  (println "Starting server on port"  "in mode" (config :run-mode))
+  (println "Starting server on host"  (config :host)
+           "port" (config :http-port)
+           "in mode" (config :run-mode))
   (run-jetty
    (if (= (config :run-mode) :dev) (wrap-reload app) app)
    {:port (config :http-port) :join? false :host (config :host)}))


Delete /root/logs

Delete /root/logs

--- src/copycat_jepsen/core.clj
+++ src/copycat_jepsen/core.clj
@@ -75,8 +75,8 @@
         jarfile "/root/.m2/repository/net/kuujo/copycat/copycat-server-example/0.6.0-SNAPSHOT/copycat-server-example-0.6.0-SNAPSHOT-shaded.jar"]
     (info node "starting copycat")
     (meh (c/exec :truncate :--size 0 "/var/log/copycat.log"))
-    (meh (c/exec :rm "/root/copycat*.log"))
     (c/su
+      (meh (c/exec :rm :-rf "/root/logs/"))
       (c/cd "/root"
             (c/exec :java :-jar jarfile local-node-arg other-node-args
                     (c/lit "2>> /dev/null >> /var/log/copycat.log & echo $!"))))))


remove compilation warning

remove compilation warning

--- occi/java/jar/src/main/clojure/slipstream/credcache/credential.clj
+++ occi/java/jar/src/main/clojure/slipstream/credcache/credential.clj
@@ -1,5 +1,6 @@
 (ns slipstream.credcache.credential
   "Management functions for credential resources within the database."
+  (:refer-clojure :exclude [update])
   (:require
     [clojure.tools.logging :as log]
     [clj-time.core :as t]


this doesn’t work for external ELB

this doesn’t work for external ELB

--- src/terraboot/infra.clj
+++ src/terraboot/infra.clj
@@ -43,11 +43,9 @@
                                          :max-number-of-public-slaves 1
                                          :public-slave-instance-type "t2.medium"
                                          :public-slave-elb-listeners [{:port 80 :protocol "http"}
-                                                                      {:port 9501 :protocol "http"}
-                                                                      {:port 5001 :protocol "tcp"}]
+                                                                      {:port 9501 :protocol "http"}]
                                          :public-slave-elb-sg [{:port 9501 :cidr_blocks [all-external]}
-                                                               {:port 80 :cidr_blocks [all-external]}
-                                                               {:port 5001 :cidr_blocks [vpc-cidr-block]}]
+                                                               {:port 80 :cidr_blocks [all-external]}]
                                          :public-slave-elb-health "HTTP:9501/"
                                          :azs azs
                                          :mesos-ami "ami-1807e377" ;; previous coreos


verify color sequence works for larger grids

--- src/tile_game/grid.cljs
+++ src/tile_game/grid.cljs
@@ -4,18 +4,19 @@

 (enable-console-print!)

-(def colors ["#000000" "#808080" "#C0C0C0" "#FFFFFF"
-             "#800000" "#FF0000" "#808000" "#FFFF00"
-             "#008000" "#00FF00" "#008080" "#00FFFF"
-             "#000080" "#0000FF" "#800080" "#FF00FF"])
+(def colors
+  (cycle ["#00B000" "#808080" "#C0C0C0" "#3030B0"
+          "#800000" "#FF0000" "#808000" "#FFFF00"
+          "#008000" "#00FF00" "#008080" "#00FFFF"
+          "#0000C0" "#3030FF" "#800080" "#FF00FF"]))

 (defonce app-state
-  (r/atom {:board (b/create-board 4)
-           :dim 4}))
+  (r/atom {:board (b/create-board 5)
+           :dim 5}))

 (defn render-tile [[x y] tile]
   (if-not (zero? tile)
-    (let [fill-color (colors tile)]
+    (let [fill-color (nth colors tile)]
       [:g {:key (str "tile-" tile)
            :on-click #(swap! app-state update-in [:board] b/slide-tile tile)}
        [:rect {:x (+ x 0.05) :y (+ y 0.05) :width 0.9 :height 0.9 :fill fill-color}]
@@ -27,7 +28,7 @@
   (let [{:keys [board dim]} @app-state]
     [:center
      [:h1 "Tile Grid"]
-     [:svg {:view-box "0 0 4 4" :width 800 :height 800}
+     [:svg {:view-box (str "0 0 " dim " " dim) :width 800 :height 800}
       (for [x (range dim) y (range dim)]
         (let [tile (nth board (+ (* y dim) x))]
           (render-tile [x y] tile)))]]))


Updates last-input on item change

Updates last-input on item change

--- src/wordsmith/core.cljs
+++ src/wordsmith/core.cljs
@@ -52,10 +52,12 @@
 ;; Left menu

 (defn update-current [event app]
-  (let [title (.. event -target -textContent)]
-    (om/update! app :input (p/get-document title))
+  (let [title (.. event -target -textContent)
+        input (p/get-document title)]
+    (om/update! app :input input)
     (om/update! app :title title)
-    (om/update! app :last-title title)))
+    (om/update! app :last-title title)
+    (om/update! app :last-input input)))

 (defn delete-click [title app]
   (put! (:channel @app) [:remove title]))


removed redundant str form

removed redundant str form

--- src/chat/client/views/new_message.cljs
+++ src/chat/client/views/new_message.cljs
@@ -68,7 +68,7 @@
        (when-let [query (second (re-find pattern text))]
          (->> emoji/unicode
               (filter (fn [[k v]]
-                        (simple-matches? k (str query))))
+                        (simple-matches? k query)))
               (map (fn [[k v]]
                      {:action
                       (fn [thread-id])


Fix bug where every second \item was discarded

--- src/clj/com/hypirion/subtex/hiccup.clj
+++ src/clj/com/hypirion/subtex/hiccup.clj
@@ -50,9 +50,12 @@
                         (unreduced (rf res v))))]
             (rf res)))
          ([res input]
-          (cond (and (not (none? @in-item)) (identical? (:type input) :invoke)
+          (cond (and (not (none? @in-item))
+                     (identical? (:type input) :invoke)
                      (= "\\item" (:name input)))
-                (rf res (to-li in-item))
+                (let [li (to-li in-item)]
+                  (vreset! in-item (rexf/subreduction rf))
+                  (rf res li))

                 (not (none? @in-item))
                 (do (vswap! in-item rexf/substep input) res)


Add altars, chests, stairs

Add altars, chests, stairs

--- src/cljc/robinson/dungeons/temple.cljc
+++ src/cljc/robinson/dungeons/temple.cljc
@@ -89,6 +89,10 @@
                                       :corridor)]
              [x y {:type cell-type}]))
          points)))
+
+(defn make-chest-items
+  []
+  [])

 (defn add-room-features
   [cells-xy]
@@ -113,10 +117,15 @@
                                                  [:vine vine-probability]
                                                  [[:shallow-water water-probability]
                                                   [:grass grass-probability]])]
-                   (if (or (and (= max-type :vine) (> max-p 0.85))
-                           (> max-p 0.8))
-                     [x y (assoc cell :type max-type)]
-                     [x y cell]))
+                   (cond
+                     (or (and (= max-type :vine) (> max-p 0.85))
+                         (> max-p 0.8))
+                       [x y (assoc cell :type max-type)]
+                     (> (rand) 0.90)
+                       [x y (rand-nth [{:type :chest :items (make-chest-items)}
+                                       {:type :altar}])]
+                     :else
+                       [x y cell]))
                (cond
                  (> moss-probability 0.7)
                    [x y (assoc cell :type (case (get cell :type)
@@ -489,8 +498,16 @@
                                  (apply merge-with-canvas cells (points-to-corridor points))))
                              cells
                              g)
-        upstairs     (conj [(first room-centers)] {:type :up-stairs})
-        downstairs   (conj [(last room-centers)] {:type :down-stairs})]
+        [[upstairs-x upstairs-y]] (shuffle (clojure.set/difference (set room-centers) junction-rooms))
+        [[downstairs-x downstairs-y]] (shuffle (filter (fn [[x y]]
+                                                         (rc/farther-than?
+                                                           (rc/xy->pos x y)
+                                                           (rc/xy->pos upstairs-x upstairs-y)
+                                                           (/ (min width height) 2.0)))
+                                                       (clojure.set/difference (set room-centers) junction-rooms)))
+        cells        (-> cells
+                       (assoc-in [upstairs-y upstairs-x :type] :up-stairs)
+                       (assoc-in [downstairs-y downstairs-x :type] :down-stairs))]
     ;(println "fcg" fcg)
     (println "g" g)
     (println "more-edges" more-edges)
@@ -498,8 +515,8 @@
     ;(println (vec rooms))
     {:place cells #_(apply merge-with-canvas (canvas width height)
                      (concat corridors rooms))
-     :up-stairs upstairs
-     :down-stairs downstairs}))
+     #_#_:up-stairs upstairs
+     #_#_:down-stairs downstairs}))

 (defn place-to-ascii
   "Convert a grid of cells into a list of strings so that it can be rendered."
@@ -525,6 +542,8 @@
                                               :bottom-left-2 "\033[38;2;191;171;143m◙\033[0m"
                                               :bottom-right-2 "\033[38;2;191;171;143m◙\033[0m"
                                               :close-door \+
+                                              :altar \┬
+                                              :chest "\033[38;2;124;97;45m■\033[0m"
                                               ;:shallow-water \~
                                               :shallow-water "\033[38;2;1;217;163m~\033[0m"
                                               :grass "\033[38;2;1;140;1m\"\033[0m"


evade

evade

--- src/cljs/infinitelives/utils/boid.cljs
+++ src/cljs/infinitelives/utils/boid.cljs
@@ -53,3 +53,11 @@
                  (* 4)                  ; 4 = c (T=Dc)
                  (vec2/scale target-vel)
                  (vec2/add target))))
+
+(defn evade [{:keys [pos] :as boid} target target-vel]
+  (flee boid (->> pos
+                 (vec2/direction target)
+                 vec2/magnitude
+                 (* 4)                  ; 4 = c (T=Dc)
+                 (vec2/scale target-vel)
+                 (vec2/add target))))


Switch back to router socket

Switch back to router socket

I'm pretty sure that the problem I was having stemmed from fundamentally
mishandling router/dealer sockets.

--- src/frereth/server/comm.clj
+++ src/frereth/server/comm.clj
@@ -138,7 +138,7 @@

 (defmethod socket-type ActionSocket
   [_]
-  #_:router :rep)
+  :router #_:rep)

 (defmethod socket-type AuthSocket
   [_]


Fixed typo in pkg.clj

Fixed typo in pkg.clj

Signed-off-by: James Turnbull <474ba67bdb289c6263b36dfd8a7bed6c85b04943@lovedthanlost.net>

--- tasks/leiningen/pkg.clj
+++ tasks/leiningen/pkg.clj
@@ -3,7 +3,7 @@
         [leiningen.fatdeb :only [fatdeb]]
         [leiningen.fatrpm6 :only [fatrpm6]]
         [leiningen.fatrpm7 :only [fatrpm7]]
-        [leiningen.fatrpm8 :only [fatrpm7]]
+        [leiningen.fatrpm8 :only [fatrpm8]]
         [leiningen.tar :only [tar]]))

 (defn pkg [project]


Rewrite parsers.core/extension.

Rewrite parsers.core/extension.

--- src/incise/parsers/core.clj
+++ src/incise/parsers/core.clj
@@ -21,7 +21,12 @@
                        (repeat parser))))

 (defn extension [^java.io.File file]
-  (last (s/split (.getName file) #"\.")))
+  "Get the extension, enforcing lower case, on the given file."
+  (-> file
+      (.getName)
+      (s/split #"\.")
+      (last)
+      (s/lower-case)))

 (defn parse [^java.io.File file]
   ((@parsers (extension file)) file))


Remove another explicit go block

Remove another explicit go block

--- src/io/aviso/rook/async.clj
+++ src/io/aviso/rook/async.clj
@@ -300,9 +300,11 @@
   ([handler options]
    (let [options' (session/session-options options)]
      (fn [request]
-       (safe-go request
-                (let [request' (session/session-request request options')]
-                  (->
-                    (handler request')
-                    <!
-                    (session/session-response request' options'))))))))+       (let [response-ch (chan 1)
+             request' (session/session-request request options')]
+         (take! (handler request')
+                (fn [handler-response]
+                  (put! response-ch (if handler-response
+                                      (session/session-response handler-response request' options')
+                                      false))))
+         response-ch)))))


Redact the cheatsheet for now.

Redact the cheatsheet for now.

--- src/klangmeister/views.cljs
+++ src/klangmeister/views.cljs
@@ -11,29 +11,6 @@
                [:button {:on-click #(handle! (action/->Play :main))} "Play"]
                [:button {:on-click #(handle! (action/->Stop :main))} "Stop"])]
     [:div {:class "controls"} play]))
-
-(defn cheatsheet []
-  (let [row (fn [term explanation example]
-              [:tr
-               [:td {:class "code"} term]
-               [:td explanation]
-               [:td {:class "code"} example]])]
-    [:table {:class "cheatsheet"}
-     [:tbody
-      (row "->>" "Make a series of updates to a melody." "(->> (phrase [1] [0]) (where :pitch inc))")
-      (row ";" "Ignore the rest of the line, so that you can put comments in." "; The melody.")
-      (row "A..G" "Put a quantity of semitones into a specified key." "(A 3) => 72")
-      (row "bpm" "Make a function to convert from beats into seconds." "((bpm 120) 3) => 1.5")
-      (row "comp" "Join two functions together." "((comp C major) 2) => 64")
-      (row "connect->" "Connect a series of synth nodes together." "(connect-> (saw 440) (low-pass 1000))")
-      (row "defn" "Define a named function." "(defn double [x] (* 2 x))")
-      (row "major" "Put a rank into a major scale." "(major 2) => 4")
-      (row "minor" "Put a rank into a minor scale." "(minor 2) => 3")
-      (row "phrase" "Use a some durations and some pitches to make a melody." "(phrase [1 1 2] [0 2 4])")
-      (row "then" "Put one melody after another." "(->> bass (then guitar))")
-      (row "times" "Repeat a melody several times." "(->> bass (times 4))")
-      (row "where" "Update an element of a melody." "(where :pitch inc notes)")
-      (row "with" "Put two melodies together." "(with bass guitar)")]]))

 (defn ribbon []
   [:a {:href "https://github.com/ctford/klangmeister"}
@@ -52,5 +29,4 @@
    [editor/render :main (-> @state-atom :main :text) handle! @state-atom]
    [controls handle! @state-atom]
    [graph/render handle! state-atom]
-   [cheatsheet]
    [ribbon]])


Fix use clause in classpath ns.

Fix use clause in classpath ns.

--- src/leiningen/classpath.clj
+++ src/leiningen/classpath.clj
@@ -1,6 +1,7 @@
 (ns leiningen.classpath
-  (:use (clojure.contrib [io :only (file)]
-                         [string :only (join)]))
+  (:use [leiningen.core :only [read-project]]
+        [clojure.java.io :only [file]]
+        [clojure.string :only [join]])
   (:import org.apache.tools.ant.types.Path))

 (defn find-lib-jars


implement /api/health url.

implement /api/health url.

--- src/metabase/api/routes.clj
+++ src/metabase/api/routes.clj
@@ -1,5 +1,5 @@
 (ns metabase.api.routes
-  (:require [compojure.core :refer [context defroutes]]
+  (:require [compojure.core :refer [context defroutes GET]]
             [compojure.route :as route]
             (metabase.api [annotation :as annotation]
                           [card :as card]
@@ -23,6 +23,7 @@
   (context "/card"         [] (-> card/routes auth/bind-current-user auth/enforce-authentication))
   (context "/dash"         [] (-> dash/routes auth/bind-current-user auth/enforce-authentication))
   (context "/emailreport"  [] (-> emailreport/routes auth/bind-current-user auth/enforce-authentication))
+  (GET     "/health"       [] {:status 200 :body {:status "ok"}})
   (context "/meta/dataset" [] (-> dataset/routes auth/bind-current-user auth/enforce-authentication))
   (context "/meta/db"      [] (-> db/routes auth/bind-current-user auth/enforce-authentication))
   (context "/meta/field"   [] (-> field/routes auth/bind-current-user auth/enforce-authentication))


Disable custom logging (rotor was broken anyway).

--- src/onyx_benchmark/peer.clj
+++ src/onyx_benchmark/peer.clj
@@ -2,7 +2,6 @@
   (:require [clojure.core.async :refer [chan dropping-buffer <!!]]
             [riemann.client :as r]
             [onyx.peer.pipeline-extensions :as p-ext]
-            [taoensso.timbre.appenders.rotor :as rotor]
             [taoensso.timbre :refer  [info warn trace fatal error] :as timbre]
             [interval-metrics.core :as im]
             [onyx.plugin.bench-plugin]
@@ -86,17 +85,6 @@
 (defn my-inc [{:keys [n] :as segment}]
   (assoc segment :n (inc n)))

-(def logging-config
-  {:appenders {:standard-out {:enabled? false}
-               :spit {:enabled? false}
-               :rotor {:min-level :trace
-                       :enabled? true
-                       :async? false
-                       :max-message-per-msecs nil
-                       :fn rotor/appender-fn}}
-   :shared-appender-config {:rotor {:path "onyx-benchmark.log"
-                                    :max-size (* 512 102400) :backlog 5}}})
-
 (defn -main [zk-addr riemann-addr id n-peers messaging & args]
   (let [peer-config {:zookeeper/address zk-addr
                      :onyx/id id
@@ -110,8 +98,7 @@
                      ;:onyx.messaging.aeron/embedded-driver? false
                      :onyx.peer/join-failure-back-off 500
                      :onyx.peer/job-scheduler :onyx.job-scheduler/greedy
-                     :onyx.messaging/impl (keyword messaging)
-                     :onyx.log/config logging-config}
+                     :onyx.messaging/impl (keyword messaging)}
         n-peers-parsed (Integer/parseInt n-peers)
         peer-group (onyx.api/start-peer-group peer-config)
         peers (onyx.api/start-peers n-peers-parsed peer-group)]


Fix retry-counter reset.

Fix retry-counter reset.

--- src/onyx_benchmark/peer.clj
+++ src/onyx_benchmark/peer.clj
@@ -43,7 +43,7 @@
           (let [cnt @counter
                 _ (reset! counter 0)
                 retry-cnt @retry-counter
-                _ (reset! retry-counter)]
+                _ (reset! retry-counter 0)]
             (info "-> " cnt " <-")
             (r/send-event client {:service "onyx-retry" :state "ok" :metric retry-cnt :tags ["benchmark"]})
             (r/send-event client {:service "onyx" :state "ok" :metric cnt :tags ["benchmark"]}))


Fix bug in boot-rig - actually wait until rig is booted!

--- src/overtone/studio/rig.clj
+++ src/overtone/studio/rig.clj
@@ -37,7 +37,7 @@
 (defn wait-until-rig-booted
   "Makes the current thread sleep until the rig completed its boot process."
   []
-  (while (not (connected?))
+  (while (not (rig-booted?))
     (Thread/sleep 100)))

 (defn boot-rig


throw a better error on change uberkey mismatch

--- src/er_cassandra/model/alia/upsert.clj
+++ src/er_cassandra/model/alia/upsert.clj
@@ -322,10 +322,16 @@
    record :- t/RecordSchema
    opts :- fns/UpsertOptsSchema]

-  (assert (or (nil? old-record)
-              (= (t/extract-uber-key-value entity old-record)
-                 (t/extract-uber-key-value entity record))))
-
+  (when (and (some? old-record)
+             (not= (t/extract-uber-key-value entity old-record)
+                   (t/extract-uber-key-value entity record)))
+    (throw (pr/error-ex ::uber-key-mismatch
+                        {:entity (-> entity :primary-table :name)
+                         :old-record-uberkey (t/extract-uber-key-value entity old-record)
+                         :record-uberkey (t/extract-uber-key-value entity record)
+                         :old-record old-record
+                         :record record
+                         :opts opts})))
   (ddo [:let [opts (ts/default-timestamp-opt opts)

               ;; separate the tru cassandra columns from non-cassandra


minor style refactor

minor style refactor

--- solutions/day09/solution.clj
+++ solutions/day09/solution.clj
@@ -4,17 +4,17 @@
 (require '[clojure.data.priority-map :as pm])
 (require '[clojure.string :as str])

-(defn line->city-pair
+(defn str->city-pair
   [string]
   (let [[cities dist] (str/split string #" = ")
-        dist (read-string dist)
-        [c1 c2] (str/split cities #" to ")]
+        [c1 c2] (str/split cities #" to ")
+        dist (read-string dist)]
     {{c1 c2} dist {c2 c1} dist}))

 (def distance-map (->> (slurp "input.txt")
                        (str/split-lines)
-                       (map line->city-pair)
-                       (reduce conj)))
+                       (map str->city-pair)
+                       (reduce merge)))

 (def cities (->> (keys distance-map)
                  (map seq)


Bump refactor-nrepl version

Bump refactor-nrepl version

--- extra/profiles.clj
+++ extra/profiles.clj
@@ -3,7 +3,7 @@
             [lein-plz "0.2.1"]
             [lein-pprint "1.1.1"]
             [codox "0.8.10"]
-            [refactor-nrepl "1.2.0-SNAPSHOT"]]
+            [refactor-nrepl "2.0.0-SNAPSHOT"]]
   :dependencies [[alembic "0.2.1"]
                  [slamhound "1.5.5"]
                  [org.clojure/tools.nrepl "0.2.7"]]


cleanup

cleanup

--- test/babel/test/en.cljc
+++ test/babel/test/en.cljc
@@ -130,7 +130,6 @@
          (fo (generate {:synsem {:cat :verb :sem {:pred :be-called
                                                   :subj {:pred :lei}
                                                   :obj {:pred :luisa}}}})))))
-
 (deftest jean-s
   (is (not (empty? (parse "Jean's")))))


add a round-trip test and a variable useful for writing more tests in the future

--- test/babel/test/it.cljc
+++ test/babel/test/it.cljc
@@ -1,7 +1,7 @@
 (ns babel.test.it
   (:refer-clojure :exclude [get-in])
   (:require [babel.engine :refer [generate]]
-            [babel.italiano.grammar :refer [small medium]]
+            [babel.italiano.grammar :refer [small medium np-grammar]]
             [babel.italiano.lexicon :refer [lexicon]]
             [babel.italiano.morphology :refer [fo]]
             [babel.italiano.workbook :refer [analyze parse]]
@@ -59,3 +59,27 @@
     (is (= "io parlo") (fo (first result)))))

+(deftest round-trip-1
+  (let [expr (generate {:synsem {:sem {:spec {:def :def}
+                                       :mod {:pred :difficile}
+                                       :number :sing
+                                     :pred :donna}}}
+                       np-grammar)]
+    (is (= (fo expr) "la donna difficila"))
+    (is (not (empty? (parse (fo expr) np-grammar))))))
+
+;; useful for adding more round-trip tests.
+(def foo
+  (take 1 (repeatedly
+           #(let [expr (generate {:synsem {:sem
+                                           {:spec {:def :top}
+                                            :mod {:pred :top}
+                                            :number :top
+                                            :pred :top}}}
+                                 np-grammar)]
+              (if (empty? (parse (fo expr) np-grammar))
+                {:fo (fo expr)
+                 :expr (get-in expr [:synsem :sem])
+                 :sem (get-in (first (parse (fo expr) np-grammar))
+                              [:synsem :sem])})))))
+


fix test cases of sorter

fix test cases of sorter

--- test/cljam/t_sorter.clj
+++ test/cljam/t_sorter.clj
@@ -41,8 +41,9 @@
                                  (str "invalid file suffix " dst-file))))
                   nil)]
     (if-not (nil? dst-wtr)
-      (target-fn src-rdr dst-wtr)
-      (target-fn src-rdr))))
+      (with-open [src src-rdr
+                  dst dst-wtr] (target-fn src dst))
+      (with-open [src src-rdr] (target-fn src)))))

 (with-state-changes [(before :facts (do (prepare-cache!)
                                         (prepare-shuffled-files!)))


More fettling grammar

More fettling grammar

--- test/irobot/t_parse.clj
+++ test/irobot/t_parse.clj
@@ -138,7 +138,7 @@
        [:record
         [:agent "User-Agent:" "thingy"]
         [:disallow "Disallow:" "/"]
-        [:extension "SOMETHING" "foobar"]]])
+        [:extension "SOMETHING" ":" "foobar"]]])

 (fact "can have more than one record"
@@ -215,10 +215,10 @@
        [:disallow "Disallow:" "/a/*/c"]]])

-;; (fact "Sitemap directives may include absolute URLs (including : characters)"
-;;   (parse "User-agent:foo\nAllow:/\nSitemap:http//bar.com/foo.xml")
-;;   =>  [:records
-;;       [:record
-;;        [:agent "User-agent:" "foo"]
-;;        [:allow "Allow:" "/"]
-;;        [:sitemap "Sitemap:" "http//bar.com/foo.xml"]]])
+(fact "Sitemap directives may include absolute URLs (including : characters)"
+  (parse "User-agent:foo\nAllow:/\nSitemap:http//bar.com/foo.xml")
+  =>  [:records
+      [:record
+       [:agent "User-agent:" "foo"]
+       [:allow "Allow:" "/"]
+       [:sitemap "Sitemap:" "http//bar.com/foo.xml"]]])


revert Java version checking

revert Java version checking

--- test/java_time_test.clj
+++ test/java_time_test.clj
@@ -1019,14 +1019,14 @@
     (let [java-version (->> (System/getProperty "java.version")
                             (re-find #"^\d+")
                             Integer/parseInt)]
-      (if (= java-version 13)
-        (testing "Java 13 treats AM as invalid"
+      (if (> java-version 11)
+        (testing "Java 13 and above treats AM as invalid"
           (let [fmt (java-time/formatter "hh:mma" {:case :sensitive})]
             (is (= (j/local-time 0 34 0 0)
                    (j/local-time fmt "12:34am")))
             (is (thrown? Exception (j/local-time fmt "12:34AM")))))

-        (testing "Java 8, 11, and 15 treats am as invalid"
+        (testing "Java 8 and 11 treats am as invalid"
           (let [fmt (java-time/formatter "hh:mma" {:case :sensitive})]
             (is (= (j/local-time 0 34 0 0)
                    (j/local-time fmt "12:34AM")))


Eliminate protocol, don't use Clojure reader for numbers

Parsing Doubles appears to be a performance drag now

--- src/main/clojure/clojure/data/json.clj
+++ src/main/clojure/clojure/data/json.clj
@@ -20,6 +20,8 @@
   (:use [clojure.pprint :only (write formatter-out)])
   (:import (java.io PrintWriter PushbackReader StringWriter
                     StringReader Reader EOFException)))
+
+(set! *warn-on-reflection* true)

 ;;; JSON READER

@@ -123,6 +125,24 @@
           (do (.append buffer (char c))
               (recur (.read stream)))))))

+(defn- read-json-number [^PushbackReader stream]
+  (let [buffer (StringBuilder.)
+        floating-point?
+          (loop [float? false]
+            (let [c (.read stream)]
+              (codepoint-case c
+                (\- \+ \0 \1 \2 \3 \4 \5 \6 \7 \8 \9)
+                (do (.append buffer (char c))
+                    (recur float?))
+                (\e \E \.)
+                (do (.append buffer (char c))
+                    (recur true))
+                (do (.unread stream c)
+                    float?))))]
+    (if floating-point?
+      (Double/valueOf (str buffer))
+      (Long/valueOf (str buffer)))))
+
 (defn- read-json-reader
   ([^PushbackReader stream keywordize? eof-error? eof-value]
      (loop [c (.read stream)]
@@ -133,10 +153,10 @@
 	 (codepoint-case c
            :whitespace (recur (.read stream))

-           ;; Read numbers with Clojure reader
+           ;; Read numbers
            (\- \0 \1 \2 \3 \4 \5 \6 \7 \8 \9)
            (do (.unread stream c)
-               (read stream true nil))
+               (read-json-number stream))

            ;; Read strings
            \" (read-json-quoted-string stream)
@@ -171,39 +191,17 @@

            (throw (Exception. (str "JSON error (unexpected character): " (char c)))))))))

-(defprotocol Read-JSON-From
-  (read-json-from [input keywordize? eof-error? eof-value]
-                  "Reads one JSON value from input String or Reader.
-  If keywordize? is true, object keys will be converted to keywords.
-  If eof-error? is true, empty input will throw an EOFException; if
-  false EOF will return eof-value. "))
-
-(extend-protocol
- Read-JSON-From
- String
- (read-json-from [input keywordize? eof-error? eof-value]
-                 (read-json-reader (PushbackReader. (StringReader. input))
-                                   keywordize? eof-error? eof-value))
- PushbackReader
- (read-json-from [input keywordize? eof-error? eof-value]
-                 (read-json-reader input
-                                   keywordize? eof-error? eof-value))
- Reader
- (read-json-from [input keywordize? eof-error? eof-value]
-                 (read-json-reader (PushbackReader. input)
-                                   keywordize? eof-error? eof-value)))
-
-(defn read-json
-  "Reads one JSON value from input String or Reader.
+(defn read-json-string
+  "Reads one JSON value from input String.
   If keywordize? is true (default), object keys will be converted to
   keywords.  If eof-error? is true (default), empty input will throw
   an EOFException; if false EOF will return eof-value. "
   ([input]
-     (read-json-from input true true nil))
+     (read-json-string input true true nil))
   ([input keywordize?]
-     (read-json-from input keywordize? true nil))
+     (read-json-string input keywordize? true nil))
   ([input keywordize? eof-error? eof-value]
-     (read-json-from input keywordize? eof-error? eof-value)))
+     (read-json-reader (PushbackReader. (StringReader. input)) keywordize? eof-error? eof-value)))

 ;;; JSON PRINTER


Wrap *out* in a PrintWriter, since it's only guaranteed to be a Writer

--- src/main/clojure/clojure/data/json.clj
+++ src/main/clojure/clojure/data/json.clj
@@ -328,7 +328,7 @@
         to turn off \\uXXXX escapes of Unicode characters."
   [x & options]
   (let [{:keys [escape-unicode] :or {escape-unicode true}} options]
-    (write-json x *out* escape-unicode)))
+    (write-json x (PrintWriter. *out*) escape-unicode)))

 ;;; JSON PRETTY-PRINTER


Fix minor docstring issue.

Fix minor docstring issue.

--- src/snergly/algorithms.cljc
+++ src/snergly/algorithms.cljc
@@ -196,7 +196,8 @@
 ;; until :max increases, at which point it lets pass the accumulated update
 ;; and starts over with the new :max value.
 (defn trailing-maxes
-  "A transducer for distances values that passes the last value containing each :max value."
+  "A transducer for distances values that collapses consecutive values with the
+  same :max into one."
   []
   (fn [xf]
     (let [prev (volatile! nil)]


Separate command to prepare statement

Separate command to prepare statement

--- src/clojure/clojurewerkz/cassaforte/cluster/client.clj
+++ src/clojure/clojurewerkz/cassaforte/cluster/client.clj
@@ -31,17 +31,18 @@
 ;; DB Ops
 ;;
 (defn ^clojure.lang.IPersistentMap execute-raw
-  [^Session client ^String query]
+  [^Session client query]
   (-> (.execute client query)
                 conv/to-map))

-;; TODO: separate prepare command from execute-prepared
+(defn ^PreparedStatement prepare
+  [^Session client ^String query]
+  (.prepare client query))

 (defn execute-prepared
   [^Session client [^String query ^java.util.List values]]
-  (let [^Query prepared-statement (.bind (.prepare client query) (to-array values))]
-    (-> (.execute client prepared-statement)
-        conv/to-map)))
+  (let [^Query prepared-statement (.bind (prepare client query) (to-array values))]
+    (execute-raw client prepared-statement)))

 (defn get-hosts
   "Returns all hosts for connected cluster"


flash message when schedule is unassigned

--- src/cljs/early_vote_site/early_vote_site_detail/events.cljs
+++ src/cljs/early_vote_site/early_vote_site_detail/events.cljs
@@ -161,7 +161,8 @@
 (defn unassign-schedule-success
   [{:keys [db]} [_ result]]
   {:db db
-   :dispatch [:schedules-list/get]})
+   :dispatch-n [[:flash/message "Schedule unassigned"]
+                [:schedules-list/get]]})

 ;; Edit Mode


Fix styling

Fix styling

--- src/uno_scoreboard/app.cljs
+++ src/uno_scoreboard/app.cljs
@@ -73,7 +73,7 @@
    (player-score name max-score score)])

 (rum/defc scoreboard < rum/reactive [data]
-  [:div.scoreboard
+  [:div.scoreboard.container-fluid
    (max-score (:max-score (rum/react data)))
    [:hr]
    (for [[name score] (:players (rum/react data))]


Minor restructuring in CLI module

Minor restructuring in CLI module

--- src/whisper2cyanite/cli.clj
+++ src/whisper2cyanite/cli.clj
@@ -11,6 +11,62 @@

 (def cli-commands #{"migrate" "validate" "calc-size" "list-files" "list-paths"
                     "info" "fetch" "help"})
+
+(declare parse-rollups check-rollups)
+
+(def cli-options
+  [["-f" "--from FROM" "From time (Unix epoch)"
+    :parse-fn #(Integer/parseInt %)
+    :validate [#(<= 0 %) "Must be a number >= 0"]]
+   ["-t" "--to TO" "To time (Unix epoch)"
+    :parse-fn #(Integer/parseInt %)
+    :validate [#(< 0 %) "Must be a number > 0"]]
+   ["-r" "--run" "Force normal run (dry run using on default)"]
+   ["-R" "--rollups ROLLUPS"
+    "Define rollups. Format: <seconds_per_point[:retention],...> Example: 60,300:31536000"
+    :parse-fn #(parse-rollups %)
+    :validate [check-rollups "Invalid rollup"]]
+   ["-j" "--jobs JOBS" "Number of jobs to run simultaneously"
+    :parse-fn #(Integer/parseInt %)
+    :validate [#(< 0 %) "Must be a number > 0"]]
+   ["-T" "--min-ttl TTL" (str "Minimal TTL. Default: " core/default-min-ttl)
+    :parse-fn #(Integer/parseInt %)
+    :validate [#(< 0 %) "Must be a number > 0"]]
+   ["-D" "--root-dir DIRECTORY" "Root directory"]
+   [nil "--cassandra-keyspace KEYSPACE"
+    (str "Cassandra keyspace. Default: " mstore/default-cassandra-keyspace)]
+   ["-O" "--cassandra-options OPTIONS"
+    "Cassandra options. Example: \"{:compression :lz4}\""
+    :parse-fn #(read-string %)
+    :validate [#(= clojure.lang.PersistentArrayMap (type %))]]
+   [nil "--cassandra-channel-size SIZE"
+    (str "Cassandra channel size in points. Default: "
+         mstore/default-cassandra-channel-size)
+    :parse-fn #(Integer/parseInt %)
+    :validate [#(< 0 %) "Must be a number > 0"]]
+   [nil "--cassandra-batch-size SIZE"
+    (str "Cassandra batch size. Default: " mstore/default-cassandra-batch-size)
+    :parse-fn #(Integer/parseInt %)
+    :validate [#(< 0 %) "Must be a number > 0"]]
+   [nil "--cassandra-batch-rate RATE" "Cassandra batch rate (batches per second, 1-100)"
+    :parse-fn #(Integer/parseInt %)
+    :validate [#(< 0 % 101) "Must be a number between 1-100"]]
+   [nil "--disable-metric-store" "Disable writing to metric store"]
+   [nil "--elasticsearch-index INDEX"
+    (str "Elasticsearch index. Default: " pstore/default-es-index)]
+   [nil "--disable-path-store" "Disable writing to path store"]
+   ["-l" "--log-file FILE" (str "Log file. Default: " wlog/default-log-file)]
+   ["-L" "--log-level LEVEL"
+    (str "Log level (all, trace, debug, info, warn, error, fatal, off). "
+         "Default: " wlog/default-log-level)
+    :validate [#(or (= (count %) 0)
+                    (not= (get logconfig/levels % :not-found) :not-found))
+               "Invalid log level"]]
+   ["-e" "--errors-file FILE"
+    (str "Dump a list of files during processing which errors occurred")]
+   ["-S" "--stop-on-error" "Stop on first non-fatal error"]
+   ["-P" "--disable-progress" "Disable progress bar"]
+   ["-h" "--help" "Show this help"]])

 (defn- check-rollups
   "Check rollups."
@@ -173,60 +229,6 @@
   [command arguments options summary]
   (exit 0 (usage summary)))

-(def cli-options
-  [["-f" "--from FROM" "From time (Unix epoch)"
-    :parse-fn #(Integer/parseInt %)
-    :validate [#(<= 0 %) "Must be a number >= 0"]]
-   ["-t" "--to TO" "To time (Unix epoch)"
-    :parse-fn #(Integer/parseInt %)
-    :validate [#(< 0 %) "Must be a number > 0"]]
-   ["-r" "--run" "Force normal run (dry run using on default)"]
-   ["-R" "--rollups ROLLUPS"
-    "Define rollups. Format: <seconds_per_point[:retention],...> Example: 60,300:31536000"
-    :parse-fn #(parse-rollups %)
-    :validate [check-rollups "Invalid rollup"]]
-   ["-j" "--jobs JOBS" "Number of jobs to run simultaneously"
-    :parse-fn #(Integer/parseInt %)
-    :validate [#(< 0 %) "Must be a number > 0"]]
-   ["-T" "--min-ttl TTL" (str "Minimal TTL. Default: " core/default-min-ttl)
-    :parse-fn #(Integer/parseInt %)
-    :validate [#(< 0 %) "Must be a number > 0"]]
-   ["-D" "--root-dir DIRECTORY" "Root directory"]
-   [nil "--cassandra-keyspace KEYSPACE"
-    (str "Cassandra keyspace. Default: " mstore/default-cassandra-keyspace)]
-   ["-O" "--cassandra-options OPTIONS"
-    "Cassandra options. Example: \"{:compression :lz4}\""
-    :parse-fn #(read-string %)
-    :validate [#(= clojure.lang.PersistentArrayMap (type %))]]
-   [nil "--cassandra-channel-size SIZE"
-    (str "Cassandra channel size in points. Default: "
-         mstore/default-cassandra-channel-size)
-    :parse-fn #(Integer/parseInt %)
-    :validate [#(< 0 %) "Must be a number > 0"]]
-   [nil "--cassandra-batch-size SIZE"
-    (str "Cassandra batch size. Default: " mstore/default-cassandra-batch-size)
-    :parse-fn #(Integer/parseInt %)
-    :validate [#(< 0 %) "Must be a number > 0"]]
-   [nil "--cassandra-batch-rate RATE" "Cassandra batch rate (batches per second, 1-100)"
-    :parse-fn #(Integer/parseInt %)
-    :validate [#(< 0 % 101) "Must be a number between 1-100"]]
-   [nil "--disable-metric-store" "Disable writing to metric store"]
-   [nil "--elasticsearch-index INDEX"
-    (str "Elasticsearch index. Default: " pstore/default-es-index)]
-   [nil "--disable-path-store" "Disable writing to path store"]
-   ["-l" "--log-file FILE" (str "Log file. Default: " wlog/default-log-file)]
-   ["-L" "--log-level LEVEL"
-    (str "Log level (all, trace, debug, info, warn, error, fatal, off). "
-         "Default: " wlog/default-log-level)
-    :validate [#(or (= (count %) 0)
-                    (not= (get logconfig/levels % :not-found) :not-found))
-               "Invalid log level"]]
-   ["-e" "--errors-file FILE"
-    (str "Dump a list of files during processing which errors occurred")]
-   ["-S" "--stop-on-error" "Stop on first non-fatal error"]
-   ["-P" "--disable-progress" "Disable progress bar"]
-   ["-h" "--help" "Show this help"]])
-
 (defn- run-command
   "Run command."
   [arguments options summary]


Define compare function for keys

Define compare function for keys

--- src/aurora/btree.cljs
+++ src/aurora/btree.cljs
@@ -8,6 +8,15 @@

 (def left-child 0)
 (def right-child 1)
+
+(defn compare-keys [x y]
+  (cond (== x y) 0 (lt x y) -1 (gt x y) 1))
+
+(defn lt-fun [a b]
+  (lt a b))
+
+(defn gt-fun [a b]
+  (gt a b))

 (deftype Tree [max-keys ^:mutable root]
   Object
@@ -211,7 +220,7 @@
               (assert (>= (count keys) min-keys) (pr-str keys min-keys)))
             (assert (<= (count keys) max-keys) (pr-str keys max-keys))
             (assert (= (count keys) (count (set keys))))
-            (assert (= (seq keys) (seq (sort-by identity #(cond (== %1 %2) 0 (lt %1 %2) -1 (gt %1 %2) 1) keys))))
+            (assert (= (seq keys) (seq (sort-by identity compare-keys keys))))
             (assert (every? #(lte lower %) keys) (pr-str lower keys))
             (assert (every? #(gte upper %) keys) (pr-str upper keys))
             (if (nil? children)
@@ -225,11 +234,22 @@
                 (assert (= (count keys) (count vals) (dec (count children))) (pr-str keys vals children))
                 (assert (= lower (.-lower (aget children 0))) (pr-str lower (.-lower (aget children 0))))
                 (assert (= upper (.-upper (aget children (- (alength children) 1)))) (pr-str upper (.-upper (aget children (- (alength children) 1)))))
-                (assert (every? #((fn [a b] (gt a b)) (aget keys %) (.-upper (aget children %))) (range (count keys))))
-                (assert (every? #((fn [a b] (lt a b)) (aget keys %) (.-lower (aget children (inc %)))) (range (count keys))))
+                (assert (every? #(gt-fun (aget keys %) (.-upper (aget children %))) (range (count keys))))
+                (assert (every? #(lt-fun (aget keys %) (.-lower (aget children (inc %)))) (range (count keys))))
                 (dotimes [i (count children)] (.valid! (aget children i) max-keys))))))
   (pretty-print [this]
                 (str "(" parent-ix ")" "|" (pr-str lower) " " (pr-str (vec keys)) " " (pr-str upper) "|")))
+
+;; 'bool' < 'number' < 'string' < 'undefined'
+(def least false)
+(def greatest js/undefined)
+
+(defn tree [min-keys]
+  (let [node (Node. nil nil #js [] #js [] nil greatest least)
+        tree (Tree. (* 2 min-keys) node)]
+    (set! (.-parent node) tree)
+    (set! (.-parent-ix node) 0)
+    tree))

 (deftype Iterator [max-keys ^:mutable node ^:mutable ix ^:mutable end?]
   Object
@@ -290,19 +310,12 @@
 (defn iterator [tree]
   (loop [node (.-root tree)]
     (if (nil? (.-children node))
-      (Iterator. (.-max-keys tree) node -1 false)
+      (if (> (alength (.-keys node)) 0)
+        (Iterator. (.-max-keys tree) node -1 false)
+        (Iterator. (.-max-keys tree) node -1 true))
       (recur (aget (.-children node) 0)))))

-;; these types bound 'number' and 'string'
-(def least false)
-(def greatest js/undefined)
-
-(defn tree [min-keys]
-  (let [node (Node. nil nil #js [] #js [] nil greatest least)
-        tree (Tree. (* 2 min-keys) node)]
-    (set! (.-parent node) tree)
-    (set! (.-parent-ix node) 0)
-    tree))
+

 ;; TESTS

@@ -380,7 +393,7 @@

 (defn run-building-prop [min-keys actions]
   (let [tree (apply-to-tree (tree min-keys) actions)
-        sorted-map (apply-to-sorted-map (sorted-map-by #(cond (== %1 %2) 0 (lt %1 %2) -1 (gt %1 %2) 1)) actions)]
+        sorted-map (apply-to-sorted-map (sorted-map-by compare-keys) actions)]
     (and (= (seq (map vec tree)) (seq sorted-map))
          (.valid! tree))))

@@ -391,7 +404,7 @@

 (defn run-lookup-prop [min-keys actions action]
   (let [tree (apply-to-tree (tree min-keys) actions)
-        sorted-map (apply-to-sorted-map (sorted-map-by #(cond (== %1 %2) 0 (lt %1 %2) -1 (gt %1 %2) 1)) actions)
+        sorted-map (apply-to-sorted-map (sorted-map-by compare-keys) actions)
         tree-result (case (nth action 0)
                       :assoc! (.assoc! tree (nth action 1) (nth action 2))
                       :dissoc! (.dissoc! tree (nth action 1)))
@@ -431,12 +444,12 @@
                 (swap! elems rest)
                 (first (first @elems)))
         :seek (do
-                (swap! elems (fn [elems] (drop-while #((fn [a b] (lt a b)) (nth % 0) (nth movement 1)) elems)))
+                (swap! elems (fn [elems] (drop-while #(lt-fun (nth % 0) (nth movement 1)) elems)))
                 (first (first @elems)))))))

 (defn run-iterator-prop [min-keys actions movements]
   (let [tree (apply-to-tree (tree min-keys) actions)
-        sorted-map (apply-to-sorted-map (sorted-map-by #(cond (== %1 %2) 0 (lt %1 %2) -1 (gt %1 %2) 1)) actions)
+        sorted-map (apply-to-sorted-map (sorted-map-by compare-keys) actions)
         iterator-results (apply-to-iterator (iterator tree) movements)
         elems-results (apply-to-elems (seq sorted-map) movements)]
     (= iterator-results elems-results)))
@@ -496,4 +509,3 @@
      (doseq [[tree movements] benches]
        (apply-to-iterator (iterator tree) movements))))
  )
-


Sketch trieterator

Sketch trieterator

--- src/aurora/btree.cljs
+++ src/aurora/btree.cljs
@@ -372,6 +372,46 @@
         (Iterator. (.-max-keys tree) node 0 true))
       (recur (aget (.-children node) 0)))))

+(deftype Trieterator [iterator seek-key ^:mutable pinned-key ^:mutable pinned-key-ix ^:mutable moving-key-ix ^:mutable end?]
+  Object
+  (key [this]
+       (aget (.key iterator) moving-key-ix))
+  (val [this]
+       (.val iterator))
+  (maintain [this]
+             (if (or (.-end? iterator)
+                     (not (or (< pinned-key-ix 0) ;; nothing to pin
+                              (identical? pinned-key (aget (.key iterator) pinned-key-ix)))))
+               (set! end? true)
+               (set! end? false)))
+  (next [this]
+        (when (false? end?)
+          (.next iterator)
+          (.maintain this)))
+  (seek [this key]
+        (when (false? end?)
+          (aset seek-key moving-key-ix key)
+          (.seek iterator seek-key)
+          (.maintain this)))
+  (down [this]
+        (assert (false? end?))
+        (assert (< moving-key-ix (alength seek-key)))
+        (let [moving-key (.key this)]
+          (aset seek-key moving-key-ix moving-key)
+          (set! pinned-key moving-key)
+          (set! pinned-key-ix moving-key-ix)
+          (set! moving-key-ix (+ moving-key-ix 1))))
+  (up [this]
+      (assert (> moving-key-ix 0))
+      (set! moving-key-ix pinned-key-ix)
+      (set! pinned-key-ix (- pinned-key-ix 1))
+      (set! pinned-key (aget seek-key pinned-key-ix))
+      (aset seek-key moving-key-ix least)))
+
+(defn trieterator [tree]
+  (let [it (iterator tree)]
+    (Trieterator. it (least-key (.-key-len tree)) nil -1 0 (.-end? it))))
+
 (deftype Intersection [iterators ^:mutable end?]
   Object
   (key [this]


Add metric collection around aggregation cache hits, misses, and waits

--- src/cfpb/qu/cache.clj
+++ src/cfpb/qu/cache.clj
@@ -12,6 +12,7 @@
             [cfpb.qu.util :refer :all]
             [cfpb.qu.data.result :refer [->DataResult]]
             [cfpb.qu.data.aggregation :as agg]
+            [cfpb.qu.metrics :as metrics]
             [clojure.string :as str]
             [clojure.core.cache :as cache :refer [defcache]]
             [clj-time.core :refer [now]]
@@ -92,9 +93,11 @@
   ([database query not-found]
      (with-db database
        (let [collection (query-to-key query)]
-         (if (coll/exists? collection)
-           (extract-result collection query)
-           not-found)))))
+         (if (coll/exists? collection)
+           (do (metrics/increment "cache.hit")
+             (extract-result collection query))
+           (do (metrics/increment "cache.wait")
+               not-found))))))

 (defn add-to-cache
   "Add the specified aggregation to the cache by running it through
@@ -259,6 +262,7 @@
                                                  :status "unprocessed"
                                                  :created (now)
                                                  :aggmap (pr-str aggmap)})
+      (metrics/increment "cache.queue")
       (catch MongoException$DuplicateKey e
         (coll/find-map-by-id *work-collection* (:to aggmap))))))


put focus on username field when they hit the login screen; allow for pressing enter for form submission on login screen

--- src/client/login.cljs
+++ src/client/login.cljs
@@ -6,6 +6,10 @@

 (def $ js/$)

+;; TODO: move this to a dom namespace
+(defn- by-id [id]
+  (.getElementById js/document id))
+
 ;;------------------------------------------------------------------------------
 ;; HTML
 ;;------------------------------------------------------------------------------
@@ -13,9 +17,10 @@
 (hiccups/defhtml login-html []
   [:div#inner-container.login
     [:div.login-container
-      [:label "What is your name?"]
-      [:input.login-name {:type "text"}]
-      [:button#submit.lg-btn "OK"]]])
+      [:form
+        [:label "What is your name?"]
+        [:input#login.login-name {:type "text"}]
+        [:button#submit.lg-btn "OK"]]]])

 ;;------------------------------------------------------------------------------
 ;; Username storage.
@@ -51,10 +56,12 @@
 ;; Events
 ;;------------------------------------------------------------------------------

+;; TODO: what to do when they don't input a username? validation?
 (defn on-submit
   "Handle the submit event."
-  []
-  (let [input (.val ($ ".login-name"))]
+  [e]
+  (.preventDefault e)
+  (let [input (.val ($ "#login"))]
     (store-login! input)
     (send-login!)
     (aset js/location "hash" "#/menu")))
@@ -63,19 +70,19 @@
 ;; Page Initialization
 ;;------------------------------------------------------------------------------

-(defn init
-  []
+(defn init []

   ; Initialize page content
   (.html ($ "#main-container") (login-html))

   ; Populate username field.
-  (.val ($ ".login-name") (get-username))
+  (.val ($ "#login") (get-username))

   ; Set username on button click.
   (.click ($ "#submit") on-submit)

-  )
+  ; Put focus on username field.
+  (.focus (by-id "login")))

 (defn cleanup
   []


add proper `:return` handling to `cljs.test/test-ns`

--- src/clj/cljs/test.clj
+++ src/clj/cljs/test.clj
@@ -226,13 +226,17 @@
   Internally binds *report-counters* to a ref initialized to
   *initial-report-counters*.  Returns the final, dereferenced state of
   *report-counters*."
-  [[quote ns :as form]]
-  (assert (and (= quote 'quote) (symbol? ns)) "Argument to test-ns must be a quoted symbol")
-  `(-> (assoc (cljs.test/empty-env) :return true)
-     (cljs.test/do-report {:type :begin-test-ns, :ns ~form})
-     ;; If the namespace has a test-ns-hook function, call that:
-     ~(if-let [v (get-in @env/*compiler* [::ana/namespaces ns :defs 'test-ns-hook])]
-        `(~(symbol (name ns) "test-ns-hook"))
-        ;; Otherwise, just test every var in the namespace.
-        `(cljs.test/test-all-vars ~form))
-     (cljs.test/do-report {:type :end-test-ns, :ns ~form})))
+  ([ns] `(cljs.test/test-ns (cljs.test/empty-env) ~ns))
+  ([env [quote ns :as form]]
+   (assert (and (= quote 'quote) (symbol? ns)) "Argument to test-ns must be a quoted symbol")
+   `(let [env# ~env
+          return# (:return env#)
+          env'# (-> (assoc env# :return true)
+                  (cljs.test/do-report {:type :begin-test-ns, :ns ~form})
+                  ;; If the namespace has a test-ns-hook function, call that:
+                  ~(if-let [v (get-in @env/*compiler* [::ana/namespaces ns :defs 'test-ns-hook])]
+                     `(~(symbol (name ns) "test-ns-hook"))
+                     ;; Otherwise, just test every var in the namespace.
+                     `(cljs.test/test-all-vars ~form))
+                  (cljs.test/do-report {:type :end-test-ns, :ns ~form}))]
+      (when return# env'#))))


tweak compiler stats printing

tweak compiler stats printing

--- src/clj/cljs/util.clj
+++ src/clj/cljs/util.clj
@@ -139,6 +139,6 @@
     `(if ~enable
        (let [start# (. System (nanoTime))
              ret# ~expr]
-         (debug-prn ~msg ", elapsed time:" (/ (double (- (. System (nanoTime)) start#)) 1000000.0) "msecs")
+         (debug-prn (str ~msg ", elapsed time:") (/ (double (- (. System (nanoTime)) start#)) 1000000.0) "msecs")
          ret#)
        ~expr)))


add test helper to check if last log entry contains a string

--- src/clj/test/core.clj
+++ src/clj/test/core.clj
@@ -56,5 +56,11 @@
     (core/play state side {:card (find-card title (get-in @state [side :hand]))
                            :server server})))

+(defn last-log-contains?
+  [state content]
+  (not (nil?
+         (re-find (re-pattern content)
+                     (get (last (get-in @state [:log])) :text)))))
+
 (load "core-game")
 (load "cards")


force conversion to byte array before inflating to avoid ClassCastException.

--- src/clj_http/util.clj
+++ src/clj_http/util.clj
@@ -55,18 +55,25 @@
       (.close gos)
       (.toByteArray baos))))

+(defn- force-byte-array
+  "force b as byte array if it is an InputStream."
+  [b]
+  (if (instance? java.io.InputStream b)
+    (IOUtils/toByteArray b)
+    b))
+
 (defn inflate
-  "Returns a zlib inflate'd version of the given byte array."
+  "Returns a zlib inflate'd version of the given byte array or InputStream."
   [b]
-  (when b
+  (when-let [data-arr (force-byte-array b)]
     (try
-      (IOUtils/toByteArray (InflaterInputStream. (ByteArrayInputStream. b)))
-      ;; broken inflate implementation server-side,
+      (IOUtils/toByteArray (InflaterInputStream. (ByteArrayInputStream. data-arr)))
+      ;; broken inflate implementation server-side
       ;; see [http://stackoverflow.com/questions/3932117/handling-http
       ;; -contentencoding-deflate]
       (catch java.util.zip.ZipException e
         (IOUtils/toByteArray
-         (InflaterInputStream. (ByteArrayInputStream. b)
+         (InflaterInputStream. (ByteArrayInputStream. data-arr)
                                (java.util.zip.Inflater. true)))))))

 (defn deflate


Workaround for figwheel's CSS reloading breakage

--- frontend/src-dev/faceboard/figwheel.cljs
+++ frontend/src-dev/faceboard/figwheel.cljs
@@ -6,4 +6,6 @@
 ; this is our workaround to include it only in dev builds

 (defn start []
-  (fw/start {:on-jsload (fn [] (. js/window faceboard_reloader))}))+  (fw/start
+    {:on-jsload    (fn [] (. js/window faceboard_reloader))
+     :url-rewriter (fn [url] (clojure.string/replace url "resources/public/" ""))}))


Fix application fmap for maps

Fix application fmap for maps

--- src/deepfns/core.cljc
+++ src/deepfns/core.cljc
@@ -17,10 +17,29 @@
 (defn- fset [f m]
   (into #{} (map (partial deepfmap f) m)))

-(defn- fassc [f m]
-  (reduce (fn [acc [k v]]
-            (assoc acc k (deepfmap f v)))
-    {} m))
+(defn- group-vals [ms k]
+  (let [matches (map #(find % k) ms)]
+    (when-not (every? nil? matches)
+      (vals (remove nil? matches)))))
+
+(defn apply-key [f ms k]
+  [k (apply (partial deepfmap f)
+       (group-vals ms k))])
+
+(defn- fassc
+  ([f m]
+   (reduce (fn [acc [k v]]
+             (assoc acc k (deepfmap f v)))
+     {} m))
+  ([f m ms]
+   (let [mcoll (cons m ms)]
+     (reduce-kv (fn [acc mk mv]
+                  ;; find all the matching keys in mcoll
+                  (when-let [keys (into #{} (flatten (map keys mcoll)))]
+                    (into {}
+                      ;; eval the nested maps and bind them to the output
+                      (map (partial apply-key f mcoll) keys))))
+       m m))))

 (defn deepfmap
   "Like fmap but it will recursively evalute all nested collections"
@@ -46,16 +65,16 @@
      (f m)))
   ([f m & ms]
    ;; same thing here but we'll mutually walk ms
-   (let [ms (cons m ms)]
+   (let [mcoll (cons m ms)]
      (cond
-       (list? m) (map (partial flst f) ms)
-       (vector? m) (map (partial fvec f) ms)
-       (seq? m) (map (partial fseq f) ms)
-       (set? m) (map (partial fset f) ms)
-       (associative? m) (map (partial fassc f) ms)
-       (fn? m) (map #(comp f %) ms)
+       (list? m) (map (partial flst f) mcoll)
+       (vector? m) (map (partial fvec f) mcoll)
+       (seq? m) (map (partial fseq f) mcoll)
+       (set? m) (map (partial fset f) mcoll)
+       (associative? m) (fassc f m ms)
+       (fn? m) (map #(comp f %) mcoll)
        :else
-       (map f ms)))))
+       (apply f mcoll)))))

 (def <-$>
   "An alias for deepfmap"
@@ -63,7 +82,7 @@

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; fapply + pure
+;;; fapply + pure + filterapply

 (declare deepfapply)

@@ -97,11 +116,6 @@
   ([fs m ms]
    (apply vector
      (mapcat #(apply map (partial deepfapply %) m ms) fs))))
-
-(defn- group-keys [ms k]
-  (let [matches (map #(find % k) ms)]
-    (when-not (every? nil? matches)
-        (vals matches))))

 (defn- assc-fapply
   ([fs m]
@@ -114,7 +128,7 @@
    (let [mcoll (cons m ms)]
      (reduce-kv (fn [acc fk f]
                   ;; find all the matching keys in mcoll
-                  (when-let [vals (group-keys mcoll fk)]
+                  (when-let [vals (group-vals mcoll fk)]
                     (assoc acc fk
                       ;; eval the nested maps and bind them to the output
                       (apply (partial deepfapply f) vals))))
@@ -207,16 +221,18 @@
                 (if-let [[_ mv] (find m fk)]
                   (assoc acc fk (filterapply f mv))
                   acc))
+     ;; start with an empty map to filter vals not in applicative
      {} fs))
   ([fs m ms]
    (let [mcoll (cons m ms)]
      (reduce-kv (fn [acc fk f]
                   ;; find all the matching keys in mcoll
-                  (if-let [vals (group-keys mcoll fk)]
+                  (if-let [vals (group-vals mcoll fk)]
                     (assoc acc fk
                       ;; eval the nested maps and bind them to the output
                       (apply (partial filterapply f) vals))
                     acc))
+       ;; use the empty map here too
        {} fs))))

 (defn filterapply
@@ -229,32 +245,22 @@
        (filterapply f m))))
   ([fs m]
    (cond
-     ;; map the fn for sequential/set types
      (list? fs) (lst-fapply fs m)
      (seq? fs) (seq-fapply fs m)
      (vector? fs) (vec-fapply fs m)
      (set? fs) (set-fapply fs m)
-     ;; match keys for maps and if found apply the fn (otherwise
-     ;;  just leave it)
      (map? fs) (assc-filterapply fs m)
-     ;; base cases:
-     ;; either use the fn
      (fn? fs) (fs m)
      :else
-     ;; or wrap list atoms in a constantly
      ((constantly fs) m)))
   ([fs m & ms]
    (let [mcoll (cons m ms)]
      (cond
-       ;; mapcat all the results for sequential/set types
        (list? fs) (lst-fapply fs m ms)
        (seq? fs) (seq-fapply fs m ms)
        (vector? fs) (vec-fapply fs m ms)
        (set? fs) (set-fapply fs m ms)
-       ;; match all keys for maps and apply the fn if ther was a match
        (map? fs) (assc-filterapply fs m ms)
-       ;; apply the fn to the args
        (fn? fs) (apply fs mcoll)
        :else
-       ;; list atoms should be constants
        (map (constantly fs) mcoll)))))


add envs table

add envs table

--- user.clj
+++ user.clj
@@ -69,6 +69,9 @@
        :sort true
        options)))

+(defn envs "List of envs and their values" []
+  (->> (System/getenv) keys (reduce #(assoc %1 %2 (System/getenv %2)) {}) table.core/table))
+
 ; Configuration
 (set! clojure.core/*print-length* 100)
 (set! clojure.core/*print-level* 5)


add translation params

add translation params

--- src/fleet/runtime.clj
+++ src/fleet/runtime.clj
@@ -35,15 +35,17 @@

 (def ^clojure.lang.Keyword ^:dynamic *transDomain* "Translation (i18n) domain: Clojure keyword" nil)
 (def ^clojure.lang.IFn     ^:dynamic translate
-  (fn [escaping-fn in transDomain]
+  (fn [escaping-fn in transDomain & args]
     (assert false (str "{fleet.runtime/translate unbound, input: '" in "'}"))))

 (defn _
   "Translation function shorthand: will call (translate escaping-fn word transDomain)."
   ([escaping-fn word]
-    (translate escaping-fn word *transDomain*))
+   (translate escaping-fn word *transDomain*))
   ([escaping-fn word transDomain]
-    (translate escaping-fn word transDomain)))
+   (translate escaping-fn word transDomain))
+  ([escaping-fn word transDomain & args]
+   (apply translate escaping-fn word transDomain args)))

 (defn make-runtime
   "Create runtime functions applied to specified escaping-fn."


rearrange and clean things up a bit

rearrange and clean things up a bit

--- src/gitmirth/core.clj
+++ src/gitmirth/core.clj
@@ -1,51 +1,56 @@
 (ns gitmirth.core
   (:gen-class)
   (:require [clj-http.client :as client]
+            [clojure
+             [pprint :as pp]
+             [zip :as zip]]
             [clojure.data.xml :as xml]
-            [clojure.data.zip.xml :as zx]
-            [clojure.zip :as zip]))
-
-(def api-url "https://misc:8443/api")
-
-(defn with-authentication
-  "Binds a cookie store to keep auth cookies, authenticates, and
-  returns the results of executing the supplied fn"
-  [func]
-  (binding [clj-http.core/*cookie-store* (clj-http.cookies/cookie-store)]
-    (client/post
-     (str api-url "/users/_login")
-     {:form-params
-      {:username "admin"
-       :password "admin"}
-      :insecure? true})
-    (func)))
-
-(defn fetch-all-channels-xml
-  "Fetch all channels from remote server"
-  []
-  (:body (client/get (str api-url "/channels") {:insecure? true})))
+            [clojure.data.zip.xml :as zx]))

 (defn to-zip
   "Takes a string of xml and returns an xml zipper"
   [x]
   (zip/xml-zip (xml/parse-str x)))

-(defn process-channels
-  ""
-  []
-  (let [channel-zips (zx/xml-> (to-zip (fetch-all-channels-xml)) :list :channel)]
-    (map #(zx/xml-> % :name zip/down zip/node) channel-zips)))
+(defn with-authentication
+  "Binds a cookie store to keep auth cookies, authenticates using the
+  supplied url/credentials, and returns the results of executing the
+  supplied fn"
+  [base-url username password func]
+  (binding [clj-http.core/*cookie-store* (clj-http.cookies/cookie-store)]
+    (client/post
+     (str base-url "/users/_login")
+     {:form-params
+      {:username username
+       :password password}
+      :insecure? true})
+    (func)))

-(defn foo
-  ""
-  []
-  (process-channels))
+(defn fetch-all-channels-zip
+  "Fetch all channels from remote server"
+  [base-url]
+  (-> base-url
+      (str "/channels")                 ;combine the base url with the rest path
+      (client/get                       ;fetch the channels via rest
+       {:insecure? true})
+      :body                             ;extract the response body
+      to-zip                            ;get an xml zipper
+      (zx/xml-> :list :channel)         ;get a zipper per channel
+      ))

-(defn dostuff
+(defn process-channel
+  "Take a channel zip and write to the filesystem"
+  [chanzip]
+  (zx/xml-> chanzip :name zip/down zip/node))
+
+(defn makeitso
   "App logic"
-  []
-  (with-authentication foo))
+  [base-url username password]
+  (with-authentication base-url username password
+    #(map process-channel (fetch-all-channels-zip base-url))))

 (defn -main
   [& args]
-  (dostuff))
+  (println "starting")
+  (pp/pprint (makeitso "https://misc:8443/api" "admin" "admin"))
+  (println "finished"))


Implemented view for adding new messages.

--- app/src/clj_web_example/ui/view/new_message.cljs
+++ app/src/clj_web_example/ui/view/new_message.cljs
@@ -1,6 +1,38 @@
 (ns clj-web-example.ui.view.new-message
-  (:require [clj-web-example.ui.view.view :as view]))
+  (:require [reagent.core :as reagent]
+            [clj-web-example.ui.utils :as utils]
+            [clj-web-example.ui.route :as route]
+            [clj-web-example.localization :refer [tr]]
+            [clj-web-example.ui.view.view :as view]))
+
+(defonce new-message (reagent/atom nil))
+
+(defn send-message
+  []
+  (utils/http-post! "/api/messages"
+                   @new-message
+                   #(do
+                      (reset! new-message nil)
+                      (route/modify-location-hash! "#"))))
+
+(defn atom-input
+  [label-text atom key]
+  [:div
+   [:label label-text]
+   [:input {:type "text"
+            :value (key @atom)
+            :on-change #(swap! atom assoc key (-> % .-target .-value))}]])
+
+(defn new-message-form
+  []
+  [:div
+   [atom-input (tr :sender) new-message :sender]
+   [atom-input (tr :message) new-message :body]
+   [:button {:type "button"
+             :on-click send-message}
+    (tr :submit)]])

 (defmethod view/render-view "new-message" []
   [:div#content
-   [:h2 "Here will be form!"]])
+   [:h2 "New message"]
+   [new-message-form]])


make the jetty webserver startup more configurable.  also enhancing the overall init process a bit so that if any exception gets thrown during init we stop and don't start the webserver.

--- src/metabase/core.clj
+++ src/metabase/core.clj
@@ -38,23 +38,38 @@
   "General application initialization function which should be run once at application startup."
   []
   (log/info "Metabase Initializing ... ")
+  (log/debug "Using Config:\n" (with-out-str (clojure.pprint/pprint config/config-all)))

   ;; startup database.  validates connection & runs any necessary migrations
-  ;; TODO - allow for env configuration regarding migrations process
-  (db/setup true)
+  (db/setup (config/config-bool :mb-db-automigrate))

-  (log/info "Metabase Initialization COMPLETE"))
+  ;; this is a temporary need until we finalize the code for bootstrapping the first user
+  (when-not (db/exists? metabase.models.user/User :id 1)
+    (db/ins metabase.models.user/User :email "admin@admin.com" :first_name "admin" :last_name "admin" :password "admin" :is_superuser true))
+
+  (log/info "Metabase Initialization COMPLETE")
+  true)

 (defn -main
   "Launch Metabase in standalone mode."
   [& args]
-  (log/info "Launching Metabase in STANDALONE mode")
+  (log/info "Starting Metabase in STANDALONE mode")

-  ;; run our main initialization function
-  (init)
-
-  ;; startup webserver
-  ;; TODO - allow for env configuration
-  (let [jetty-config {:port 3000}]
-    (ring-jetty/run-jetty app jetty-config)))+  ;; run application init and if there are no issues then continue on to launching the webserver
+  (when (try
+          (init)
+          (catch Exception e
+            (log/error "Metabase Initialization FAILED: " (.getMessage e))))
+    ;; startup webserver
+    (let [jetty-config (->> {:port (config/config-int :mb-jetty-port)
+                             :host (config/config-str :mb-jetty-host)
+                             :join? (config/config-bool :mb-jetty-join?)
+                             :daemon? (config/config-bool :mb-jetty-daemon?)
+                             :max-threads (config/config-int :mb-jetty-maxthreads)
+                             :min-threads (config/config-int :mb-jetty-minthreads)
+                             :max-queued (config/config-int :mb-jetty-maxqueued)
+                             :max-idle-time (config/config-int :mb-jetty-maxidletime)}
+                         (medley/filter-vals identity))]
+      (log/info "Launching Embedded Jetty Webserver with config:\n" (with-out-str (clojure.pprint/pprint jetty-config)))
+      (ring-jetty/run-jetty app jetty-config))))