(maint) Remove config->puppet-config unused in 1.x

Previously config->puppet-config is defined but never referenced in the
1.x series.  This patch removes the dead code.  This change should
probably not be applied if merged up into the 2.x series.

--- src/clj/puppetlabs/services/jruby/jruby_puppet_internal.clj
+++ src/clj/puppetlabs/services/jruby/jruby_puppet_internal.clj
@@ -133,20 +133,6 @@
     ;; information.
     (.runScriptlet "require 'jar-dependencies'")
     (.runScriptlet "require 'puppet/server/master'")))
-
-(schema/defn ^:always-validate config->puppet-config :- HashMap
-  "Given the raw jruby-puppet configuration section, return a
-  HashMap with the configuration necessary for ruby Puppet."
-  [config :- jruby-schemas/JRubyPuppetConfig]
-  (let [puppet-config (new HashMap)]
-    (doseq [[setting dir] [[:master-conf-dir "confdir"]
-                           [:master-code-dir "codedir"]
-                           [:master-var-dir "vardir"]
-                           [:master-run-dir "rundir"]
-                           [:master-log-dir "logdir"]]]
-      (if-let [value (get config setting)]
-        (.put puppet-config dir (fs/absolute-path value))))
-    puppet-config))

 (schema/defn borrow-with-timeout-fn :- jruby-schemas/JRubyPuppetBorrowResult
   [timeout :- schema/Int


Shorten another function

Shorten another function

--- common/src/play_clj/render.clj
+++ common/src/play_clj/render.clj
@@ -57,9 +57,9 @@
 (defmethod sprite-batch BatchTiledMapRenderer [screen]
   (.getSpriteBatch (:renderer screen)))

-(defn draw-entities!
+(defn draw!
   ([screen]
-    (draw-entities! screen (:entities screen)))
+    (draw! screen (:entities screen)))
   ([screen entities]
     (let [batch (sprite-batch screen)]
       (.begin batch)


updated [org.apache.httpcomponents/httpclient to 4.5.13 in search-relevancy-test (#1136)

--- search-relevancy-test/project.clj
+++ search-relevancy-test/project.clj
@@ -23,7 +23,7 @@
                  [commons-io "2.6"]
                  [nasa-cmr/cmr-system-int-test "0.1.0-SNAPSHOT"]
                  [nasa-cmr/cmr-transmit-lib "0.1.0-SNAPSHOT"]
-                 [org.apache.httpcomponents/httpclient "4.5.6"]
+                 [org.apache.httpcomponents/httpclient "4.5.13"]
                  [org.apache.httpcomponents/httpcore "4.4.10"]
                  [org.clojure/clojure "1.10.0"]
                  [org.clojure/tools.reader "1.3.2"]


Improve and fix coner cases with row-envents

--- src/cider_ci/utils/row_events.clj
+++ src/cider_ci/utils/row_events.clj
@@ -10,24 +10,45 @@
     [logbug.thrown :as thrown]
     ))

+(defn process-last-row [table-name state-atom row-handler]
+  (swap! state-atom
+         (fn [_]
+           (when-let [last-row (I>> identity-with-logging
+                                    [(str "SELECT * FROM " table-name
+                                          " ORDER BY created_at DESC, id LIMIT 1")]
+                                    (jdbc/query (rdbms/get-ds))
+                                    first)]
+             (snatch {} (row-handler last-row))
+             last-row))))
+
+
+
+; 1. we compare to the timestamp of the row with the given id instead of
+;   the saved created_at because the latter might not be exactly the same
+;   (loosing bits due to coercion)
+; 2. this row might not even exist anymore; e.g. because it has been removed
+;     by the sweeper or something else (truncate); in that case we query all
+;     events of the last 24 hours as a fallback
+
+(defn process-new-rows [table-name state-atom row-handler]
+  (swap! state-atom
+         (fn [last-processed-row]
+           (or (I>> identity-with-logging
+                    [(str "SELECT * FROM " table-name
+                          " WHERE created_at > "
+                          "  (SELECT COALESCE(max(created_at), (now() - interval '24 hours')) "
+                          "   FROM " table-name " WHERE id = ?)"
+                          " ORDER BY created_at ASC LIMIT 1000")
+                     (:id last-processed-row)]
+                    (jdbc/query (rdbms/get-ds))
+                    (map (fn [row] (snatch {} (row-handler row)) row))
+                    last)
+               last-processed-row))))
+
 (defn process
   [table-name state-atom row-handler]
-  (when-not @state-atom
-    (when-let [last-row (I>> identity-with-logging
-                             [(str "SELECT * FROM " table-name
-                                   " ORDER BY created_at DESC, id LIMIT 1")]
-                             (jdbc/query (rdbms/get-ds))
-                             first)]
-      (snatch {} (row-handler last-row))
-      (reset! state-atom last-row)))
-  (when-let [after-row @state-atom]
-    (if-let [lst (I>> identity-with-logging
-                      [(str "SELECT * FROM " table-name
-                            " WHERE created_at >= ? AND id != ?"
-                            " ORDER BY created_at ASC , id LIMIT 100")
-                       (:created_at after-row) (:id after-row)]
-                      (jdbc/query (rdbms/get-ds))
-                      (map (fn [row] (snatch {} (row-handler row)) row))
-                      last)]
-      (reset! state-atom lst)
-      (reset! state-atom after-row))))
+  (locking state-atom
+    (if-not @state-atom
+      (process-last-row table-name state-atom row-handler)
+      (process-new-rows table-name state-atom row-handler))))
+


Fix dashboard updating

Fix dashboard updating

Changes to the build page's Pusher channels accidentally had the backend
adding `@all` to the end of the user's personal Pusher channel name.
This subscribes to that channel. We'll clean it up when we clean up the
old channel name, after the backend has been fixed and rolled completely.

--- src-cljs/frontend/pusher.cljs
+++ src-cljs/frontend/pusher.cljs
@@ -45,7 +45,11 @@
     ;; This will be removed once the entire fleet is using the pusher-id-based
     ;; channel name.
     true (conj (str "private-" (:login user)))
-    (:pusher_id user) (conj (str "private-" (:pusher_id user)))))
+    (:pusher_id user) (conj (str "private-" (:pusher_id user))
+                            ;; This will be removed once the entire fleet is
+                            ;; clear of the bug that appends "@all" to channel
+                            ;; names even if they don't need it.
+                            (str "private-" (:pusher_id user) "@all"))))

 (defn build-channel-base
   [{:keys [project-name build-num vcs-type]}]


Added system-based pid, cpu, and mem extraction functions.

--- src/cmr/dev/env/manager/components/docker.clj
+++ src/cmr/dev/env/manager/components/docker.clj
@@ -25,6 +25,18 @@
 (defn get-container-state
   [system service-key]
   (docker/state (get-opts system service-key)))
+
+(defn get-container-pid
+  [system service-key]
+  (docker/pid (get-opts system service-key)))
+
+(defn get-container-cpu
+  [system service-key]
+  (docker/get-cpu (get-opts system service-key)))
+
+(defn get-container-mem
+  [system service-key]
+  (docker/get-mem (get-opts system service-key)))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;   Lifecycle Implementation   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Map call removed from replace alias function

--- src/cmr/search/services/legacy_parameters.clj
+++ src/cmr/search/services/legacy_parameters.clj
@@ -16,7 +16,7 @@
   [params]
   (if (map? (:exclude params))
     (update-in params [:exclude]
-               #(when % (set/rename-keys % param-aliases)))
+               #(set/rename-keys % param-aliases))
     params))


Use timeseries instead of topN for query with breakout by timestamp

--- src/metabase/driver/druid/query_processor.clj
+++ src/metabase/driver/druid/query_processor.clj
@@ -14,17 +14,21 @@
                                                RelativeDateTimeValue
                                                Value)))

-;;             +-----> ::select
-;; ::query ----|                     +----> ::timeseries
-;;             +----> ::ag-query ----|                             +----> ::topN
-;;                                   +----> ::grouped-ag-query ----|
-;;                                                                 +----> ::groupBy
-(derive ::select           ::query)
-(derive ::ag-query         ::query)
-(derive ::timeseries       ::ag-query)
-(derive ::grouped-ag-query ::ag-query)
-(derive ::topN             ::grouped-ag-query)
-(derive ::groupBy          ::grouped-ag-query)
+
+;;             +-----> ::select      +----> :groupBy
+;; ::query ----|                     |
+;;             +----> ::ag-query ----+----> ::topN
+;;                                   |                       +----> total
+;;                                   +----> ::timeseries ----|
+;;                                                           +----> grouped-timeseries
+
+(derive ::select             ::query)
+(derive ::ag-query           ::query)
+(derive ::topN               ::ag-query)
+(derive ::groupBy            ::ag-query)
+(derive ::timeseries         ::ag-query)
+(derive ::total              ::timeseries)
+(derive ::grouped-timeseries ::timeseries)

 (def ^:private ^:dynamic *query*
   "The INNER part of the query currently being processed.
@@ -227,7 +231,10 @@

 (defmulti ^:private handle-breakout query-type-dispatch-fn)

-(defmethod handle-breakout ::query [_ _ _]) ; only topN & groupBy handle breakouts
+(defmethod handle-breakout ::query [_ _ _]) ; only topN , grouped-timeseries & groupBy handle breakouts
+
+(defmethod handle-breakout ::grouped-timeseries [_ {[breakout-field] :breakout} druid-query]
+  (assoc druid-query :granularity (:unit breakout-field)))

 (defmethod handle-breakout ::topN [_ {[breakout-field] :breakout} druid-query]
   (assoc druid-query :dimension (->dimension-rvalue breakout-field)))
@@ -395,6 +402,14 @@
                                                      {:dimension (->rvalue field)
                                                       :direction direction}))))

+(defmethod handle-order-by ::grouped-timeseries [_ {{ag-type :aggregation-type} :aggregation, [breakout-field] :breakout, [{field :field, direction :direction}] :order-by} druid-query]
+  (let [field             (->rvalue field)
+        breakout-field    (->rvalue breakout-field)
+        sort-by-breakout? (= field breakout-field)]
+    (if (and sort-by-breakout? (= direction :descending))
+      (assoc druid-query :descending true)
+      druid-query)))
+

 ;;; ### handle-fields

