Close proxy channels when a transport goes away

--- src/dragonmark/circulate/core.cljx
+++ src/dragonmark/circulate/core.cljx
@@ -823,8 +823,16 @@

             (async/close! remote-proxy)
             (do
-              (async/>! sender-chan {:type :bye})
+              (async/put! sender-chan {:type :bye})
               (reset! running? false))
+              (dorun
+               (as-> @guid-to-chan
+                     info
+                     (vals info)
+                     (filter :proxy info)
+                     (map :chan info)
+                     (map async/close! info)
+                     ))
             ;; FIXME what else do we close down?
             )
           (proxy-info [this] [chan-to-guid guid-to-chan])


fixed some formatting

fixed some formatting

--- src/frontend/server-interface.cljs
+++ src/frontend/server-interface.cljs
@@ -101,37 +101,37 @@
     (println "Received set-loop signal with looping?:" looping?)
     (swap! app-state/app-state assoc :looping? looping?)))

-(.oncore/socket "hash-found"
+(.on core/socket "hash-found"
   (fn [file-hash]
     (println "File exists on server. Hash: " file-hash)
     (swap! app-state/app-state assoc :file-hashes (dissoc (:file-hashes @app-state/app-state) file-hash))))

-(.oncore/socket "hash-not-found"
+(.on core/socket "hash-not-found"
   (fn [file-hash]
     (println "File does not exist on server. Will upload. Hash: " file-hash)
     (let [file (get (:file-hashes @app-state/app-state) file-hash)]
       (swap! app-state/app-state assoc :file-hashes (dissoc (:file-hashes @app-state/app-state) file-hash))
       (core/upload-file file))))

-(.oncore/socket "user-muted"
+(.on core/socket "user-muted"
   (fn [socket-id]
     (println "Received mute-user signal for"socket-id)
     (swap! app-state/app-state assoc :users (merge (:users @app-state/app-state)
                                          {socket-id (merge (get (:users @app-state/app-state ) socket-id)
                                                            {"muted" true})}))))

-(.oncore/socket "user-unmuted"
+(.on core/socket "user-unmuted"
   (fn [socket-id]
     (println "Received umute-user signal for"socket-id)
     (swap! app-state/app-state assoc :users (merge (:users @app-state/app-state)
                                          {socket-id (merge (get (:users @app-state/app-state) socket-id)
                                                            {"muted" false})}))))

-(.oncore/socket "upload-cancelled"
+(.on core/socket "upload-cancelled"
   (fn [id]
     (swap! app-state/app-state assoc :current-uploads-info
       (dissoc (:current-uploads-info @app-state/app-state) id))))

-(.oncore/socket "track-order-change"
+(.on core/socket "track-order-change"
   (fn [track-order]
     (swap! app-state/app-state assoc :track-order (js->clj track-order))))


Further protection to bad tags

Further protection to bad tags

--- src/cljs-admin/sbsk_admin/events.cljs
+++ src/cljs-admin/sbsk_admin/events.cljs
@@ -270,11 +270,12 @@
  :edit-current-video/add-tag
  (fn  [db [_ tag]]
    (if-not (clojure.string/blank? tag)
-     (let [db' (-> db
+     (let [tag' (clojure.string/trim tag)
+           db' (-> db
                    (assoc :dirty? true)
                    (update-in [:current-video :meta :tags] set)
-                   (update-in [:current-video :meta :tags] conj tag)
-                   (update-in [:tags] conj tag))]
+                   (update-in [:current-video :meta :tags] conj tag')
+                   (update-in [:tags] conj tag'))]
        (db/reintegrate-current-video db'))
      db)))


Extract features from wiki titles

Extract features from wiki titles

--- src/clojure/real_wsdm/wiki_ngrams.clj
+++ src/clojure/real_wsdm/wiki_ngrams.clj
@@ -29,8 +29,21 @@
     {}
     (map #(->> % tokenize (map stem) extract-ngrams) lines)))

-(defn -main
+(defn titles
+  [lines]
+  (reduce
+    add-ngram
+    {}
+    (filter #(<= (count %) 3) (map #(->> % tokenize (map stem)) lines))))
+
+(defn extract-ngrams
   [wiki-titles-path]
   (with-open [rdr (io/reader wiki-titles-path)]
-    (doseq [[:ngram count] (ngram-count (line-seq rdr))]
+    (doseq [[ngram count] (ngram-count (line-seq rdr))]
       (println (str (str/join " " ngram) "\t" count)))))
+
+(defn extract-titles
+  [wiki-titles-path]
+  (with-open [rdr (io/reader wiki-titles-path)]
+    (doseq [[ngram _] (titles (line-seq rdr))]
+      (println (str (str/join " " ngram) "\t" 100)))))


remove selected jobs

remove selected jobs

--- src-cljs/frontend/components/pages/run.cljs
+++ src-cljs/frontend/components/pages/run.cljs
@@ -50,8 +50,7 @@
              job-name :job/name
              run :job/run
              {:keys [build/vcs-type build/org build/repo build/number]} :job/build}
-            (om-next/props this)
-            {:keys [selected?]} (om-next/get-computed this)]
+            (om-next/props this)]
         (card/basic
          (element :content
            (html
@@ -60,15 +59,13 @@
               [:div.status-heading
                [:div.status-name
                 [:span.job-status (status/icon (status-class status))]
-                (if selected?
-                  [:span.job-name job-name]
-                  [:a {:href
-                       (routes/v1-build-path vcs-type
-                                             org
-                                             repo
-                                             nil
-                                             number)}
-                   [:span.job-name job-name]])]
+                [:a {:href
+                     (routes/v1-build-path vcs-type
+                                           org
+                                           repo
+                                           nil
+                                           number)}
+                 [:span.job-name job-name]]]
                [:div.status-actions
                 (button/icon {:label "Retry job-name"
                               :disabled? true}


reverted opts back to being a lazy seq in button-ajax so we don't break the ajax call

--- src-cljs/frontend/controllers/controls.cljs
+++ src-cljs/frontend/controllers/controls.cljs
@@ -74,9 +74,11 @@
 (defn button-ajax
   "An ajax/ajax wrapper that releases the current managed-button after the API
   request.  Exists to faciliate migration away from stateful-button."
-  [method url message channel & {:keys [events] :as opts}]
-  (let [uuid frontend.async/*uuid*
-        c (chan)]
+  [method url message channel & opts]
+  (let [uuid frontend.async/*uuid*
+        c (chan)
+        events (-> (apply hash-map opts)
+                   :events)]
     (apply ajax/ajax method url message c opts)
     (go-loop []
       (when-let [[_ status _ :as event] (<! c)]


fix copy/paste origin without destination

--- src-cljs/frontend/controllers/controls.cljs
+++ src-cljs/frontend/controllers/controls.cljs
@@ -1370,7 +1370,7 @@
                                     :layer/document doc-id
                                     :points (when (:layer/path l) (parse-points-from-path (:layer/path l))))
                              (utils/update-when-in [:layer/points-to] (fn [dests]
-                                                                        (set (map #(update-in % [:db/id] eid-map) dests))))
+                                                                        (set (filter :db/id (map #(update-in % [:db/id] eid-map) dests)))))
                              (#(move-layer % %
                                            {:snap-x snap-move-x :snap-y snap-move-y
                                             :move-x move-x :move-y move-y :snap-paths? true}))


Add proportion lock to icons

Add proportion lock to icons

--- frontend/src/uxbox/main/ui/workspace/sidebar/options/icon_measures.cljs
+++ frontend/src/uxbox/main/ui/workspace/sidebar/options/icon_measures.cljs
@@ -40,7 +40,11 @@
                   value (parse-int value nil)
                   sid (:id shape)
                   props {attr value}]
-              (st/emit! (uds/update-position sid props))))]
+              (st/emit! (uds/update-position sid props))))
+          (on-proportion-lock-change [event]
+            (if (:proportion-lock shape)
+              (st/emit! (uds/unlock-proportions (:id shape)))
+              (st/emit! (uds/lock-proportions (:id shape)))))]
     (let [size (geom/size shape)]
       (html
        [:div.element-set {:key (str (:id menu))}
@@ -56,7 +60,10 @@
              :min "0"
              :value (precision (:width size) 2)
              :on-change (partial on-size-change :width)}]]
-          [:div.lock-size i/lock]
+          [:div.lock-size
+           {:class (when (:proportion-lock shape) "selected")
+            :on-click on-proportion-lock-change}
+           i/lock]
           [:div.input-element.pixels
            [:input.input-text
             {:placeholder "Height"


Add performance check on auto-diff.

Add performance check on auto-diff.

--- ws/expression-performance.clj
+++ ws/expression-performance.clj
@@ -45,20 +45,21 @@
 (interpreter/->jexpr vars expr)
 ;; @@
 ;; =>
-;;; {"type":"html","content":"#<Plus algebolic.expression.Plus@560ea43b>","value":"#<Plus algebolic.expression.Plus@560ea43b>"}
+;;; {"type":"html","content":"#<Plus algebolic.expression.Plus@6d5c05f3>","value":"#<Plus algebolic.expression.Plus@6d5c05f3>"}
 ;; <=

 ;; @@
 (criterium/quick-bench (interpreter/->jexpr vars expr))
 ;; @@
 ;; ->
-;;; WARNING: Final GC required 32.09562087113482 % of runtime
-;;; Evaluation count : 1252098 in 6 samples of 208683 calls.
-;;;              Execution time mean : 517.630096 ns
-;;;     Execution time std-deviation : 18.672823 ns
-;;;    Execution time lower quantile : 493.348366 ns ( 2.5%)
-;;;    Execution time upper quantile : 540.500155 ns (97.5%)
-;;;                    Overhead used : 1.964170 ns
+;;; WARNING: Final GC required 3.7470610997475293 % of runtime
+;;; WARNING: Final GC required 31.738205166041112 % of runtime
+;;; Evaluation count : 1241982 in 6 samples of 206997 calls.
+;;;              Execution time mean : 503.066835 ns
+;;;     Execution time std-deviation : 10.441452 ns
+;;;    Execution time lower quantile : 490.550936 ns ( 2.5%)
+;;;    Execution time upper quantile : 515.515403 ns (97.5%)
+;;;                    Overhead used : 2.030744 ns
 ;;;
 ;; <-
 ;; =>
@@ -76,13 +77,13 @@
 (criterium/quick-bench (interpreter/evaluate expr vars coords))
 ;; @@
 ;; ->
-;;; WARNING: Final GC required 33.70842496708887 % of runtime
-;;; Evaluation count : 22902 in 6 samples of 3817 calls.
-;;;              Execution time mean : 27.058773 µs
-;;;     Execution time std-deviation : 1.544751 µs
-;;;    Execution time lower quantile : 25.369139 µs ( 2.5%)
-;;;    Execution time upper quantile : 28.550102 µs (97.5%)
-;;;                    Overhead used : 1.964170 ns
+;;; WARNING: Final GC required 31.395296907447566 % of runtime
+;;; Evaluation count : 22866 in 6 samples of 3811 calls.
+;;;              Execution time mean : 25.616821 µs
+;;;     Execution time std-deviation : 468.087448 ns
+;;;    Execution time lower quantile : 25.035431 µs ( 2.5%)
+;;;    Execution time upper quantile : 26.171148 µs (97.5%)
+;;;                    Overhead used : 2.030744 ns
 ;;;
 ;; <-
 ;; =>
@@ -104,17 +105,13 @@
 (criterium/quick-bench (score/abs-error vars coords data expr))
 ;; @@
 ;; ->
-;;; WARNING: Final GC required 31.79588711321808 % of runtime
-;;; Evaluation count : 19278 in 6 samples of 3213 calls.
-;;;              Execution time mean : 32.052864 µs
-;;;     Execution time std-deviation : 326.871096 ns
-;;;    Execution time lower quantile : 31.512308 µs ( 2.5%)
-;;;    Execution time upper quantile : 32.442756 µs (97.5%)
-;;;                    Overhead used : 1.928557 ns
-;;;
-;;; Found 1 outliers in 6 samples (16.6667 %)
-;;; 	low-severe	 1 (16.6667 %)
-;;;  Variance from outliers : 13.8889 % Variance is moderately inflated by outliers
+;;; WARNING: Final GC required 28.82074300864181 % of runtime
+;;; Evaluation count : 19266 in 6 samples of 3211 calls.
+;;;              Execution time mean : 33.961617 µs
+;;;     Execution time std-deviation : 693.839476 ns
+;;;    Execution time lower quantile : 33.087240 µs ( 2.5%)
+;;;    Execution time upper quantile : 34.735046 µs (97.5%)
+;;;                    Overhead used : 2.030744 ns
 ;;;
 ;; <-
 ;; =>
@@ -150,6 +147,27 @@
 ;; <=

 ;; **
+;;; Evaluation with derivatives speed:
+;; **
+
+;; @@
+(criterium/quick-bench (interpreter/evaluate-d expr vars coords))
+;; @@
+;; ->
+;;; WARNING: Final GC required 29.61508409878209 % of runtime
+;;; Evaluation count : 7164 in 6 samples of 1194 calls.
+;;;              Execution time mean : 88.134369 µs
+;;;     Execution time std-deviation : 3.554069 µs
+;;;    Execution time lower quantile : 83.040215 µs ( 2.5%)
+;;;    Execution time upper quantile : 90.738566 µs (97.5%)
+;;;                    Overhead used : 2.030744 ns
+;;;
+;; <-
+;; =>
+;;; {"type":"html","content":"nil","value":"nil"}
+;; <=
+
+;; **
 ;;; ## Expression manipulation
 ;; **


Time render!

Time render!

--- src/aurora/editor/ui.cljs
+++ src/aurora/editor/ui.cljs
@@ -509,6 +509,7 @@
 (def queued? false)

 (defn render! []
+  (js/console.time "render!")
   (let [start (now)
         tree (root-ui)]
     (js/React.renderComponent (node tree) (dom/$ "#wrapper"))
@@ -527,6 +528,7 @@
     (when-let [rp (dom/$ "#render-perf")]
       (dom/html rp (.toFixed (- (now) start) 3)))
     (set! queued? false)
+    (js/console.timeEnd "render!")
     ))

 (defn queue-render []


swap deprecated sente adapter with new style

--- src/braid/server/sync.clj
+++ src/braid/server/sync.clj
@@ -1,8 +1,7 @@
 (ns braid.server.sync
   (:require [mount.core :as mount :refer [defstate]]
             [taoensso.sente :as sente]
-            [taoensso.sente.server-adapters.http-kit
-             :refer [sente-web-server-adapter]]
+            [taoensso.sente.server-adapters.http-kit :refer [get-sch-adapter]]
             [taoensso.sente.packers.transit :as sente-transit]
             [compojure.core :refer [GET POST routes defroutes context]]
             [ring.middleware.anti-forgery :refer [*anti-forgery-token*]]
@@ -26,7 +25,7 @@
 (let [packer (sente-transit/get-transit-packer :json)
       {:keys [ch-recv send-fn ajax-post-fn ajax-get-or-ws-handshake-fn
               connected-uids]}
-      (sente/make-channel-socket! sente-web-server-adapter
+      (sente/make-channel-socket! (get-sch-adapter)
                                   {:user-id-fn
                                    (fn [ob] (get-in ob [:session :user-id]))
                                    :packer packer})]


add util fn to parse transit

add util fn to parse transit

--- src/braid/server/util.clj
+++ src/braid/server/util.clj
@@ -25,3 +25,8 @@
         writer (transit/writer out :msgpack)]
     (transit/write writer form)
     (.toByteArray out)))
+
+(defn transit->form
+  [^bytes ts]
+  (let [in (ByteArrayInputStream. ts)]
+    (transit/read (transit/reader in :msgpack))))


Code layout fixes

Code layout fixes

--- src/catalog/web/views.clj
+++ src/catalog/web/views.clj
@@ -267,10 +267,14 @@
       (anti-forgery-field)
       [:div.form-group
        (form/label "editorial" "Editorial:")
-       (form/text-area {:class "form-control" :data-provide "markdown" :data-hidden-buttons "cmdImage cmdCode" :data-resize "vertical" :rows 30} "editorial" editorial)]
+       (form/text-area {:class "form-control" :data-provide "markdown"
+                        :data-hidden-buttons "cmdImage cmdCode"
+                        :data-resize "vertical" :rows 30} "editorial" editorial)]
       [:div.form-group
        (form/label "recommended" "Buchtipps:")
-       (form/text-area {:class "form-control" :data-provide "markdown" :data-hidden-buttons "cmdImage cmdCode" :data-resize "vertical" :rows 30} "recommended" recommendation)]
+       (form/text-area {:class "form-control" :data-provide "markdown"
+                        :data-hidden-buttons "cmdImage cmdCode"
+                        :data-resize "vertical" :rows 30} "recommended" recommendation)]
       (form/submit-button {:class "btn btn-default"} "Submit")))))

 (defn editorial [request fmt year issue editorial recommended]


The world-fence now uses world-cmd-loop.

--- src/cbfg/world-fence.cljs
+++ src/cbfg/world-fence.cljs
@@ -1,11 +1,10 @@
 (ns cbfg.world-fence
-  (:require-macros [cbfg.ago :refer [ago-loop achan-buf aalts aput]])
+  (:require-macros [cbfg.ago :refer [achan-buf]])
   (:require [cljs.core.async :refer [chan]]
             [cbfg.vis :refer [vis-init get-el-value]]
             [cbfg.fence :refer [make-fenced-pump]]
             [cbfg.fence-test]
-            [cbfg.world-base :refer [replay-cmd-ch world-replay
-                                     render-client-hist start-test]]))
+            [cbfg.world-base :refer [replay-cmd-ch world-cmd-loop start-test]]))

 (def cmd-handlers
   {"add"    (fn [c] (assoc c :rq #(cbfg.world-base/example-add % c)))
@@ -22,29 +21,12 @@
                                         :x (js/parseInt (get-el-value "x"))
                                         :y (js/parseInt (get-el-value "y"))
                                         :delay (js/parseInt (get-el-value "delay"))
-                                        :fence (= (get-el-value "fence") "1")}))
-        client-hist (atom {})] ; Keyed by opaque -> [request, replies].
+                                        :fence (= (get-el-value "fence") "1")}))]
     (vis-init (fn [world vis-chs]
                 (let [in-ch (achan-buf world 100)
                       out-ch (achan-buf world 0)]
-                  (ago-loop client world [num-ins 0 num-outs 0]
-                            (let [[v ch] (aalts client [cmd-ch out-ch])
-                                  ts (+ num-ins num-outs)]
-                              (cond
-                               (= ch cmd-ch) (if (= (:op v) "replay")
-                                               (world-replay in-ch vis-chs world-vis-init el-prefix
-                                                             @client-hist (:replay-to v))
-                                               (let [cmd (assoc-in v [:opaque] ts)
-                                                     cmd-rq ((get cmd-handlers (:op cmd)) cmd)]
-                                                 (render-client-hist (swap! client-hist
-                                                                            #(assoc % ts [cmd nil])))
-                                                 (aput client in-ch cmd-rq)
-                                                 (recur (inc num-ins) num-outs)))
-                               (= ch out-ch) (when v
-                                               (do (render-client-hist (swap! client-hist
-                                                                              #(update-in % [(:opaque v) 1]
-                                                                                conj [ts v])))
-                                                   (recur num-ins (inc num-outs)))))))
+                  (world-cmd-loop world cmd-handlers cmd-ch
+                                  in-ch out-ch vis-chs world-vis-init el-prefix)
                   (make-fenced-pump world "main" in-ch out-ch @max-inflight true)))
               el-prefix nil init-event-delay)
     cmd-inject-ch))


check that we actually read something in cjls.repl.server/read-request

--- src/main/clojure/cljs/repl/server.clj
+++ src/main/clojure/cljs/repl/server.clj
@@ -90,11 +90,12 @@
      :headers headers}))

 (defn read-request [rdr]
-  (let [line (.readLine rdr)]
+  (if-let [line (.readLine rdr)]
     (cond
       (.startsWith line "POST") (read-post line rdr)
       (.startsWith line "GET") (read-get line rdr)
-      :else {:method :unknown :content line})))
+      :else {:method :unknown :content line})
+    {:method :unknown :content nil}))

 (defn- status-line [status]
   (case status


:lipstick: Minor code reorganization on data.workspace ns file.

--- frontend/src/uxbox/main/data/workspace.cljs
+++ frontend/src/uxbox/main/data/workspace.cljs
@@ -358,6 +358,63 @@
       (let [local (:workspace-local state)]
         (assoc-in state [:workspace-cache page-id] local)))))

+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Data Persistence
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(declare persist-changes)
+(declare diff-and-commit-changes)
+
+(defn initialize-page-persistence
+  [page-id]
+  (ptk/reify ::initialize-persistence
+    ptk/UpdateEvent
+    (update [_ state]
+      (assoc state ::page-id page-id))
+
+    ptk/WatchEvent
+    (watch [_ state stream]
+      (let [stoper (rx/filter #(or (ptk/type? ::finalize %)
+                                   (ptk/type? ::initialize-page %))
+                              stream)
+            notifier (->> stream
+                          (rx/filter (ptk/type? ::commit-changes))
+                          (rx/debounce 2000)
+                          (rx/merge stoper))]
+        (rx/merge
+         (->> stream
+              (rx/filter (ptk/type? ::commit-changes))
+              (rx/map deref)
+              (rx/buffer-until notifier)
+              (rx/map vec)
+              (rx/filter (complement empty?))
+              (rx/map #(persist-changes page-id %))
+              (rx/take-until (rx/delay 100 stoper)))
+         (->> stream
+              (rx/filter #(satisfies? IBatchedChange %))
+              (rx/debounce 200)
+              (rx/map (fn [_] (diff-and-commit-changes page-id)))
+              (rx/take-until stoper)))))))
+
+(defn persist-changes
+  [page-id changes]
+  (ptk/reify ::persist-changes
+    ptk/WatchEvent
+    (watch [_ state stream]
+      (let [session-id (:session-id state)
+            page (get-in state [:pages page-id])
+            changes (->> changes
+                         (mapcat identity)
+                         (map #(assoc % :session-id session-id))
+                         (vec))
+            params {:id (:id page)
+                    :revn (:revn page)
+                    :changes changes}]
+        (->> (rp/mutation :update-page params)
+             (rx/map shapes-changes-commited))))))
+
+
 (defn- generate-operations
   [ma mb]
   (let [ma-keys (set (keys ma))
@@ -409,60 +466,6 @@
             undo-changes (generate-changes curr prev)]
         (when-not (empty? changes)
           (rx/of (commit-changes changes undo-changes)))))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Data Persistence
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(declare persist-changes)
-
-(defn initialize-page-persistence
-  [page-id]
-  (ptk/reify ::initialize-persistence
-    ptk/UpdateEvent
-    (update [_ state]
-      (assoc state ::page-id page-id))
-
-    ptk/WatchEvent
-    (watch [_ state stream]
-      (let [stoper (rx/filter #(or (ptk/type? ::finalize %)
-                                   (ptk/type? ::initialize-page %))
-                              stream)
-            notifier (->> stream
-                          (rx/filter (ptk/type? ::commit-changes))
-                          (rx/debounce 2000)
-                          (rx/merge stoper))]
-        (rx/merge
-         (->> stream
-              (rx/filter (ptk/type? ::commit-changes))
-              (rx/map deref)
-              (rx/buffer-until notifier)
-              (rx/map vec)
-              (rx/filter (complement empty?))
-              (rx/map #(persist-changes page-id %))
-              (rx/take-until (rx/delay 100 stoper)))
-         (->> stream
-              (rx/filter #(satisfies? IBatchedChange %))
-              (rx/debounce 200)
-              (rx/map (fn [_] (diff-and-commit-changes page-id)))
-              (rx/take-until stoper)))))))
-
-(defn persist-changes
-  [page-id changes]
-  (ptk/reify ::persist-changes
-    ptk/WatchEvent
-    (watch [_ state stream]
-      (let [session-id (:session-id state)
-            page (get-in state [:pages page-id])
-            changes (->> changes
-                         (mapcat identity)
-                         (map #(assoc % :session-id session-id))
-                         (vec))
-            params {:id (:id page)
-                    :revn (:revn page)
-                    :changes changes}]
-        (->> (rp/mutation :update-page params)
-             (rx/map shapes-changes-commited))))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Data Fetching & Uploading


fix inference regressions

fix inference regressions

--- src/clj/cljs/analyzer.clj
+++ src/clj/cljs/analyzer.clj
@@ -423,11 +423,11 @@
       :do  (infer-tag env (:ret e))
       :method (infer-tag env (:expr e))
       :def (infer-tag env (:init e))
-      :invoke  (let [f (:f e)]
-                 (or (and (-> f :info :fn-var) (:ret-tag f))
-                     (infer-tag env
-                       (assoc (find-matching-method f (:args e)) :op :method))
-                     'any))
+      :invoke (let [{info :info :as f} (:f e)]
+                (or (and (:fn-var info) (:ret-tag info))
+                    (infer-tag env
+                      (assoc (find-matching-method f (:args e)) :op :method))
+                    'any))
       :if (let [then-tag (infer-tag env (:then e))
                 else-tag (infer-tag env (:else e))]
             (cond
@@ -571,8 +571,10 @@
           init-expr (when (contains? args :init)
                       (disallowing-recur
                         (analyze (assoc env :context :expr) (:init args) sym)))
-          tag (or tag (:tag init-expr))
           fn-var? (and init-expr (= (:op init-expr) :fn))
+          tag (if fn-var?
+                (or (:ret-tag init-expr) tag)
+                tag)
           export-as (when-let [export-val (-> sym meta :export)]
                       (if (= true export-val) name export-val))
           doc (or (:doc args) (-> sym meta :doc))]
@@ -609,7 +611,9 @@
                                (cond-> (select-keys method
                                          [:max-fixed-arity :variadic])
                                  tag (assoc :tag tag))))
-                        (:methods init-expr))})))
+                        (:methods init-expr))})
+          (when (and fn-var? tag)
+            {:ret-tag tag})))
       (merge {:env env :op :def :form form
               :name name :var var-expr :doc doc :init init-expr}
         (when tag


CLJS-684: throw on circular dependency

CLJS-684: throw on circular dependency

--- src/clj/cljs/analyzer.clj
+++ src/clj/cljs/analyzer.clj
@@ -25,6 +25,7 @@
 (def ^:dynamic *cljs-static-fns* false)
 (def ^:dynamic *cljs-macros-path* "/cljs/core")
 (def ^:dynamic *cljs-macros-is-classpath* true)
+(def ^:dynamic *cljs-dep-set* (with-meta #{} {:dep-path []}))
 (def -cljs-macros-loaded (atom false))

 (def ^:dynamic *cljs-warnings*
@@ -804,13 +805,16 @@

 (declare analyze-file)

-(defn analyze-deps [deps]
-  (doseq [dep deps]
-    (when-not (contains? (::namespaces @env/*compiler*) dep)
-      (let [relpath (ns->relpath dep)]
-        (when (io/resource relpath)
-          (no-warn
-            (analyze-file relpath)))))))
+(defn analyze-deps [lib deps]
+  (binding [*cljs-dep-set* (vary-meta (conj *cljs-dep-set* lib) update-in [:dep-path] conj lib)]
+    (assert (every? #(not (contains? *cljs-dep-set* %)) deps)
+      (str "Circular dependency detected " (-> *cljs-dep-set* meta :dep-path)))
+    (doseq [dep deps]
+      (when-not (contains? (::namespaces @env/*compiler*) dep)
+        (let [relpath (ns->relpath dep)]
+          (when (io/resource relpath)
+            (no-warn
+              (analyze-file relpath))))))))

 (defn check-uses [uses env]
   (doseq [[sym lib] uses]
@@ -917,7 +921,7 @@
                   (apply merge-with merge m (map (spec-parsers k) libs)))
                 {} (remove (fn [[r]] (= r :refer-clojure)) args))]
     (when (seq @deps)
-      (analyze-deps @deps))
+      (analyze-deps name @deps))
     (when (seq uses)
       (check-uses uses env))
     (set! *cljs-ns* name)


refer-clojure, used correctly, prevents redefs of core names. refs #64

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -64,6 +64,12 @@
   (let [sym (symbol name)]
     (get (:requires (:ns env)) sym sym)))

+(defn core-name?
+  "Is sym visible from core in the current compilation namespace?"
+  [env sym]
+  (and (get (:defs (@namespaces 'cljs.core)) sym)
+       (not (contains? (-> env :ns :excludes) sym))))
+
 (defn resolve-existing-var [env sym]
   (let [s (str sym)
         lb (-> env :locals sym)
@@ -90,7 +96,7 @@
                       sym))))

          :else
-         (let [full-ns (if (get (:defs (@namespaces 'cljs.core)) sym)
+         (let [full-ns (if (core-name? env sym)
                          'cljs.core
                          (-> env :ns :name))]
            (confirm-var-exists env full-ns sym)
@@ -120,7 +126,7 @@

          :else
          (munge (symbol (str
-                         (if (get (:defs (@namespaces 'cljs.core)) sym)
+                         (if (core-name? env sym)
                            'cljs.core
                            (-> env :ns :name))
                          "." (munge (name sym))))))]
@@ -695,26 +701,36 @@

 (defmethod parse 'ns
   [_ env [_ name & args] _]
-  (let [{requires :require requires-macros :require-macros :as params}
+  (let [excludes
+        (reduce (fn [s [k exclude xs]]
+                  (if (= k :refer-clojure)
+                    (do
+                      (assert (= exclude :exclude) "Only [:refer-clojure :exclude [names]] form supported")
+                      (into s xs))
+                    s))
+                #{} args)
+        {requires :require requires-macros :require-macros :as params}
         (reduce (fn [m [k & libs]]
                   (assoc m k (into {}
                                    (map (fn [[lib as alias]]
                                           (assert (and alias (= :as as)) "Only [lib.ns :as alias] form supported")
                                           [alias lib])
                                         libs))))
-                {} args)]
+                {} (remove (fn [[r]] (= r :refer-clojure)) args))]
     (set! *cljs-ns* name)
     (require 'cljs.core)
     (doseq [nsym (vals requires-macros)]
       (clojure.core/require nsym))
     (swap! namespaces #(-> %
                            (assoc-in [name :name] name)
+                           (assoc-in [name :excludes] excludes)
                            (assoc-in [name :requires] requires)
                            (assoc-in [name :requires-macros]
                                      (into {} (map (fn [[alias nsym]]
                                                      [alias (find-ns nsym)])
                                                    requires-macros)))))
-    {:env env :op :ns :name name :requires requires :requires-macros requires-macros}))
+    {:env env :op :ns :name name :requires requires
+     :requires-macros requires-macros :excludes excludes}))

 (defmethod parse 'deftype*
   [_ env [_ tsym fields] _]


voodoo to make reload work in development

--- src/clj/relembra/core.clj
+++ src/clj/relembra/core.clj
@@ -75,7 +75,7 @@
   (GET  "/chsk" req (ring-ajax-get-or-ws-handshake req))
   (POST "/chsk" req (ring-ajax-post req))

-  (resources "/")
+  (resources (if in-development "/public" "/"))
   (files "/")
   (not-found "Page not found."))


Joe closes #4 add timeout. Also force application/xml needed by Travis

--- src/clj_cctray/reader.clj
+++ src/clj_cctray/reader.clj
@@ -1,15 +1,19 @@
 (ns clj-cctray.reader
   (:require [org.httpkit.client :as httpkit]))

+(def ^:private http-kit-options {:insecure? true
+                                 :timeout 30000
+                                 :headers {"Accept" "application/xml"}})
+
 (defn http-read-unsecured-httpkit [url]
-  (:body @(httpkit/get url {:insecure? true})))
+  (:body @(httpkit/get url http-kit-options)))

 (defn http-read-unsecured->String [url]
   (let [raw-response (http-read-unsecured-httpkit url)]
     (java.io.ByteArrayInputStream. (.getBytes raw-response))))

 (defn decide-reader [url]
-  (if (.startsWith url "https") :httpkit :standard))
+  (if (.startsWith (.toLowerCase url) "http") :httpkit :standard))

 (def readers {:httpkit http-read-unsecured->String
               :standard identity})


Code style cleanups and a bit more om.

Code style cleanups and a bit more om.

--- src/cljs/primes/core.cljs
+++ src/cljs/primes/core.cljs
@@ -82,8 +82,28 @@

 (enable-console-print!)

+
 (def app-state (atom {:title "Integer composite groups"
                       :up-to 10}))
+
+
+(defn title [app]
+  (om/component (dom/h2 #js {:className "title"} (:title app))))
+
+
+(defn add-more
+  "Extend the range of numbers we are looking at"
+  [app]
+  (om/transact! app :up-to (partial + 100)))
+
+
+(defn numseq [app]
+  (om/component
+   (dom/div #js {:className "numseq"}
+            "Up to: " (:up-to app) "  "
+            (dom/button #js {:onClick #(add-more app)}
+                        "show more"))))
+

 (defn group-view
   "Render the contents of one group (set) of numbers."
@@ -99,30 +119,19 @@
               (dom/small nil (dom/i nil (str/join ", " numbers)))))))

-(defn add-more
-  "Extend the range of numbers we are looking at"
-  [app]
-  (om/transact! app :up-to (partial + 100)))
-
-(defn numseq [app]
-  (om/component (dom/div #js {:className "numseq"} "abc" (:up-to app)"def")))
-
-
-(defn groups-views
+(defn groups-view
   "Render all the groups"
   [app owner]
   (reify
     om/IRenderState
     (render-state [this state]
       (dom/div nil
-               (dom/h2 nil (:title app))
-               (dom/button #js {:onClick #(add-more app)} "show more")
-               (om/build numseq app)
-               " ggg "
+               (om/build title app)
                (om/build numseq app)
                (apply dom/ul nil
                       (om/build-all group-view (nums/group-signatures (:up-to app))))))))

+
 (om/root groups-view
          app-state
          {:target (. js/document (getElementById "app"))})


Delete unused def for map icons

Delete unused def for map icons

--- src/cljs_leaflet/geo.cljs
+++ src/cljs_leaflet/geo.cljs
@@ -15,14 +15,6 @@
                                        "CC-BY-SA, "
                                        "Imagery © Mapbox")
                      :id "mapbox.streets"} }})
-
-;; cljsjs doesn't come with leaflet image assets, so we create our own icons
-(defonce map-icon
-  {:icon (.icon js/L (clj->js {
-    :iconUrl "https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-icon-2x.png"
-    :shadowUrl "https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png"
-    :iconSize [25 41]
-    :iconAnchor [12 41] }))})

 ;; cljsjs doesn't come with image assets, so substitute with circlemarker settings
 (defonce gj-marker-settings


Moar.

Moar.

--- src/clojurecraft/core.clj
+++ src/clojurecraft/core.clj
@@ -20,6 +20,7 @@
      0x0B :playerposition
      0x0C :playerlook
      0x0D :playerpositionlook
+     0x0E :playerdigging
 })
 (def packet-ids (apply assoc {} (mapcat reverse packet-types)))

@@ -139,6 +140,15 @@
       (-write-float conn yaw)
       (-write-float conn pitch)
       (-write-bool conn onground))
+
+(defn write-packet-playerdigging [conn {status :status x :x y :y z :z face :face}]
+      (-write-byte conn (:playerdigging packet-ids))
+
+      (-write-byte conn status)
+      (-write-int conn x)
+      (-write-byte conn y)
+      (-write-int conn z)
+      (-write-byte conn face))

 ; Writing Wrappers -----------------------------------------------------------------
@@ -156,6 +166,7 @@
         (= packet-type :playerposition)     (write-packet-playerposition conn payload)
         (= packet-type :playerlook)         (write-packet-playerlook conn payload)
         (= packet-type :playerpositionlook) (write-packet-playerpositionlook conn payload)
+        (= packet-type :playerdigging)      (write-packet-playerdigging conn payload)
         )
       (flushc conn))

@@ -254,6 +265,14 @@
           (assoc :yaw (-read-float conn))
           (assoc :pitch (-read-float conn))
           (assoc :onground (-read-bool conn))))
+
+(defn read-packet-playerdigging [conn]
+      (-> {}
+          (assoc :status (-read-byte conn))
+          (assoc :x (-read-int conn))
+          (assoc :y (-read-byte conn))
+          (assoc :z (-read-int conn))
+          (assoc :face (-read-byte conn))))

 ; Reading Wrappers -----------------------------------------------------------------
@@ -274,6 +293,7 @@
             (= packet-type :updatehealth)       (read-packet-updatehealth conn)
             (= packet-type :respawn)            (read-packet-respawn conn)
             (= packet-type :playerpositionlook) (read-packet-playerpositionlook conn)
+            (= packet-type :playerdigging)      (read-packet-playerdigging conn)
             :else (str "UNKNOWN PACKET TYPE: " packet-id)
             ))
         (println "\n\n\n")))


Reformat

Reformat

--- src/clojush/translate.clj
+++ src/clojush/translate.clj
@@ -65,42 +65,72 @@
   (if program
     program
     (let [translated-program
-          (loop [prog [] ; The Push program incrementally being built
-                 gn genome ; The linear Plush genome, where items will be popped off the front. Each item is a map containing at least the key :instruction, and unless the program is flat, also :close
-                 num-parens-here 0 ; The number of parens that still need to be added at this location.
-                 paren-stack '()] ; Whenever an instruction requires parens grouping, it will push either :close or :close-open on this stack. This will indicate what to insert in the program the next time a paren is indicated by the :close key in the instruction map.
+          (loop [prog []
+                 ; The Push program incrementally being built
+
+                 gn genome
+                 ; The linear Plush genome, where items will be popped off the
+                 ; front. Each item is a map containing at least the key
+                 ; :instruction, and unless the program is flat, also :close
+
+                 num-parens-here 0
+                 ; The number of parens that still need to be added at this
+                 ; location.
+
+                 paren-stack '()
+                 ; Whenever an instruction requires parens grouping, it will
+                 ; push either :close or :close-open on this stack. This will
+                 ; indicate what to insert in the program the next time a paren
+                 ; is indicated by the :close key in the instruction map.
+                 ]
             (cond
               ; Check if need to add close parens here
-              (< 0 num-parens-here) (recur (cond
-                                             (= (first paren-stack) :close) (conj prog :close)
-                                             (= (first paren-stack) :close-open) (conj (conj prog :close) :open)
-                                             :else prog) ; If paren-stack is empty, we won't put any parens in even though the :close epigenetic marker indicated to do so
-                                           gn
-                                           (dec num-parens-here)
-                                           (rest paren-stack))
+              (< 0 num-parens-here)
+              (recur (cond
+                       (= (first paren-stack) :close)
+                       (conj prog :close)
+                       ;
+                       (= (first paren-stack) :close-open)
+                       (conj (conj prog :close) :open)
+                       ;
+                       ; If paren-stack is empty, we won't put any parens in
+                       ; even though the :close epigenetic marker indicated to
+                       ; do so
+                       :else prog
+                       )
+                     gn
+                     (dec num-parens-here)
+                     (rest paren-stack))
               ; Check if at end of program but still need to add parens
               (and (empty? gn)
-                   (not (empty? paren-stack))) (recur prog
-                                                      gn
-                                                      (count paren-stack)
-                                                      paren-stack)
+                   (not (empty? paren-stack)))
+              (recur prog
+                     gn
+                     (count paren-stack)
+                     paren-stack)
               ; Check if done
-              (empty? gn) (open-close-sequence-to-list (apply list prog))
-              ; Check for no-oped instruction. This instruction will be replaced by exec_noop, but will still have effects like :close count
-              (= (:silent (first gn)) :no-op) (recur (conj prog 'exec_noop)
-                                                     (rest gn)
-                                                     (get (first gn) :close 0)
-                                                     paren-stack)
+              (empty? gn)
+              (open-close-sequence-to-list (apply list prog))
+              ; Check for no-oped instruction. This instruction will be replaced
+              ; by exec_noop, but will still have effects like :close count
+              (= (:silent (first gn)) :no-op)
+              (recur (conj prog 'exec_noop)
+                     (rest gn)
+                     (get (first gn) :close 0)
+                     paren-stack)
               ; Check for silenced instruction
-              (get (first gn) :silent false) (recur prog
-                                                    (rest gn)
-                                                    num-parens-here
-                                                    paren-stack)
+              (get (first gn) :silent false)
+              (recur prog
+                     (rest gn)
+                     num-parens-here
+                     paren-stack)
               ; If here, ready for next instruction
-              :else (let [number-paren-groups (lookup-instruction-paren-groups (:instruction (first gn)))
+              :else (let [number-paren-groups (lookup-instruction-paren-groups
+                                                (:instruction (first gn)))
                           new-paren-stack (if (>= 0 number-paren-groups)
                                             paren-stack
-                                            (list-concat (repeat (dec number-paren-groups) :close-open)
+                                            (list-concat (repeat (dec number-paren-groups)
+                                                                 :close-open)
                                                          '(:close)
                                                          paren-stack))]
                       (if (= 'noop_delete_prev_paren_pair (:instruction (first gn)))
@@ -114,10 +144,12 @@
                                    (conj prog (:instruction (first gn)))
                                    (conj (conj prog (:instruction (first gn))) :open)))
                                (rest gn)
-                               (get (first gn) :close 0) ; The number of close parens to put after this instruction; if :close isn't in instruction map, default to zero
+                               (get (first gn) :close 0)
+                               ; ^ The number of close parens to put after this instruction;
+                               ; if :close isn't in instruction map, default to zero
                                new-paren-stack)))))]
       (if (> (count-points translated-program) max-points)
-        '() ; Translates to an empty programs if program exceeds max-points
+        '() ; Translates to an empty program if program exceeds max-points
         translated-program))))

 (defn population-translate-plush-to-push


If exceeds max points, translates to empty program

--- src/clojush/translate.clj
+++ src/clojush/translate.clj
@@ -110,15 +110,9 @@
                                (rest gn)
                                (get (first gn) :close 0) ; The number of close parens to put after this instruction; if :close isn't in instruction map, default to zero
                                new-paren-stack)))))]
-      (if (<= (count-points translated-program) max-points)
-        translated-program
-        (do
-          (println "WARNING: A translated program was bigger than max-points. Recuring translation after removing the last instruction in genome.")
-          (println "  genome length:" (count genome))
-          (println "  points in program:" (count-points translated-program))
-          (println "  :max-points:" max-points)
-          (recur {:genome (butlast genome)}
-                 argmap))))))
+      (if (> (count-points translated-program) max-points)
+        '() ; Translates to an empty programs if program exceeds max-points
+        translated-program))))

 (defn population-translate-plush-to-push
   "Converts the population of Plush genomes into Push programs."


Fix namespace in comment tests

Fix namespace in comment tests

--- src/cognitect/transit.clj
+++ src/cognitect/transit.clj
@@ -237,8 +237,8 @@

 (comment

-  (require 'transit)
-  (in-ns 'transit)
+  (require 'cognitect.transit)
+  (in-ns 'cognitect.transit)

   (import [java.io File ByteArrayInputStream ByteArrayOutputStream OutputStreamWriter])


WIP on concordance display

WIP on concordance display

--- src/cljs/cglossa/result_views/cwb/core.cljs
+++ src/cljs/cglossa/result_views/cwb/core.cljs
@@ -27,21 +27,22 @@
 (defn- process-field
   "Processes a pre-match, match, or post-match field."
   [field]
-  (-> field
-      ;; Extract any speaker IDs and put them in front of their segments
-      (str/replace #"<who_name\s*(.+?)>"
-                   "<$1>")
-      (str/replace #"</who_name>" "")
-      (str/replace #"span class=" "span_class=")
-      (str/split #"\s+")
-      (map (fn [token]
-             (if (.contains token "span_class=")
-               token                                        ; Don't touch HTML spans
-               (str/split token #"/")                       ; The slash separates CWB attributes
-               ;; TODO: Handle Opentip jQuery attributes, or use something else?
-               )))
-      (#(str/join \space %))
-      (str/replace #"span_class=" "span class=")))
+  (as-> field $
+        ;; Extract any speaker IDs and put them in front of their segments
+        (str/replace $ #"<who_name\s*(.+?)>"
+                     "<$1>")
+        (str/replace $ #"</who_name>" "")
+        (str/replace $ #"span class=" "span_class=")
+        (str/split $ #"\s+")
+        (map (fn [token]
+               (if (re-find #"span_class=" token)
+                 token                                      ; Don't touch HTML spans
+                 (str/split token #"/")                     ; The slash separates CWB attributes
+                 ;; TODO: Handle Opentip jQuery attributes, or use something else?
+                 ))
+             $)
+        (str/join \space $)
+        (str/replace $ #"span_class=" "span class=")))

 (defn- id-column [result]
   ;; If the 'match' property is defined, we know that we have a result from a monolingual
@@ -96,9 +97,9 @@
            [b/glyphicon {:glyph "volume-up"}]]
           [b/button {:bs-size  "xsmall" :title "Show waveform" :style {:width "100%"}
                      :on-click #(toggle-player index "wfplayer" "audio" a)}
-           [:img {:src "img/waveform.png"}]])]
-       (id-column result)
-       (text-columns result))]))
+           [:img {:src "img/waveform.png"}]])])
+     (id-column result)
+     (text-columns result)]))

 (defn- extra-row [result attr {:keys [corpus]}]
   (let [sound?       (:has-sound corpus)
@@ -148,7 +149,8 @@
                       [:tr
                        [:td {:col-span 10}
                         [:WFplayer {:media-obj (:media-obj res-info)}]]]))]
-    (flatten [main extras media-row])))
+    #_(flatten [main extras media-row])
+    main))

 (defmethod concordance-table :default [{:keys [search-results] :as a} m]
   (let [results @search-results]
@@ -156,7 +158,7 @@
      [b/table {:striped true :bordered true}
       [:tbody
        (map result-rows
-            results
-            (range (count results))
-            (repeat a)
-            (repeat m))]]]))
+             results
+             (range (count results))
+             (repeat a)
+             (repeat m))]]]))


4clojure:: impl the comparisons func -> yielding the relantionship between 2 numbers

--- src/clojure_learning/4clojure-exercises.clj
+++ src/clojure_learning/4clojure-exercises.clj
@@ -847,3 +847,41 @@

 ;; demo:
 (zipmapp [:a :b :c] [1 2 3]) ; {:c 3, :b 2, :a 1}
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; For any orderable data type it's possible to derive all of the
+;; basic comparison operations (<, ≤, =, ≠, ≥, and >) from a single operation
+;; (any operator but = or ≠ will work).
+;; Write a function that takes three arguments, a less than operator for the
+;; data and two items to compare.
+;; The function should return a keyword describing the relationship between the two items.
+;; The keywords for the relationship between x and y are as follows:
+;; x = y → :eq
+;; x > y → :gt
+;; x < y → :lt
+;; (= :gt (__ < 5 1))
+;; (= :eq (__ (fn [x y] (< (count x) (count y))) "pear" "plum"))
+(defn comparison
+  [lower-fn & ops]
+ (let [lower-compl-map {[true false] :lt
+                        [false true] :gt
+                        [false false] :eq}
+       lower? (apply lower-fn ops)
+       higher? (apply lower-fn (reverse ops))]
+     (lower-compl-map [lower? higher?])))
+
+;; demo:
+(= :gt (comparison < 5 1)) ; true
+(comparison < 1 4) ; :lt
+(comparison < 5 5) ; :eq
+
+((complement <) 3 3) ; true --> WTF???
+
+;; or the more idiomatic version
+(defn comparison
+  [lower-fn & ops]
+ (let [lower-compl-map {[true false] :lt
+                        [false true] :gt
+                        [false false] :eq}]
+     (lower-compl-map (map #(lower-fn (first %) (second %)) (list ops (reverse ops))))))


Don’t break build for experimental warnings


Fixing the indexer system.

Fixing the indexer system.

--- indexer-app/src/cmr/indexer/system.clj
+++ indexer-app/src/cmr/indexer/system.clj
@@ -74,7 +74,8 @@
                                system
                                component-order)]

-    (event-handler/subscribe-to-events {:system started-system})
+    (when (:queue-broker system)
+      (event-handler/subscribe-to-events {:system started-system}))

     (info "System started")
     started-system))


Korjaa react-varoitukset

Korjaa react-varoitukset

--- mtg-pairings-server/src/cljs/mtg_pairings_server/components/paging.cljs
+++ mtg-pairings-server/src/cljs/mtg_pairings_server/components/paging.cljs
@@ -8,9 +8,9 @@
                                         :selected)}
    (inc num)])

-(defn pager [event subscription num-pages]
+(defn pager [id event subscription num-pages]
   (let [selected-page (subscribe subscription)]
-    (fn pager-render [event subscription num-pages]
+    (fn pager-render [id event subscription num-pages]
       (let [shown-pages (if (<= num-pages 7)
                           (range 0 num-pages)
                           (concat [0]
@@ -23,11 +23,14 @@
          (if (pos? @selected-page)
            [:div.button.prev-page {:on-click #(dispatch [event (dec @selected-page)])} "<"]
            [:div.button.prev-page.disabled "<"])
-         (mapcat (fn [[prev cur]]
-                   [(when (and (some? prev) (> (- cur prev) 1))
-                      [:div.button.separator.disabled "···"])
-                    [page-button #(dispatch [event cur]) @selected-page cur]])
-                 (partition 2 1 (cons nil shown-pages)))
+         (doall
+           (mapcat (fn [[prev cur]]
+                     [(when (and (some? prev) (> (- cur prev) 1))
+                        ^{:key (str id "separator-" cur)}
+                        [:div.button.separator.disabled "···"])
+                      ^{:key (str id "button-" cur)}
+                      [page-button #(dispatch [event cur]) @selected-page cur]])
+                   (partition 2 1 (cons nil shown-pages))))
          (if (< @selected-page (dec num-pages))
            [:div.button.next-page {:on-click #(dispatch [event (inc @selected-page)] inc)} ">"]
            [:div.button.next-page.disabled ">"])]))))
@@ -39,8 +42,8 @@
     (fn with-paging-render [page-event page-subsription data-subscription component]
       (let [num-pages (Math/ceil (/ (count @data) items-per-page))]
         [:div
-         [pager page-event page-subscription num-pages]
+         [pager (str page-event "-1-") page-event page-subscription num-pages]
          [component (->> @data
                          (drop (* @page items-per-page))
                          (take items-per-page))]
-         [pager page-event page-subscription num-pages]]))))
+         [pager (str page-event "-2-") page-event page-subscription num-pages]]))))


lein-release plugin: preparing 0.1.0 release

--- re-frame-simple/project.clj
+++ re-frame-simple/project.clj
@@ -1,4 +1,4 @@
-(defproject re-view/re-frame-simple "0.1.0-SNAPSHOT"
+(defproject re-view/re-frame-simple "0.1.0"

   :description "re-view syntax for re-frame"


more work done fleshing out schema

more work done fleshing out schema

--- src/five_points/model.clj
+++ src/five_points/model.clj
@@ -1,18 +1,36 @@
 (ns five-points.model
   (:require [schema.core :as s]
-            [five-points.validate :as v]))
-
-(s/defschema Kin-Id (s/constrained s/Str #(re-matches #"kin[A-Za-z0-9]{10}" %) 'Kin-Id))
-
-(s/defschema Caste-Id (s/constrained s/Str #(re-matches #"caste[A-Za-z0-9]{10}" %) 'Caste-Id))
-
-(s/defschema Skill-Id (s/constrained s/Str #(re-matches #"skill[A-Za-z0-9]{10}" %) 'Skill-Id))
-
-(s/defschema Skill-Set-Id (s/constrained s/Str #(re-matches #"skst[A-Za-z0-9]{10}" %) 'Skill-Set-Id))
-
-(s/defschema Item-Id (s/constrained s/Str #(re-matches #"item[A-Za-z0-9]{10}" %) 'Item-Id))
-
-(s/defschema Char-Id (s/constrained s/Str #(re-matches #"char[A-Za-z0-9]{10}" %) 'Char-Id))
+            [five-points.validate :as v])
+  (:import (javafx.scene.effect Effect)
+           (cljpdf.text Chapter)))
+
+(s/defschema Kin-Id (s/constrained s/Str #(re-matches #"kin_[A-Za-z0-9]{10}" %) 'Kin-Id))
+
+(s/defschema Caste-Id (s/constrained s/Str #(re-matches #"caste_[A-Za-z0-9]{10}" %) 'Caste-Id))
+
+(s/defschema Skill-Id (s/constrained s/Str #(re-matches #"skill_[A-Za-z0-9]{10}" %) 'Skill-Id))
+
+(s/defschema Skill-Set-Id (s/constrained s/Str #(re-matches #"skst_[A-Za-z0-9]{10}" %) 'Skill-Set-Id))
+
+(s/defschema Item-Id (s/constrained s/Str #(re-matches #"item_[A-Za-z0-9]{10}" %) 'Item-Id))
+
+(s/defschema Char-Id (s/constrained s/Str #(re-matches #"char_[A-Za-z0-9]{10}" %) 'Char-Id))
+
+(s/defschema Check-Id (s/constrained s/Str #(re-matches #"chk_[A-Za-z0-9]{10}" %) 'Check-Id))
+
+(s/defschema Damage-Id (s/constrained s/Str #(re-matches #"dmg_[A-Za-z0-9]{10}" %) 'Damage-Id))
+
+(s/defschema Condition-Id (s/constrained s/Str #(re-matches #"cond_[A-Za-z0-9]{10}" %) 'Condition-Id))
+
+(s/defschema Obstacle-Id (s/constrained s/Str #(re-matches #"obst_[A-Za-z0-9]{10}" %) 'Obstacle-Id))
+
+(s/defschema Maze-Id (s/constrained s/Str #(re-matches #"maze_[A-Za-z0-9]{10}" %) 'Maze-Id))
+
+(s/defschema Room-Id (s/constrained s/Str #(re-matches #"room_[A-Za-z0-9]{10}" %) 'Room-Id))
+
+(s/defschema NPC-Id (s/constrained s/Str #(re-matches #"npc_[A-Za-z0-9]{10}" %) 'NPC-Id))
+
+(s/defschema Question-Id (s/constrained s/Str #(re-matches #"q_[A-Za-z0-9]{10}" %) 'Question-Id))

 (s/defschema GameTime {:value s/Int
                        :unit (s/enum :Minor-Action :Major-Action :Minute :Hour :Day :Month :Year)})
@@ -28,15 +46,47 @@
           :Sense
           :Charm))

+(s/defschema Custom-Check
+  {:id Check-Id
+   :name s/Str
+   :description s/Str
+   :stat Stat})
+
 (s/defschema Check (s/enum
                      :Push :Pull :Jump :Catch :Throw :Run :Climb :Grab :Hold :Block :Melee-Attack
                      :Balance :Tumble :Dodge :Parry :Range-Attack :Hide
                      :Resist :Heal-Self
-                     :Find :Recall :Learn :Triage :Cure
+                     :Find :Recall :Learn :Triage :Cure :Aim
                      :Look :Smell :Taste :Touch :Hear :Detect-Psychic
                      :Inspire :Sway :Mock :Tame :Lie))

 (s/defschema Stats {Stat Score})
+
+(s/defschema Impact (s/enum :immune :guarded :exposed))
+
+(s/defschema Size (s/enum :tiny :small :medium :large :giant :huge :gargantuan))
+
+(s/defschema Damage-Type
+  {:id Damage-Id
+   :name s/Str
+   :description s/Str})
+
+(s/defschema Susceptability
+  {:types #{Damage-Id}
+   :impact Impact})
+
+(s/defschema Limitation
+  (s/cond-pre
+    Condition-Id
+    Stats
+    {(s/enum :edge :burden) (s/cond-pre Check Stat Check-Id)}
+    Susceptability))
+
+(s/defschema Condition
+  {:id Condition-Id
+   :name s/Str
+   :description s/Str
+   :limitations #{Limitation}})

 (s/defschema Prerequisite
   (s/constrained
@@ -46,13 +96,25 @@
      (s/optional-key :skills) #{Skill-Id}}
     not-empty))

-(s/defschema Bonus
+(s/defschema All-Checks (s/cond-pre Check Stat Check-Id))
+
+(s/defschema Effect-Check-Value
+  {:score (s/cond-pre Score (s/enum :talent :mastery))
+   (s/optional-key :multiplier) (s/cond-pre s/Int :level)})
+
+(s/defschema Effect
   {:description s/Str
-   :check (s/either Check Stat)
-   :value (s/either Score :talent {:talent s/Int} {:level Score} {:talent :level})
    (s/optional-key :lvl) s/Int
    (s/optional-key :invocation) GameTime
-   (s/optional-key :duration) GameTime})
+   (s/optional-key :duration) GameTime
+   (s/optional-key :frequency) GameTime
+   :target {(s/enum :count :lvl-) s/Int
+            :values #{(s/enum :self :ally :opponent)}}
+   :effect (s/cond-pre
+             {Condition-Id {:check All-Checks
+                            :mark s/Int}}
+             {(s/enum :edge :burden) All-Checks}
+             {(s/cond-pre All-Checks Damage-Id) Effect-Check-Value})})

 (s/defschema Starting
   (s/constrained
@@ -66,6 +128,7 @@
    :name s/Str
    :stats Stats
    :description s/Str
+   (s/optional-key :size) Size
    (s/optional-key :starting) Starting})

 (s/defschema Caste
@@ -82,7 +145,7 @@
    :type [s/Str]
    (s/optional-key :lvl) s/Int
    (s/optional-key :prerequisites) Prerequisite
-   (s/optional-key :bonuses) #{Bonus}})
+   (s/optional-key :effects) #{Effect}})

 (s/defschema Skill-Set
   {:id Skill-Set-Id
@@ -99,7 +162,7 @@
    (s/optional-key :lvl) s/Int
    (s/optional-key :bonded) (s/eq true)
    (s/optional-key :prerequisites) Prerequisite
-   (s/optional-key :bonuses) #{Bonus}
+   (s/optional-key :effects) #{Effect}
    (s/optional-key :heft) (s/enum :heavy :light)
    (s/optional-key :time-to-equip) GameTime
    :cost {:value s/Int :unit s/Str}})
@@ -114,13 +177,87 @@
    :skills #{Skill-Id}
    :items #{Item-Id}})

+(s/defschema Solution
+  {:check All-Checks
+   :mark s/Int
+   (s/enum :succeed :fail) Effect})
+
+(s/defschema Obstacle
+  {:id Obstacle-Id
+   :name s/Str
+   :description s/Str
+   :effects #{Effect}
+   :solutions #{Solution}})
+
 (s/defschema Context
   (s/constrained
-    {:kin {Kin-Id Kin}
-     :castes {Caste-Id Caste-Id}
+    {:checks {Check-Id Custom-Check}
+     :damage-types {Damage-Id Damage-Type}
+     :conditions {Condition-Id Condition}
+     :kin {Kin-Id Kin}
+     :castes {Caste-Id Caste}
      :items {Item-Id Item}
      :skills {Skill-Id Skill}
      :skill-sets {Skill-Set-Id Skill-Set}
-     :characters {Char-Id Character}}
+     :characters {Char-Id Character}
+     :obstacles {Obstacle-Id Obstacle}}
     v/validate-compendium
     'Compendium))
+
+(s/defschema Answer
+  {:text s/Str
+   :next #{Question-Id}})
+
+(s/defschema Question-Node
+{:id Question-Id
+ :question s/Str
+ :answer (s/cond-pre
+           Answer
+           {:checks #{{:check All-Checks
+                       :mark s/Int}}
+            :fail Answer
+            :succeed Answer})})
+
+(s/defschema NPC
+  {:character Char-Id
+   :questions {Question-Id Question-Node}
+   :base-line #{Question-Id}})
+
+(s/defschema Position {:x s/Int :y s/Int})
+
+(s/defschema Door
+  {:label s/Str
+   :description s/Str
+   :to Room-Id})
+
+(s/defschema Room
+  {:id Room-Id
+   :name s/Str
+   :description s/Str
+   :shape (s/cond-pre
+            {:width s/Int :height s/Int}
+            {:points [Position]})
+   (s/optional-key :doors) #{Door}
+   (s/optional-key :contents){Position (s/cond-pre Char-Id NPC-Id Obstacle-Id Item-Id)}})
+
+(s/defschema Maze
+  {:rooms {Room-Id Room}
+   :entrance Room-Id
+   :exit Room-Id})
+
+(s/defschema Chapter
+  {:intro s/Str
+   :outro s/Str
+   :maze Maze-Id})
+
+(s/defschema Story
+  {:title s/Str
+   :prologue s/Str
+   :epilogue s/Str
+   :chapters [Chapter]})
+
+(s/defschema Adventure
+  {:context Context
+   :story Story
+   :mazes {Maze-Id Maze}
+   :NPCs {NPC-Id NPC}})


Replace set-status function in servlet namespace

--- ring-servlet/src/ring/util/servlet.clj
+++ ring-servlet/src/ring/util/servlet.clj
@@ -66,11 +66,6 @@
           :servlet-context      (.getServletContext servlet)
           :servlet-context-path (.getContextPath request)}))

-(defn- set-status
-  "Update a HttpServletResponse with a status code."
-  [^HttpServletResponse response, status]
-  (.setStatus response status))
-
 (defn- set-headers
   "Update a HttpServletResponse with a map of headers."
   [^HttpServletResponse response, headers]
@@ -104,7 +99,7 @@
      (when (nil? response-map)
        (throw (NullPointerException. "Response map is nil")))
      (when status
-       (set-status response status))
+       (.setStatus response status))
      (set-headers response headers)
      (protocols/write-body body (make-output-stream response context)))))


Upgrade to latest Clojure

Upgrade to latest Clojure

--- lein-template/project.clj
+++ lein-template/project.clj
@@ -6,7 +6,7 @@
   :url "http://modularity.org/"
   :license {:name "The MIT License"
             :url "http://opensource.org/licenses/MIT"}
-  :dependencies [[org.clojure/clojure "1.7.0-alpha4"]
+  :dependencies [[org.clojure/clojure "1.7.0-RC2"]
                  ;; EDN reader with location metadata
                  [org.clojure/tools.reader "0.8.3"]
                  [org.clojure/tools.logging "0.2.6"]]


analyze/merge.clj: added hadoop context and cite linking

--- src/org/altlaw/jobs/analyze/merge.clj
+++ src/org/altlaw/jobs/analyze/merge.clj
@@ -2,7 +2,9 @@
   (:refer clojure.set)
   (:require [org.altlaw.util.hadoop :as h]
             [org.altlaw.util.log :as log]
+            [org.altlaw.util.context :as context]
             [org.altlaw.db.privacy :as priv]
+            [org.altlaw.extract.cites :as cites]
             [org.altlaw.util.merge-fields :as merge]))

 (h/setup-mapreduce)
@@ -13,9 +15,14 @@
     (do (h/counter "Removed documents")
         (log/info "Skipping removed document " docid)
         nil)
-    [[docid (merge/merge-fields documents)]]))
+    (let [merged-doc (merge/merge-fields documents)
+          linked-html (cites/link-citations (:html merged-doc))]
+      [[docid (assoc merged-doc :html linked-html)]])))

 ;;; METHOD IMPLEMENTATIONS
+
+(defn reducer-configure [this jobconf]
+  (context/use-hadoop-jobconf jobconf))

 (def reducer-reduce (partial h/standard-reduce my-reduce))


removed a file

removed a file

--- mqi.clj
+++ mqi.clj
@@ -1,4 +0,0 @@
-(use '[ontrail mongodb] 'monger.operators)
-
-(require '[monger.query :as mq]
-	 '[monger.collection :as mc])


Reworked examples

Reworked examples


CMR-1109: Refactored code for opendata personnel->contact-email function.

--- search-app/src/cmr/search/results_handlers/opendata_results_handler.clj
+++ search-app/src/cmr/search/results_handlers/opendata_results_handler.clj
@@ -75,9 +75,8 @@
   "Returns a contact email from the personnel record or the default if one
   is not available."
   [personnel]
-  (or (when-let [contacts (:contacts personnel)]
-        (when-let [contact (first (filter #(= "email" (:type %)) contacts))]
-          (:value contact)))
+  (or (:value (first (filter #(= "email" (:type %))
+                             (:contacts personnel))))
       DEFAULT_CONTACT_EMAIL))

 (defmethod elastic-results/elastic-result->query-result-item :opendata


Fix nil resources bug in scheduler

Fix nil resources bug in scheduler

--- scheduler/src/cook/mesos/scheduler.clj
+++ scheduler/src/cook/mesos/scheduler.clj
@@ -829,10 +829,12 @@
                           (timers/start-stop-time! ; Use this in go blocks, time! doesn't play nice
                             incubator-offer-received-duration
                             (let [annotated-offers (map (fn [offer]
-                                                          (assoc offer
-                                                                 :time-received (time/now)
-                                                                 :driver driver
-                                                                 :fid fid))
+                                                          (-> offer
+                                                              (assoc :time-received (time/now)
+                                                                     :driver driver
+                                                                     :fid fid)
+                                                              (update-in [:resources :cpus] #(or % 0.0))
+                                                              (update-in [:resources :mem] #(or % 0.0))))
                                                         offers)
                                   ids (map :id offers)]
                               (incubate! ids)


(PCP-385) Log incoming PCP messages to pcp-access

Logging incoming PCP messages with the pcp-access logger whenever the
onMessage handler is invoked.

--- src/puppetlabs/pcp/broker/core.clj
+++ src/puppetlabs/pcp/broker/core.clj
@@ -485,6 +485,13 @@
     (websockets-client/send! websocket (encode error-msg))
     nil))

+(defn log-access
+  [lvl message-data]
+  (sl/maplog
+    [:puppetlabs.pcp.broker.pcp_access lvl]
+    message-data
+    "{accessoutcome} {remoteaddress} {commonname} {source} {messagetype} {messageid} {destination}"))
+
 ;; NB(ale): using (s/Maybe Websocket) in the signature for the sake of testing
 (s/defn process-message! :- (s/maybe Connection)
   "Deserialize, validate (authentication, authorization, and expiration), and
@@ -508,16 +515,17 @@
         (try+
           (case (validate-message broker capsule connection is-association-request)
             :to-be-ignored-during-association
-            ;; TODO(ale): log access (PCP-385); doing nothing for now
-            (do)
+            (log-access :warn (assoc message-data :accessoutcome "IGNORED_DURING_ASSOCIATION"))
             :not-authenticated
             (let [not-authenticated-msg (i18n/trs "Message not authenticated")]
+              (log-access :warn (assoc message-data :accessoutcome "AUTHENTICATION_FAILURE"))
               (if is-association-request
                 ;; send an unsuccessful associate_response and close the WebSocket
                 (process-associate-request! broker capsule connection not-authenticated-msg)
                 (send-error-message message not-authenticated-msg connection)))
             :not-authorized
             (let [not-authorized-msg (i18n/trs "Message not authorized")]
+              (log-access :warn (assoc message-data :accessoutcome "AUTHORIZATION_FAILURE"))
               (if is-association-request
                 ;; send an unsuccessful associate_response and close the WebSocket
                 (process-associate-request! broker capsule connection not-authorized-msg)
@@ -525,7 +533,7 @@
                 (send-error-message message not-authorized-msg connection)))
             :expired
             (do
-              ;; TODO(ale): log access (PCP-385)
+              (log-access :warn (assoc message-data :accessoutcome "EXPIRED"))
               (if is-association-request
                 ;; send back the ttl-expired immediately, without queueing
                 (let [response (make-ttl_expired-message message)
@@ -535,7 +543,7 @@
               nil)
             :to-be-processed
             (do
-              ;; TODO(ale): log access (PCP-385)
+              (log-access :info (assoc message-data :accessoutcome "AUTHORIZATION_SUCCESS"))
               (let [uri (broker-uri broker)
                     capsule (capsule/add-hop capsule uri "accepted")]
                 (if (= (:targets message) ["pcp:///server"])
@@ -547,13 +555,17 @@
             ;; default case
             (assert false (i18n/trs "unexpected message validation outcome")))
           (catch map? m
-            ;; This is a processing error, say an uncaught exception in
-            ;; any of the stuff we meant to do
+            (log-access :warn (assoc message-data :accessoutcome "PROCESSING_ERROR"))
             (send-error-message
               message
               (i18n/trs "Error {0} handling message: {1}" (:type m) (:message &throw-context))
               connection))))
       (catch map? m
+        (sl/maplog
+          [:puppetlabs.pcp.broker.pcp_access :warn]
+          (assoc (connection/summarize connection) :type :deserialization-failure
+                                                   :outcome "DESERIALIZATION_ERROR")
+          "{outcome} {remoteaddress} {commonname} unknown unknown unknown unknown unknown")
         ;; TODO(richardc): this could use a different message_type to
         ;; indicate an encoding error rather than a processing error
         (send-error-message nil (i18n/trs "Could not decode message") connection)))))


[#9061] fix fetching balances for keycard acc

--- src/status_im/multiaccounts/login/core.cljs
+++ src/status_im/multiaccounts/login/core.cljs
@@ -29,7 +29,8 @@
             [taoensso.timbre :as log]
             [status-im.ui.screens.db :refer [app-db]]
             [status-im.multiaccounts.biometric.core :as biometric]
-            [status-im.utils.identicon :as identicon]))
+            [status-im.utils.identicon :as identicon]
+            [status-im.ethereum.eip55 :as eip55]))

 (def rpc-endpoint "https://goerli.infura.io/v3/f315575765b14720b32382a61a89341a")
 (def contract-address "0xfbf4c8e2B41fAfF8c616a0E49Fb4365a5355Ffaf")
@@ -130,6 +131,13 @@
    current-network
    (types/deserialize networks)])

+(defn convert-multiaccount-addresses
+  [multiaccount]
+  (let [update-address #(update % :address eip55/address->checksum)]
+    (-> multiaccount
+        update-address
+        (update :accounts (partial mapv update-address)))))
+
 (fx/defn get-config-callback
   {:events [::get-config-callback]}
   [{:keys [db] :as cofx} config]
@@ -139,7 +147,8 @@
               {:db (assoc db
                           :networks/current-network current-network
                           :networks/networks networks
-                          :multiaccount multiaccount)}
+                          :multiaccount (convert-multiaccount-addresses
+                                         multiaccount))}
               ;; NOTE: initializing mailserver depends on user mailserver
               ;; preference which is why we wait for config callback
               (protocol/initialize-protocol {:default-mailserver true})


Add error handling to tweeting process. Complete with sassy error handling.

--- markov-clj/src/markov_clj/twitter.clj
+++ markov-clj/src/markov_clj/twitter.clj
@@ -36,8 +36,9 @@
                                (map :text)))

 (defn tweet-the-twitter [text]
-  (statuses-update :oauth-creds my-creds
-                   :params {:status text}))
+  (try (statuses-update :oauth-creds my-creds
+                    :params {:status text})
+       (catch Exception e (println "Bitch I ain't stopping for no error."))))

 (defn store-followers [ids]
   (->>
@@ -68,8 +69,7 @@

 (defn create-and-send-tweet [[screen-name tweets]]
   (->> (make-valid-tweet screen-name tweets)
-       println
-       ;; tweet-the-twitter
+       tweet-the-twitter
        )
   )


Parameterize start-markov-thread

Parameterize start-markov-thread

--- markov-clj/src/markov_clj/twitter.clj
+++ markov-clj/src/markov_clj/twitter.clj
@@ -96,13 +96,13 @@
   (let [tweets (get-tweets handle)]
     (create-and-send-tweet [handle tweets])))

-(defn start-markov-thread []
+(defn start-markov-thread [screen-name]
   (loop []
     (Thread/sleep (* 60 15000))
-    (process-followers "mockingmarkov")
+    (process-followers screen-name)
     (recur)))

-(defn -main [] (start-markov-thread))
+(defn -main [] (start-markov-thread "mockingmarkov"))

 ;; (markov-clj.util/tick-now 500 #(println "Hey there!"))


Simplify project.clj so that jar will actually build

--- jvm/project.clj
+++ jvm/project.clj
@@ -10,19 +10,17 @@
             :url "https://raw.githubusercontent.com/Parsely/streamparse/master/LICENSE"
             :distribution :repo}
   :min-lein-version "2.0.0"
-  :dependencies [[commons-collections/commons-collections "3.2.1"]
-                 ;;[org.clojars.hsestupin/storm-spirit "0.1.0"] <-- depends on wrong version of Storm
+  :dependencies [
+                 [org.clojure/clojure  "1.5.1"]
                  ]
   :profiles {:dev
               {:dependencies [
                               [org.apache.storm/storm-core "0.9.4"]
-                              [org.clojure/data.json "0.2.4"]
-                              [org.testng/testng "6.8.5"]
-                              [org.easytesting/fest-assert-core "2.0M8"]
-                              [org.mockito/mockito-all "1.9.0"]
-                              [org.jmock/jmock "2.6.0"]]
+                              [org.clojure/data.json "0.2.6"]
+                              ]
                }}
   :source-paths ["src"]
   :test-paths ["test"]
   :resource-paths ["resources"]
-  :aot :all)
+  :aot :all
+  )


Found a bug that shows up on whitespace compilation

--- src/shoreleave/remotes/common.cljs
+++ src/shoreleave/remotes/common.cljs
@@ -4,6 +4,7 @@
             [goog.Uri.QueryData :as query-data]
             [goog.structs :as structs]
             [goog.string :as gstr]
+            [goog.net.EventType :as gevent]
             [shoreleave.browser.cookies :as cookies]
             [shoreleave.remotes.protocols :as r-protocols]))


method key is readonly (#1056)

method key is readonly (#1056)

* use destructuring

* add ANON role when request is not authenticated

* methodKey is readonly

--- ssclj/jar/src/com/sixsq/slipstream/ssclj/resources/session_template.clj
+++ ssclj/jar/src/com/sixsq/slipstream/ssclj/resources/session_template.clj
@@ -83,7 +83,7 @@
                         :description "key used to identify this authentication source"
                         :type        "string"
                         :mandatory   true
-                        :readOnly    false
+                        :readOnly    true
                         :order       1}
           :redirectURI {:displayName "Redirect URI"
                         :category    "general"


Add a version unit test

Add a version unit test

--- test/com/billpiel/sayid/core_test.clj
+++ test/com/billpiel/sayid/core_test.clj
@@ -19,6 +19,8 @@

 (t/use-fixtures :each fixture)

+(t/deftest version-test
+  (t/is (string? sd/version)))

 (t/deftest add-remove-trace-ns


Quick fix for trying to fix build in travis. Real problem is that public api of porwigle.core is kinda tacky at the moment.

--- test/porwigle/handler/public_test.clj
+++ test/porwigle/handler/public_test.clj
@@ -7,7 +7,8 @@

   (testing "When page is non existent 404 with empty body is expected"

-    (with-redefs [porwigle.core/eval-page (fn [_] "")]
+    (with-redefs [porwigle.core/eval-page (fn [_] "")
+                  porwigle.core/pagestructure (fn [_] {:content ""})]

       (let [response (handle-request {:uri "/non-existent"})]
         (is (= 404 (:status response)))
@@ -15,7 +16,8 @@

   (testing "When page exists 200 with contents as body is expected"

-    (with-redefs [porwigle.core/eval-page (fn [_] "body")]
+    (with-redefs [porwigle.core/eval-page (fn [_] "body")
+                  porwigle.core/pagestructure (fn [_] {:content "body"})]

       (let [response (handle-request {:uri "/existing"})]
         (is (= 200 (:status response)))


More consistent kwarg formatting

More consistent kwarg formatting

--- src/semantic_csv/core.clj
+++ src/semantic_csv/core.clj
@@ -175,13 +175,12 @@
   "This function wraps together all of the various input processing capabilities into one, with options
   controlled by an opts hash with a heavy-handed/opinionated set of defaults:

-  * `:header`: bool; consume the first row as a header?
-  * `:comment-re`: specify a regular expression to use for commenting out lines, or something falsey
+  * `:header` - bool; consume the first row as a header?
+  * `:comment-re` - specify a regular expression to use for commenting out lines, or something falsey
      if filtering out comment lines is not desired.
-  * `:remove-empty`: also remove empty rows? Defaults to true.
-  * `:cast-fns`: optional map of `colname | index -> cast-fn`; row maps will have the values as output by the
-     assigned `cast-fn`.
-              `(cast-fns row-name)` to the string val"
+  * `:remove-empty` - also remove empty rows? Defaults to true.
+  * `:cast-fns` - optional map of `colname | index -> cast-fn`; row maps will have the values as output by the
+     assigned `cast-fn`."
   ([{:keys [comment-re header remove-empty cast-fns]
                   :or   {comment-re   #"^\#"
                          header       true
@@ -203,6 +202,7 @@
 ;;       (doall
 ;;         (process (csv/parse-csv in-file)
 ;;                  :cast-fns {:this #(Integer/parseInt %)})))
+

 ;; ## parse-and-process


CMR-4320 remove debug code

CMR-4320 remove debug code

--- umm-spec-lib/src/cmr/umm_spec/validation/temporal_extent.clj
+++ umm-spec-lib/src/cmr/umm_spec/validation/temporal_extent.clj
@@ -25,7 +25,6 @@
   "Validate that the collection ends at present flag and end date time are
   not both set"
   [field-path value]
-  (proto-repl.saved-values/save 16)
   (when (and (= true (:EndsAtPresentFlag value))
              (seq (:RangeDateTimes value))
              (not (some nil? (map :EndingDateTime (:RangeDateTimes value)))))


Include metadata when creating entry

Include metadata when creating entry

--- src/single_track/core.clj
+++ src/single_track/core.clj
@@ -85,25 +85,22 @@
    (if-let [cv (get m k)]
      (if (vector? cv)
        (assoc m k (conj cv v))
-       (assoc m k (vector cv v)))
+       (assoc m k [cv v]))
      (assoc m k v)))
   ([m [k v]]
    (put m k v)))
-
-(defn put-af
-  [m {:keys [:artist :album :title] :as v}]
-  (put m [artist album title] v))

 (defn af-key [{:keys [:artist :album :title] :as v}]
   [artist album title])

 (defn entry [v]
-  (vector (af-key v) v))
+  (let [af (metadata v)]
+    [(af-key af) af]))

 (defn -main
   ([] (-main "."))
   ([dir]
    (set-logger-level! "org.jaudiotagger" Level/OFF)
-   (reduce put {} (map entry (filtered dir)))))
+   (pprint (reduce put {} (map entry (filtered dir))))))

 #_(-main)


Fix test

Fix test

--- test/yetibot/core/test/commands/history.clj
+++ test/yetibot/core/test/commands/history.clj
@@ -15,16 +15,18 @@
               :next-cmds ["scount"]
               :skip-next-n (atom 0)})

-(history-for-cmd-sequence ["count"] chat-source)
+(def extra-where {:is-yetibot false})

-(history-for-cmd-sequence ["random"] chat-source)
+(history-for-cmd-sequence ["count"] chat-source extra-where)

-(history-for-cmd-sequence ["tail 3"] chat-source)
+(history-for-cmd-sequence ["random"] chat-source extra-where)

-(history-for-cmd-sequence ["head 3"] chat-source)
+(history-for-cmd-sequence ["tail 3"] chat-source extra-where)

-(history-for-cmd-sequence ["head"] chat-source)
+(history-for-cmd-sequence ["head 3"] chat-source extra-where)

-(history-for-cmd-sequence ["tail"] chat-source)
+(history-for-cmd-sequence ["head"] chat-source extra-where)

-(history-for-cmd-sequence ["grep 3$"] chat-source)
+(history-for-cmd-sequence ["tail"] chat-source extra-where)
+
+(history-for-cmd-sequence ["grep 3$"] chat-source extra-where)


Fix typo

Fix typo

--- src/zooniverse_live/websocket.cljs
+++ src/zooniverse_live/websocket.cljs
@@ -13,7 +13,7 @@
 (def format-msgs
   (comp (map #(.-data %))
         (map trim-newline)
-        (filter #(not (some (apply set %) ["Heartbeat" "String Start"])))
+        (filter #(not (some (apply set %) ["Heartbeat" "Stream Start" ""])))
         (map str->clj)))

 (defn request


include root namespace in list of modified namespaces in bake.compile/stale-namespaces

--- bake/bake/compile.clj
+++ bake/bake/compile.clj
@@ -21,7 +21,8 @@
                 (let [namespace (second (read-file-ns-decl sourcefile))
                       classfile (classfile namespace)]
                   (if (and (> (.lastModified sourcefile) (.lastModified classfile)))
-                    (union stale (dependents @dep-graph namespace))
+                    (union stale (conj (dependents @dep-graph namespace)
+                                       namespace))
                     stale)))
               #{} (find-clojure-sources-in-dir (File. source-path))))))


Silly util for hotloading dependencies with pomegranate

--- src/strange_coop/util.clj
+++ src/strange_coop/util.clj
@@ -1,5 +1,6 @@
 (ns strange-coop.util
-  (:require [clojure.data.csv :as csv]))
+  (:require [clojure.data.csv :as csv]
+            [cemerick.pomegranate :refer [add-dependencies]]))

 (defn log
@@ -33,3 +34,7 @@
   (.addShutdownHook (Runtime/getRuntime) (Thread. f)))

+(defn load-dep
+  [dep]
+  (add-dependencies :coordinates [dep] :repositories (merge cemerick.pomegranate.aether/maven-central {"clojars" "http://clojars.org/repo"})))
+


beta cores instead of alpha with right docker vs

--- src/terraboot/cluster.clj
+++ src/terraboot/cluster.clj
@@ -3,7 +3,7 @@
             [terraboot.vpc :as vpc]
             [terraboot.cloud-config :refer [cloud-config]]))

-(def current-coreos-ami "ami-07f1ec6b")
+(def current-coreos-ami "ami-1807e377")

 (defn mesos-instance-user-data []
   {:coreos {:units [{:name "etcd.service" :command "stop" :mask true}


influxdb-ip added for all boxes

influxdb-ip added for all boxes

--- src/terraboot/cluster.clj
+++ src/terraboot/cluster.clj
@@ -388,7 +388,8 @@
                                        :exhibitor-s3-bucket (cluster-unique "exhibitor-s3-bucket")
                                        :internal-lb-dns (cluster-output-of "aws_elb" "internal-lb" "dns_name")
                                        :fallback-dns (vpc/fallback-dns vpc/vpc-cidr-block)
-                                       :number-of-masters min-number-of-masters}
+                                       :number-of-masters min-number-of-masters
+                                       :influxdb-ip (output-of "aws_instance" "influxdb" "private_ip")                                       }
                                 :lifecycle { :create_before_destroy true }})

              (resource "aws_route53_record" (cluster-unique "masters")
@@ -446,7 +447,8 @@
                                        :exhibitor-s3-bucket (cluster-unique "exhibitor-s3-bucket")
                                        :internal-lb-dns (cluster-output-of "aws_elb" "internal-lb" "dns_name")
                                        :fallback-dns (vpc/fallback-dns vpc/vpc-cidr-block)
-                                       :number-of-masters min-number-of-masters}
+                                       :number-of-masters min-number-of-masters
+                                       :influxdb-ip (output-of "aws_instance" "influxdb" "private_ip")                                       }
                                 :lifecycle { :create_before_destroy true }

                                 })


remove some leftover debug cruft [ci skip]

--- frontend/components/forms.cljs
+++ frontend/components/forms.cljs
@@ -56,7 +56,6 @@
     (append-cycle owner :loading)
     (let [{:keys [uuid channel]} (register-channel! owner)]
       (binding [frontend.async/*uuid* uuid]
-        frontend.async/*uuid*
         (go (append-cycle owner (<! channel))
             (deregister-channel! owner uuid))
         (apply handler args)))))


add back the dummy chat

add back the dummy chat

--- src-cljs/frontend/components/chat.cljs
+++ src-cljs/frontend/components/chat.cljs
@@ -131,10 +131,11 @@
                                     " for help."]
                         :chat/color "#00b233"
                         :session/uuid chat-bot
-                        :server/timestamp (js/Date. 0)}]
+                        :server/timestamp (js/Date.)}]
         (html
          [:section.chat-log
           [:div.chat-messages {:ref "chat-messages"}
+           (om/build chat-item dummy-chat {:opts {:show-sender? true}})
            (let [chat-groups (group-by #(date->bucket (:server/timestamp %)) chats)]
              (for [[time chat-group] (sort-by #(:server/timestamp (first (second %)))
                                               chat-groups)]
@@ -143,10 +144,11 @@
                                (not= #{"Today"} (set (keys chat-groups))))
                        [:h2.chat-date time])
                      (for [[prev-chat chat] (partition 2 1 (concat [nil] (sort-by :server/timestamp chat-group)))]
-                       (om/build chat-item chat {:key :db/id
-                                                 :opts {:client-id client-id
-                                                        :show-sender? (not= (chat-model/display-name prev-chat client-id)
-                                                                            (chat-model/display-name chat client-id))}})))))]
+                       (om/build chat-item chat
+                                 {:key :db/id
+                                  :opts {:client-id client-id
+                                         :show-sender? (not= (chat-model/display-name prev-chat client-id)
+                                                             (chat-model/display-name chat client-id))}})))))]
           [:form {:on-submit #(do (cast! :chat-submitted)
                                   false)
                   :on-key-down #(when (and (= "Enter" (.-key %))


add flash notification to ssh-key add

add flash notification to ssh-key add

--- src-cljs/frontend/controllers/api.cljs
+++ src-cljs/frontend/controllers/api.cljs
@@ -552,7 +552,9 @@
   [target message status {:keys [resp context]} state]
   (if-not (= (:project-id context) (project-model/id (get-in state state/project-path)))
     state
-    (assoc-in state (conj state/project-data-path :new-ssh-key) {})))
+    (-> state
+        (assoc-in (conj state/project-data-path :new-ssh-key) {})
+        (state/add-flash-notification "Your key has been successfully added."))))

 (defmethod post-api-event! [:save-ssh-key :success]
   [target message status {:keys [context resp]} previous-state current-state]


Added test cases

Added test cases

--- test/clinvar_submitter/ld_test.clj
+++ test/clinvar_submitter/ld_test.clj
@@ -7,7 +7,9 @@
             [com.github.jsonldjava.utils JsonUtils]
             [java.util Map List]))

-(def t (generate-symbol-table "data/dmwg2.json" "data/context-new.jsonld"))
+(def interp-path "data/dmwg2.json")
+(def context-path "data/cg-interpretation.jsonld")
+(def t (generate-symbol-table interp-path context-path))
 (def node  {"id" "_:b404","type" "Conservation","allele" "http://reg.genome.network/allele/CA012832","algorithm" "phastconsp7way","score" "1","contribution" {"id" "_:b405"}})
 (def m (vals t))
 (def interps ((prop= t "VariantInterpretation" "type") m))
@@ -17,7 +19,7 @@

 (deftest generate-symbol-table-test
 (testing "Test if symbol table is generated from jason input files"
-(is (= t (generate-symbol-table "data/dmwg2.json" "data/context-new.jsonld")))
+(is (= t (generate-symbol-table "data/dmwg2.json" "data/cg-interpretation.jsonld")))
 (println "SYMBOL TABLE")
 (json/pprint (take 5 t))))


Removes bad require

Removes bad require

--- test/clj/clojure/lang/out_test.clj
+++ test/clj/clojure/lang/out_test.clj
@@ -3,7 +3,6 @@
   (:require [clojure.test                       :refer :all]
             [clojure.next                       :refer :all]
             [clojure.support.test-seq           :refer [test-seq]]
-            [clojure.lang.persistent-sorted-set :refer [sorted-set]]
             [clojure.lang.protocols             :refer [IMeta ISeq ISeqable ISequential]]))

 (deftest print-simple-test


fix transitive dependencies

fix transitive dependencies

--- jar-prslib/build.boot
+++ jar-prslib/build.boot
@@ -21,11 +21,11 @@
   #(reduce conj % [["sixsq" {:url (sixsq-repo (get-env :version) (get-env :edition))}]])

   :dependencies
-  '[[org.clojure/clojure "1.8.0" :scope "provided"]
-    [org.clojure/tools.logging "0.3.1" :scope "provided"]
-    [org.clojure/data.json "0.2.6" :scope "provided"]
-    [com.sixsq.slipstream/SlipStreamPersistence "3.6-SNAPSHOT" :scope "provided"]
-    [com.sixsq.slipstream/SlipStreamClientAPI-jar "3.6-SNAPSHOT" :scope "provided"]
+  '[[org.clojure/clojure "1.8.0"]
+    [org.clojure/tools.logging "0.3.1"]
+    [org.clojure/data.json "0.2.6"]
+    [com.sixsq.slipstream/SlipStreamPersistence "3.6-SNAPSHOT"]
+    [com.sixsq.slipstream/SlipStreamClientAPI-jar "3.6-SNAPSHOT"]
     [adzerk/boot-test "1.1.0" :scope "test"]
     [adzerk/boot-reload "0.4.5" :scope "test"]
     [tolitius/boot-check "0.1.1" :scope "test"]


Refactor

Refactor

--- test/icecap/handlers/core_test.clj
+++ test/icecap/handlers/core_test.clj
@@ -51,8 +51,9 @@

 (deftest execute-tests
   (testing "execute single step"
-    (is (= (execution-order (td/success-step 1))
-           [1])))
+    (let [plan (td/success-step 1)
+          order (execution-order plan)]
+      (is (= order [1]))))
   (testing "execute some plans consisting of ordered steps"
     (let [names (vec (range 10))
           plan (success-steps names)
@@ -68,8 +69,7 @@
     (let [ordered-head (success-steps [1 2 3])
           unordered-middle (success-steps #{4 5 6})
           ordered-tail (success-steps [7 8 9])
-          plan (into (conj ordered-head unordered-middle)
-                     ordered-tail)
+          plan (vec (concat ordered-head [unordered-middle] ordered-tail))
           spec [[1 2 3] #{4 5 6} [7 8 9]]]
       (is (match-seq-spec spec (execution-order plan))))))


Protect application state from access and alteration

By keeping the application state atom inside a let binding, it cannot be accessed
from the outside, thus protecting it from (accidental) mutilation from the outside.
Instead, the only way to interact with the application state shall be through
putting messages put on the channels passed as parameters in the init-state function.

--- Clojure-Websockets/MainApp/src/cljs/birdwatch/state/data.cljs
+++ Clojure-Websockets/MainApp/src/cljs/birdwatch/state/data.cljs
@@ -2,15 +2,17 @@
   (:require [birdwatch.state.initial :as i]
             [birdwatch.state.comm :as c]))

-;;;; Application state in a single atom.
-(def app (atom {}))
-
 (defn init-state
-  "Init app state and wire all channels required in the state namespace."
+  "Init app state and wire all channels required in the state namespace. The app
+   atom is held inside the let binding of this function and thus protected from
+   outside access / alteration. The only way to interact with it is by sending
+   messages on channels, such the provided data channel for adding new data or
+   sending commands on the cmd-chan."
   [data-chan qry-chan stats-chan cmd-chan state-pub-chan]
-  (i/init app)
-  (c/stats-loop stats-chan app)
-  (c/data-loop data-chan app)
-  (c/cmd-loop cmd-chan state-pub-chan app)
-  (c/connect-qry-chan qry-chan)
-  (c/broadcast-state state-pub-chan app))
+  (let [app (atom {})]
+    (i/init app)
+    (c/stats-loop stats-chan app)
+    (c/data-loop data-chan app)
+    (c/cmd-loop cmd-chan state-pub-chan app)
+    (c/connect-qry-chan qry-chan)
+    (c/broadcast-state state-pub-chan app)))


Helpful function for testing coercion from repl

--- test/testing/plan_schema/core.cljc
+++ test/testing/plan_schema/core.cljc
@@ -58,9 +58,12 @@
            (io/make-parents parsed-edn)
            (spit parsed-edn (with-out-str (pprint out-edn)))
            (spit parsed-json (with-out-str (pprint out-json)))
-           (is false (prn-str "Files differ" parsed-edn parsed-json))))))
+           (is false (prn-str "Files differ" parsed-edn parsed-json)))))))

-   )
+(defn do-coerce [infile file-format]
+  ; file-format is keyword, :htn or :tpn
+  (execute-action (System/getProperty "user.dir") infile "-" file-format)
+  nil)

 (deftest test-json
   (testing "test json"


Quiet signature test for now.

Quiet signature test for now.

--- test/vault/data/signature_test.clj
+++ test/vault/data/signature_test.clj
@@ -48,8 +48,9 @@
                     (sig/blob-signer blob-store provider)
                     (edn-data/edn-blob value)
                     (sig/verify blob-store))]
-      (println "Signed blob:")
+      #_
       (binding [puget/*colored-output* true]
+        (println "Signed blob:")
         (edn-data/print-blob blob)
         (newline) (newline)
         (puget/pprint blob)))))


app cleanup

app cleanup

--- rn-app/src/cljs/meo/ui.cljs
+++ rn-app/src/cljs/meo/ui.cljs
@@ -5,8 +5,6 @@
             [cljs.pprint :as pp]
             [meo.helpers :as h]
             [meo.utils.parse :as p]))
-
-(defonce put-fn-atom (r/atom nil))

 (def ReactNative (js/require "react-native"))
 (def react-native-camera (js/require "react-native-camera"))
@@ -30,7 +28,7 @@

 (reg-sub :entries (fn [db _] (:entries db)))

-(defn menu-bar [local]
+(defn menu-bar [local put-fn]
   (let [defaults {:background-color "blue"
                   :padding-left     15
                   :padding-right    15
@@ -50,8 +48,7 @@
                     :padding-right  10}}
       [touchable-highlight
        {:style    (merge defaults {:background-color "green"})
-        :on-press #(let [put-fn @put-fn-atom
-                         new-entry (p/parse-entry (:md @local))
+        :on-press #(let [new-entry (p/parse-entry (:md @local))
                          new-entry-fn (h/new-entry-fn put-fn new-entry nil)]
                      (new-entry-fn)
                      (swap! local assoc-in [:md] ""))}
@@ -68,16 +65,14 @@
         (if (:cam @local) "hide cam" "ws")]]
       [touchable-highlight
        {:style    defaults
-        :on-press #(let [put-fn @put-fn-atom]
-                     (put-fn [:sync/initiate]))}
+        :on-press #(put-fn [:sync/initiate])}
        [text {:style {:color       "white"
                       :text-align  "center"
                       :font-weight "bold"}}
         "sync"]]
       [touchable-highlight
        {:style    defaults
-        :on-press #(let [put-fn @put-fn-atom]
-                     (put-fn [:state/reset]))}
+        :on-press #(put-fn [:state/reset])}
        [text {:style {:color       "white"
                       :text-align  "center"
                       :font-weight "bold"}}
@@ -89,33 +84,29 @@
                     :padding-right  10}}
       [touchable-highlight
        {:style    defaults
-        :on-press #(let [put-fn @put-fn-atom]
-                     (put-fn [:healthkit/weight]))}
+        :on-press #(put-fn [:healthkit/weight])}
        [text {:style {:color       "white"
                       :text-align  "center"
                       :font-weight "bold"}}
         "weight"]]
       [touchable-highlight
        {:style    defaults
-        :on-press #(let [put-fn @put-fn-atom]
-                     (put-fn [:healthkit/bp]))}
+        :on-press #(put-fn [:healthkit/bp])}
        [text {:style {:color       "white"
                       :text-align  "center"
                       :font-weight "bold"}}
         "bp"]]
       [touchable-highlight
        {:style    defaults
-        :on-press #(let [put-fn @put-fn-atom]
-                     (dotimes [n 2]
-                       (put-fn [:healthkit/steps n])))}
+        :on-press #(dotimes [n 2]
+                     (put-fn [:healthkit/steps n]))}
        [text {:style {:color       "white"
                       :text-align  "center"
                       :font-weight "bold"}}
         "steps"]]
       [touchable-highlight
        {:style    defaults
-        :on-press #(let [put-fn @put-fn-atom]
-                     (put-fn [:healthkit/sleep]))}
+        :on-press #(put-fn [:healthkit/sleep])}
        [text {:style {:color       "white"
                       :text-align  "center"
                       :font-weight "bold"}}
@@ -149,7 +140,7 @@
                       :text-align    "center"}}
         (str (count @entries) " entries")]

-       [menu-bar local]
+       [menu-bar local put-fn]

        (when-let [barcode (:barcode @local)]
          [text {:style {:font-size     10
@@ -201,25 +192,12 @@
                        :default-value  (:md @local)
                        :keyboard-type  "twitter"
                        :on-change-text (fn [text]
-                                         (swap! local assoc-in [:md] text))}])]
-
-       #_[text {:style {:font-size     10
-                        :font-weight   "500"
-                        :color         "#CCC"
-                        :margin-bottom 20
-                        :text-align    "center"}}
-          (with-out-str (pp/pprint (second (last (sort-by first @entries)))))]
-       #_[image {:source logo-img
-                 :style  {:width         80
-                          :height        80
-                          :margin-bottom 5}}]
-       ])))
+                                         (swap! local assoc-in [:md] text))}])]])))

 (defn state-fn [put-fn]
   (let [app-root (app-root put-fn)
         register #(r/reactify-component app-root)]
-    (.registerComponent app-registry "meo" register)
-    (reset! put-fn-atom put-fn))
+    (.registerComponent app-registry "meo" register))
   {:observed rdb/app-db})

 (defn cmp-map [cmp-id]


don't require a first name

don't require a first name

--- src/pc/crm.clj
+++ src/pc/crm.clj
@@ -19,7 +19,7 @@

 (def dribbble-user-link-re #"^https://dribbble\.com/([^/]+)$")
 (defn find-dribbble-username [cust]
-  (when (and (:cust/first-name cust) (:cust/last-name cust))
+  (when (:cust/last-name cust)
     (some->> (search-dribbble (str (:cust/first-name cust) " " (:cust/last-name cust)))
       (map #(get % "link"))
       (filter #(re-find dribbble-user-link-re %))