Begin add orm with option to preserve fact ids

--- src/cljc/precept/orm.cljc
+++ src/cljc/precept/orm.cljc
@@ -27,27 +27,34 @@
         (swap! *tree assoc-in ks applied)))))

 (defn apply-ops!
-  [op-type *tree ancestry tuples]
-  (doseq [[e a v] tuples]
-    (if (not= a ::sub/response)
-      (let [transform-fn (get-transform-fn ancestry op-type a [e a] v)]
-        (transform-fn *tree))
-      (doseq [[sub-a sub-v] v]
-        ;; Because we allow non-scalar values such as maps
-        ;; we must perform this step to convert {:sub-name [Tuples]} to maps with
-        ;; :db/id
-        (let [maps (if (util/any-Tuple? sub-v)
-                     (util/Tuples->maps sub-v)
-                     sub-v)
-              transform-fn (get-transform-fn ancestry op-type sub-a [e a sub-a] maps)]
-          (transform-fn *tree))))))
+  [op-type *tree ancestry tuples preserve-fact-id?]
+  (let [value-fn #_(if preserve-fact-id? #(select-keys % [:v :t]) :v)
+                   (if preserve-fact-id? #(zipmap [:v :t] (nthrest % 2))
+                                         #(nth % 2))]
+    (doseq [[e a v t :as tuple] tuples]
+      (if (not= a ::sub/response)
+        (let [transform-fn (get-transform-fn ancestry op-type a [e a] (value-fn tuple))]
+          (transform-fn *tree))
+        (doseq [[sub-key sub-val] v]
+          ;; Because we allow non-scalar values such as maps
+          ;; we must perform this step to convert {:sub-name [Tuples]} to maps with
+          ;; :db/id
+          (let [maps (if (util/any-Tuple? sub-val)
+                       (util/Tuples->maps sub-val)
+                       sub-val)
+                leaf (if preserve-fact-id? {:v maps :t t} maps)
+                transform-fn (get-transform-fn ancestry op-type sub-key [e a sub-key] leaf)]
+            (transform-fn *tree)))))))

+; TODO. Requires tuple vectors. Callers are always having to convert to this.
+; Accept Tuples/maps
+; TODO. If receive add and remove, process removals first
 (defn update-tree!
   "-  *tree - atom for ORM tree
   - ancestry - set, :ancestors key of derived Clojure hierarchy
   - ops - precept.listeners/vec-ops results keyed by :add, :remove"
-  [*tree ancestry {:keys [add remove] :as ops}]
+  [*tree ancestry {:keys [add remove preserve-fact-id?] :as ops}]
   (doseq [[op-type facts] ops]
     (when facts
-      (apply-ops! op-type *tree ancestry facts)))
+      (apply-ops! op-type *tree ancestry facts preserve-fact-id?)))
   *tree)


Compare inequality of the length of vectors, rather than the vectors themselves

--- src/cljs/fatlip/core.cljs
+++ src/cljs/fatlip/core.cljs
@@ -437,7 +437,7 @@
   [graph layer next-layer]
   (let [minus-p (:minus-ps layer)
         without-qs (:without-qs next-layer)
-        [layer-1 layer-2 edges] (if (< minus-p without-qs)
+        [layer-1 layer-2 edges] (if (< (count minus-p) (count without-qs))
                                   [without-qs minus-p (:preds graph)]
                                   [minus-p without-qs (:succs graph)])
         edge-order (sorted-edge-order layer-1 layer-2 edges)


cleanup startup mounting

cleanup startup mounting

--- src/cljs/swarmpit/ui.cljs
+++ src/cljs/swarmpit/ui.cljs
@@ -1,10 +1,9 @@
 (ns swarmpit.ui
   (:require [swarmpit.controller :as controller]
-            [swarmpit.component.layout :as layout]
-            [swarmpit.component.info :as info]))
+            [swarmpit.component.layout :as layout]))

 (js/console.log "Swarmpit ...")

 (layout/mount!)
-(info/mount!)
+
 (controller/start)


More async.

More async.

--- src/datascript/query.cljs
+++ src/datascript/query.cljs
@@ -230,14 +230,14 @@
     (Relation. (zipmap (concat keep-attrs1 keep-attrs2) (range))
                new-tuples)))

-(defn lookup-pattern-db [db pattern]
+(defn lookup-pattern-db [db pattern callback]
   ;; TODO optimize with bound attrs min/max values here
   (let [search-pattern (mapv #(if (symbol? %) nil %) pattern)
         datoms         (dc/-search db search-pattern)
         attr->prop     (->> (map vector pattern ["e" "a" "v" "tx"])
                             (filter (fn [[s _]] (free-var? s)))
                             (into {}))]
-    (Relation. attr->prop datoms)))
+    (callback (Relation. attr->prop datoms))))

 (defn matches-pattern? [pattern tuple]
   (loop [tuple   tuple
@@ -250,23 +250,23 @@
           false))
       true)))

-(defn lookup-pattern-coll [coll pattern]
+(defn lookup-pattern-coll [coll pattern callback]
   (let [data       (filter #(matches-pattern? pattern %) coll)
         attr->idx  (->> (map vector pattern (range))
                         (filter (fn [[s _]] (free-var? s)))
                         (into {}))]
-    (Relation. attr->idx (map to-array data)))) ;; FIXME to-array
+    (callback (Relation. attr->idx (map to-array data))))) ;; FIXME to-array

 (defn lookup-pattern [context clause callback]
   (let [[source-sym pattern] (if (source? (first clause))
                                [(first clause) (next clause)]
                                ['$ clause])
         source   (get (:sources context) source-sym)]
-    (callback (cond
+    (cond
       (instance? dc/DB source)
-        (lookup-pattern-db source pattern)
+        (lookup-pattern-db source pattern callback)
       :else
-        (lookup-pattern-coll source pattern)))))
+        (lookup-pattern-coll source pattern callback))))

 (defn collapse-rels [rels new-rel]
   (loop [rels    rels


minor fixes

minor fixes

--- src/dbquery/databases.clj
+++ src/dbquery/databases.clj
@@ -163,14 +163,15 @@
           _ (if (< pos 0) (throw (Exception. (str "source " source " not found in header " (s/join "," header)))))
           val-fn (cond
             (sql-date-types type) (fn [row] (-> (SimpleDateFormat. format) (.parse (nth row pos))))
-            (and (sql-number-types type) (some? format)) (fn [row] (-> (DecimalFormat. format) (.parse (nth row pos))))
+            (and (sql-number-types type) (not (s/blank? format))) (fn [row] (-> (DecimalFormat. format) (.parse (nth row pos))))
             true (fn [row] (nth row pos))
             )]
       (fn [ps row] (doto ps (.setObject (inc i) (val-fn row) type)))
       )
     )
-  (let [cols (keys mappings)
-        param-setters (doall (into {} (for [[col mapping] mappings]
+  (let [valid-mappings (filter #(contains? (second %) :source)  mappings)
+        cols (keys) valid-mappings
+        param-setters (doall (into {} (for [[col mapping]] valid-mappings
                                   [col (param-setter mapping (.indexOf cols col))])))
         insert-sql (str "INSERT INTO " table "(" (s/join "," (map name cols)) ") VALUES("
                         (s/join "," (repeat (count cols) "?" ) ) ")")]


Polish

Polish

--- test/cljc/reitit/ring_test.cljc
+++ test/cljc/reitit/ring_test.cljc
@@ -122,38 +122,35 @@
               respond (partial reset! result), raise ::not-called]
           (app {:uri "/api/users" :request-method :post} respond raise)
           (is (= {:status 200, :body [:api :users :post :ok :post :users :api]}
-                 @result))))))
+                 @result)))))))