@@ -429,7 +444,7 @@

 (defmethod handle-limit ::timeseries [_ {limit :limit} _]
   (when limit
-    (log/warn (u/format-color 'red "WARNING: It doesn't make sense to limit an aggregate query without any breakouts, since it will always return one row. Ignoring the LIMIT clause."))))
+    (log/warn (u/format-color 'red "WARNING: Druid doenst allow limitSpec in timeseries queries. Ignoring the LIMIT clause."))))

 (defmethod handle-limit ::topN [_ {limit :limit} druid-query]
   (when limit
@@ -460,12 +475,14 @@
                     0 :none
                     1 :one
                       :many)
-        agg?      (boolean (and ag-type (not= ag-type :rows)))]
-    (match [breakouts agg?]
-      [:none false] ::select
-      [:none  true] ::timeseries
-      [:one      _] ::topN
-      [:many     _] ::groupBy)))
+        agg?      (boolean (and ag-type (not= ag-type :rows)))
+        ts?       (boolean (some #(instance? DateTimeField %) breakout-fields))]
+    (match [breakouts agg? ts?]
+      [:none  false    _] ::select
+      [:none  true     _] ::total
+      [:one   _     true] ::grouped-timeseries
+      [:one   _    false] ::topN
+      [:many  _        _] ::groupBy)))

 (defn- build-druid-query [query]
@@ -492,9 +509,14 @@
 (defmulti ^:private post-process query-type-dispatch-fn)

 (defmethod post-process ::select     [_ results] (->> results first :result :events (map :event)))
-(defmethod post-process ::timeseries [_ results] (map :result results))
+(defmethod post-process ::total [_ results] (map :result results))
 (defmethod post-process ::topN       [_ results] (-> results first :result))
 (defmethod post-process ::groupBy    [_ results] (map :event results))
+
+(defmethod post-process ::grouped-timeseries [_ results]
+  (->> results
+    (map (fn [event]
+      (conj {:timestamp (:timestamp event)} (:result event)))))

 (defn post-process-native
   "Post-process the results of a *native* Druid query.


[FIX #3591] always show full link

[FIX #3591] always show full link

Signed-off-by: Julien Eluard <c768e13f1ba4c3ebed2909a1fc1e4b50bb021a2f@gmail.com>

--- src/status_im/chat/views/message/message.cljs
+++ src/status_im/chat/views/message/message.cljs
@@ -127,7 +127,7 @@
                            {:key      idx
                             :style    {:color colors/blue}
                             :on-press #(on-press url)}
-                           (utils/truncate-str text 32 true)])
+                           url])
                         text)))
        vec))


Disable 'Tap for options' on Desktop

Disable 'Tap for options' on Desktop

--- src/status_im/chat/views/message/message.cljs
+++ src/status_im/chat/views/message/message.cljs
@@ -281,9 +281,12 @@
                                                                           :message-id message-id}])))}
    [react/view style/not-sent-view
     [react/text {:style style/not-sent-text}
-     (i18n/message-status-label :not-sent)]
-    [react/view style/not-sent-icon
-     [vector-icons/icon :icons/warning {:color colors/red}]]]])
+     (i18n/message-status-label (if platform/desktop?
+                                  :not-sent-without-tap
+                                  :not-sent))]
+    (when-not platform/desktop?
+      [react/view style/not-sent-icon
+       [vector-icons/icon :icons/warning {:color colors/red}]])]])

 (defview command-status [{{:keys [network]} :params}]
   (letsubs [current-network [:network-name]]


Fix test for latest 0.10.0 release.

Fix test for latest 0.10.0 release.

--- test/onyx/peer/dashboard_colors_flow_test.clj
+++ test/onyx/peer/dashboard_colors_flow_test.clj
@@ -66,7 +66,7 @@
 (def batch-size 10)

 (def colors-in-chan (chan 100))
-(def colors-in-buffer (atom nil))
+(def colors-in-buffer (atom {}))

 (def red-out-chan (chan (sliding-buffer 100)))

@@ -274,21 +274,6 @@

 (def green (take-segments! green-out-chan 50))

-(def red-expectatations
-  #{{:color "white"}
-    {:color "red"}
-    {:color "orange"}})
-
-(def blue-expectatations
-  #{{:color "white"}
-    {:color "blue"}
-    {:color "orange"}})
-
-(def green-expectatations
-  #{{:color "white"}
-    {:color "green"}
-    {:color "orange"}})
-
 (run-test-fixture :chrome
                   (fn []
                     (Thread/sleep 50000)


More time before starting the server, for CI

--- test/onyx/plugin/input_broker_reboot_test.clj
+++ test/onyx/plugin/input_broker_reboot_test.clj
@@ -121,7 +121,7 @@

 (def stopped-server (component/stop kafka-server))

-(Thread/sleep 4000)
+(Thread/sleep 6000)

 (def started-again (component/start stopped-server))


fixed error

fixed error

--- test/purnam_karma_testing/test_sweet_doc.cljs
+++ test/purnam_karma_testing/test_sweet_doc.cljs
@@ -15,7 +15,8 @@

 (def o {:a 1 :b 2 :c 3})

-(facts [[{:doc "Basic Hashmaps"}]]
+(facts [[{:doc "Basic Hashmaps"
+          :globals [o {:a 1 :b 2 :c 3}]}]]
   (o :a)       => 1
   (o :a)       => #(not= 0 %)
   (get o :b)   => 2


Fix crash when using --filter

Fix crash when using --filter

--- src/bltool/core.clj
+++ src/bltool/core.clj
@@ -74,7 +74,7 @@
         out-games (filter-games bl-games in-games)]
     (printf "Read %d games in %s format.\n" (count in-games) (:from *opts*))
     (if (:filter *opts*)
-      (printf "After filtering, %d remain.\n"))
+      (printf "After filtering, %d remain.\n" (count out-games)))
     (printf "Writing game list to %s.\n" (:to *opts*))
     (data/write-games (:to *opts*) out-games)))


Introduced with-altered-vars

Introduced with-altered-vars

as an abstraction of with-memoized-fns.

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

--- src/conexp/util.clj
+++ src/conexp/util.clj
@@ -215,21 +215,36 @@
   [& strings]
   (die-with-error IllegalStateException strings))

+(defmacro with-altered-vars
+  "Executes the code given in a dynamic environment where the var
+  roots of the given names are altered according to the given
+  bindings. The bindings have the form [name_1 f_1 name_2 f_2 ...]
+  where f_i is applied to the original value of the var associated
+  with name_i to give the new value which will be in place during
+  execution of body. The old value will be restored after execution
+  has been finished."
+  [bindings & body]
+  (when-not (even? (count bindings))
+    (illegal-argument "Bindings must be given pairwise."))
+  (let [bindings (partition 2 bindings),
+        bind-gen (for [[n _] bindings] [(gensym) n])]
+    `(let ~(vec (mapcat (fn [[name thing]] [name `(deref (var ~thing))])
+                        bind-gen))
+       (try
+         ~@(map (fn [[thing f]]
+                  `(alter-var-root (var ~thing) ~f))
+                bindings)
+         ~@body
+         (finally
+          ~@(map (fn [[name thing]]
+                   `(alter-var-root (var ~thing) (constantly ~name)))
+                 bind-gen))))))
+
 (defmacro with-memoized-fns
   "Runs code in body with all given functions memoized."
   [functions & body]
-  (let [function-gensyms (into {} (for [f functions] [(gensym) f]))]
-    `(let ~(vec (mapcat (fn [[f-name f]] [f-name `(deref (var ~f))])
-                        function-gensyms))
-       (try
-         ~@(map (fn [f]
-                  `(alter-var-root (var ~f) memoize))
-                functions)
-         ~@body
-          (finally
-           ~@(map (fn [[name-f f]]
-                    `(alter-var-root (var ~f) (constantly ~name-f)))
-                  function-gensyms))))))
+  `(with-altered-vars ~(vec (mapcat (fn [f] [f `memoize]) functions))
+     ~@body))

 (defmacro memo-fn
   "Defines memoized, anonymous function."


Fixed default post-process

Fixed default post-process

--- pigpen-core/src/main/clojure/pigpen/runtime.clj
+++ pigpen-core/src/main/clojure/pigpen/runtime.clj
@@ -137,7 +137,7 @@
   (fn [platform serialization-type]
     [platform serialization-type]))

-(defmethod post-process :default [_ _] identity)
+(defmethod post-process :default [_ _] first)

 (defn exec
   "Applies the composition of fs, flattening intermediate results. Each f must


corrected consentir

corrected consentir

--- src/babel/espanol/lexicon.clj
+++ src/babel/espanol/lexicon.clj
@@ -96,10 +96,9 @@
              :synsem {:cat :verb
                       :sem {:pred :confess}}}

-   "consentir" {:espanol {:boot-stem1 "consient"
-                        :boot-stem2 "consent"}
-             :synsem {:cat :verb
-                      :sem {:pred :consent}}}
+   "consentir" {:espanol {:boot-stem "consient"}
+                :synsem {:cat :verb
+                         :sem {:pred :consent}}}

    "conservar" [{:synsem {:cat :verb
                           :sem {:pred :conserve}}}


Add all-formats to translations

Add all-formats to translations

--- src/catalog/layout/common.clj
+++ src/catalog/layout/common.clj
@@ -23,6 +23,7 @@
                 :kinderbücher-ab-6 :kinderbücher-ab-10 :jugendbücher :kinder-und-jugendsachbücher])

 (def ^:dynamic translations {:inhalt "Inhaltsverzeichnis"
+                             :all-formats "Neu im Sortiment"
                              :hörbuch "Neue Hörbücher"
                              :braille "Neue Braillebücher"
                              :grossdruck "Neue Grossdruckbücher"


fully implement Demolition Run

fully implement Demolition Run

--- src/clj/game/cards-events.clj
+++ src/clj/game/cards-events.clj
@@ -95,7 +95,18 @@
                                      :effect (effect (move target :hand))} card nil)))}

    "Demolition Run"
-   {:prompt "Choose a server" :choices ["HQ" "R&D"] :effect (effect (run target))}
+   {:prompt "Choose a server" :choices ["HQ" "R&D"]
+    :abilities [{:msg (msg "trash " (:title (:card (first (get-in @state [side :prompt])))) " at no cost")
+                 :effect (effect (trash-no-cost))}]
+    :effect (effect (run target)
+                    (prompt! card (str "Click Demolition Run in the play area to trash a card being accessed at no cost") ["OK"] {})
+                    (resolve-ability
+                      {:effect (req (let [c (move state side (last (:discard runner)) :play-area)]
+                                      (card-init state side c false)
+                                      (register-events state side
+                                                       {:run-ends {:effect (effect (trash c))}} c)))}
+                     card nil))
+    :events {:run-ends nil}}

    "Diesel"
    {:effect (effect (draw 3))}


Create almost working badge gallery search

--- src/clj/salava/gallery/db.clj
+++ src/clj/salava/gallery/db.clj
@@ -34,15 +34,16 @@

-(defn badge-adverts-where-params [country name issuer-name id recipient-name]
+(defn badge-adverts-where-params [country name issuer-name recipient-name]
   (let [where-params {}]

     (-> where-params
                                         ;(conj (map-collection " and ba.id = ? " id ))
-        #_(conj (map-collection  " AND CONCAT(u.first_name,' ',u.last_name) LIKE ?" (if recipient-name (str "%" recipient-name "%")) ))
-        (conj (map-collection " and ba.country = ? " country (not= country "all")))
+        (conj (map-collection  " AND CONCAT(u.first_name,' ',u.last_name) LIKE ?" (if recipient-name (str "%" recipient-name "%")) ))
+        (conj (map-collection " and u.country = ? " country (not= country "all")))
         (conj (map-collection " AND bc.name LIKE ? " (if name (str "%" name "%"))))
         (conj (map-collection " AND ic.name LIKE ? " (if issuer-name (str "%" issuer-name "%"))))
+
         )))

@@ -67,59 +68,61 @@
           :db (hikari-cp.core/make-datasource {:adapter "mysql",
                                                :username "root",
                                                :password "isokala",
-                                               :database-name "salava_extra1",
+                                               :database-name "salavareal",
                                                :server-name "localhost"})})

-(def most-messages
-  "SELECT bc.id, bc.name, bc.image_file, bc.description, ic.name AS issuer_content_name, ic.url AS issuer_content_url, MAX(b.ctime) AS ctime, badge_content_id  FROM social_event AS se
-  JOIN badge AS b ON se.object = b.badge_content_id
-                    JOIN badge_content AS bc ON b.badge_content_id = bc.id
-                    JOIN issuer_content AS ic ON b.issuer_content_id = ic.id
-                    LEFT JOIN user AS u ON b.user_id = u.id
-                    WHERE b.status = 'accepted' AND b.deleted = 0 AND b.revoked = 0 AND (b.expires_on IS NULL OR b.expires_on > UNIX_TIMESTAMP())
-
-  GROUP BY bc.id, bc.name, bc.image_file, bc.description, ic.name, ic.url, b.badge_content_id")
-
-(def lo
-  "select distinct bc.id, count(se.id) as messagecount, count(b.id) as ownercount,  bc.name, bc.image_file, bc.description, ic.name AS issuer_content_name, ic.url AS issuer_content_url, MAX(b.ctime) AS ctime from badge_content as bc
-  left join badge as b on bc.id = b.badge_content_id AND  b.status = 'accepted' AND b.deleted = 0 AND b.revoked = 0
-  left join social_event as se on bc.id = se.object and se.verb = 'message'
-  JOIN issuer_content AS ic ON b.issuer_content_id = ic.id
-  group by bc.id;")
-
-(defn get-badge-adverts [ctx country tags badge-name issuer-name order id user-id show-followed-only recipient-name]
-  (let [;where-params (badge-adverts-where-params country badge-name issuer-name id recipient-name)
-        ;user-id (or user-id "NULL") ;set null if nil
-       ; where   (str (apply str (keys where-params))  (if show-followed-only  " AND scba.user_id IS NOT NULL ")) ;add IS NOT NULL when user want only followed adverts
-        params [] ;(cons user-id (vec (vals where-params)))  ;add user-id to params
+
+
+
+(def hakujenhaku
+  "select distinct  bc.name, ic.name AS issuer_content_name, count(distinct b.id) as owners, MAX(b.ctime) AS ctime
+FROM badge_content as bc
+INNER JOIN badge as b on bc.id = b.badge_content_id AND  b.status = 'accepted' AND b.deleted = 0 AND b.revoked = 0 AND (b.expires_on IS NULL OR b.expires_on > UNIX_TIMESTAMP())
+INNER JOIN issuer_content AS ic ON b.issuer_content_id = ic.id
+group by bc.id
+ORDER BY owners desc")
+
+(defn get-badge-adverts [ctx country tags badge-name issuer-name order id recipient-name]
+  (let [where-params (badge-adverts-where-params country badge-name issuer-name recipient-name)
+        where  (apply str (keys where-params))
+        params  (vec (vals where-params))  ;add user-id to params
         ;tags (vec (vals tags))
         order (cond
                 ;(= order "mtime") "ORDER BY ba.mtime DESC"
                 (= order "name") "ORDER BY bc.name"
                 (= order "issuer_content_name") "ORDER BY ic.name"
+                (= order "owners") "ORDER BY owners DESC"
                 :else "ORDER BY ctime DESC")
-        query (str "SELECT bc.id, bc.name, bc.image_file, bc.description, ic.name AS issuer_content_name, ic.url AS issuer_content_url, MAX(b.ctime) AS ctime, badge_content_id  FROM badge AS b
-                    JOIN badge_content AS bc ON b.badge_content_id = bc.id
-                    JOIN issuer_content AS ic ON b.issuer_content_id = ic.id
-                    LEFT JOIN user AS u ON b.user_id = u.id
-                    WHERE b.status = 'accepted' AND b.deleted = 0 AND b.revoked = 0 AND (b.expires_on IS NULL OR b.expires_on > UNIX_TIMESTAMP()) "
-
-                  ; where
+        query (str
+               "select bc.id, bc.name, ic.name AS issuer_content_name, count(distinct b.id) as owners, MAX(b.ctime) AS ctime
+FROM badge_content as bc
+INNER JOIN badge as b on bc.id = b.badge_content_id AND  b.status = 'accepted' AND b.deleted = 0 AND b.revoked = 0 AND (b.expires_on IS NULL OR b.expires_on > UNIX_TIMESTAMP())
+INNER JOIN issuer_content AS ic ON b.issuer_content_id = ic.id
+INNER JOIN user as u on b.user_id =  u.id
+WHERE bc.id IN
+	(SELECT DISTINCT badge_content_id FROM badge WHERE visibility != 'private' AND  status = 'accepted' AND deleted = 0 AND revoked = 0 AND (expires_on IS NULL OR expires_on > UNIX_TIMESTAMP()))
+ "
+
+
+
+                  where

-                   "GROUP BY bc.id, bc.name, bc.image_file, bc.description, ic.name, ic.url, b.badge_content_id "
+                   "GROUP BY bc.id "
                    order
                    )
         search (jdbc/with-db-connection
                  [conn (:connection (get-db ctx))]
                  (jdbc/query conn (into [query] params)))]
+    (dump where)
     search
     #_(if (not-empty tags)
       (filter-tags search tags)
       search)))

-(dump )
-(count (get-badge-adverts ctx nil nil nil nil nil nil nil nil nil))
+
+(time  (count (get-badge-adverts ctx nil nil nil nil "owners" nil nil) ))
+
 (:name (first (get-badge-adverts ctx nil nil nil nil "mtime" nil nil nil nil)))

 (defn public-badges-by-user
@@ -158,8 +161,7 @@
                     WHERE b.status = 'accepted' AND b.deleted = 0 AND b.revoked = 0 AND (b.expires_on IS NULL OR b.expires_on > UNIX_TIMESTAMP())"
                    where
                    " GROUP BY bc.id, bc.name, bc.image_file, bc.description, ic.name, ic.url, b.badge_content_id
-                    ORDER BY ctime DESC
-                    LIMIT 100")
+                    ORDER BY ctime DESC")
         badgesearch (jdbc/with-db-connection
                   [conn (:connection (get-db ctx))]
                   (jdbc/query conn (into [query] params)))
@@ -169,6 +171,8 @@
         assochelper (fn [user recipients] (assoc user  :recipients (get recipientsmap (:badge_content_id user))))]
     (map assochelper badgesearch recipients)))

+(dump )
+(time (count (public-badges ctx nil nil nil nil)))
 (defn user-country
   "Return user's country id"
   [ctx user-id]
@@ -299,3 +303,80 @@
 (defn meta-tags [ctx badge-content-id]
   (let [badge-content (select-common-badge-content {:id badge-content-id} (into {:result-set-fn first} (get-db ctx)))]
     (rename-keys badge-content {:image_file :image :name :title})))
+
+
+ id: ffb7074f567518bf28aee587e032a0023652289273f044c04d2a8fcab8d82e20
+       messagecount: 2
+         ownercount: 2
+               name: Peukaloija
+         image_file: file/a/9/c/0/a9c0fcac0b074362e21b9707b78e2a8f208e1bbe016b0ee8a391afc4b1376b96.svg
+        description: Niille jotka eivät vain voi pitää näppejä erossa.
+issuer_content_name: Example organisation
+ issuer_content_url: http://www.example.com
+              ctime: 1491893984
+
+                id: ffb7074f567518bf28aee587e032a0023652289273f044c04d2a8fcab8d82e20
+               name: Peukaloija
+         image_file: file/a/9/c/0/a9c0fcac0b074362e21b9707b78e2a8f208e1bbe016b0ee8a391afc4b1376b96.svg
+        description: Niille jotka eivät vain voi pitää näppejä erossa.
+issuer_content_name: Example organisation
+ issuer_content_url: http://www.example.com
+              ctime: 1491893984
+   badge_content_id: ffb7074f567518bf28aee587e032a0023652289273f044c04d2a8fcab8d82e20
+
+
+
+
+
+explain select distinct bc.id, count(distinct bm.id) as messagecount, count(distinct b.id) as ownercount,  bc.name, bc.image_file, bc.description, ic.name AS issuer_content_name, ic.url AS issuer_content_url, MAX(b.ctime) AS ctime from badge_content as bc
+  join badge as b on bc.id = b.badge_content_id AND  b.status = 'accepted' AND b.deleted = 0 AND b.revoked = 0
+  inner join badge_message as bm on bc.id = bm.badge_content_id and bm.deleted = 0
+  JOIN issuer_content AS ic ON b.issuer_content_id = ic.id
+group by bc.id;
+
+explain select distinct bc.id, count(distinct bm.id) as messagecount, count(distinct b.id) as ownercount,  bc.name, bc.image_file, bc.description, ic.name AS issuer_content_name, ic.url AS issuer_content_url, MAX(b.ctime) AS ctime from badge as b
+  inner join  badge_content as bc  on  b.badge_content_id = bc.id
+  inner join badge_message as bm on b.badge_content_id = bm.badge_content_id and bm.deleted = 0
+inner JOIN issuer_content AS ic ON b.issuer_content_id = ic.id
+WHERE  b.status = 'accepted' AND b.deleted = 0 AND b.revoked = 0
+group by bc.id;
+
+
+ALTER TABLE `badge_message` ADD INDEX `badge_content_id` (`badge_content_id`)
+ALTER TABLE `badge` ADD INDEX `badge_content_id` (`badge_content_id`)
+ALTER TABLE `badge` ADD INDEX `issuer_content_id` (`issuer_content_id`)
+name
+
+
+;; select badge_content and messages
+;; here can add "in this month"
+
+select count(distinct bm.id) as count, bm.badge_content_id from badge_message as bm group by bm.badge_content_id
+
+;; select owners and badge_content
+
+;; - here can add "in this month"
+
+select count(distinct b.id) as count, b.badge_content_id from badge as b group by b.badge_content_id ORDER by count desc
+
+
+select count(distinct bm.id) as count, b.badge_content_id from badge as b
+join badge_message as bm on b.badge_content_id = bm.badge_content_id and bm.deleted = 0
+GROUP BY b.badge_content_id;
+
+;;tarvitaan:
+;; badge_content_id, bc.name,bc.image_file, ic_name
+
+select
+
+select distinct  bc.name, ic.name AS issuer_content_name, count(distinct b.id) as owners, MAX(b.ctime) AS ctime
+FROM badge_content as bc
+INNER JOIN badge as b on bc.id = b.badge_content_id AND  b.status = 'accepted' AND b.deleted = 0 AND b.revoked = 0
+INNER JOIN issuer_content AS ic ON b.issuer_content_id = ic.id
+group by bc.id
+ORDER BY owners desc
+
+
+
+(defn get-stuff [ctx]
+  )


indent OCD

indent OCD

--- src/clj/shadow/cljs/build.clj
+++ src/clj/shadow/cljs/build.clj
@@ -98,25 +98,25 @@

 (defn usable-resource? [{:keys [type provides requires] :as rc}]
   (or (= :cljs type) ;; cljs is always usable
-    (seq provides) ;; provides something is useful
-    (seq requires) ;; requires something is less useful?
-    (= "goog/base.js" (:name rc)) ;; doesnt provide/require anything but is useful
-    ))
+      (seq provides) ;; provides something is useful
+      (seq requires) ;; requires something is less useful?
+      (= "goog/base.js" (:name rc)) ;; doesnt provide/require anything but is useful
+      ))

 (defn is-jar? [^String name]
   (.endsWith (str/lower-case name) ".jar"))

 (defn is-cljs-file? [^String name]
   (or (.endsWith (str/lower-case name) ".cljs")
-    (.endsWith (str/lower-case name) ".cljc")))
+      (.endsWith (str/lower-case name) ".cljc")))

 (defn is-js-file? [^String name]
   (.endsWith (str/lower-case name) ".js"))

 (defn is-cljs-resource? [^String name]
   (or (is-cljs-file? name)
-    (is-js-file? name)
-    ))
+      (is-js-file? name)
+      ))

 (defn cljs->js-name [name]
   (str/replace name #"\.cljs$" ".js"))
@@ -289,7 +289,7 @@
         (let [^JarEntry jar-entry (.nextElement entries)
               name (.getName jar-entry)]
           (if (or (not (is-cljs-resource? name))
-                (should-ignore-resource? state name))
+                  (should-ignore-resource? state name))
             (recur result)
             (let [url (URL. (str "jar:file:" abs-path "!/" name))
                   rc (inspect-resource state
@@ -374,7 +374,7 @@
         mfile (io/file manifest-cache-dir manifest-name)
         jar-file (io/file path)
         manifest (if (and (.exists mfile)
-                       (>= (.lastModified mfile) (.lastModified jar-file)))
+                          (>= (.lastModified mfile) (.lastModified jar-file)))
                    (read-jar-manifest mfile)
                    (let [manifest (create-jar-manifest state path)]
                      (io/make-parents mfile)
@@ -403,7 +403,7 @@
     (for [file (file-seq root)
           :let [abs-path (.getAbsolutePath file)]
           :when (and (is-cljs-resource? abs-path)
-                  (not (.isHidden file)))
+                     (not (.isHidden file)))
           :let [
                 name (-> abs-path
                          (.substring root-len)
@@ -673,18 +673,18 @@
         cache-js (io/file cache-dir "src" js-name)]

     (when (and (.exists cache-file)
-            (> (.lastModified cache-file) last-modified)
-            (.exists cache-js)
-            (> (.lastModified cache-js) last-modified)
-
-            (let [min-age (->> (get-deps-for-ns state ns)
-                               (map #(get-in state [:sources % :last-modified]))
-                               #_(map (fn [{:keys [name last-modified] :as src}]
-                                        (prn [:last-mod name last-modified])
-                                        last-modified))
-                               (remove nil?) ;; might not have :last-modified (eg. runtime-setup)
-                               (reduce (fn [a b] (Math/max a b))))]
-              (> (.lastModified cache-file) min-age)))
+               (> (.lastModified cache-file) last-modified)
+               (.exists cache-js)
+               (> (.lastModified cache-js) last-modified)
+
+               (let [min-age (->> (get-deps-for-ns state ns)
+                                  (map #(get-in state [:sources % :last-modified]))
+                                  #_(map (fn [{:keys [name last-modified] :as src}]
+                                           (prn [:last-mod name last-modified])
+                                           last-modified))
+                                  (remove nil?) ;; might not have :last-modified (eg. runtime-setup)
+                                  (reduce (fn [a b] (Math/max a b))))]
+                 (> (.lastModified cache-file) min-age)))

       (let [cache-data (read-cache cache-file)]

@@ -728,17 +728,17 @@
    make sure you are in with-compiler-env"
   [{:keys [cache-dir cache-level] :as state} {:keys [jar] :as src}]
   (let [cache? (and cache-dir
-                 ;; i don't trust the register-constant! stuff for now
-                 (not (:emit-constants state))
-                 (or (= cache-level :all)
-                   (and (= cache-level :jars)
-                     jar)))]
+                    ;; i don't trust the register-constant! stuff for now
+                    (not (:emit-constants state))
+                    (or (= cache-level :all)
+                        (and (= cache-level :jars)
+                             jar)))]
     (or (when cache?
           (load-cached-cljs-resource state src))
-      (let [src (do-compile-cljs-resource state src)]
-        (when cache?
-          (write-cached-cljs-resource state src))
-        src))))
+        (let [src (do-compile-cljs-resource state src)]
+          (when cache?
+            (write-cached-cljs-resource state src))
+          src))))

 (defn merge-provides [state provided-by provides]
   (reduce
@@ -764,10 +764,10 @@

 (defn valid-resource? [{:keys [type input name provides requires] :as src}]
   (and (contains? #{:js :cljs} type)
-    (instance? clojure.lang.IDeref input)
-    (string? name)
-    (set? provides)
-    (set? requires)))
+       (instance? clojure.lang.IDeref input)
+       (string? name)
+       (set? provides)
+       (set? requires)))

 (defn is-cljc? [^String name]
   (.endsWith name ".cljc"))
@@ -831,7 +831,7 @@
      [(:logger state) (format "Find cljs resources in path: \"%s\"" path)]
      (let [file (io/file path)]
        (if (or (not (.exists file))
-             (not (.isDirectory file)))
+               (not (.isDirectory file)))
          (throw (ex-info (format "\"%s\" does not exist or is not a directory" path) {:path path}))
          (-> state
              (assoc-in [:source-paths path] (assoc opts
@@ -985,7 +985,7 @@
     [(:logger state) (format "Flushing to disk")]
     (doseq [{:keys [type name compiled] :as src} (vals sources)
             :when (and (= :cljs type)
-                    compiled)]
+                       compiled)]

       (let [{:keys [js-name output]} src
             target (io/file work-dir js-name)]
@@ -1445,10 +1445,10 @@

           ;; skip files we already have since source maps are kinda expensive to generate
           :when (or (not (.exists target))
-                  (nil? last-modified) ;; runtime-setup doesn't have last-modified
-                  (> (or (:compiled-at src) ;; js is not compiled but maybe modified
-                       last-modified)
-                    (.lastModified target)))]
+                    (nil? last-modified) ;; runtime-setup doesn't have last-modified
+                    (> (or (:compiled-at src) ;; js is not compiled but maybe modified
+                           last-modified)
+                      (.lastModified target)))]

     (io/make-parents target)


little refactoring in consumer.zk/messages

--- src/clj_kafka/consumer/zk.clj
+++ src/clj_kafka/consumer/zk.clj
@@ -36,9 +36,8 @@
 (defn messages
   "Creates a sequence of messages from the given topics."
   [consumer & topics]
-  (let [topic-and-streams (.createMessageStreams consumer (topic-map topics))
-        [queue-seq queue-put] (pipe)]
-    (doseq [[topic streams] topic-and-streams]
+  (let [[queue-seq queue-put] (pipe)]
+    (doseq [[topic streams] (.createMessageStreams consumer (topic-map topics))]
       (future (doseq [msg (iterator-seq (.iterator (first streams)))]
                 (queue-put (assoc (to-clojure msg) :topic topic)))))
     queue-seq))


Don't advance a turn when bumping into walls

--- src/cljc/robinson/update.cljc
+++ src/cljc/robinson/update.cljc
@@ -86,9 +86,18 @@
   (or (is-direction? keyin)
       (contains? #{:up-left :up-right :down-left :down-right} keyin)))

+;; Indicate that the player action advanced time (this will include getting hungrier/thirstier, updating visibility, monsters attacking, updating cells, etc.
 (defn inc-time
   [state]
-  (update-in state [:world :time] inc))
+  (assoc-in state [:world :inc-time] true))
+
+(defn inc-time?
+  [state]
+  (get-in state [:world :inc-time] false))
+
+(defn clear-inc-time
+  [state]
+  (rc/dissoc-in state [:world :inc-time]))

 (defn next-font
   [state]
@@ -383,7 +392,9 @@
     (log/info "not mounted-on-raft?" (not (rw/player-mounted-on-raft? state)))
     (cond
       (rp/player-paralyzed? state)
-        (rc/append-log "You can not move (paralyzed).")
+        (-> state
+          (rc/append-log "You can not move (paralyzed).")
+          inc-time)
       (and (not (rw/collide? state target-x target-y {:include-npcs? false}))
            (not (rw/player-mounted-on-raft? state)))
         (as-> state state
@@ -400,12 +411,14 @@
                     items (get cell :items)]
                 (if (seq items)
                   (rdesc/search state)
-                  state)))))
+                  state))))
+          (inc-time state))
       (= (get (rw/npc-at-xy state target-x target-y) :in-party?) true)
         (-> state
           (assoc-in [:world :player :pos :x] target-x)
           (assoc-in [:world :player :pos :y] target-y)
-          (pick-up-gold)
+          pick-up-gold
+          inc-time
           (rc/map-in [:world :npcs]
                      (fn [npc] (if (and (= (-> npc :pos :x) target-x)
                                         (= (-> npc :pos :y) target-y))
@@ -423,6 +436,7 @@
             state)
           (assoc-in state [:world :player :pos :x] target-x)
           (assoc-in state [:world :player :pos :y] target-y)
+          (inc-time state)
           ;; rafting = more hunger
           (update-in state [:world :player :hunger] (partial + 0.05 ))
           ;;
@@ -433,11 +447,12 @@
               state)))
       ;; Hack down destroyable cells.
       (rw/type->destroyable? (get target-cell :type))
-        (destroy-cell state target-x target-y)
+        (-> state
+          (destroy-cell target-x target-y)
+          inc-time)
       ;; collided with a wall or door, nothing to be done.
       :else
         state)))