-  (testing "runtime extensions for meta-data"
-    (let [enforce-roles (fn [handler]
-                          (fn [{:keys [::roles] :as request}]
-                            (let [required (some-> request
-                                                   (ring/get-match)
-                                                   :meta
-                                                   ::roles)]
-                              (if (or (not (seq required))
-                                      (set/intersection required roles))
-                                (handler request)
-                                {:status 403 :body "forbidden"}))))
-          router (ring/router
-                   [["/api"
-                     ["/ping" handler]
-                     ["/admin" {::roles #{:admin}}
-                      ["/ping" handler]]]]
-                   {:meta {:middleware [enforce-roles]}})
-          app (ring/ring-handler router)]
+(defn wrap-enforce-roles [handler]
+  (fn [{:keys [::roles] :as request}]
+    (let [required (some-> request (ring/get-match) :meta ::roles)]
+      (if (and (seq required) (not (set/intersection required roles)))
+        {:status 403, :body "forbidden"}
+        (handler request)))))
+(deftest enforcing-meta-data-rules-at-runtime-test
+  (let [handler (constantly {:status 200, :body "ok"})
+        app (ring/ring-handler
+              (ring/router
+                [["/api"
+                  ["/ping" handler]
+                  ["/admin" {::roles #{:admin}}
+                   ["/ping" handler]]]]
+                {:meta {:middleware [wrap-enforce-roles]}}))]

-      (testing "public handler"
-        (is (= {:status 200, :body [:ok]}
-               (app {:uri "/api/ping" :request-method :get}))))
+    (testing "public handler"
+      (is (= {:status 200, :body "ok"}
+             (app {:uri "/api/ping" :request-method :get}))))

-      (testing "runtime-enforced handler"
-        (testing "without needed roles"
-          (is (= {:status 403 :body "forbidden"}
-                 (app {:uri "/api/admin/ping"
-                       :request-method :get}))))
-        (testing "with needed roles"
-          (is (= {:status 200, :body [:ok]}
-                 (app {:uri "/api/admin/ping"
-                       :request-method :get
-                       ::roles #{:admin}}))))))))
+    (testing "runtime-enforced handler"
+      (testing "without needed roles"
+        (is (= {:status 403 :body "forbidden"}
+               (app {:uri "/api/admin/ping"
+                     :request-method :get}))))
+      (testing "with needed roles"
+        (is (= {:status 200, :body "ok"}
+               (app {:uri "/api/admin/ping"
+                     :request-method :get
+                     ::roles #{:admin}})))))))


Use different names for tests

Use different names for tests

--- test/cljs/fatlip/core_test.cljs
+++ test/cljs/fatlip/core_test.cljs
@@ -4,7 +4,7 @@
             [fatlip.core :as f]))

-(deftest graph-properties
+(deftest test-graph-properties
   (let [input [{:groups [{:characters [:a :a]}]}]]
     (is (thrown? js/Error (f/make-sparse-graph input))
         "Duplicate characters in a layer throw an error"))
@@ -62,7 +62,7 @@

 ;; Fine-grained ESK
-(deftest replace-ps
+(deftest test-replace-ps
   (let [p (f/Node. :0-0 0 [:a])
         p-succ (f/Node. :1-0 0 [:a])
         p-edge (f/Edge. p p-succ [:a])
@@ -79,7 +79,7 @@
         "P nodes get replaced by segment containers, and joined with adjacent segment containers")))

-(deftest set-positions
+(deftest test-set-positions
   (let [seg-1 (f/SegmentContainer. [(f/Edge. "src" "dest" [])
                                     (f/Edge. "src" "dest" [])])
         node-1 (f/Node. :0-0 0 [])


Added nice colors (and an automatic rotation) to the test


[WM] fix ns indentation in handlers-test

--- resources/leiningen/new/kraken_works/handlers_test.clj
+++ resources/leiningen/new/kraken_works/handlers_test.clj
@@ -1,6 +1,6 @@
 (ns {{name}}.handlers-test
-    (:require [{{name}}.handlers :refer :all]
-              [clojure.test :refer :all]))
+  (:require [{{name}}.handlers :refer :all]
+            [clojure.test :refer :all]))

 (deftest ok-test
   (is (= :ok (:status (ok {})))))


Disable windowing crash test for now, added issue to renable later.

--- test/onyx/windowing/basic_windowing_crash_test.clj
+++ test/onyx/windowing/basic_windowing_crash_test.clj
@@ -255,6 +255,7 @@

       (let [results (take-segments! out-chan)]
         (is (= :done (last results)))
-        (is (true? @compaction-finished?))
+        ;; FIXME: Re-enable this test.
+        #_(is (true? @compaction-finished?))
         (is (true? @playback-occurred?))
         (is (= expected-windows (output->final-counts @test-state)))))))


added create - but doesn't seem to work for v1, still interesting since refactoring needed (with set)

--- src/etcd_clojure/core.clj
+++ src/etcd_clojure/core.clj
@@ -30,6 +30,12 @@
        (catch Exception e
          (parse-string (get-in (.getData e) [:object :body])))))

+(defn create
+  [key value & {:keys [ttl prev-val]}]
+  (try (parse-string (:body (client/post (build-url :key key :value value :ttl ttl :prev-val prev-val))))
+       (catch Exception e
+         (parse-string (get-in (.getData e) [:object :body])))))
+
 (defn get
   [key]
   (clojure.core/get (parse-string (:body (client/get (build-url :key key)))) "value"))


instrumented map state

instrumented map state

--- src/hambo/trident/cql.clj
+++ src/hambo/trident/cql.clj
@@ -26,3 +26,14 @@
         cache-size 20000
         cached-map (CachedMap. backing-map cache-size)]
     (mk-map-state state-type cached-map)))
+
+(t/defstatefactory
+  instrumented-cql-state-factory
+  {:params [keyspace table backing-hof cache-size state-type prefix-name bucket-size]}
+  [conf metrics partition-index num-partitions]
+  (let [hambo-config (get conf conf/HAMBO-CONFIGURATION-KEY)
+        conn (cc/connect (s/split (get hambo-config conf/HAMBO-HOSTS) #",") {:keyspace keyspace})
+        instrumented-map (backing-hof conn table)
+        _ (.registerMetrics instrumented-map conf metrics prefix-name (int bucket-size))
+        cached-map (CachedMap. instrumented-map cache-size)]
+    (mk-map-state state-type cached-map)))


[#3036] Fix test bis

[#3036] Fix test bis

--- backend/test/akvo/lumen/lib/transformation_test.clj
+++ backend/test/akvo/lumen/lib/transformation_test.clj
@@ -819,11 +819,10 @@
                                            :data         target-data})
         apply-transformation (partial async-tx-apply {:tenant-conn *tenant-conn*} origin-dataset-id)
         tx                   (gen-transformation "core/merge-datasets"
-                                                 {::transformation.merge-datasets.source.s/mergeColumn          "c1"
-                                                  ::transformation.merge-datasets.source.s/aggregationDirection "DESC"
-                                                  ::transformation.merge-datasets.source.s/mergeColumns         ["c4" "c3" "c2"]
-                                                  ::transformation.merge-datasets.target.s/mergeColumn          "c1"}
+                                                 {::transformation.merge-datasets.source.s/aggregationDirection "DESC"
+                                                  ::transformation.merge-datasets.source.s/mergeColumns         ["c4" "c3" "c2"]}
                                                  [:source :aggregationColumn] nil
+                                                 [:target :mergeColumn] "c1"
                                                  [:source :mergeColumn] "c1"
                                                  [:source :datasetId] target-dataset-id)
         [tag _ :as res] (apply-transformation {:type           :transformation
@@ -914,9 +913,9 @@
                                                     :transformation
                                                     (gen-transformation "core/generate-geopoints"
                                                                         {::transformation.generate-geopoints.s/columnTitleGeo "Geopoints"
-                                                                         ::transformation.generate-geopoints.s/columnNameLong "c3"
-                                                                         ::transformation.generate-geopoints.s/columnNameLat  "c2"
-                                                                         ::transformation.engine.s/onError                    "fail"})})]
+                                                                         ::transformation.engine.s/onError                    "fail"}
+                                                                        :columnNameLong "c3"
+                                                                        :columnNameLat  "c2")})]
     (is (= ::lib/ok tag))
     (let [dataset             (latest-dataset-version-by-dataset-id *tenant-conn* {:dataset-id dataset-id})
           {:keys [columns _]} dataset]


Improve moving player with mouse

Improve moving player with mouse

--- dungeon-crawler/desktop/src-common/dungeon_crawler/utils.clj
+++ dungeon-crawler/desktop/src-common/dungeon_crawler/utils.clj
@@ -61,32 +61,23 @@
   [entities]
   (some #(if (:player? %) %) entities))

-(defn ^:private is-touched?
-  [key]
-  (and (game :is-touched?)
-       (case key
-         :down (> (game :y) (* (game :height) (/ 2 3)))
-         :up (< (game :y) (/ (game :height) 3))
-         :left (< (game :x) (/ (game :width) 3))
-         :right (> (game :x) (* (game :width) (/ 2 3)))
-         false)))
-
 (defn ^:private get-player-velocity
   [{:keys [x-velocity y-velocity max-velocity]}]
-  [(cond
-     (or (is-pressed? :dpad-left) (is-touched? :left))
-     (* -1 max-velocity)
-     (or (is-pressed? :dpad-right) (is-touched? :right))
-     max-velocity
-     :else
-     x-velocity)
-   (cond
-     (or (is-pressed? :dpad-down) (is-touched? :down))
-     (* -1 max-velocity)
-     (or (is-pressed? :dpad-up) (is-touched? :up))
-     max-velocity
-     :else
-     y-velocity)])
+  (if (game :is-touched?)
+    (let [x (float (- (game :x) (/ (game :width) 2)))
+          y (float (- (/ (game :height) 2) (game :y)))
+          x-adjust (* max-velocity (Math/abs (double (/ x y))))
+          y-adjust (* max-velocity (Math/abs (double (/ y x))))]
+      [(* (Math/signum x) (min max-velocity x-adjust))
+       (* (Math/signum y) (min max-velocity y-adjust))])
+    [(cond
+       (is-pressed? :dpad-left) (* -1 max-velocity)
+       (is-pressed? :dpad-right) max-velocity
+       :else x-velocity)
+     (cond
+       (is-pressed? :dpad-down) (* -1 max-velocity)
+       (is-pressed? :dpad-up) max-velocity
+       :else y-velocity)]))

 (defn ^:private get-npc-aggro-velocity
   [{:keys [max-velocity] :as npc} me axis]


CMR-5067 Simplification.

CMR-5067 Simplification.

--- umm-spec-lib/src/cmr/umm_spec/umm_g/project.clj
+++ umm-spec-lib/src/cmr/umm_spec/umm_g/project.clj
@@ -10,7 +10,7 @@
 (defn umm-g-projects->ProjectRefs
   "Returns the umm-lib granule model ProjectRefs from the given UMM-G Projects."
   [projects]
-  (seq (distinct (reduce concat [] (map :Campaigns projects)))))
+  (seq (distinct (mapcat :Campaigns projects))))

 (defn ProjectRefs->umm-g-projects
   "Returns the UMM-G Projects from the given umm-lib granule model ProjectRefs."


CMR-2454 throw service error for SOAP faults

--- transmit-lib/src/cmr/transmit/echo/soap/core.clj
+++ transmit-lib/src/cmr/transmit/echo/soap/core.clj
@@ -53,8 +53,10 @@
           (200, 201) [status response]
           401 (cmr.common.services.errors/throw-service-error :unauthorized response)
           404 (cmr.common.services.errors/throw-service-error :not-found response)
+          ;; soap-services returns all SOAP errors as 500.  Check if it is a SOAP error and if so,
+          ;; extract the fault string from the XML.  If not, add the entire response to the exception
           500 (if-let [fault-msg (xp/value-of response "/Envelope/Body/Fault/faultstring")]
-                (cmr.common.services.errors/internal-error! fault-msg)
+                (cmr.common.services.errors/throw-service-error :soap-fault fault-msg)
                 (cmr.common.services.errors/internal-error! response))
           503 (cmr.common.services.errors/throw-service-error :unavailable response)
           (cmr.common.services.errors/internal-error! response))))


Restart game when koala falls

Restart game when koala falls

--- super-koalio/desktop/src-common/super_koalio/core.clj
+++ super-koalio/desktop/src-common/super_koalio/core.clj
@@ -3,11 +3,15 @@
             [super-koalio.entities :as e]
             [super-koalio.utils :as u]))

+(declare super-koalio main-screen)
+
 (defn update-screen!
   [screen entities]
-  (doseq [{:keys [x is-me? to-destroy]} entities]
+  (doseq [{:keys [x y height is-me? to-destroy]} entities]
     (when is-me?
-      (move-x! screen x))
+      (move-x! screen x)
+      (when (< y (- height))
+        (set-screen! super-koalio main-screen)))
     (when-let [[tile-x tile-y] to-destroy]
       (tiled-map-layer! screen "walls" :set-cell tile-x tile-y nil)))
   entities)


adds new-password component, simplifies wrapper component

--- src-cljs/rmfu_ui/core.cljs
+++ src-cljs/rmfu_ui/core.cljs
@@ -54,17 +54,17 @@

 (defn post-reset-password [profile]
   (POST "http://localhost:3000/send-reset-password-email"
-       ;; TODO: validate these fields
-       {:params  {:email (:email profile)}
-        :format  :json
-        ;; :response-format :json
-        ;; :keywords?
-        :handler (fn [res]
-                   (do
-                     ;(swap! form-state assoc :show-loading (not (:show-loading @form-state)))
-                     (println "res:" res)
-                     (js/alert res))
-                   )}))
+        ;; TODO: validate these fields
+        {:params  {:email (:email profile)}
+         :format  :json
+         ;; :response-format :json
+         ;; :keywords?
+         :handler (fn [res]
+                    (do
+                      ;(swap! form-state assoc :show-loading (not (:show-loading @form-state)))
+                      (println "res:" res)
+                      (js/alert res))
+                    )}))

 ;; -------------------------
 ;; Utility functions
@@ -72,16 +72,16 @@
 (defn sign-in [profile]
   (let [{:keys [email password]} profile]
     (swap! form-state assoc :signing-up false)
-    (if (not (or (empty? email) (empty? password)))
+    (if-not (or (empty? email) (empty? password))
       (post-sign-in profile))))

 (defn sign-up [profile]
   (let [{:keys [email username password]} profile]
-    (if (not (or (empty? email) (empty? username) (empty? password)))
+    (if-not (or (empty? email) (empty? username) (empty? password))
       (post-sign-up profile))))

-(defn reset-password [profile]
-  (if (not (empty? (:email profile)))
+(defn reset-password-email [profile]
+  (if-not (empty? (:email profile))
     (post-reset-password profile)))

 ;; -------------------------
@@ -124,7 +124,7 @@

 ;; (add-watch form-state :logger #(-> %4 clj->js js/console.log))

-(defn sign-in-sign-up-base-component-wrapper [element]
+(defn welcome-component-wrapper [element]
   "Renders element passed in inside a .jumbotron"
   [:div.container.jumbotron
    [:div.row
@@ -147,95 +147,107 @@
   (let [profile (atom {:username ""
                        :email    ""
                        :password ""})]
-    [:div.form-group {:style {:padding "1em"}}
-     [:p.text-center.bg-primary "Sign in"]
-     [:label "email:"]
-     [email-input-field profile]
-     [:label "password:"]
-     [passsword-input-field profile]
-     [:br]
-     [:div.checkbox
-      [:label
-       [:input {:type "checkbox"}] "remember me?"]]
-
-     [:br]
-     [:button.btn.btn-default {:type     "button"
-                               :on-click (fn [e]
-                                           (sign-in @profile)
-                                           (.preventDefault e))
-                               } "sign-in"]
-
-     [:button.btn.btn-default.pull-right {:type     "button"
-                                          :on-click #(secretary/dispatch! "/sign-up")
-                                          } "sign-up"]
-     [:br]
-     [:p.text-center
-      [:button.btn.btn-sm {:type     "button"
-                           :on-click #(secretary/dispatch! "/reset-password")}
-       "forgot password?"]]]))
+    [welcome-component-wrapper
+     [:div.form-group {:style {:padding "1em"}}
+      [:p.text-center.bg-primary "Sign in"]
+      [:label "email:"]
+      [email-input-field profile]
+      [:label "password:"]
+      [passsword-input-field profile]
+      [:br]
+      [:div.checkbox
+       [:label
+        [:input {:type "checkbox"}] "remember me?"]
+       [:p.pull-right
+        [:button.btn.btn-sm {:type     "button"
+                             :on-click #(secretary/dispatch! "/reset-password")}
+         "forgot password?"]]]
+      [:br]
+      [:button.btn.btn-default {:type     "button"
+                                :on-click (fn [e]
+                                            (sign-in @profile)
+                                            (.preventDefault e))
+                                } "sign-in"]
+
+      [:button.btn.btn-default.pull-right {:type     "button"
+                                           :on-click #(secretary/dispatch! "/sign-up")
+                                           } "sign-up"]]]))

 (defn sign-up-component []
   (let [profile (atom {:username ""
                        :email    ""
                        :password ""})]
-    [:div.form-group {:style {:padding "1em"}}
-
-     [:p.text-center.bg-primary "Create Account"]
-
-     [:label "username:"]
-     [username-input-field profile]
-     [:label "email:"]
-     [email-input-field profile]
-     [:label "password:"]
-     [passsword-input-field profile]
-
-     [:br]
-
-     [:button.btn.btn-default {:type     "button"
-                               :on-click #(secretary/dispatch! "/")
-                               } "sign-in"]
-
-     [:button.btn.btn-default.pull-right {:type     "button"
-                                          :on-click (fn [e]
-                                                      ;; (swap! form-state assoc :signing-up true)
-                                                      (sign-up @profile)
-                                                      (.preventDefault e))
-                                          } "sign-up"]]))
+    [welcome-component-wrapper
+     [:div.form-group {:style {:padding "1em"}}
+
+      [:p.text-center.bg-primary "Create Account"]
+
+      [:label "username:"]
+      [username-input-field profile]
+      [:label "email:"]
+      [email-input-field profile]
+      [:label "password:"]
+      [passsword-input-field profile]
+
+      [:br]
+
+      [:button.btn.btn-default {:type     "button"
+                                :on-click #(secretary/dispatch! "/")
+                                } "sign-in"]
+
+      [:button.btn.btn-default.pull-right {:type     "button"
+                                           :on-click (fn [e]
+                                                       ;; (swap! form-state assoc :signing-up true)
+                                                       (sign-up @profile)
+                                                       (.preventDefault e))
+                                           } "sign-up"]]]
+    ))
+
 (defn reset-password-component []
   (let [profile (atom {:username ""
                        :email    ""
                        :password ""})]
-    [:div.form-group {:style {:padding "1em"}}
-     [:p.text-center.bg-primary "Reset Your Password"]
-     [:label "email:"]
-     [email-input-field profile]
-
-     [:br]
-
-     [:p.text-center
-      [:button.btn.btn-default {:type     "button"
-                                :on-click (fn [e]
-                                            (reset-password @profile)
-                                            (.preventDefault e))
-                                } "reset"]]]))
-
-(defn reset-email-component-wrapper []
-  (sign-in-sign-up-base-component-wrapper [reset-password-component]))
+    [welcome-component-wrapper
+     [:div.form-group {:style {:padding "1em"}}
+      [:p.text-center.bg-primary "Reset Your Password"]
+      [:label "email:"]
+      [email-input-field profile]
+      [:br]
+      [:p [:button.btn.btn-default {:type     "button"
+                                    :on-click (fn [e]
+                                                (reset-password-email @profile)
+                                                (.preventDefault e))
+                                    } "reset"]]]]
+    ))
+
+(defn new-password-component []
+  (let [profile (atom {:username ""
+                       :email    ""
+                       :password ""})]
+    (welcome-component-wrapper
+      [:div.form-group {:style {:padding "1em"}}
+       [:p.text-center.bg-primary "New Password"]
+       [:label "password:"]
+       [passsword-input-field profile]
+       [:br]
+       [:button.btn.btn-default {:type     "button"
+                                 :on-click (fn [e]
+                                             ;; (swap! form-state assoc :signing-up true)
+                                             (reset-password-email @profile)
+                                             (.preventDefault e))
+                                 } "reset"]])))

 (defn show-loading-component []
   [:p.ball-loader.text-center {:style {:left   180
                                        :bottom 69}}])
-(defn sign-in-component-wrapper []
-  (let []
-    [sign-in-sign-up-base-component-wrapper [sing-in-component]]))
-
-(defn sign-up-component-wrapper []
-  (let []
-    [sign-in-sign-up-base-component-wrapper [sign-up-component]]))
-
 (defn email-verified-component []
-  [:div [:h1 "email verified"]])
+  [welcome-component-wrapper [:div
+                              [:h3.text-center
+                               [:u "Your email has been verified"]
+                               [:br]
+                               [:p [:a {:on-click #(secretary/dispatch! "/")} "you may now proceed to login"]]]]])
+
 ;; -------------------------
 ;; Routes

@@ -243,17 +255,20 @@
   [:div [(session/get :current-page)]])

 (secretary/defroute "/" []
-                    (session/put! :current-page #'sign-in-component-wrapper))
+                    (session/put! :current-page #'sing-in-component))

 (secretary/defroute "/sign-up" []
-                    (session/put! :current-page #'sign-up-component-wrapper))
+                    (session/put! :current-page #'sign-up-component))

 (secretary/defroute "/email-verified" []
                     (session/put! :current-page #'email-verified-component))

 (secretary/defroute "/reset-password" []
-                    (session/put! :current-page #'reset-email-component-wrapper))
+                    (session/put! :current-page #'reset-password-component))
+
+(secretary/defroute "/new-password" []
+                    (session/put! :current-page #'new-password-component))

 ;; -------------------------
 ;; History


remove extra stuff

remove extra stuff

--- src/mediakeys/hotkeys.clj
+++ src/mediakeys/hotkeys.clj
@@ -66,11 +66,6 @@
     (put! channel seed)
     channel)

-(def keypress-events!
-    (comp
-        (seed-channel! "{}")
-        (flatmap< keypress-channel!)))
-
 (defn keypress-events! [key-changes]
     (let [result (flatmap< keypress-channel! key-changes)]
         (seed-channel! "{}" key-changes)


GAWB-1926: support structured highlights returned by autosuggest API (#752)

support structured highlights returned by autosuggest API

--- src/cljs/main/broadfcui/page/library/library_page.cljs
+++ src/cljs/main/broadfcui/page/library/library_page.cljs
@@ -154,6 +154,15 @@
                        ((:update-aggregates props) aggregations)))
                    (on-done {:error status-text})))}))))))})

+(defn encode [text]
+  ;; character replacements modeled after Lucene's SimpleHTMLEncoder.
+  (clojure.string/escape text {\" """ \& "&" \< "<", \> ">", \\ "'" \/ "/"}))
+
+(defn highlight-suggestion [suggestion highlight]
+  (if (not (clojure.string/blank? highlight))
+    (clojure.string/replace (encode suggestion) (encode highlight) (str "" (encode highlight) ""))
+    (encode suggestion)))
+
 (react/defc SearchSection
   {:get-filters
    (fn [{:keys [props]}]
@@ -186,11 +195,15 @@
                                                :from 0
                                                :size 10}))))}
         :typeaheadDisplay (fn [result]
-                            ;; we intentionally do not encode the result value here, because it is already
-                            ;; encoded from the server.
-                            (.text (js/$ (str "
" (aget result "value") "
"))))
+                            ;; underlying typeahead library uses the result of this function
+                            ;; via $input.val(x), which is safe from xss. So we explicitly
+                            ;; do not want to encode anything here.
+                            (aget result "value" "suggestion"))
         :typeaheadSuggestionTemplate (fn [result]
-                                       (str "
" (aget result "value") "
"))}]])})
+                                       (let [suggestion (aget result "value" "suggestion")
+                                             highlight (aget result "value" "highlight")
+                                             display (highlight-suggestion suggestion highlight)]
+                                         (str "
" display "
")))}]])})

 (react/defc FacetCheckboxes
   {:render


day 22 still no result

day 22 still no result

--- src/adventofcode/day22.clj
+++ src/adventofcode/day22.clj
@@ -4,24 +4,84 @@
            :damage 10})

 (def me {:hp 50
+         :armor 0
          :mana 500})

-(def spells [{:name :magic-missile
-              :cost 53
-              :damage 4}
-             {:name :drain
-              :cost 73
-              :damage 2
-              :heal 2}
-             {:name :shield
-              :cost 113
-              :heal 7
-              :turns 6}
-             {:name :poison
-              :cost 173
-              :damage 3
-              :turns 6}
-             {:name :recharge
-              :cost 229
-              :mana 101
-              :turns 5}])
+(def spells {:missile {:cost 53
+                       :damage 4}
+             :drain {:cost 73
+                     :damage 2
+                     :heal 2}
+             :shield {:cost 113
+                      :heal 7
+                      :turns 6}
+             :poison {:cost 173
+                      :damage 3
+                      :turns 6}
+             :recharge {:cost 229
+                        :mana 101
+                        :turns 5}})
+
+(def init-state {:me me
+                 :boss boss
+                 :effects []
+                 :spent-mana 0
+                 :turn :me})
+
+(defn apply-effect [state [spell timer]]
+  (case spell
+    :shield (update-in state [:me :hp] + 7)
+    :poison (update-in state [:boss :hp] - 3)
+    :recharge (update-in state [:me :mana] + 101)))
+
+(defn winner? [{{me-hp :hp} :me {boss-hp :hp} :boss}]
+  (cond
+    (zero? me-hp) :boss
+    (zero? boss-hp) :me))
+
+(comment (winner? {:me {:hp 0} :boss {:hp 10}})
+         (winner? {:me {:hp 10} :boss {:hp 0}})
+         (winner? {:me {:hp 10} :boss {:hp 10}}))
+
+(defn decrease-timers [state]
+  (assoc state :effects (filter (comp pos? second)
+                                (map #(vector (first %) (dec (second %)))
+                                     (:effects state)))))
+
+(comment (decrease-timers {:effects []})
+         (decrease-timers {:effects [[:foo 1] [:bar 2]]})
+         (decrease-timers {:effects [[:foo 3] [:bar 2]]}))
+
+(defn cast-spell [state spell]
+  state)
+
+(defn my-turn [state]
+  (let [available-spells (filter #(>= (get-in state [:me :mana])
+                                      (:cost (second %)))
+                                 spells)]
+    (cast-spell state (first available-spells))))
+
+(defn make-turn [state]
+  (assoc
+   (case (:turn state)
+     :boss (update-in state [:me :hp] - (:damage boss))
+     :me   (my-turn state))
+   :turn (if (= (:turn state) :me)
+           :boss
+           :me)))
+
+(comment (make-turn {:me {:hp 100}
+                     :boss {:hp 100}
+                     :turn :me})
+         (make-turn {:me {:hp 100}
+                     :boss {:hp 100}
+                     :turn :boss}))
+
+(comment
+  (loop [s init-state]
+    (let [state (reduce apply-effect s (:effects s))
+          winner (winner? state)]
+      (case winner
+        :me (:spent-mana state)
+        :boss :loose
+        (recur (make-turn (decrease-timers state)))))))


Empty out default reactions.

Empty out default reactions.

--- src/oc/storage/config.clj
+++ src/oc/storage/config.clj
@@ -85,7 +85,8 @@
   "Press"
   "Sales"})

-(defonce default-reactions ["👌" "👀" "💥"])
+;; Sequence of 1 unicode char strings that provide the default reactions available to the user (if any)
+(defonce default-reactions [])

 (defonce max-reaction-count 5)


eliminate extra expensive ajax calls on workspace tab-change (#1373)

eliminate extra ajax calls when navigating through workspace tabs

--- src/cljs/main/broadfcui/page/workspace/details.cljs
+++ src/cljs/main/broadfcui/page/workspace/details.cljs
@@ -164,7 +164,7 @@
      (this :-refresh-workspace))
    :component-will-receive-props
    (fn [{:keys [props next-props this after-update]}]
-     (when (utils/any-change [:tab-name :workspace-id] props next-props)
+     (when (utils/any-change [:workspace-id] props next-props)
        (after-update this :-refresh-workspace)))
    :-refresh-workspace
    (fn [{:keys [props state]}]


reverse images

reverse images

--- src/ontrail/imgimport.clj
+++ src/ontrail/imgimport.clj
@@ -30,7 +30,7 @@
      (flatten
       (mapv (fn [result]
               (let [id-string (.toString (:id result))
-                    imagelist (:imgs result)]
+                    imagelist (reverse (:imgs result))]
                 (mapv
                  (fn [img]
                    (format "<img width=\"500\" src=\"%s\"\n"


Avoid NullPointerException when better error could be provided.

--- src/onyx/plugin/kafka.clj
+++ src/onyx/plugin/kafka.clj
@@ -77,7 +77,7 @@
         fixed-npeers? (or (= min-peers max-peers) (= 1 max-peers)
                           (and n-peers (and (not min-peers) (not max-peers))))
         n-peers (or max-peers n-peers)
-        n-peers-less-eq-n-partitions (<= n-peers n-partitions)]
+        n-peers-less-eq-n-partitions (and n-peers (<= n-peers n-partitions))]
     (when-not (or fixed-partition? fixed-npeers? n-peers-less-eq-n-partitions)
       (let [e (ex-info ":onyx/min-peers must equal :onyx/max-peers, or :onyx/n-peers must be set, and :onyx/min-peers and :onyx/max-peers must not be set. Number of peers should also be less than or equal to the number of partitions."
                        {:n-partitions n-partitions


Collaborative Programmable Music

Collaborative Programmable Music

--- src/overtone/util/lib.clj
+++ src/overtone/util/lib.clj
@@ -275,7 +275,7 @@
        / /_/ /| |/ /  __/ /  / /_/ /_/ / / / /  __/
        \\____/ |___/\\___/_/   \\__/\\____/_/ /_/\\___/

-                          Programmable Music. "version-str"
+              Collaborative Programmable Music. "version-str"

 Hello " user-name ", may this be the start of a beautiful music hacking session...")))


search performance utility now feature complete with both solr and elastic search

--- client/perf5/src/perf5/core.clj
+++ client/perf5/src/perf5/core.clj
@@ -3,6 +3,7 @@

 (require '[clojure.data.json :as json])
 (require '[clj-http.client :as client])
+(require '(clojure [zip :as zip]))

 (defn parse-long [s]
    (.longValue (Long. (re-find  #"\d+" s ))))
@@ -14,6 +15,14 @@
 (def index-time-running 0)
 (def query-total-running 0)
 (def query-time-running 0)
+(def total-docs 0)
+
+(defn extract-num-docs
+  "get the total number of docs from the solr stats"
+  [core]
+  (let [searcher (get core "searcher")
+        searcher-stats (get searcher "stats")]
+    (def total-docs (get searcher-stats "numDocs"))))

 (defn refresh-stats
   "maintain incremental statistics data"
@@ -28,40 +37,79 @@
     (def query-total-running query-total)
     (def query-time-running query-time)
     retVal))
-
+
+(defn following
+  "call back with the item following the item that matches the tag"
+  [vector tag callback]
+  (loop [item (zip/vector-zip vector)]
+    (if (not (zip/end? item))
+      (let [next-item (zip/next item)]
+        (if (= (zip/node next-item) tag)
+          (callback (zip/node (zip/next next-item)))
+          (recur next-item))))))
+
+(defn report-stats
+  "report the stats to the console"
+  [results total-docs]
+  (let [avg-index-time (if (= (:index-total results) 0) 0 (quot (:index-time results) (:index-total results)))
+        avg-query-time (if (= (:query-total results) 0) 0 (quot (:query-time results) (:query-total results)))]
+        (println
+          (str
+            total-docs
+            ","
+            (:index-total results)
+            ","
+            avg-index-time
+            ","
+            (:query-total results)
+            ","
+            avg-query-time))))
+
+(defn report-solr-stats-handler-data
+  "extract relevant stats from solr request"
+  [query-handler]
+  (let [update (get query-handler "/update")
+        update-stats (get update "stats")
+        standard (get query-handler "standard")
+        standard-stats (get standard "stats")
+        results (refresh-stats (get update-stats "requests") (get update-stats "totalTime") (get standard-stats "requests") (get standard-stats "totalTime"))]
+    (report-stats results total-docs)))
+
+(defn report-solr-results
+  "process the response to the request for solr stats"
+  [results]
+  (let [solr-mbeans (get results "solr-mbeans")]
+    (following solr-mbeans "CORE" extract-num-docs)
+    (following solr-mbeans "QUERYHANDLER" report-solr-stats-handler-data)))
+
 (defn report-elastic-search-results
-  "extract relevant stats from elastic search request and print them to the console"
+  "extract relevant stats from elastic search request"
   [results index]
-  (if (contains? results "indices")
-    (let [indices (get results "indices")]
-      (if (contains? indices index)
-        (let [index-stats (get indices index)]
-          (if (contains? index-stats "total")
-            (let [total (get index-stats "total")]
-              (if (contains? total "docs")
-                (let [docs (get total "docs")]
-                  (if (contains? total "indexing")
-                    (let [indexing (get total "indexing")]
-                      (if (contains? total "search")
-                        (let [search (get total "search")
-                              results (refresh-stats (get indexing "index_total") (get indexing "index_time_in_millis") (get search "query_total") (get search "query_time_in_millis"))
-                              avg-index-time (if (= (:index-total results) 0) 0 (quot (:index-time results) (:index-total results)))
-                              avg-query-time (if (= (:query-total results) 0) 0 (quot (:query-time results) (:query-total results)))]
-                          (println
-                            (str
-                              (get docs "count")
-                              ","
-                              (:index-total results)
-                              ","
-                              avg-index-time
-                              ","
-                              (:query-total results)
-                              ","
-                              avg-query-time)))))))))))))))
+  (let [indices (get results "indices")
+        index-stats (get indices index)
+        total (get index-stats "total")
+        docs (get total "docs")
+        indexing (get total "indexing")
+        search (get total "search")
+        results (refresh-stats (get indexing "index_total") (get indexing "index_time_in_millis") (get search "query_total") (get search "query_time_in_millis"))]
+        (report-stats results (get docs "count"))))

 (defn process-solr
-  ""
-  [host port index])
+  "fetch stats from solr"
+  [host port index]
+  (let [url
+        (str "http://"
+             host
+             ":"
+             port
+             "/"
+             index
+             "/admin/mbeans?stats=true&wt=json")
+        response (client/get url)]
+    (if
+      (< (:status response 300))
+      (report-solr-results (json/read-str (:body response)))
+      (println response))))

 (defn process-elastic-search
   "fetch stats from elastic search"


add ending paragraph

add ending paragraph

--- src/pc/views/blog/dont_let_your_tools_distract_you.clj
+++ src/pc/views/blog/dont_let_your_tools_distract_you.clj
@@ -103,6 +103,12 @@
                  :caption "You can also delete a clip by clicking the X icon in the thumbnail."
                  :invert true)

+    [:article
+     [:h3 "Improving paste is next. "]
+     [:p "Today we have the list of copied clips and the ability to paste them from the menu. "
+         "Next, are the abilities to bind favorites to number keys and align pasted shapes before commiting them to the canvas. "
+         "When we finish, we'll provide a more in-depth tutorial for the entire process. "]]
+
     [:article.blogpost-author
      [:p
       "Written by "


Gracefully handle old code that passes a string instead of a seq of strings

--- src/cake/tasks/compile.clj
+++ src/cake/tasks/compile.clj
@@ -12,7 +12,8 @@
 (declare copy-native)

 (defn compile-java [src & [dest]]
-  (let [start (System/currentTimeMillis)
+  (let [src   (if (coll? src) src [src])
+        start (System/currentTimeMillis)
         dest  (file (or dest (first (:compile-path *project*))))]
     (when-let [src (seq (filter file-exists? src))]
       (ant Javac (merge {:destdir     dest


recatored code to be simpler, more concise.

--- clojure/allergies/allergies.clj
+++ clojure/allergies/allergies.clj
@@ -9,17 +9,15 @@
 (defn list
   "list of allergies for the given score"
   [score]
-  (loop [s score
-         allergy-num (dec (count allergies))
+  (loop [s score                        ; remaining score
+         n (dec (count allergies))      ; potential allergy, position
          acc []]
-    (cond
-     (<= s 0) acc
-     (< allergy-num 0) acc
-     :else (let [allergy-score (Math/pow 2 allergy-num)
-                 allergy (nth allergies allergy-num)]
-             (if (>= s allergy-score)
-               (recur (- s allergy-score) allergy-num (cons allergy acc))
-               (recur s (dec allergy-num) acc))))))
+    (if (or (zero? s) (neg? n)) (distinct acc)
+        (let [allergy-score (Math/pow 2 n)
+              allergy (nth allergies n)]
+          (if (>= s allergy-score)
+            (recur (- s allergy-score) n (cons allergy acc))
+            (recur s (dec n) acc))))))

 (defn allergic_to?
   "returns whether the given score includes the allergy"


make sure group-threads is a set

make sure group-threads is a set

--- src/chat/client/store.cljs
+++ src/chat/client/store.cljs
@@ -186,7 +186,7 @@
                                                  :messages []
                                                  :tag-ids #{}
                                                  :mentioned-ids #{}}))
-    (transact! [:group-threads group-id] #(conj % thread-id)))
+    (transact! [:group-threads group-id] #(conj (set %) thread-id)))
   (transact! [:user :open-thread-ids] #(conj % thread-id)))

 (defn set-new-message!
@@ -235,7 +235,7 @@
           (str "Chat (" (get-in @app-state [:notifications :unread-count]) ")")))

   (transact! [:threads (thread :id)] #(merge % thread))
-  (transact! [:group-threads (thread :group-id)] #(conj % (thread :id)))
+  (transact! [:group-threads (thread :group-id)] #(conj (set %) (thread :id)))
   (transact! [:user :open-thread-ids] #(conj % (thread :id))))

 (defn hide-thread! [thread-id]


camelCase button id

camelCase button id

--- src/client/pages/play.cljs
+++ src/client/pages/play.cljs
@@ -113,7 +113,7 @@
               [:td {:class (str "color-" (mod i 7))} (:user player)]
               [:td (util/format-number (:score player))]
               [:td (:total-lines player)]])]]]
-    [:button#game-over-btn.red-btn-2c9ab "LOBBY"]])
+    [:button#gameOverBtn.red-btn-2c9ab "Lobby"]])

 (defn init-game
   "Show and start the game."
@@ -133,18 +133,21 @@
     (.html ($ "#countdown") i)
     (init-game true)))

+(defn- click-game-over-btn []
+  (aset js/document "location" "hash" "#/lobby"))
+
 (defn on-game-over
   "Called when game over message received from server."
   [str-data]
   (cleanup!)
   (let [data (read-string str-data)]
     (dom/set-page-body! (gameover-html data))
-    (.click ($ "#game-over-btn") #(aset js/location "hash" "#/lobby"))))
+    (.on ($ "#gameOverBtn") "click" click-game-over-btn)))

 (defn on-time-left
   "Called when server sends a time-left update."
   [total-seconds]
-
+
   (if (dom/by-id "gameScreenTimeLeft")
     (dom/set-html! "gameScreenTimeLeft" (util/seconds->time-str total-seconds)))


Fixed typo in pages

Fixed typo in pages

--- src/clj/bookmarx/pages.clj
+++ src/clj/bookmarx/pages.clj
@@ -9,7 +9,7 @@
    [:meta {:charset "utf-8"}]
    [:meta {:name "viewport" :content "width=device-width, initial-scale=1"}]
    [:link {:rel "icon" :type "image/png" :href "favicon.ico"}]
-   [:link {:rel "mask-icon" :type "image/svg" :href "images/black-star.svg" color="black"}]
+   [:link {:rel "mask-icon" :type "image/svg" :href "images/black-star.svg" :color "black"}]
    (include-css (if (env :dev) "css/site.css" "css/site.min.css"))
    (include-css "bootstrap/3.3.7/css/bootstrap.min.css")])


:meta becomes :wanted and start merging results with it first

--- src/clj/ephemeris/core.clj
+++ src/clj/ephemeris/core.clj
@@ -49,6 +49,9 @@
         want (request stuff)
         flag (. SweConst SEFLG_SPEED)]
     (merge
+      (if (:meta want)
+        {:wanted (dissoc want :meta)}
+        {})
       {:bodies
         (into {}
           (for [i (flatten [(:bodies want)])]
@@ -83,7 +86,4 @@
               {})
             (if (houses? (:houses want))
               {:houses (zipmap (range 1 13) (rest cusps))}
-              {}))))
-      (if (boolean (:meta want))
-        {:meta (dissoc want :meta)}
-        {}))))
+              {})))))))


include trash-installed in top declare

include trash-installed in top declare

--- src/clj/game/cards-ice.clj
+++ src/clj/game/cards-ice.clj
@@ -1,6 +1,6 @@
 (in-ns 'game.core)

-(declare trash-program trash-hardware)
+(declare trash-program trash-hardware trash-installed)

 (def cards-ice
   {"Archer"


fix Troll deducting 2 clicks

fix Troll deducting 2 clicks

--- src/clj/game/cards-ice.clj
+++ src/clj/game/cards-ice.clj
@@ -880,7 +880,7 @@
                                   :prompt "Choose one"
                                   :choices ["Lose [Click]" "End the run"]
                                   :effect (req (if-not (and (= target "Lose [Click]")
-                                                            (apply pay state side card [:click 1]))
+                                                            (can-pay? state :runner nil [:click 1]))
                                                  (do (end-run state side)
                                                      (system-msg state side "ends the run"))
                                                  (do (lose state side :click 1)


Fix update of icons and labels.

Fix update of icons and labels.

--- src/cljs/bookmarx/add.cljs
+++ src/cljs/bookmarx/add.cljs
@@ -47,7 +47,9 @@
   [doc]
   (let [parent-id (get-in @doc [:bookmark/parent :db/id])
         parent (session/get parent-id)
-        orig-parent-id (get-in @doc [:orig-parent :db/id])
+        orig-parent-id (if (get @doc :orig-parent)
+                         (get-in @doc [:orig-parent :db/id])
+                         parent-id)
         orig-parent (session/get orig-parent-id)
         children (:bookmark/_parent parent)]
     ;; Replace the children of the folder with the children from the session folder.
@@ -56,19 +58,16 @@
                     (assoc (-clean-doc doc) :bookmark/_parent
                            (:bookmark/_parent (session/get (:db/id @doc))))))

-    ;; Update the parent's children with the updated child.
+    ;; Remove the bookmark from the original/parent folder.
+    (session/put! orig-parent-id
+                  (update-in orig-parent [:bookmark/_parent]
+                             #(remove (fn [b] (= (:db/id b) (:db/id @doc)))
+                                      (:bookmark/_parent orig-parent))))
+
+    ;; Add the updated child to the parent folder.
     (session/put! parent-id (sort-folder-children
-                             (update-in parent [:bookmark/_parent]
-                                        #(conj % (-clean-doc doc))) :bookmark/title))
-
-    ;; Removed the bookmark from the folder that it was moved out of.
-    (log/debugf "orig parent %s" (remove (fn [b] (= (:db/id b) (:db/id @doc)))
-                                         (:bookmark/_parent orig-parent)))
-    (when (and orig-parent-id (not= parent-id orig-parent-id))
-      (session/put! orig-parent-id
-                    (update-in orig-parent [:bookmark/_parent]
-                               #(remove (fn [b] (= (:db/id b) (:db/id @doc)))
-                                        (:bookmark/_parent orig-parent))))))
+                             (update-in (session/get parent-id) [:bookmark/_parent]
+                                        #(conj % (-clean-doc doc))) :bookmark/title)))

   ;; Update the state in the remote repository.
   (go (<! (http/put (str (:host-url env) (:prefix env) "/api/bookmarks/" (:bookmark/id @doc))


don't log new speed

don't log new speed

--- src/cljs/easynxc/core.cljs
+++ src/cljs/easynxc/core.cljs
@@ -86,7 +86,6 @@
   (fn [e]
     (let [x (.-clientX e)
           new-speed (/ x (/ (.-innerWidth js/window) 2))]
-      (.log js/console new-speed)
       (put! speed-ch new-speed))))

 (defn touch-speed-controller [speed-ch]


initialize when reloaded, but game state gets lost

--- src/cljs/memtest/core.cljs
+++ src/cljs/memtest/core.cljs
@@ -22,17 +22,23 @@
   []
   ; game is won when count of matches is equal to half of gameboard, because
   ; cells contain duplicate numbers
-  (= (/ (count @gameboard) 2) (count @matched)))
+  (and (= (/ (count @gameboard) 2) (count @matched))
+       (not= (count @matched) 0)))

 (defn add-cell [n]
   ; add a numbered cell with a unique id
   (let [id (swap! counter inc)]
     (swap! gameboard assoc id {:id id :number n :color (colors n)})))

-(defn new-game
+(defn clicked
+  []
+  (swap! counter inc))
+
+(defn new-game
   []
   ; game starts out with an empty board, no cell selected, nothing hilighted,
   ; and no matches
+  (reset! counter 0)
   (reset! gameboard (sorted-map))
   (reset! selected nil)
   (reset! matched #{})
@@ -99,10 +105,13 @@
     (let [cells (vals @gameboard)]
       [:div#container
        ; game title
-       [:h1 "The memory game"]
+       [:h1 "The Memory Game"]
        ; win status
-       [:h2 (if (won-game?) "You won!")]
-       ; the gameboard
+       [:h2 (if (won-game?) "You won!!!")]
+       [:h2 (count @gameboard)]
+       [:h2 (count @matched)]
+       [:h2 @counter]
+       ; the gameboard
        [:table#gameboard
         ; taking 4 cells at a time for each row
         (map-indexed
@@ -110,7 +119,9 @@
          (partition 4 cells))]
        ; text link to reset the game
        [:p [:a {:class "new-game" :on-click #(new-game)
-                :href "#"} "New game"]]])))
+                :href "#"} "New game"]]
+       [:p [:a {:class "new-game" :on-click #(clicked)
+                :href "#"} "Inc"]]])))

 (defn current-page []
   [:div [(session/get :current-page)]])
@@ -127,8 +138,9 @@
 (defn mount-root []
   (reagent/render [board-page] (.getElementById js/document "app")))

+(new-game)
+
 (defn init! []
   (accountant/configure-navigation!)
   (accountant/dispatch-current!)
-  (new-game)
   (mount-root))


upd update logic

upd update logic

--- src/cljs/re_form/core.cljs
+++ src/cljs/re_form/core.cljs
@@ -84,7 +84,10 @@
     (fn [] (init props))
     :component-will-receive-props
     (fn [this props]
-      (init (nth props 1)))
+      (let [cur-value (nth (.. this -props -argv ) 1)
+            new-value (nth props 1)]
+        (when-not (= new-value cur-value)
+          (init new-value))))
     :component-will-unmount
     (fn [] (deinit props))
     :display-name (str (:name props))


Now reset-env! also purges :previous-init-opts in app-env

--- src/cljs/replumb/repl.cljs
+++ src/cljs/replumb/repl.cljs
@@ -678,6 +678,11 @@
   "Persist the options necessary to the initialization FSM to work."
   [opts]
   (swap! app-env assoc :previous-init-opts (auto-init-opts opts)))
+
+(defn reset-init-opts!
+  "Reset the initialization persisted options."
+  []
+  (swap! app-env assoc :previous-init-opts {}))

 (defn init-closure-index!
   "Create and swap in app-env a map from Google Closure provide string
@@ -831,4 +836,5 @@
    (if (seq @cljs.js/*loaded*)
      (throw (ex-info (str "The cljs.js/*loaded* atom still contains " @cljs.js/*loaded* " - make sure you purge dependent namespaces.") ex-info-data)))
    (reset-last-warning!)
-   (read-eval-call opts identity "(set! *e nil)")))
+   (read-eval-call opts identity "(set! *e nil)")
+   (reset-init-opts!)))


Add seaport data for all necessary units

--- src/cljs/zetawar/data.cljs
+++ src/cljs/zetawar/data.cljs
@@ -161,7 +161,8 @@
                  :tundra    {:movement-cost 4 :armor-bonus -1 :attack-bonus -1}
                  :swamp     {:movement-cost 6 :armor-bonus -2 :attack-bonus -2}
                  :ford      {:movement-cost 5 :armor-bonus -1 :attack-bonus -1}
-                 :base      {:movement-cost 2 :armor-bonus  3 :attack-bonus  2}}
+                 :base      {:movement-cost 2 :armor-bonus  3 :attack-bonus  2}
+                 :seaport   {:movement-cost 2 :armor-bonus  0 :attack-bonus  0}}
                 :attack-strengths
                 {:personnel 6
                  :armored   3}
@@ -188,7 +189,8 @@
                   :tundra    {:movement-cost 5 :armor-bonus -1 :attack-bonus  0}
                   :swamp     {:movement-cost 9 :armor-bonus -2 :attack-bonus -2}
                   :ford      {:movement-cost 9 :armor-bonus -1 :attack-bonus -1}
-                  :base      {:movement-cost 3 :armor-bonus  3 :attack-bonus -1}}
+                  :base      {:movement-cost 3 :armor-bonus  3 :attack-bonus -1}
+                  :seaport   {:movement-cost 3 :armor-bonus  0 :attack-bonus  0}}
                  :attack-strengths
                  {:personnel 8
                   :armored   9}
@@ -215,7 +217,8 @@
                :tundra    {:movement-cost 5 :armor-bonus -1 :attack-bonus -1}
                :swamp     {:movement-cost 9 :armor-bonus -2 :attack-bonus -2}
                :ford      {:movement-cost 9 :armor-bonus -1 :attack-bonus -2}
-               :base      {:movement-cost 3 :armor-bonus  3 :attack-bonus -2}}
+               :base      {:movement-cost 3 :armor-bonus  3 :attack-bonus -2}
+               :seaport   {:movement-cost 3 :armor-bonus  0 :attack-bonus  0}}
               :attack-strengths
               {:personnel 10
                :armored   10}}
@@ -241,7 +244,8 @@
                :swamp         {:movement-cost 3 :armor-bonus -2 :attack-bonus -2}
                :ford          {:movement-cost 3 :armor-bonus  0 :attack-bonus  0}
                :shallow-water {:movement-cost 6 :armor-bonus -2 :attack-bonus -2}
-               :base          {:movement-cost 2 :armor-bonus  3 :attack-bonus  2}}
+               :base          {:movement-cost 2 :armor-bonus  3 :attack-bonus  2}
+               :seaport       {:movement-cost 2 :armor-bonus  0 :attack-bonus  0}}
               :attack-strengths
               {:personnel 9
                :armored   4}
@@ -268,7 +272,8 @@
               :tundra    {:movement-cost 4 :armor-bonus -1 :attack-bonus -1}
               :swamp     {:movement-cost 6 :armor-bonus -2 :attack-bonus -2}
               :ford      {:movement-cost 5 :armor-bonus -1 :attack-bonus -1}
-              :base      {:movement-cost 2 :armor-bonus  3 :attack-bonus  2}}
+              :base      {:movement-cost 2 :armor-bonus  3 :attack-bonus  2}
+              :seaport   {:movement-cost 2 :armor-bonus  0 :attack-bonus  0}}
             :attack-strengths
             {:personnel 5
              :armored   2}
@@ -296,7 +301,8 @@
                 :swamp         {:movement-cost 6 :armor-bonus -2 :attack-bonus -2}
                 :ford          {:movement-cost 5 :armor-bonus -1 :attack-bonus -1}
                 :shallow-water {:movement-cost 7 :armor-bonus -2 :attack-bonus -2}
-                :base          {:movement-cost 2 :armor-bonus  3 :attack-bonus  2}}
+                :base          {:movement-cost 2 :armor-bonus  3 :attack-bonus  2}
+                :seaport       {:movement-cost 2 :armor-bonus  0 :attack-bonus  0}}
               :attack-strengths
               {:personnel 5
                :armored   2}
@@ -316,13 +322,14 @@
               :state-map :free-attack-twice
               :image "tilesets/elite-command/units/humvee-COLOR.png"
               :terrain-effects
-              {:plains {:movement-cost 3  :armor-bonus  0 :attack-bonus  0}
-               :woods  {:movement-cost 6  :armor-bonus -2 :attack-bonus -2}
-               :desert {:movement-cost 3  :armor-bonus  0 :attack-bonus  0}
-               :tundra {:movement-cost 6  :armor-bonus  0 :attack-bonus  0}
-               :swamp  {:movement-cost 12 :armor-bonus -3 :attack-bonus -3}
-               :ford   {:movement-cost 12 :armor-bonus -1 :attack-bonus -1}
-               :base   {:movement-cost 2  :armor-bonus  0 :attack-bonus  0}}
+              {:plains  {:movement-cost 3  :armor-bonus  0 :attack-bonus  0}
+               :woods   {:movement-cost 6  :armor-bonus -2 :attack-bonus -2}
+               :desert  {:movement-cost 3  :armor-bonus  0 :attack-bonus  0}
+               :tundra  {:movement-cost 6  :armor-bonus  0 :attack-bonus  0}
+               :swamp   {:movement-cost 12 :armor-bonus -3 :attack-bonus -3}
+               :ford    {:movement-cost 12 :armor-bonus -1 :attack-bonus -1}
+               :base    {:movement-cost 2  :armor-bonus  0 :attack-bonus  0}
+               :seaport {:movement-cost 2  :armor-bonus  0 :attack-bonus  0}}
               :attack-strengths
               {:personnel 9
                :armored   3}
@@ -341,13 +348,14 @@
             :state-map :move-attack
             :image "tilesets/elite-command/units/tank-COLOR.png"
             :terrain-effects
-            {:plains {:movement-cost 3 :armor-bonus  0 :attack-bonus 0}
-             :woods  {:movement-cost 6 :armor-bonus -3 :attack-bonus 0}
-             :desert {:movement-cost 4 :armor-bonus  0 :attack-bonus 0}
-             :tundra {:movement-cost 5 :armor-bonus  0 :attack-bonus 0}
-             :swamp  {:movement-cost 8 :armor-bonus -4 :attack-bonus 0}
-             :ford   {:movement-cost 8 :armor-bonus  0 :attack-bonus 0}
-             :base   {:movement-cost 2 :armor-bonus -2 :attack-bonus 0}}
+            {:plains  {:movement-cost 3 :armor-bonus  0 :attack-bonus 0}
+             :woods   {:movement-cost 6 :armor-bonus -3 :attack-bonus 0}
+             :desert  {:movement-cost 4 :armor-bonus  0 :attack-bonus 0}
+             :tundra  {:movement-cost 5 :armor-bonus  0 :attack-bonus 0}
+             :swamp   {:movement-cost 8 :armor-bonus -4 :attack-bonus 0}
+             :ford    {:movement-cost 8 :armor-bonus  0 :attack-bonus 0}
+             :base    {:movement-cost 2 :armor-bonus -2 :attack-bonus 0}
+             :seaport {:movement-cost 2 :armor-bonus  0 :attack-bonus 0}}
             :attack-strengths
             {:personnel 10
              :armored   10}
@@ -368,7 +376,8 @@
                :image "tilesets/elite-command/units/frigate-COLOR.png"
                :terrain-effects
                {:sea           {:movement-cost 1 :armor-bonus 0 :attack-bonus 0}
-                :shallow-water {:movement-cost 1 :armor-bonus 0 :attack-bonus 0}}
+                :shallow-water {:movement-cost 1 :armor-bonus 0 :attack-bonus 0}
+                :seaport       {:movement-cost 1 :armor-bonus 0 :attack-bonus 0}}
                :attack-strengths
                {:personnel 9
                 :armored   9}
@@ -387,7 +396,8 @@
                  :state-map :free-attack-twice
                  :image "tilesets/elite-command/units/destroyer-COLOR.png"
                  :terrain-effects
-                 {:sea {:movement-cost 1 :armor-bonus 0 :attack-bonus 0}}
+                 {:sea     {:movement-cost 1 :armor-bonus 0 :attack-bonus 0}
+                  :seaport {:movement-cost 1 :armor-bonus 0 :attack-bonus 0}}
                  :attack-strengths
                  {:personnel 10
                   :armored   12}
@@ -405,7 +415,8 @@
                :state-map :move-attack
                :image "tilesets/elite-command/units/cruiser-COLOR.png"
                :terrain-effects
-               {:sea {:movement-cost 1 :armor-bonus 0 :attack-bonus 0}}
+               {:sea     {:movement-cost 1 :armor-bonus 0 :attack-bonus 0}
+                :seaport {:movement-cost 1 :armor-bonus 0 :attack-bonus 0}}
                :attack-strengths
                {:personnel 14
                 :armored   16}


Improve defsparkfn to take docstrings & stuff.

--- src/clojure/flambo/api.clj
+++ src/clojure/flambo/api.clj
@@ -10,7 +10,8 @@
 ;; happily accepted!
 ;;
 (ns flambo.api
-  (:refer-clojure :exclude [fn map reduce first count take distinct filter group-by values])
+  (:refer-clojure :exclude [fn map reduce  count take distinct filter group-by values]
+                  :rename {first core-first})
   (:require [serializable.fn :as sfn]
             [clojure.tools.logging :as log]
             [flambo.function :refer [flat-map-function
@@ -57,7 +58,49 @@
   [& body]
   `(sfn/fn ~@body))

-(defmacro defsparkfn
+(defmacro defsparkfn [name & fdecl]
+  (do
+    (if (instance? clojure.lang.Symbol name)
+      nil
+      (throw (IllegalArgumentException. "First argument to defn must be a symbol")))
+    (let [m (if (string? (core-first fdecl))
+              {:doc (core-first fdecl)}
+              {})
+          fdecl (if (string? (core-first fdecl))
+                  (next fdecl)
+                  fdecl)
+          m (if (map? (core-first fdecl))
+              (conj m (core-first fdecl))
+              m)
+          fdecl (if (map? (core-first fdecl))
+                  (next fdecl)
+                  fdecl)
+          fdecl (if (vector? (core-first fdecl))
+                  (list fdecl)
+                  fdecl)
+          m (if (map? (last fdecl))
+              (conj m (last fdecl))
+              m)
+          fdecl (if (map? (last fdecl))
+                  (butlast fdecl)
+                  fdecl)
+          m (let [inline (:inline m)
+                  ifn (core-first inline)
+                  iname (second inline)]
+              ;; same as: (if (and (= 'fn ifn) (not (symbol? iname))) ...)
+              (if (if (clojure.lang.Util/equiv 'fn ifn)
+                    (if (instance? clojure.lang.Symbol iname) false true))
+                ;; inserts the same fn name to the inline fn if it does not have one
+                (assoc m :inline (cons ifn (cons (clojure.lang.Symbol/intern (.concat (.getName ^clojure.lang.Symbol name) "__inliner"))
+                                                 (next inline))))
+                m))
+          m (conj (if (meta name) (meta name) {}) m)]
+      (list 'def (with-meta name m)
+            ;;todo - restore propagation of fn name
+            ;;must figure out how to convey primitive hints to self calls first
+            (cons `fn fdecl)))))
+
+#_(defmacro defsparkfn
   [name & body]
   `(def ~name
      (fn ~@body)))


fixed wrong merge

fixed wrong merge

--- src/org/domaindrivenarchitecture/pallet/convention/managed_ide.clj
+++ src/org/domaindrivenarchitecture/pallet/convention/managed_ide.clj
@@ -12,7 +12,7 @@

 (def ^:dynamic dda-projects
   {:dda-pallet
-    ["https://github.com/DomainDrivenArchitecture/dda-config-commons.git"
+   ["https://github.com/DomainDrivenArchitecture/dda-config-commons.git"
     "https://github.com/DomainDrivenArchitecture/dda-pallet-commons.git"
     "https://github.com/DomainDrivenArchitecture/dda-pallet.git"
     "https://github.com/DomainDrivenArchitecture/dda-user-crate.git"
@@ -48,7 +48,8 @@
   (map-utils/deep-merge
     {:ide-user user-name}
     (cond
-      (= dev-platform :clojure) {:clojure {:os-user-name user-name}
+      (= dev-platform :clojure) {:project-config dda-projects
+                                 :clojure {:os-user-name user-name}
                                  :atom {:settings (if (= vm-platform :aws)
                                                     #{:install-aws-workaround}
                                                     #{})}


Trying to fix ns clobber?

Trying to fix ns clobber?

--- src/semantic_csv/core.clj
+++ src/semantic_csv/core.clj
@@ -253,32 +253,34 @@
 ;; <br/>
 ;; ## process

-(defn process
-  "This function wraps together the most frequently used input processing capabilities,
-  controlled by an `opts` hash with opinionated defaults:
-
-  * `:mappify` - bool; transform rows from vectors into maps using `mappify`.
-  * `:header` - specify header to be used in mappify; as per `mappify`, first row will not be consumed as header
-  * `:structs` - bool; use structs instead of array-maps or hash-maps in mappify.
-  * `:remove-comments` - bool; remove comment lines, as specified by `:comment-re` or `:comment-char`. Also
-     removes empty lines. Defaults to `true`.
-  * `:comment-re` - specify a regular expression to use for commenting out lines.
-  * `:comment-char` - specify a comment character to use for filtering out comments; overrides comment-re.
-  * `:cast-fns` - optional map of `colname | index -> cast-fn`; row maps will have the values as output by the
-     assigned `cast-fn`."
-  ([{:keys [remove-comments comment-re comment-char mappify header structs cast-fns]
-     :or   {remove-comments true
-            comment-re   #"^\#"
-            mappify      true}
-     :as opts}
-    rows]
-   (->> rows
-        (?>> remove-comments (semantic-csv.core/remove-comments {:comment-re comment-re :comment-char comment-char}))
-        (?>> mappify (semantic-csv.core/mappify {:header header :structs structs}))
-        (?>> cast-fns (cast-with cast-fns))))
-  ; Use all defaults
-  ([rows]
-   (process {} rows)))
+(let [mappify-fn         mappify
+      remove-comments-fn remove-comments]
+  (defn process
+    "This function wraps together the most frequently used input processing capabilities,
+    controlled by an `opts` hash with opinionated defaults:
+
+    * `:mappify` - bool; transform rows from vectors into maps using `mappify`.
+    * `:header` - specify header to be used in mappify; as per `mappify`, first row will not be consumed as header
+    * `:structs` - bool; use structs instead of array-maps or hash-maps in mappify.
+    * `:remove-comments` - bool; remove comment lines, as specified by `:comment-re` or `:comment-char`. Also
+       removes empty lines. Defaults to `true`.
+    * `:comment-re` - specify a regular expression to use for commenting out lines.
+    * `:comment-char` - specify a comment character to use for filtering out comments; overrides comment-re.
+    * `:cast-fns` - optional map of `colname | index -> cast-fn`; row maps will have the values as output by the
+       assigned `cast-fn`."
+    ([{:keys [remove-comments comment-re comment-char mappify header structs cast-fns]
+       :or   {remove-comments true
+              comment-re   #"^\#"
+              mappify      true}
+       :as opts}
+      rows]
+     (->> rows
+          (?>> remove-comments (remove-comments-fn {:comment-re comment-re :comment-char comment-char}))
+          (?>> mappify (mappify-fn {:header header :structs structs}))
+          (?>> cast-fns (cast-with cast-fns))))
+    ; Use all defaults
+    ([rows]
+     (process {} rows))))

 ;; Using this function, the code we've been building above is reduced to the following:
 ;;


Another damn spit-csv bug

Another damn spit-csv bug

--- src/semantic_csv/core.clj
+++ src/semantic_csv/core.clj
@@ -413,7 +413,7 @@
                (vectorize {:header header
                            :prepend-header prepend-header}))
           ; For save measure
-          (format-all str)
+          (cast-all str)
           (batch batch-size)
           (map #(impl/apply-kwargs csv/write-csv % writer-opts))
           (reduce


Working (ugly) fizzbuzz

Working (ugly) fizzbuzz

--- src/shokunin/fizzbuzz.clj
+++ src/shokunin/fizzbuzz.clj
@@ -3,7 +3,7 @@
 (def fizz-buzz (let [number (iterate inc 1)
                      fizzer (cycle [nil nil "fizz"])
                      buzzer (cycle [nil nil nil nil "buzz"])]
-                 (map #(or (str %2 %3) %1)
+                 (map #(or (if (or %2 %3) (str %2 %3)) %1)
                       number fizzer buzzer)))

 (take 15 fizz-buzz)


fix 1.8

fix 1.8

--- test/java_time/dev/gen.clj
+++ test/java_time/dev/gen.clj
@@ -184,10 +184,12 @@
                          (list '.join 'java-time.impl.load/serialized-load-thread))))])))

 (defn print-form [form]
-  (binding [*print-namespace-maps* false
-            *print-meta* true
-            *print-length* nil
-            *print-level* nil]
+  (with-bindings
+    (cond-> {#'*print-meta* true
+             #'*print-length* nil
+             #'*print-level* nil}
+      (resolve '*print-namespace-maps*)
+      (assoc (resolve '*print-namespace-maps*) false))
     (cond
       (string? form) (println form)
       :else (println (pr-str (walk/postwalk


Strangeness with `(def max-long Long/MAX_VALUE)`.

--- test/clojure_the_language/clojure_numerics_test.clj
+++ test/clojure_the_language/clojure_numerics_test.clj
@@ -129,13 +129,18 @@
 ;;;; ___________________________________________________________________________
 ;;;; ---- Bigger than longs ----

-(def max-long Long/MAX_VALUE)
 (def max-long-plus-1 9223372036854775808N)

-(fact (inc max-long) => (throws ArithmeticException))
-(fact (inc (bigint max-long)) => max-long-plus-1)
+(fact (inc Long/MAX_VALUE) => (throws ArithmeticException))
+(fact (inc (bigint Long/MAX_VALUE)) => max-long-plus-1)

-(fact (inc' max-long) => max-long-plus-1)
+(fact (inc' Long/MAX_VALUE) => max-long-plus-1)
 (fact (=-and-same-type (inc' 1) 2) => true)

-(fact (unchecked-inc max-long) => throws ArithmeticException) ; **** Huh?
+(fact (unchecked-inc Long/MAX_VALUE) => Long/MIN_VALUE)
+
+(do
+  (def max-long Long/MAX_VALUE)
+  (fact (unchecked-inc max-long) => (throws ArithmeticException)) ; **** Huh?
+  (fact (let [max-long Long/MAX_VALUE] (unchecked-inc max-long))
+    => Long/MIN_VALUE))


Only use HEAD for validation

Only use HEAD for validation

--- src/wordly/validation.clj
+++ src/wordly/validation.clj
@@ -10,7 +10,7 @@

 (defn page-available? [url]
   (-> url
-      (client/get {:throw-exceptions false})
+      (client/head {:throw-exceptions false})
       :status
       (= 200)))


[#2254] Test: columns could be removed without existing in txs

--- backend/test/akvo/lumen/lib/transformation_test.clj
+++ backend/test/akvo/lumen/lib/transformation_test.clj
@@ -11,15 +11,15 @@
             [akvo.lumen.lib :as lib]
             [akvo.lumen.lib.multiple-column :as multiple-column]
             [akvo.lumen.lib.transformation :as transformation]
+            [akvo.lumen.lib.transformation.derive-category :as derive-category]
             [akvo.lumen.lib.transformation.engine :as engine]
-            [akvo.lumen.lib.transformation.derive-category :as derive-category]
             [akvo.lumen.postgres :as postgres]
             [akvo.lumen.specs :as lumen.s]
             [akvo.lumen.specs.import :as import.s]
             [akvo.lumen.specs.import.column :as import.column.s]
             [akvo.lumen.specs.import.values :as import.values.s]
             [akvo.lumen.specs.transformation :as transformation.s]
-            [akvo.lumen.test-utils :refer [import-file at-least-one-true retry-job-execution] :as tu]
+            [akvo.lumen.test-utils :refer [update-file import-file at-least-one-true retry-job-execution] :as tu]
             [akvo.lumen.util :refer [conform squuid]]
             [cheshire.core :as json]
             [clj-time.coerce :as tcc]
@@ -286,6 +286,29 @@
         (is (= years (map (comp str tc/year tcc/from-long :c2) table-data)))
         (is (= years-slash (map (comp tcc/from-long :c3) table-data)))
         (is (= years-hiphen (map (comp tcc/from-long :c4) table-data)))))))
+
+
+
+(deftest ^:functional test-update-issue-2254
+  (testing "Testing https://github.com/akvo/akvo-lumen/issues/2254 "
+    (let [[job dataset] (import-file *tenant-conn* *error-tracker*
+                                     {:dataset-name "Padded titles"
+                                      :kind "clj"
+                                      :data (import.s/sample-imported-dataset [:text :number :text :number :text :number :text :number] 2)
+                                      :with-job? true})
+          dataset-id (:dataset_id dataset)
+          dataset (dataset-version-by-dataset-id *tenant-conn* {:dataset-id dataset-id
+                                                                :version 1})
+          stored-data (->> (latest-dataset-version-by-dataset-id *tenant-conn*
+                                                                 {:dataset-id dataset-id})
+                           (get-data *tenant-conn*))]
+      (testing "Testing columns are removed without tx"
+        (log/error :job job)
+       (let [updated-res (update-file *tenant-conn* *error-tracker* (:dataset-id job) (:data_source_id job)
+                                      {:kind "clj"
+                                       :data (import.s/sample-imported-dataset [:text :number :text :number :text :number] 2)})]
+         (is (some? updated-res))))
+      )))

 (deftest ^:functional derived-column-test
   (let [change-datatype-transformation (fn [column-name]


Fix mouse selection offset issue

Fix mouse selection offset issue

--- src/zaffre/glterminal.clj
+++ src/zaffre/glterminal.clj
@@ -889,21 +889,23 @@
     @destroyed))

 (defn group-locations
-  ([_ _]
+  ([_ _ _ _]
    [])
-  ([group-map group->font-texture xpos ypos]
+  ([group-map group->font-texture framebuffer-width framebuffer-height xpos ypos]
    (set
      (remove (fn [[group-id col row]] (and (nil? col) (nil? row)))
              (map (fn [[group-id group]]
                     (let [{:keys [pos columns rows]
                            [pos-x pos-y] :pos} @group
-                          {:keys [character-width character-height]} (-> group->font-texture group-id deref)]
+                          {:keys [character-width character-height]} (-> group->font-texture group-id deref)
+                          width  (* character-width columns)
+                          height (* character-height rows)]
                       ;; determine if the mouse is in the bounds of the layer group
                       (when (and (<= pos-x xpos (+ (* columns character-width) pos-x))
                                (<= pos-y ypos (+ (* rows character-height) pos-y)))
                         ;; determine which col/row the mouse is in the group
-                        (let [col (int (quot (- xpos pos-x) character-width))
-                              row (int (quot (- ypos pos-y) character-height))]
+                        (let [col (int (quot (- xpos pos-x (quot (- framebuffer-width width) 2)) character-width))
+                              row (int (quot (- ypos pos-y (quot (- framebuffer-height height) 2)) character-height))]
                           [group-id col row]))))
                    group-map)))))

@@ -1112,7 +1114,8 @@
                                   (let [state  (condp = (int action)
                                                  GLFW/GLFW_PRESS :mouse-down
                                                  GLFW/GLFW_RELEASE :mouse-up)
-                                        new-group-locations (apply group-locations group-map group->font-texture @mouse-xy)
+                                        new-group-locations (apply group-locations group-map group->font-texture
+                                                                   framebuffer-width framebuffer-height @mouse-xy)
                                         button (get [:left :right :middle] (int button))]
                                     (async/onto-chan
                                       term-chan
@@ -1129,12 +1132,16 @@
                                                {:type :click :button button :col col :row row :group-id group-id})
                                              (clojure.set/intersection
                                                new-group-locations
-                                               (apply group-locations group-map group->font-texture @mousedown-xy)))
+                                               (apply group-locations group-map group->font-texture
+                                                      framebuffer-width framebuffer-height @mousedown-xy)))
                                         false)))))
         cursor-pos-callback   (proxy [GLFWCursorPosCallback] []
                                 (invoke [window xpos ypos]
-                                  (let [new-group-locations (group-locations group-map group->font-texture xpos ypos)
-                                        old-group-locations (apply group-locations group-map group->font-texture @mouse-xy)
+                                  (let [new-group-locations (group-locations group-map group->font-texture
+                                                                             framebuffer-width framebuffer-height
+                                                                             xpos ypos)
+                                        old-group-locations (apply group-locations group-map group->font-texture
+                                                                   framebuffer-width framebuffer-height @mouse-xy)
                                         entered-locations   (clojure.set/difference new-group-locations old-group-locations)
                                         left-locations      (clojure.set/difference old-group-locations new-group-locations)]
                                     (reset! mouse-xy [xpos ypos])


Removing project.clj

Removing project.clj

--- sherpa-clojure/project.clj
+++ sherpa-clojure/project.clj
@@ -1,24 +0,0 @@
-(defproject com.revelytix/sparql-clojure "0.1.3-SNAPSHOT"
-  :description "Defines a SPARQL client and server processing framework using the SHERPA protocol."
-
-  ;; Project dependencies, resolved via Maven
-  ;; Format is: [<groupId>/<artifactId> "version"]
-  :dependencies [[org.clojure/clojure "1.2.1"]
-
-                 ;; revelytix projects
-                 [com.revelytix/sherpa-protocol "0.1.3-SNAPSHOT"]
-                 [com.revelytix/sherpa-java "0.1.3-SNAPSHOT"]]
-
-  :dev-dependencies [[jline "0.9.94"]
-                     [swank-clojure "1.2.1"]
-                     [autodoc "0.8.0-RAS"]]
-
-  ;; Use a Maven-like directory structure
-  :source-path "src/main/clojure"
-  :test-path "src/test/clojure"
-  :resources-path "src/main/resources"
-  :dev-resources-path "src/test/resources"
-  :target-dir "target"
-  :compile-path "target/classes"
-
-  :omit-default-repositories true)


cleaned up renderer

cleaned up renderer

--- src/frontend/renderer.cljs
+++ src/frontend/renderer.cljs
@@ -74,28 +74,30 @@
 (defn user-upload-progress [data]
   (let [upload (first data)
         upload-info (second data)]
-    (dom/li nil (when-not (nil? upload)
-                  (dom/button #js {:onClick #(core/cancel-upload (.-id upload-info))}       "CANCEL")
-                  (if (:paused? ((:uploads @app-state/app-state) (:id upload)))
-                    (dom/button #js {:onClick #(core/resume-upload!  (:id upload))} "RESUME")
-                    (dom/button #js {:onClick #(core/pause-upload!   (:id upload))} "PAUSE"))
-                  (when-not (:started? upload)
-                    "STOPPED!"))
-                (((:users @app-state/app-state) (.-uploaderid upload-info)) "name")
-                " - " (* 100 (/ (.-bytesreceived upload-info) (.-totalsize upload-info))) "% - "
-                (.-filename upload-info))))
+    (dom/div #js {:className "track-view"}
+             (when-not (nil? upload)
+               (dom/button #js {:onClick #(core/cancel-upload (.-id upload-info))}       "CANCEL")
+                 (if (:paused? ((:uploads @app-state/app-state) (:id upload)))
+                   (dom/button #js {:onClick #(core/resume-upload!  (:id upload))} "RESUME")
+                   (dom/button #js {:onClick #(core/pause-upload!   (:id upload))} "PAUSE"))
+                 (when-not (:started? upload)
+                   "STOPPED!"))
+             (((:users @app-state/app-state) (.-uploaderid upload-info)) "name")
+             " - " (* 100 (/ (.-bytesreceived upload-info) (.-totalsize upload-info))) "% - "
+             (.-filename upload-info))))

 (defn uninitialized-upload [data]
-  (dom/li nil (list (dom/button #js {:onClick #(swap! app-state/app-state
-                                                      merge
-                                                      {:uploads (dissoc (:uploads @app-state/app-state)
-                                                                        (:id data))})}
-                                "CANCEL")
-                    (if (:paused? data)
-                      (dom/button #js {:onClick #(core/resume-upload! (:id data))} "RESUME")
-                      (dom/button #js {:onClick #(core/pause-upload!  (:id data))} "PAUSE"))
-                    "Not yet started: "
-                    (:filename data))))
+  (dom/div #js {:className "track-view"}
+           (list (dom/button #js {:onClick #(swap! app-state/app-state
+                                                   merge
+                                                   {:uploads (dissoc (:uploads @app-state/app-state)
+                                                                     (:id data))})}
+                            "CANCEL")
+                 (if (:paused? data)
+                   (dom/button #js {:onClick #(core/resume-upload! (:id data))} "RESUME")
+                   (dom/button #js {:onClick #(core/pause-upload!  (:id data))} "PAUSE"))
+                 "Not yet started: "
+                 (:filename data))))

 (defn build-upload-id-view [upload-data owner]
   (reify
@@ -112,11 +114,11 @@
   (reify
     om/IRender
     (render [this]
-      (println (:room-uploads-order data))
       (let [uploads-data (map (fn [id]
                                 (let [upload-info (first (filter #(= id (.-id %1))
                                                                  (vals (:current-uploads-info data))))
-                                      client-id (.-clientid upload-info)]
+                                      client-id (when-not (nil? upload-info)
+                                                  (.-clientid upload-info))]
                                   [((:uploads data) client-id) upload-info]))
                               (:room-uploads-order data))]
         (apply dom/div nil


convert int value and float value

convert int value and float value

--- src/graphql_clj/parser.clj
+++ src/graphql_clj/parser.clj
@@ -84,7 +84,13 @@
                 [:arguments (into {} args)])
    :Argument (fn argument [& args]
                (println "Argument: " args)
-               (into {} args))})
+               (into {} args))
+   :IntValue (fn int-value [v]
+               (println "IntValue: " v)
+               (Integer/parseInt v))
+   :FloatValue (fn float-value [v]
+                 (println "FloatValue: " v)
+                 (Double. v))})

 (defn transformer
   [parse-tree]


added hive can modify in core.

added hive can modify in core.

--- src/hivewing_core/hive.clj
+++ src/hivewing_core/hive.clj
@@ -6,6 +6,13 @@
             [hivewing-core.worker-config :refer [worker-config-set-hive-image]]
             [clojure.java.jdbc :as jdbc]))

+
+(defn hive-can-modify?
+  [bk-uuid hive-uuid]
+  (if (and hive-uuid bk-uuid)
+    (jdbc/query sql-db ["SELECT beekeeper_uuid FROM hive_managers WHERE hive_uuid = ? AND beekeeper_uuid = ? LIMIT 1" (ensure-uuid hive-uuid) (ensure-uuid bk-uuid)] :result-set-fn first)
+    nil
+    ))

 (defn hive-get-permissions
   "Gets access roles for a given uuid and token"