-

 (defn move-left
   "moves the player one space to the left provided he/she is able."
@@ -694,6 +709,7 @@
         (rp/update-inventory-item :flashlight (fn [item] (assoc item :state :off)))
         (rc/append-log "You turn the flashlight off.")
         (inc-time)
+        ;TODO: remove?
         (update-visibility)
         (assoc-in [:world :current-state] :normal))
       :off
@@ -702,9 +718,11 @@
           (rp/update-inventory-item :flashlight (fn [item] (assoc item :state :on)))
           (rc/append-log "You turn the flashlight on.")
           (inc-time)
+          ;TODO: remove?
           (update-visibility)
           (assoc-in [:world :current-state] :normal))
         (-> state
+          ;TODO: remove?
           (inc-time)
           (rc/append-log state "You try turning the flashlight on, but nothing happens."))))))

@@ -2912,14 +2930,14 @@
                            \c          [identity               :close           false]
                            \.          [do-rest                :normal          true]
                            :numpad5    [do-rest                :normal          true]
-                           :left       [move-left              :normal          true]
-                           :down       [move-down              :normal          true]
-                           :up         [move-up                :normal          true]
-                           :right      [move-right             :normal          true]
-                           :up-left    [move-up-left           :normal          true]
-                           :up-right   [move-up-right          :normal          true]
-                           :down-left  [move-down-left         :normal          true]
-                           :down-right [move-down-right        :normal          true]
+                           :left       [move-left              :normal          false]
+                           :down       [move-down              :normal          false]
+                           :up         [move-up                :normal          false]
+                           :right      [move-right             :normal          false]
+                           :up-left    [move-up-left           :normal          false]
+                           :up-right   [move-up-right          :normal          false]
+                           :down-left  [move-down-left         :normal          false]
+                           :down-right [move-down-right        :normal          false]
                            :space      [action-select          :action-select   false]
                            \q          [quaff-select           identity         false]
                            \w          [identity               :wield           false]
@@ -3256,6 +3274,15 @@
     ;(log/debug "current-state" current-state)
     (if (or (contains? table keyin) (contains? table :else))
       (let [[transition-fn new-state advance-time] (if (contains? table keyin) (get table keyin) (get table :else))
+            ;; some states conditionally advance time by calling (advance-time state)
+            ;; check to see if this has occurred if advance-time was not set in the state transition entry
+            advance-time (if-not advance-time
+                           (inc-time? state)
+                           advance-time)
+            ;; clear inc-time flag if set
+            state        (if (inc-time? state)
+                           (clear-inc-time state)
+                           state)
             ;; if the table contains keyin, then pass through transition-fn assuming arity-1 [state]
             ;; else the transition-fn takes [state keyin]. Bind keying so that it becomes arity-1 [state]
             _ (log/debug "current-state" (get-in state [:world :current-state]))


refactor a bit game logic

refactor a bit game logic

--- src/cljs/tictactoe/logic.cljs
+++ src/cljs/tictactoe/logic.cljs
@@ -5,29 +5,30 @@
 ;; Constants

 (def board-size 3)
+
 (def coordinates
   (for [x (range board-size)
         y (range board-size)]
     [x y]))

-(def rows (partition 3 coordinates))
-(def cols (utils/transpose rows))
+(def empty-board
+  (into {}
+    (map (fn [c] [c :cell/empty]))
+    coordinates))
+
 (def diags
   [(filter #(= (first %) (second %)) coordinates)
    (filter #(= (dec board-size) (reduce + %)) coordinates)])
+
+(def rows (partition board-size coordinates))
+(def cols (utils/transpose rows))
 (def lines (concat rows cols diags))

 ;; Game logic

-(defn new-empty-board
-  []
-  (into {} (map (fn [c] [c :cell/empty])) coordinates))
-
-(defn new-game
-  "Instantiate a new game (empty board and reset player)"
-  []
-  [{:board (new-empty-board) :player :cell/cross}])
+(defn new-game []
+  [{:board empty-board :player :cell/cross}])

 (defn convert-cell
   "Convert the cell to the new player"
@@ -35,9 +36,7 @@
   (assoc board [x y] player))

 (defn next-player [current]
-  (case current
-    :cell/cross :cell/circle
-    :cell/circle :cell/cross))
+  (if (= :cell/cross current) :cell/circle :cell/cross))

 (defn winning-line?
   [board line]


Don't clear timers when changing screens

--- src/clojure/nightmod/game.clj
+++ src/clojure/nightmod/game.clj
@@ -15,10 +15,9 @@

     (set-game-screen! main-screen text-screen)"
   [& game-screens]
-  (on-gl ; clear existing timers and assets
-         (stop-timers!)
+  (on-gl ; clear existing assets
          (doseq [gs game-screens]
-           (-> gs :screen (swap! #(dissoc % :timers :renderer :layers))))
+           (-> gs :screen (swap! #(dissoc % :renderer :layers))))
          (asset-manager! manager/manager :clear)
          ; set the supplied screen(s) with the overlay screen added at the end
          (apply set-screen!


allow  hiccup syntax in DOMElement :content

--- src/com/kaicode/infamous.cljs
+++ src/com/kaicode/infamous.cljs
@@ -1,7 +1,9 @@
 (ns ^:figwheel-always com.kaicode.infamous
+  (:require-macros [hiccups.core :as hiccups :refer [html]])
   (:require [com.kaicode.Famous]
             [cljs.core.async :refer [put! chan]]
-            [datascript :as d]))
+            [datascript :as d]
+            [hiccups.runtime :as hiccupsrt]))

 (enable-console-print!)

@@ -112,7 +114,10 @@
                            :let [name (name (first a))
                                  value (second a)]]
                           (cond
-                            (= name "content") (.. component (setContent value))
+                            (= name "content") (let [content (if (vector? value)
+                                                               (html value)
+                                                               value)]
+                                                    (.. component (setContent content)))
                             (= name "id") (do (.. component (setId value)))
                             (= name "classes") (doseq [clz value]
                                                       (.. component (addClass clz)))


Update defsystem doc string

Update defsystem doc string

--- src/com/palletops/leaven.cljx
+++ src/com/palletops/leaven.cljx
@@ -28,8 +28,10 @@
 (defmacro defsystem
   "Macro to build a system defrecord out of `components`, a sequence
   of keywords that specify the sub-components.  The record will
-  implement ILifecycle and IStatus by calling the protocol methods
-  on each of the components."
+  implement ILifecycle and IStatus by calling the protocol methods on
+  each of the components.  The `start` method calls the sub-components
+  in the specified order.  The `stop` method calls the sub-components
+  in the reverse order."
   [record-name components]
   (letfn [(start-subcomp [k] `(update-in [~k] start))
           (stop-subcomp [k] `(update-in [~k] stop))


removing unused dependencies

removing unused dependencies

--- date_scanner/project.clj
+++ date_scanner/project.clj
@@ -17,8 +17,6 @@
                  [systems.casemgr.utils/utils "0.1.0-SNAPSHOT"]
                  [systems.casemgr.utils/channel-monitor "0.1.0-SNAPSHOT"]
                  [systems.casemgr.utils/pathdb "0.1.0-SNAPSHOT" :exclusions [org.clojure/clojure junit]]
-                 [systems.casemgr.casemgr/utils "0.1.0-SNAPSHOT"]
-                 [systems.casemgr.casemgr/state "0.1.0-SNAPSHOT"]
                  ]

   :plugins [[lein-figwheel "0.5.8"]


add inspect state helper

add inspect state helper

--- src-cljs/frontend/core.cljs
+++ src-cljs/frontend/core.cljs
@@ -337,6 +337,9 @@
     (when (and (env/development?) (= js/window.location.protocol "http:"))
       (swallow-errors (setup-browser-repl)))))

+(defn ^:export inspect-state []
+  (js/console.log (clj->js @debug-state)))
+
 #_(defn reinstall-om! []
   (install-om debug-state (find-app-container (find-top-level-node)) (:comms @debug-state)))


Reformat

Reformat

--- src/icecap/rest.clj
+++ src/icecap/rest.clj
@@ -30,11 +30,11 @@
            :body {:error error}})))
     (context "/:encoded-cap" [encoded-cap]
       (GET "/" request
-           (let [cap (safebase64-decode encoded-cap)]
-             (spy (<!! (execute-cap cap components)))))
+        (let [cap (safebase64-decode encoded-cap)]
+          (spy (<!! (execute-cap cap components)))))
       (DELETE "/" request
-              (let [cap (safebase64-decode encoded-cap)]
-                (spy (<!! (revoke-cap cap components))))))))
+        (let [cap (safebase64-decode encoded-cap)]
+          (spy (<!! (revoke-cap cap components))))))))

 (defn ^:private wrap-components
   "Adds some components to each request map."


Use genereated-assets-root stefon option to implement uri-root.

--- src/incise/once.clj
+++ src/incise/once.clj
@@ -13,16 +13,16 @@
   [& {:as config}]
   (conf/merge config)
   (conf/avow!)
-  (let [{:keys [out-dir uri-root precompiles]} (conf/get)
-        stefon-pre-opts {:mode :production
-                         :serving-root out-dir
-                         :uri-root uri-root
-                         :precompiles precompiles}]
+  (let [{:keys [out-dir uri-root precompiles]} (conf/get)]
     (info "Clearing out" (str \" out-dir \"))
     (delete-recursively (file out-dir))
-    (with-options stefon-pre-opts
+    (with-options {:mode :production
+                   :serving-root out-dir
+                   :precompiles precompiles}
       (info "Precompiling assets...")
       (precompile)
       (info "Done.")
-      (load-parsers-and-layouts)
-      (doall (parse-all-input-files)))))
+      (with-options (when uri-root
+                      {:generated-assets-root (str \/ uri-root "/assets/")})
+        (load-parsers-and-layouts)
+        (doall (parse-all-input-files))))))


Removing clojure.contrib.seq-utils dependency.

--- src/clojush.clj
+++ src/clojush.clj
@@ -22,7 +22,6 @@
   (:require
     [clojure.zip :as zip]
     [clojure.contrib.math :as math]
-    [clojure.contrib.seq-utils :as seq-utils]
     [clojure.walk :as walk]
     [clojure.string :as string]
     [local-file]))
@@ -1364,10 +1363,18 @@
         (pop-item :code (pop-item :code state)))
       state)))

+;; clojure.contrib/positions disappeared from libraries, but this is the function
+;;   with the old indexed function expanded.
+(defn positions
+  "Returns a lazy sequence containing the positions at which pred
+is true for items in coll."
+  [pred coll]
+  (for [[idx elt] (map vector (iterate inc 0) coll) :when (pred elt)] idx))
+
 (define-registered code_position
   (fn [state]
     (if (not (empty? (rest (:code state))))
-      (push-item (or (first (seq-utils/positions #{(stack-ref :code 1 state)}
+      (push-item (or (first (positions #{(stack-ref :code 1 state)}
                               (ensure-list (stack-ref :code 0 state))))
                    -1)
         :integer


Fixed bugs in string_concat.

Fixed bugs in string_concat.

--- src/clojush.clj
+++ src/clojush.clj
@@ -997,8 +997,8 @@
   string_concat
   (fn [state]
     (if (not (empty? (rest (:string state))))
-      (if (>= max-string-length (+ (len (stack-ref :string 1 state))
-                                   (stack-ref :string 0 state)))
+      (if (>= max-string-length (+ (count (stack-ref :string 1 state))
+                                   (count (stack-ref :string 0 state))))
         (push-item (str (stack-ref :string 1 state)
                         (stack-ref :string 0 state))
                    :string


Add post-process-blocks fn

Add post-process-blocks fn

--- src/luaclj/core.clj
+++ src/luaclj/core.clj
@@ -7,8 +7,12 @@
             [luaclj.library :refer :all]
             [com.rpl.specter :refer [select
                                      ALL
+                                     LAST
+                                     STAY
                                      select-first
                                      pred
+                                     if-path
+                                     cond-path
                                      subselect
                                      transform
                                      walker]]
@@ -50,9 +54,8 @@
   )
 (defmacro or= [arg values]
   `(or ~@(map #(= arg %1) values)))
-
-(defn chunk-fn [& args]
-  (println "chunk-fn:" args)
+(defn post-process-blocks [& args]
+  (println "post-process-blocks" args)
   (let [set-var-pred #(= 'set! (safe-some-> %1 first))
         all-vars (set (map second
                            (select (walker set-var-pred) args)))
@@ -92,9 +95,32 @@
                                     global-var-init-statements))
         let-statements (into init-statements let-statements)
         expr `(let-mutable ~let-statements ~return-value)]
-    (println "chunk-fn2:" global-var-init-statements)
+    (println "post-process-blocks out:" let-statements)
+    ;(println "chunk-fn3:" global-var-init-statements)
     expr
     ))
+
+(comment
+
+  (select
+    [ALL
+     (if-path (pred #(= (safe-some-> %1 first) 'clojure.core/fn))
+             LAST
+             STAY)]
+
+    `((clojure.core/fn :a :b)
+      (let-mutable [:a :b])))
+  )
+(defn chunk-fn [& args]
+  (println "chunk-fn:" args)
+  (let [r (transform [ALL
+                (if-path (pred #(= (safe-some-> %1 first) 'clojure.core/fn))
+                         LAST
+                         STAY) ]
+               #(post-process-blocks %1)
+               args)]
+    (println "chunk-fn result:" r)
+    (first (transform [ALL] #(apply list %1) r))))

 (defn block-fn [& args]
   (println "block-fn args:" args)
@@ -394,8 +420,65 @@
         "return"
         [:explist [:exp [:prefixexp [:var [:Name "e"]]]]]]]
       "end"]]]]
+
+((proteus/let-mutable
+  [G__16357
+   nil
+   G__16358
+   false
+   t
+   nil
+   t1
+   nil
+   sum
+   nil
+   key
+   nil
+   t2
+   nil
+   _
+   (do
+    (clojure.core/when (clojure.core/not G__16358) (do (set! sum 0)))
+    (clojure.core/when
+     (clojure.core/not G__16358)
+     (clojure.core/doseq
+      [j (clojure.core/range 1 100)]
+      (clojure.core/when
+       (clojure.core/not G__16358)
+       (do (set! sum (+ sum j))))))
+    (clojure.core/when
+     (clojure.core/not G__16358)
+     (do (set! t {1 1, 2 10, 3 30})))
+    (clojure.core/when
+     (clojure.core/not G__16358)
+     (do (set! t (clojure.core/assoc t "a" 9))))
+    (clojure.core/when (clojure.core/not G__16358) (do (set! key 22)))
+    (clojure.core/when
+     (clojure.core/not G__16358)
+     (do (set! t1 {"a" 2, "b" 3, "c" 4})))
+    (clojure.core/when
+     (clojure.core/not G__16358)
+     (do (set! t2 {key 10, "a" 20, "b" 30, "c" 40})))
+    (clojure.core/when
+     (clojure.core/not G__16358)
+     (do (set! t2 (clojure.core/assoc t2 "a" 30))))
+    (clojure.core/when
+     (clojure.core/not G__16358)
+     (clojure.core/doseq
+      [[i v] (ipairs t2)]
+      (clojure.core/when
+       (clojure.core/not G__16358)
+       (do (set! sum (+ sum v))))))
+    (clojure.core/when
+     (clojure.core/not G__16358)
+     (do (set! G__16358 true) (set! G__16357 sum))))]
+  G__16357))
+
+
 (pprint (lua-parser (slurp "resources/test/function.lua")))
-(pprint (lua-parser (slurp "resources/test/for.lua")))
+(eval (insta/transform transform-map (lua-parser (slurp "resources/test/basic.lua"))))
+(eval (insta/transform transform-map (lua-parser (slurp "resources/test/basic1.lua"))))
+(eval (insta/transform transform-map (lua-parser (slurp "resources/test/for.lua"))))
 (eval (insta/transform transform-map (lua-parser (slurp "resources/test/function.lua"))))
   (try (pprint (insta/transform transform-map (lua-parser (slurp "resources/test/function.lua"))))
        (catch Exception ex (clojure.stacktrace/print-stack-trace ex)))


adjust REPL in-ns behavior to match CLJS default

fixes #398

--- src/main/shadow/cljs/repl.clj
+++ src/main/shadow/cljs/repl.clj
@@ -352,9 +352,8 @@
   ;; form is (in-ns (quote the-ns))
   (let [[q ns] quoted-ns]
     (if (nil? (get-in state [:sym->id ns]))
-      ;; FIXME: create empty ns and switch to it
-      (do (prn [:did-not-find ns])
-          state)
+      ;; if (in-ns 'foo.bar) does not exist we just do (ns foo.bar) instead
+      (repl-ns state read-result (list 'ns ns))
       (let [{:keys [resource-name] :as rc}
             (data/get-source-by-provide state ns)


adding a offset commit to zookeer

adding a offset commit to zookeer

--- qanal/src/qanal/kafka.clj
+++ qanal/src/qanal/kafka.clj
@@ -358,11 +358,11 @@
     topics-conf)))

 (defn refresh-fetching-specs [{:keys [topics zk metadata] :as state}]
-  (update-in state [:fetching] merge (fetching-specs topics zk metadata)))
+  (update-in state [:fetching] (partial merge (fetching-specs topics zk metadata))))

 ;; TODO: REVIEW DOC-STRING
-(defn- consumer-offsets
+(defn- consumer-offsets!
   "Returns the stored consumer offset in zookeeper for the provided group-id.
    This offset is stored in the zookeeper location
            /consumers/<group-id>/offsets/<topic>/<partition-id>
@@ -382,7 +382,41 @@

 (defn refresh-consumer-offsets [{:keys [zk] :as state}]
-  (update-in state [:fetching] #(consumer-offsets zk %)))
+  (update-in state [:fetching] #(consumer-offsets! zk %)))
+
+
+(defn refresh-all-topics-metadata
+  "It refreshes all metadata, keeps track when last update was made"
+  [kafka-state]
+  (-> kafka-state
+      refresh-partitions
+      refresh-brokers
+      refresh-fetching-specs
+      refresh-consumer-offsets
+      (assoc-in [:last-update] (java.util.Date.))))
+
+
+(defn commit-offsets!
+  "it commits the consumed offsets to zookeeper and update the state"
+  [state-atom]
+  (let [{:keys [zk fetching] :as state} @state-atom
+
+        committed
+        (into {}
+              (for [[k {:keys [group-id topic partition consumer-offset committed-offset] :as v}] fetching]
+                [k
+                 (if (> consumer-offset (or committed-offset -1))
+                   (do
+                     ;; TODO: this should accept a list of topics/partions/offsets
+                     ;; TODO: what if this fails?
+                     (set-offset! zk group-id topic partition consumer-offset)
+                     (assoc v :committed-offset consumer-offset))
+                   v)]))
+        new-state (assoc state :fetching committed)]
+    ;; if it doesn't happen not a big deal, the real values are
+    ;; committed to zk, and they will be updated again
+    ;; at the next round
+    (compare-and-set! state-atom state new-state)))

 (defmacro forever-do [name sleep & body]
@@ -408,14 +442,8 @@
            (Thread/sleep _sleep#))))))

-(defn refresh-all-topics-metadata! [kafka-state]
-  (swap! kafka-state
-         #(-> %
-              refresh-partitions
-              refresh-brokers
-              refresh-fetching-specs
-              refresh-consumer-offsets
-              (assoc-in [:last-update] (java.util.Date.)))))
+(defn refresh-state! [kafka-state]
+  (swap! kafka-state refresh-all-topics-metadata))

 (defn- start-metadate-update-thread []
   (forever-do "updating kafka metadata" 5000
@@ -423,6 +451,7 @@

+
 (comment

   (set-zk-connection! kafka-state {"zookeeper.connect" "docker:49153" :group-id "some-consumer-id" :fetch-size 1024000})
@@ -434,4 +463,6 @@

   kafka-state

+  (commit-offsets! kafka-state)
+
   )


filter by board uuid

filter by board uuid

--- src/oc/storage/api/boards.clj
+++ src/oc/storage/api/boards.clj
@@ -42,7 +42,10 @@
   ([conn org :guard map? board :guard #(or (:draft %) (= (:slug %) (:slug board-res/default-drafts-board))) ctx]
   (let [org-slug (:slug org)
         slug (:slug board)
-        entries (entry-res/list-entries-by-org-author conn (:uuid org) (-> ctx :user :user-id) :draft {})
+        all-drafts (entry-res/list-entries-by-org-author conn (:uuid org) (-> ctx :user :user-id) :draft {})
+        entries (if (:draft board)
+                  (filterv #(= (:board-uuid %) (:uuid board)) all-drafts)
+                  all-drafts)
         board-uuids (distinct (map :board-uuid entries))
         boards (filter map? (map #(board-res/get-board conn %) board-uuids))
         board-map (zipmap (map :uuid boards) boards)


some style

some style

--- frontend/components/build.cljs
+++ frontend/components/build.cljs
@@ -91,7 +91,8 @@
                        {:react-key (:index container)}))
           [:a.container-selector.add-containers
             {:role "button"
-             :href (build-model/path-for-parallelism build)}
+             :href (build-model/path-for-parallelism build)
+             :title "adjust parallelism"}
             [:span "+"]
             [:span "-"]]]])))))


Removed intern+keep-meta

Removed intern+keep-meta

We use `defalias` instead.

* src/midje/sweet.clj:

--- src/midje/sweet.clj
+++ src/midje/sweet.clj
@@ -40,16 +40,10 @@
        :dynamic true}
   *include-midje-checks* *include-midje-checks*)

-;; TODO: How is this different from defalias?
-(defn- intern+keep-meta [ns sym v]
-  (intern ns sym v)
-  (let [newguy (get (ns-interns ns) sym)]
-    (alter-meta! newguy merge (meta v))))
-
-(intern+keep-meta *ns* 'before  #'background/before)
-(intern+keep-meta *ns* 'after   #'background/after)
-(intern+keep-meta *ns* 'around  #'background/around)
-(intern+keep-meta *ns* 'formula #'parse-formulas/formula)
+(defalias before  background/before)
+(defalias after   background/after)
+(defalias around  background/around)
+(defalias formula parse-formulas/formula)

 (when (doc/appropriate?)
   (immigrate-from 'midje.doc doc/for-sweet)


use bind >>= to fix real world problem

use bind >>= to fix real world problem

--- src/monad/monad.clj
+++ src/monad/monad.clj
@@ -26,7 +26,7 @@
   (assoc order :total (- (:total order) discount)))

 (defn place [order]
-  (prn (str "total price: $" (:total order))))
+  (str "total price: $" (:total order)))

 (defn place-order
   [order]
@@ -55,21 +55,108 @@
 (comment
   (place-order another-order) "CompilerException java.lang.NullPointerException")

-(defn apply-shipping-costs [order shipping-rate]
-  (if shipping-rate
-    (assoc order :total (+ (:total order) shipping-rate))
-    order))
-
-(defn apply-discount-code [order discount]
-  (if discount
-    (assoc order :total (- (:total order) discount))
-    order))
-
 ;;如果要避免空指针导致整个系统崩溃 只能是用无休止的判断来避免
 ;;而且照理来说要把货物运往巴西由于没有标明运费是无法上架的 但是现在的系统并没有对这一点进行相应的处理
 ;;虽然有方法可以让这个系统更加健壮正确 但是那就需要更多无谓的if判断来做到
-(place-order another-order)
+
+(comment
+  (defn apply-shipping-costs [order shipping-rate]
+    (if shipping-rate
+      (assoc order :total (+ (:total order) shipping-rate))
+      order))
+
+  (defn apply-discount-code [order discount]
+    (if discount
+      (assoc order :total (- (:total order) discount))
+      order))
+
+  (place-order another-order))

 ;;now use monad to fix it

 ;;use algo.monads
+;;看algo.monads源码可以看到maybe-m是内建的maybe monad 这个monad表示一个可能计算失败的上下文
+
+(defn place-order-use-monad [order]
+  (domonad maybe-m
+    [order order
+     shipping-rate (calculate-shipping-rate (:address order))
+     discount (lookup-discount-code (:discount-code order))]
+    (-> order
+        (apply-shipping-costs shipping-rate)
+        (apply-discount-code discount)
+        (place))))
+
+;;使用了maybe monad之后我们就可以大胆放心的使用空指针了 因为我们不需要担心空指针会使我们的系统在运行的某一步中出错导致崩溃 因为只要某一步出现了nil 那么maybe monad会让这个nil保存在上下文中 知道返回出去为止
+;;不需要用大量的if去判断nil的情况 因为只要一个地方出现了nil 那么整个系统返回的就是一个nil 并且不会崩溃 只要判断返回值即可
+;;就像haskell中的maybe monad 如果一个地方出现了Nothing 那么之后所有操作返回的都是Nothing 但是并不会导致系统崩溃 最终用guard或者pattern match来处理最终的结果值是Nothing还是(Just a)即可
+;;domonad这个宏就是haskell中的do notation用来避免monad的嵌套
+(place-order-use-monad order)
+(place-order-use-monad another-order)
+
+;;implement a simple maybe monad
+
+(def maybe-monad
+  {:return (fn [v] v)
+   :bind   (fn [mv f]
+             (if mv
+               (f mv)
+               nil))})
+
+(-> another-order
+    ((:bind maybe-monad)
+      (fn [order]
+        (-> (calculate-shipping-rate (:address order))
+            ((:bind maybe-monad)
+              (fn [shipping-rate]
+                (-> (lookup-discount-code (:discount-code order))
+                    ((:bind maybe-monad)
+                      (fn [discount]
+                        ((:return maybe-monad)
+                          (-> order
+                              (apply-shipping-costs shipping-rate)
+                              (apply-discount-code discount)
+                              (place))))))))))))
+
+;;可以看到加入有一个值是nil 那么整个表达式就直接返回nil了不会再继续执行嵌入的fn了
+
+;;implement it more like haskell
+
+(defprotocol Monad
+  (return [context value] "return :: a -> ma")
+  (>>= [m f] ">>= :: m a -> (a -> m b) -> m b")
+  (>> [ma mb] ">> :: m a -> m b -> m b just ignore the first value"))
+
+(defrecord Maybe [value]
+  Monad
+  (return [context v] (->Maybe v))
+  (>>= [m f]
+    (let [v (:value m)]
+      (if v (f v) m)))
+  (>> [ma mb]
+    (>>= ma (fn [_] mb))))
+
+(:value (return (->Maybe nil) false))
+
+(:value (>>= (->Maybe 9) (fn [x] (return (->Maybe nil) (* x 10)))))
+(:value (>>= (->Maybe nil) (fn [x] (return (->Maybe nil) (* x 10)))))
+
+;;使用bind操作符 也就是使用monad就可以消除一大堆的if操作 但是如果不用do notation 一大堆的bind嵌套也蛮乱的 但是相对于一坨一坨的if nil? 要美观不少
+;;monad就是将上下午的操作放入内部 外部代码可以简洁 一致 比如maybe monad就是把处理计算失败出现空指针这个上下文放入到了bind函数内部来处理 而不是把这些细节暴露到外部
+
+(defn place-order-use-bind
+  [order]
+  (:value (>>= (->Maybe order)
+               (fn [order]
+                 (>>= (->Maybe (calculate-shipping-rate (:address order)))
+                      (fn [shipping-rate]
+                        (>>= (->Maybe (lookup-discount-code (:discount-code order)))
+                             (fn [discount]
+                               (return (->Maybe nil)
+                                       (-> order
+                                           (apply-shipping-costs shipping-rate)
+                                           (apply-discount-code discount)
+                                           (place)))))))))))
+
+(place-order-use-bind order)
+(place-order-use-bind another-order)


improve field and method auto-reflection

Java classes may have static members with the same name as instance ones

--- src/insn/op.clj
+++ src/insn/op.clj
@@ -5,7 +5,7 @@
   (e.g., IF_ICMPEQ) use a dash instead (e.g., if-icmpeq)."
   (:refer-clojure :exclude [compile pop])
   (:require [insn.util :as util])
-  (:import [java.lang.reflect Method]))
+  (:import [java.lang.reflect Field Method Modifier]))

 (defmulti ^:private -op
   "Return an op data map representing a op visitor fn to be called
@@ -72,11 +72,19 @@
   If the type is not provided, it will be determined through reflection.
   In this case, the class must be given as a string or Class object."
   ([v cls fname]
-   (let [cls (if (class? cls)
+   (let [fname (name fname)
+         cls (if (class? cls)
                cls
                (Class/forName cls))
-         f (.getField ^Class cls (name fname))]
-     (&fn v cls fname (.getType f))))
+         static? (not (#{Opcodes/GETFIELD Opcodes/PUTFIELD} &op))
+         types (for [^Field f (.getFields ^Class cls)
+                     :when (and (= fname (.getName f))
+                                (= static?
+                                   (Modifier/isStatic (.getModifiers f))))]
+                 (.getType f))]
+     (if (== 1 (count types))
+       (&fn v cls fname (first types))
+       (throw (ex-info (str "no field found with name '" fname "'") {})))))
   ([v cls fname ftype]
    (.visitFieldInsn v &op (util/class-desc cls)
                     (name fname) (util/type-desc ftype))))
@@ -162,8 +170,11 @@
                             cls
                             (Class/forName cls))
                       arity (long desc-or-arity)
+                      static? (= Opcodes/INVOKESTATIC &op)
                       descs (for [^Method m (.getMethods ^Class cls)
-                                  :when (= mname (.getName m))
+                                  :when (and (= mname (.getName m))
+                                             (= static?
+                                                (Modifier/isStatic (.getModifiers m))))
                                   :let [desc (.getParameterTypes m)]
                                   :when (or (neg? arity)
                                             (== arity (count desc)))]


[fix] Interface bug.

[fix] Interface bug.

--- src/ombs/db/old.clj
+++ src/ombs/db/old.clj
@@ -139,10 +139,9 @@
               (sql/where (not= :status (statuses :finished)))))

 (defn get-event
-  ([ename date] get-event (get-eid ename date))
-  ([eid] (first (sql/select events (sql/where {:id eid}))))
+  ([ename date] (get-event (get-eid ename date)))
+  ([eid] (sql/select events (sql/where {:id eid})))
   )
-

 (defn get-price
   ([ename date]


Rethink the way I throw out the ns form

Rethink the way I throw out the ns form

--- src/oxcart/core.clj
+++ src/oxcart/core.clj
@@ -108,7 +108,12 @@
                           [e & exprs] (rest mform)]
                      (if-not (seq exprs)
                        [statements e]
-                       (recur (conj statements e) exprs)))]
+                       (recur (conj statements e) exprs)))
+
+                   ;; If we are in the do of an (ns), discard all forms.
+                   options (if (#{'clojure.core/ns 'ns} (first form))
+                             (dissoc options :forms)
+                             options)]

                (doseq [expr statements]
                  (eval expr options))
@@ -124,7 +129,10 @@
              true
              ;; Bare expression handling
              ;; ----------------------------
-             (do ;; Run the code for side-effects
+             (do ;; Run the code for side-effects.
+
+                 (println (first form))
+
                  (let [res (when (and eval?
                                       (not (= 'clojure.core (.name *ns*))))
                              (em.jvm/eval mform))]
@@ -132,11 +140,22 @@
                    (let [ast (-> mform
                                  (util/ast))]

-                     ;; Add to the accumulator for the whole read program
-                     ;;
-                     ;; Builds a mapping of the form
+                     ;; Add to the accumulator for the whole read
+                     ;; program. Note that the following forms are
+                     ;; discarded:
+                     ;;
+                     ;; - clojure.core/require
+                     ;; - clojure.core/use
+                     ;; - clojure.core/refer
+                     ;; - clojure.core/import
                      (when (and forms
-                                (atom? forms))
+                                (atom? forms)
+                                (not (#{'clojure.core/require 'require
+                                        'clojure.core/use     'use
+                                        'clojure.core/refer   'refer
+                                        'clojure.core/import  'import
+                                        'clojure.core/import* 'import*}
+                                      (first form))))
                        (swap! forms
                               #(-> %1
                                    (update-in [(.name *ns*) :forms]
@@ -200,8 +219,7 @@
          (with-redefs [clojure.core/load   oxcart.core/load
                        clojure.core/eval   oxcart.core/eval
                        clojure.core/gensym oxcart.core/gensym]
-           (with-macro-redefs [#'clojure.core/ns              @#'oxcart.core-redefs/ns
-                               #'clojure.core/defmulti        @#'oxcart.core-redefs/defmulti
+           (with-macro-redefs [#'clojure.core/defmulti        @#'oxcart.core-redefs/defmulti
                                #'clojure.core/defmethod       @#'oxcart.core-redefs/defmethod
                                #'clojure.core/deftype         @#'oxcart.core-redefs/deftype
                                #'clojure.core/defprotocol     @#'oxcart.core-redefs/defprotocol
@@ -254,13 +272,18 @@
      {:pre [(seq? passes)
             (every? fn? passes)
             (fn? emitter)]}
-     (let [forms (atom [])
-           defs  (atom {})
+     (let [forms  (atom [])
+           defs   (atom {})
            config {:debug? false
                    :exec?  true
                    :forms forms}]
        ;; Loads and macroexpands all the code using the built config
        ;; to generate the forms and defs structures.
+       ;;
+       ;; By definition of a well formed Clojure program, loading the
+       ;; "root" resource must load all depended resources, otherwise
+       ;; there will be a symbol resolution error in the compiling
+       ;; Clojure runtime.
        (load res config)

        (let [settings (:passes settings)]
@@ -269,6 +292,8 @@

        ;; Having taken an O(Nᵏ) compile operation to the face we now
        ;; run the emitter and call it quits.
-       (let [settings (:emitter settings)]
+       (let [settings (:emitter settings)
+             settings (merge settings
+                             (select-keys settings [:entry]))]
          (emitter @forms settings)))
      nil))


clearer implementation

clearer implementation

--- src/cljs/org/broadinstitute/firecloud_ui/common/table.cljs
+++ src/cljs/org/broadinstitute/firecloud_ui/common/table.cljs
@@ -12,6 +12,9 @@

 (def ^:private initial-rows-per-page 10)
+
+(defn select-persistence-keys [atom]
+  (select-keys @atom [:column-meta :query-params :filter-group-index]))

 (defn date-column [props]
@@ -313,7 +316,7 @@
                   :no-data? (empty? clipped-rows))))))
    :component-did-mount
    (fn [{:keys [this state locals]}]
-     (swap! locals assoc :initial-state (select-keys @state [:column-meta :query-params :filter-group-index]))
+     (swap! locals assoc :initial-state (select-persistence-keys @state))
      (react/call :refresh-rows this)
      (set! (.-onMouseMoveHandler this)
            (fn [e]
@@ -341,7 +344,7 @@
        (react/call :refresh-rows this))
      (when (and (:state-key props)
                 (not (:dragging? @state))
-                (not (= (select-keys @state [:column-meta :query-params :filter-group-index]) (:initial-state @locals))))
+                (not (= (select-persistence-keys @state) (:initial-state @locals))))
        (persistence/save {:key (:state-key props) :state state :only [:column-meta :query-params :filter-group-index]})))
    :component-will-unmount
    (fn [{:keys [this]}]


Key code constant

Key code constant

--- src/todomvc_reagent/core.cljs
+++ src/todomvc_reagent/core.cljs
@@ -1,6 +1,12 @@
 (ns todomvc-reagent.core
   (:require [reagent.core :as r]
             [clojure.string :as s]))
+
+;; -------------------------
+;; Constants
+
+(def KEY_ENTER 13)
+(def KEY_ESCAPE 27)

 ;; -------------------------
 ;; Db
@@ -62,10 +68,16 @@
         :placeholder placeholder
         :on-blur save
         :on-change #(reset! val (-> % .-target .-value))
-        :on-key-down #(case (.-which %)
-                        13 (save)
-                        27 (stop)
-                        nil)}])))
+        :on-key-down #(cond
+                        (= (.-which %) KEY_ENTER) (save)
+                        (= (.-which %) KEY_ESCAPE) (stop)
+                        :else nil)}])))
+
+(defn todo-header [title placeholder]
+  [:header.header
+   [:h1 title]
+   [todo-input {:class "new-todo" :placeholder placeholder
+                :on-save add-todo}]])

 (defn todo-item []
   (let [editing (r/atom false)]
@@ -115,10 +127,7 @@
            active-cnt (- (count items) completed-cnt)]
       [:div
        [:section.todoapp
-        [:header.header
-         [:h1 "reagent"]
-         [todo-input {:class "new-todo" :placeholder "What needs to be done?"
-                      :on-save add-todo}]]
+        [todo-header "reagent" "What needs to be done?"]

         (when (pos? (count items))
           [:div


Add header

Add header

--- src/todomvc_reagent/core.cljs
+++ src/todomvc_reagent/core.cljs
@@ -1,17 +1,23 @@
 (ns todomvc-reagent.core
-    (:require [reagent.core :as reagent]))
+    (:require [reagent.core :as r]))
+
+(def todos
+  (r/atom [{:value "Create a TodoMVC template"} {:value "Rule the web"}]))

 ;; -------------------------
 ;; Views
+
+(defn todo-header [title placeholder]
+  [:header.header
+   [:h1 title]
+   [:input.new-todo
+    {:autofocus true, :placeholder placeholder}]])

 (defn home-page []
   (fn []
     [:div
      [:section.todoapp
-      [:header.header
-       [:h1 "todos"]
-       [:input.new-todo
-        {:autofocus true, :placeholder "What needs to be done?"}]]
+      [todo-header "reagent" "What needs to be done?"]

       [:section.main
        [:input.toggle-all {:type "checkbox"}]
@@ -58,7 +64,7 @@
 ;; Initialize app

 (defn mount-root []
-  (reagent/render [home-page] (.getElementById js/document "app")))
+  (r/render [home-page] (.getElementById js/document "app")))

 (defn init! []
   (mount-root))


got a good verbcoach-index-fn for filtering out accusative pronouns

--- src/babel/italiano/lab.cljc
+++ src/babel/italiano/lab.cljc
@@ -1,7 +1,8 @@
 (ns babel.italiano.lab
   (:require
    [babel.directory] ;; this is needed even though there are no references to directory in here.
-   [babel.generate :as g :refer [frontier generate get-lexemes]]
+   [babel.generate :as g :refer [frontier generate]]
+   [babel.index :refer [create-indices lookup-spec]]
    [babel.italiano :as italiano :refer [model morph morph-ps parse]]
    #?(:cljs [babel.logjs :as log])
    #?(:clj [clojure.tools.logging :as log])
@@ -285,27 +286,58 @@
                 (time (generate spec model))))))))

+
+(def verbcoach-grammar
+  #{
+    "s-aux"
+    "s-conditional-nonphrasal"
+    "s-conditional-phrasal"
+    "s-future-nonphrasal"
+    "s-future-phrasal"
+    "s-imperfetto-nonphrasal"
+    "s-imperfetto-phrasal"
+    "s-present-nonphrasal"
+    "s-present-phrasal"
+    "vp-aux-22-nonphrasal-comp"
+    "vp-aux-phrasal-complement"
+    "vp-aux-nonphrasal-complement"
+    "vp-32"
+    "vp-pronoun-nonphrasal"
+    "vp-pronoun-phrasal"
+    })
+
+(def verbcoach-index-fn
+  (let [index-lexicon-on-paths
+        [[:italiano :italiano]
+         [:synsem :aux]
+         [:synsem :cat]
+         [:synsem :essere]
+         [:synsem :infl]
+         [:synsem :sem :pred]]]
+
+    (fn [spec]
+      (let [lexicon
+            (into {}
+                  (for [[k vals] (:lexicon model)]
+                    (let [filtered-vals
+                          (filter (fn [v]
+                                    (or (not (= :noun (u/get-in v [:synsem :cat])))
+                                        (and (= :noun (u/get-in v [:synsem :cat]))
+                                             (not (= :acc (u/get-in v [:synsem :case]))))
+                                        (and (= :noun (u/get-in v [:synsem :cat]))
+                                             (= :acc (u/get-in v [:synsem :case]))
+                                             (= true (u/get-in v [:synsem :reflexive])))))
+                                  vals)]
+                      (if (not (empty? filtered-vals))
+                        [k filtered-vals]))))]
+        (lookup-spec spec (create-indices lexicon index-lexicon-on-paths) index-lexicon-on-paths)))))
+
 (defn arrabbiarsi
   "generate arrabiarsi sentences with a grammar subset."
   []
   (let [grammar
         (filter
-         #(contains?
-           #{"s-aux"
-             "s-conditional-nonphrasal"
-             "s-conditional-phrasal"
-             "s-future-nonphrasal"
-             "s-future-phrasal"
-             "s-imperfetto-nonphrasal"
-             "s-imperfetto-phrasal"
-             "s-present-nonphrasal"
-             "s-present-phrasal"
-             "vp-aux-22-nonphrasal-comp"
-             "vp-aux-phrasal-complement"
-             "vp-aux-nonphrasal-complement"
-             "vp-32"
-             "vp-pronoun-nonphrasal"
-             "vp-pronoun-phrasal"} (u/get-in % [:rule]))
+         #(contains? verbcoach-grammar (u/get-in % [:rule]))
          (:grammar model))
         spec {:root {:italiano {:italiano "arrabbiarsi"}}
               :synsem {:cat :verb
@@ -315,9 +347,10 @@
                        :subcat []}}]
     (repeatedly
      #(println
-       (morph-ps (binding [babel.generate/println? false
+       (morph-ps (binding [babel.generate/println? true
                            babel.generate/truncate? false
-                           babel.generate/grammar grammar]
+                           babel.generate/grammar grammar
+                           babel.generate/index-fn verbcoach-index-fn]
                    (time (generate spec model))))))))

 (defn stampare
@@ -325,36 +358,23 @@
   []
   (let [grammar
         (filter
-         #(contains?
-           #{"s-aux"
-             "s-conditional-nonphrasal"
-             "s-conditional-phrasal"
-             "s-future-nonphrasal"
-             "s-future-phrasal"
-             "s-imperfetto-nonphrasal"
-             "s-imperfetto-phrasal"
-             "s-present-nonphrasal"
-             "s-present-phrasal"
-             "vp-aux-22-nonphrasal-comp"
-             "vp-aux-phrasal-complement"
-             "vp-aux-nonphrasal-complement"
-             "vp-32"
-             "vp-pronoun-nonphrasal"
-             "vp-pronoun-phrasal"} (u/get-in % [:rule]))
+         #(contains? verbcoach-grammar (u/get-in % [:rule]))
          (:grammar model))
         spec {:root {:italiano {:italiano "stampare"}}
               :synsem {:cat :verb
+                       :aux false
                        :modified false
                        :sem {:tense :past
-                             :obj :unspec
                              :aspect :progressive}
                        :subcat []}}]
+
     (repeatedly
      #(println
-       (morph-ps (binding [babel.generate/println? false
-                           babel.generate/truncate? false
-                           babel.generate/grammar grammar]
-                   (time (generate spec model))))))))
+       (morph (binding [babel.generate/println? true
+                        babel.generate/truncate? false
+                        babel.generate/index-fn verbcoach-index-fn
+                        babel.generate/grammar grammar]
+                (time (generate spec model))))))))

 (defn chiamarsi-ps
   "generate chiamarsi sentences with parse trees"


Fixed parsing of test data.

Fixed parsing of test data.

--- satellite-slave/src/satellite_slave/recipes.clj
+++ satellite-slave/src/satellite_slave/recipes.clj
@@ -18,17 +18,17 @@
             [satellite-slave.util :refer [every]]))

 (defn make-recipe-cmd
-  [x & xs]
-  (str (:satellite-recipe-prefix settings) (java.io.File/separator) "satellite-recipes " x (apply str xs)))
+  [& xs]
+  ([(str "/home/tsram/satellite_slave" (java.io.File/separator) "satellite-recipes") xs]))

 (defn free-memory
   [threshold period]
   {:riemann {:ttl (* 5 (.getSeconds period))
              :service "free memory in MB"}
-   :test {:command (make-recipe-cmd "free-mem")
+   :test {:command (make-recipe-cmd "free-memory")
           :schedule (every period)
           :output {:out (fn [out]
-                          (let [v (Integer/parseInt out)]
+                          (let [v (Integer/parseInt (clojure.string/trim out))]
                             [(> v threshold) v]))}
           :timeout 5}})

@@ -40,28 +40,28 @@
           :schedule (every period)
           :timeout 5
           :output {:out (fn [out]
-                          (let [v (Integer/parseInt out)]
+                          (let [v (Integer/parseInt (clojure.string/trim out))]
                             [(> v threshold) v]))}}})

 (defn free-swap-iff-swap
   [threshold period]
   {:riemann {:ttl (* 5 (.getSeconds period))
-             :service "free swap in MB"}
+             :service "free swap iff swap in MB"}
    :test {:command (make-recipe-cmd "swap-info")
           :schedule (every period)
           :timeout 5
           :output {:out (fn [out]
-                          (let [[configured used free] (map (fn [o] (Integer/parseInt o)) (clojure.string/split out #"\s+"))]
+                          (let [[configured used free] (map (fn [o] (Integer/parseInt (clojure.string/trim o))) (clojure.string/split out #"\s+"))]
                             [(or (= configured 0) (> free threshold)) free]))}}})

 (defn percentage-used
   [threshold path period]
   {:riemann {:ttl (* 5 (.getSeconds period))
              :service (str "percentage used of " path)}
-   :test {:command (str "satellite-recipes percentage-used" path)
+   :test {:command (make-recipe-cmd "percentage-used" path)
           :schedule (every period)
           :output {:out (fn [out]
-                          (let [v (Integer/parseInt out)]
+                          (let [v (Integer/parseInt (clojure.string/trim out))]
                             [(< v threshold) v]))}
           :timeout 5}})

@@ -81,17 +81,17 @@
    :test {:command (make-recipe-cmd "num-uninterruptable-processes")
           :schedule (every period)
           :output {:out (fn [out]
-                          (let [v (Integer/parseInt out)]
+                          (let [v (Integer/parseInt (clojure.string/trim out))]
                             [(< v threshold) v]))}}})

 (defn load-average
   [threshold period]
   {:riemann {:ttl (* 5 (.getSeconds period))
              :service "load average over past 15 minutes"}
-   :test {:command (make-recipe-cmd "uptime")
+   :test {:command (make-recipe-cmd "load-average")
           :schedule (every period)
           :output {:out (fn [out]
-                          (let [v (Float/parseFloat out)]
+                          (let [v (Float/parseFloat (clojure.string/trim out))]
                             [(< v threshold) v]))}}})

 (defn file-exists


Initial work on fontSize rendering on text shapes.

--- src/uxbox/ui/shapes/text.cljs
+++ src/uxbox/ui/shapes/text.cljs
@@ -132,6 +132,13 @@
    :style {:stroke "#333" :fill "transparent"
            :stroke-opacity "0.4"}})

+(def ^:const +style-attrs+
+  [:font-size])
+
+(defn- build-style
+  [{:keys [font-size]}]
+  (merge {} (when font-size {:fontSize (str font-size "px")})))
+
 (defmethod uusc/render-shape :builtin/text
   [{:keys [id x1 y1 x2 y2 content drawing? editing?] :as shape}]
   (let [key (str id)
@@ -139,12 +146,14 @@
         size (ush/size shape)
         props {:x x1 :y y1
                :transform (str rfm)}
-        attrs (merge props size)]
+        attrs (merge props size)
+        style (build-style shape)]
+
     (html
      [:g
       (if (or drawing? editing?)
         [:g
          [:rect (merge attrs +select-rect-attrs+)]])
       [:foreignObject attrs
-       [:p {:ref "container"} content]]])))
+       [:p {:ref "container" :style style} content]]])))


fix: [bug] wrong param

fix: [bug] wrong param

--- src/bulk_trader/geojit.cljs
+++ src/bulk_trader/geojit.cljs
@@ -17,5 +17,5 @@
         trader (if logged-in? trader-name nil)]
     (swap! g/app-state assoc
            :trader trader
-           :logged-in logged-in?)
+           :logged-in? logged-in?)
     logged-in?))


adding domain

adding domain

--- src/celestial/hosts_api.clj
+++ src/celestial/hosts_api.clj
@@ -39,6 +39,7 @@
   :cpus {:type :int :description "Not relevant in ec2"}
   :memory {:type :int :description "Not relevant in ec2"}
   :disk {:type :int :description "Not relevant in ec2"}
+  :domain {:type :string :description "dns domain"}
   :hostname :string :user :string :os :string :ip {:type :string :description "Not relevant in ec2"})

 (defmodel aws :min-count :int :max-count :int :instance-type :string


fix password reset page

fix password reset page

--- src/chat/server/handler.clj
+++ src/chat/server/handler.clj
@@ -156,12 +156,13 @@
       (invites/request-reset (assoc user :email email)))
     {:status 200 :body (pr-str {:ok true})})
   (GET "/reset" [user token]
-    (if-let [u (and (invites/verify-reset-nonce user token)
-                 (db/with-conn (db/user-by-id (java.util.UUID/fromString user))))]
-      {:status 200
-       :headers {"Content-Type" "text/html"}
-       :body (invites/reset-page u token)}
-      {:status 401}))
+    (let [user-id (java.util.UUID/fromString user)]
+      (if-let [u (and (invites/verify-reset-nonce {:id user-id} token)
+                   (db/with-conn (db/user-by-id (java.util.UUID/fromString user))))]
+        {:status 200
+         :headers {"Content-Type" "text/html"}
+         :body (invites/reset-page u token)}
+        {:status 401})))
   (POST "/reset" [new_password token user_id now hmac :as req]
     (let [user-id (java.util.UUID/fromString user_id)
           fail {:status 400 :headers {"Content-Type" "text/plain"}}]


More on atoms.

More on atoms.

--- test/com/nomistech/clojure_the_language/intro_to_state.clj
+++ test/com/nomistech/clojure_the_language/intro_to_state.clj
@@ -118,7 +118,7 @@
                                             (swap! n-attempts-atom inc)
                                             (Thread/sleep (rand-int 100))
                                             (inc n))))))))
-            (report-on-what-is-happenning []
+            (report-on-what-is-happening []
               (loop []
                 (println [@competing-updates-atom
                           @n-attempts-atom])
@@ -130,7 +130,7 @@
               [@competing-updates-atom
                @n-attempts-atom])]
       (create-competing-threads)
-      (report-on-what-is-happenning)
+      (report-on-what-is-happening)
       (wrap-up-and-result))))

 (fact "About concurrency and atoms"


some experiments with more relations

some experiments with more relations

--- src/clj/ceres/collector.clj
+++ src/clj/ceres/collector.clj
@@ -6,6 +6,7 @@
             [monger.conversion :refer [from-db-object]]
             [monger.query :refer :all]
             [monger.joda-time]
+            [aprint.core :refer [aprint]]
             [net.cgrand.enlive-html :as enlive]
             [clj-time.format :as f]
             [taoensso.timbre :as timbre]
@@ -137,3 +138,72 @@
                  origin (store-origin (assoc % :article (:_id article) :record oid :ts ts :source source))]
              {:article (update-in article [:ts] (fn [x] (f/unparse custom-formatter x))) :origin (str (:_id origin))}))
         articles)))))
+
+
+
+(defn store-user [{{:keys [id screen_name followers_count created_at]} :user}]
+  (let [date (f/parse custom-formatter created_at)]
+      (mc/insert-and-return
+       @db
+       "user"
+       {:id id
+        :screen_name screen_name
+        :created_at date})))
+
+(defn store-followers-count [uid followers-count date]
+  (mc/insert
+   @db
+   "followers"
+   {:user uid
+    :followers-count followers-count
+    :date date}))
+
+
+(defn store-published [uid tid url-id type ts]
+  (mc/insert
+   @db
+   "published"
+   {:user uid
+    :tweet tid
+    :url url-id
+    :type type
+    :ts ts}))
+
+(defn store-url [url uid ts]
+  (mc/insert
+   @db
+   "url"
+   {:url url
+    :user uid
+    :ts ts}))
+
+(comment
+
+  (time
+   (letfn [(user-exists? [{{:keys [id]} :user}] (mc/find-one @db "user" {:id id}))]
+     (let [tweets (mc/find-maps @db "tweets" {:created_at {$gt (t/date-time 2014 7 1)
+                                                           $lt (t/date-time 2014 8 1)}})]
+       (doall
+        (pmap #(when-not (user-exists? %) (store-user %)) tweets)))))
+
+
+
+  (time
+   (let [origins (mc/find-maps @db "origins" {:source {$ne nil}})]
+     (doall
+      (map
+       (fn [{:keys [article tweet ts source]}]
+         (let [uid (:_id (mc/find-one-as-map @db "user" {:screen_name source}))
+               url (if article
+                     (:url (mc/find-map-by-id @db "articles" article))
+                     nil)]
+           (if url
+             (store-url url uid ts)
+             :unknown)))
+       origins))))
+
+
+  (let [uid (:_id (mc/find-one-as-map @db "user" {:screen_name "SZ"}))]
+    (mc/count @db "url" {:user uid}))
+
+  )


Figured out event format

Figured out event format

--- src/clj/om_sente/server.clj
+++ src/clj/om_sente/server.clj
@@ -33,17 +33,18 @@

 (defn handle-data
   "Main event processor."
-  [[event & args :as data]]
+  [{:keys [client-uuid ring-req event] :as data}]
   ;; right now we just echo back anything we receive
-  (println "handle-data" data)
-  (case event
-    :test/echo (chsk-send! "test" data)))
+  (println "handle-data" event)
+  (let [[ev-id & payload] event]
+    (chsk-send! "test" [:test/reply (first payload)])))

 (defn -main [& args]
   (println "starting -main")
-  (go (loop [data (<! ch-chsk)]
-        (handle-data data)
-        (recur (<! ch-chsk))))
+  (go (loop []
+        (println "waiting for data...")
+        (handle-data (<! ch-chsk))
+        (recur)))
   (println "about to start server")
   (let [port (or (System/getenv "PORT") 8444)]
     (kit/run-server #'server {:port port})))


Reworked query validation

Reworked query validation

--- src/clj/sparqlab/sparql.clj
+++ src/clj/sparqlab/sparql.clj
@@ -9,7 +9,8 @@
             [clojure.java.io :as io]
             [stencil.core :refer [render-file]]
             [stencil.loader :refer [set-cache]])
-  (:import [org.apache.jena.query ARQ DatasetFactory Query QueryExecutionFactory
+  (:import [java.io StringReader]
+           [org.apache.jena.query ARQ DatasetFactory Query QueryExecutionFactory
                                   QueryFactory QueryParseException Syntax]
            [org.apache.jena.update UpdateAction UpdateFactory]
            [org.apache.jena.rdf.model Model ModelFactory]
@@ -19,7 +20,8 @@
            [org.apache.jena.sparql.core Var]
            [org.apache.jena.graph Node]
            [org.apache.jena.arq.querybuilder ConstructBuilder]
-           [org.topbraid.spin.arq ARQ2SPIN]))
+           [org.topbraid.spin.arq ARQ2SPIN]
+           [org.apache.jena.sparql.lang.sparql_11 ParseException SPARQLParser11 Token]))

 (def arq-context
   (doto (.copy (ARQ/getContext))
@@ -91,13 +93,36 @@
   [^Query query]
   (string/trim (.serialize query)))

-(defn validate-query-syntax
+(defn- get-error-offset
+  "Compute offset of a syntax `exception` in `query` based on line and column numbers."
+  [^String query
+   ^ParseException exception]
+  (let [current-token (.currentToken exception)
+        query-lines (take (.beginLine current-token) (string/split-lines query))]
+    (+ (reduce + (map (comp inc count) (butlast query-lines))) ; Offset from the preceding lines
+       (count (take (+ (.beginColumn current-token) ; Offset from the preceding token
+                       (count (.image current-token)))
+                    (last query-lines))))))
+
+(defn- get-expected-tokens
+  "Get string representations of the tokens expected by `exception`."
+  [^ParseException exception]
+  (let [token-images (.tokenImage exception)
+        idxs (flatten (mapv vec (.expectedTokenSequences exception)))]
+    (map (partial aget token-images) idxs)))
+
+(defn valid-query?
+  "Validates syntax of `query`."
   [^String query]
-  (try (QueryFactory/create query Syntax/syntaxSPARQL_11)
-       (catch QueryParseException ex
-         {:message (.getMessage ex)
-          :line (.getLine ex)
-          :column (.getColumn ex)})))
+  (let [empty-query (doto (Query.) (.setStrict true))
+        parser (doto (SPARQLParser11. (StringReader. query))
+                 (.setQuery empty-query))]
+    (try (do (.QueryUnit parser)
+             {:valid? true})
+         (catch ParseException ex
+           {:expected (get-expected-tokens ex)
+            :offset (get-error-offset query ex)
+            :valid? false}))))

 (defn normalize-query
   [^Query query]


Add type check

Add type check

--- src/cljs/dato/lib/core.cljs
+++ src/cljs/dato/lib/core.cljs
@@ -369,6 +369,8 @@

 ;; XXX: Unsure about -nr variant
 (defn set-state-nr! [owner map]
+  ;; No nested collections allowed (except sets, for now)
+  {:pre [(not (some #(or (map? %) (vector? %)) (vals map)))]}
   (let [conn                       (conn (om/get-shared owner [:dato]))
         eid                        (dato-node-id owner)
         entity                     (merge {:db/id eid} map)