fix event gtag

fix event gtag

--- src/clojurescript/nossal/app/app.cljs
+++ src/clojurescript/nossal/app/app.cljs
@@ -40,8 +40,19 @@
   (.call js/Array.prototype.slice array-like))

 (defn gtag [& args]
-  (do (alert! args)
+  (do (alert! (clj->js args))
       (apply js/gtag (clj->js args))))
+
+
+(defn addTrackEvent [where event]
+  (.addEventListener where
+                     (:on event)
+                     (fn [e] (gtag (:request event)
+                                   (:eventAction (:vars event))
+                                   (let [ev (:vars event)]
+                                     {:event_category (:eventCategory ev)
+                                      :event_label (:eventLabel ev)
+                                      :value (:value ev)})))))

 (defn analytics-setup [data]
   (doseq [event (:triggers data)]
@@ -50,19 +61,9 @@
         "click"
         (when-let [elements (not-empty (->Array (.querySelectorAll js/document (:selector conf))))]
           (doseq [element elements]
-            (.addEventListener element (:on conf) (fn [e] (gtag (:request conf) (:on conf) (:vars conf))))))
+            (addTrackEvent element conf)))
         "visible" (alert! (str ">>>> " (:request conf)))
-        (.addEventListener js/document (:on conf) (fn [e] (gtag (:request conf) (:on conf) (:vars conf))))))))
-      ; (if (= "click" (:on conf))
-      ;   (when-let [elements (not-empty (->Array (.querySelectorAll js/document (:selector conf))))]
-      ;     (doseq [element elements]
-      ;       (.addEventListener element (:on conf) (fn [e] (println (:vars conf))))))
-      ;   (.addEventListener js/document (:on conf) (fn [e] (println (:request conf))))))))
-        ; (let [element (or (.querySelectorAll js/document (:selector conf))) js/window])))))
-      ;   (do
-      ;    (println element)
-      ;    (.addEventListener element (:on conf) (fn [e] (println e))))))))
-
+        (addTrackEvent js/document conf)))))

 ; (.addEventListener js/document "DOMContentLoaded" (fn [] (analytics-setup data-analytics)))
 (analytics-setup data-analytics)


No restriction on :children collection type

--- src/com/wsscode/pathom/specs/ast.cljc
+++ src/com/wsscode/pathom/specs/ast.cljc
@@ -9,7 +9,7 @@
 (s/def ::union-key ::q/property)

 (s/def ::children
-  (s/coll-of ::node :kind vector?))
+  (s/coll-of ::node))

 (s/def ::root
   (s/and (s/keys :req-un [::type ::children])


Validate entries via checks with better errors first

--- src/onyx/static/validation.clj
+++ src/onyx/static/validation.clj
@@ -43,11 +43,11 @@
 (defn validate-catalog
   [catalog]
   (no-duplicate-entries catalog)
-  (schema/validate Catalog catalog)
   (doseq [entry catalog]
     (name-and-type-not-equal entry)
     (min-and-max-peers-sane entry)
-    (min-max-n-peers-mutually-exclusive entry)))
+    (min-max-n-peers-mutually-exclusive entry))
+  (schema/validate Catalog catalog))

 (defn validate-workflow-names [{:keys [workflow catalog]}]
   (when-let [missing-names (->> workflow


wip: resolve field

wip: resolve field


Don't bring in clojurescript deps for the other tasks

--- build.boot
+++ build.boot
@@ -4,14 +4,13 @@
   :dependencies '[[org.clojure/test.check "0.9.0" :scope "test"]
                   [adzerk/boot-cljs "1.7.228-1" :scope "test"]
                   ; project deps
-                  [org.clojure/clojurescript "1.9.225"]
                   [org.clojure/clojure "1.9.0-alpha13"]
                   [leiningen "2.7.0" :exclusions [leiningen.search]]
                   [ring "1.4.0"]
                   [play-cljs/lein-template "0.6.4"]
-                  [eval-soup "1.0.0"]
-                  [paren-soup "2.6.1"]
-                  [cljsjs/codemirror "5.19.0-0"]])
+                  [eval-soup "1.0.0"
+                   :exclusions [org.clojure/clojurescript
+                                org.clojure/core.async]]])

 (require
   '[adzerk.boot-cljs :refer [cljs]])
@@ -41,5 +40,10 @@
   (comp (aot) (pom) (uber) (jar) (sift) (target)))

 (deftask build-cljs []
+  (set-env! :dependencies
+    (conj (get-env :dependencies)
+      '[org.clojure/clojurescript "1.9.225"]
+      '[paren-soup "2.6.1"]
+      '[cljsjs/codemirror "5.19.0-0"]))
   (comp (cljs :optimizations :advanced) (target)))


Fix seek?

Fix seek?

--- src/aurora/btree.cljs
+++ src/aurora/btree.cljs
@@ -254,10 +254,10 @@
               (set! ix 0)
               #js [(aget (.-keys node) ix) (aget (.-vals node) ix)]))))
   (seek [this key]
-        (when (false? end?)
-          (loop []
+        (loop []
+          (when (false? end?)
             (let [upper (.-upper node)]
-              (if (gt key upper)
+              (if (lt upper key)
                 (if (instance? Node (.-parent node))
                   (do
                     (set! ix (.-parent-ix node))
@@ -266,15 +266,22 @@
                   (do
                     (set! end? true)
                     nil))
-                (do
+                (loop []
                   (set! ix (.seek node key ix))
-                  (let [ix-key (aget (.-keys node) ix)]
-                    (if (and (not (nil? (.-children node))) (lt key ix-key))
+                  (if (>= ix (alength (.-keys node)))
+                    (do
+                      (set! node (aget (.-children node) ix))
+                      (set! ix 0)
+                      (recur))
+                    (if (or (== key (aget (.-keys node) ix))
+                            (nil? (.-children node))
+                            (let [lower (.-upper (aget (.-children node) ix))]
+                              (lt lower key)))
+                      #js [(aget (.-keys node) ix) (aget (.-vals node) ix)]
                       (do
                         (set! node (aget (.-children node) ix))
                         (set! ix 0)
-                        (recur))
-                      #js [(aget (.-keys node) ix) (aget (.-vals node) ix)])))))))))
+                        (recur)))))))))))

 (defn iterator [tree]
   (loop [node (.-root tree)]
@@ -432,6 +439,10 @@
                  movements (gen/vector gen-movement)]
                 (run-iterator-prop min-keys actions movements)))

+(run-iterator-prop 1 [[:assoc! 0 0] [:assoc! 1 0] [:assoc! "" 0]] [[:next] [:next] [:seek 0]])
+
+;; (run-iterator-prop 4 [[:dissoc! 42] [:dissoc! 5] [:assoc! "ls-[`6aH|B" 42] [:assoc! "U?cj$9\\z)#oM34=^q~{C!^2=,|9+`er<^.;&" 28] [:assoc! 39 -24] [:assoc! 35 "<hlNVmw$iuLQ\\OoTocIj1$0ey<gI]MFe{~QL}j4sA"] [:assoc! "<~2zx)<'`=:W^" "k6+h%O!hprN66}~:2w"] [:dissoc! -19] [:assoc! -8 "p"] [:dissoc! "M/oCnKtZ4da<kZ.:!9"] [:assoc! -43 ".P(t8Qrw&vkf!b=XVZRmQHO#s/`*gp<ptU ZJ;O`HCDs _Z7tKCj/pU"] [:dissoc! "P&gv~dExsi8!oC!k}%,Kp=3^F;M1xv\\jUJADsE/N+3P/- ]7\\2-x8Tg4q7gQ>O(_"] [:assoc! 46 "G-vqh1ho1rP V}|U`QIfd$^S8eqUOa+\"_]^"] [:assoc! -21 "z$mOg%pS!K+*1c83?I$]dt>t{}:`5LXIfh|c#rHD,0n0;J^n{k"] [:dissoc! -25] [:dissoc! "k1n!Tk|'<Vd`hh<LDg6b*W'yy\\8/*D8:|bC-$ZT:"] [:dissoc! -53] [:assoc! 5 "1YxP6gc~2z"] [:dissoc! "=B.N\\MGcrb]xmG=E6tl6uRuL$L"] [:assoc! -23 "d7)>77Y5!w*/o5ZzrkKRh@Y\\<LS%Lx1`P(mi^g;CtKwq=m3otO@?((Ts'Z+~"] [:assoc! -9 -50] [:dissoc! 35] [:assoc! -49 "XBtp;FwWolcsLFP=xqKH28{er7Pe: b"] [:dissoc! "xtv<<Ox@PuHA(Bxp1nz{B.pE"]] [[:seek -18] [:seek -10] [:seek 37] [:seek "/Bpk}b*\\ubgU4ygT(P.Dw{(g(+# 2M2{(A5,}L]^KVTmS{:qT3}&<`1,j<9Ino"] [:seek 0] [:seek "<$?Oj'&Z$%I45PQ_d"] [:next] [:seek "C\"|LbCx)Nfq]_=rpHOQlL;L$"] [:next] [:seek "JV\"WZVE,`"] [:seek "3<sb\\l5rj'Prv,E]|f=GADJTFl{37P9Hd9~ vaG^YJwWk9At):yzo'DW}Q.z8?"] [:next] [:next] [:next] [:seek ")U+owBxdsR}^{65[?ovtiQO.A<,S@Y1EIxJH_`!@A2%"] [:next] [:seek -9] [:next] [:next] [:seek "^FGwOMy0\"_5vT(--dv`;:kywuKD8SMG_9)X'pX6w"] [:next] [:seek -52] [:seek -25] [:seek 34] [:next] [:seek "hz^rHA%v! (g~b3eL|XHB>'2mY9A\"uMa9$z'3.X_s9faCq["] [:seek "Wzyzi.uuK?rp#k[|M^NI:L)nh&"] [:seek -63] [:next] [:next] [:seek "P$I'|"] [:next] [:seek "A@:N^g]\\qXB:."] [:seek -2] [:next] [:seek "uH6<0u[rpc]8oUcmED"] [:seek -36] [:next] [:seek "<2%43s;qEJSN^WfQ5=b03/.<?E_SA5Cd~ZHp}jCVWR$q\"E:/?Om,]{D-n"] [:next]])
+
 (comment
   (dc/quick-check 1000 least-prop)
   (dc/quick-check 1000 greatest-prop)
@@ -441,9 +452,10 @@
   (dc/quick-check 1000 anti-symmetric-prop)
   (dc/quick-check 1000 total-prop)
   (dc/quick-check 100 (building-prop gen-assoc))
-  (dc/quick-check 1000 (building-prop gen-action))
+  (dc/quick-check 100 (building-prop gen-action))
   (dc/quick-check 100 (lookup-prop gen-action))
   (dc/quick-check 100 iterator-prop)
+

   (defn f []
     (time
@@ -468,5 +480,14 @@
          (.assoc! tree (js/Math.sin i) (* 2 i))))))

   (h)
+
+  (do
+    (def samples (gen/sample (gen/tuple gen/s-pos-int (gen/vector gen-action) (gen/vector gen-movement)) 100))
+    (def trees (for [[min-keys actions _] samples]
+                 (apply-to-tree (tree min-keys) actions)))
+    (def benches (mapv vector trees (map #(nth % 2) samples)))
+    (time
+     (doseq [[tree movements] benches]
+       (apply-to-iterator (iterator tree) movements))))
  )


Adds comment

Adds comment

--- src/hundred_pushups/android/core.cljs
+++ src/hundred_pushups/android/core.cljs
@@ -177,8 +177,11 @@
         ;; TODO input validation
         ;; setup https://github.com/clj-time/clj-time
         ;; use JS plugins https://github.com/xgfe/react-native-datepicker https://www.npmjs.com/package/react-native-date-time-picker
-
-      [view {:style {:flex 1 :padding 20}}
+
+       [view {:style {:flex 1 :padding 20}}
+        ;; https://facebook.github.io/react-native/docs/scrollview.html
+        ;; Keep in mind that ScrollViews must have a bounded height in order to work, since they contain unbounded-height children into a bounded container (via a scroll interaction).
+        ;; Forgetting to transfer {flex: 1} down the view stack can lead to errors here, which the element inspector makes easy to debug.
        [scroll-view {:style {:flex 1}}
         (for [row @white-list]
           [view {:key row}


Really fixes #34

Really fixes #34

--- src/adzerk/boot_cljs.clj
+++ src/adzerk/boot_cljs.clj
@@ -126,16 +126,17 @@
       (core/with-pre-wrap fileset
         (core/empty-dir! tmp-result)
         (let [{:keys [main incs cljs] :as fs} (deps/scan-fileset fileset)]
-          (loop [[m & more] main, {{:keys [optimizations]} :opts :as ctx} ctx, dep-order nil]
-            (if m
-              (let [docroot   (.getParent (io/file (core/tmppath m)))
-                    ctx       (prep-compile (prep-context m fs docroot ctx))
-                    dep-order (->> (compile ctx @pod)
-                                   (map #(.getPath (util/rooted-file docroot %)))
-                                   (concat dep-order))]
-                (copy-to-docroot docroot ctx)
-                (recur more ctx dep-order))
-              (-> fileset
-                  (core/add-resource tmp-result)
-                  (core/add-meta (-> fileset (deps/external incs) (deps/compiled dep-order)))
-                  core/commit!))))))))
+          (loop [[m & more] main, dep-order nil]
+            (let [{{:keys [optimizations]} :opts :as ctx} ctx]
+              (if m
+                (let [docroot   (.getParent (io/file (core/tmppath m)))
+                      ctx       (prep-compile (prep-context m fs docroot ctx))
+                      dep-order (->> (compile ctx @pod)
+                                     (map #(.getPath (util/rooted-file docroot %)))
+                                     (concat dep-order))]
+                  (copy-to-docroot docroot ctx)
+                  (recur more dep-order))
+                (-> fileset
+                    (core/add-resource tmp-result)
+                    (core/add-meta (-> fileset (deps/external incs) (deps/compiled dep-order)))
+                    core/commit!)))))))))


Explored vectors and keywords...next, lists

--- ParlezVousClojure/clojure_data_structures.clj
+++ ParlezVousClojure/clojure_data_structures.clj
@@ -63,5 +63,79 @@
 ({:who-is-bad-to-the-bone "George Thoroughgood"} :who-is-bad-to-the-bone)
 ; => "George Thoroughgood

-; -------------------------------------------------------------------------------
+; ------------------------------------------------------------------------------
 ; Keywords
+
+;; NOTE (to self): I've been overthinking 'keywords' in Clojure,
+;; wondering if they were sometimes acting as symbols - however,
+;; it appears that they really are just signifiers for map keys
+
+;; Per the Clojure documentation, keywords are:
+
+;; "symbolic identifiers that evaluate to themselves, providing very fast equality tests"
+
+;; Whereas, symbols are:
+
+;; "identifiers that are normally used to refer to something else. They can be used
+;; in programs to refer to function parameters, let bindings, class names and global vars..."
+
+;; Further, we might think of using keywords as lightwieght "constant strings" for the keys of a hash-map
+;; or the dispatch values of a multimethod
+
+;; Symbols, then, are generally used to name variables and functions and it's less common to
+;; manipulate them as objects directyl except in macros.
+
+;; Examples
+:doom
+:black
+:death
+:speed
+:progressive
+:symphonic
+
+;; As we saw with the built-in 'get' method, a keyword can be used to lookup a value in a data structure
+(get {:bat "meatloaf" :out "mashed potatoes" :of "green peas" :hell "ketchup"} :bat)
+; => "meatloaf"
+
+;; However, we can write this more succinctly because we're using keywords:
+(:bat {:bat "meatloaf" :out "mashed potatoes" :of "green peas" :hell "ketchup"})
+  ; => "meatloaf"
+
+;; We could also provide a default value, just like we did with the 'get' method (on line 57)
+(:ozzy {:bat "meatloaf" :out "mashed potatoes" :of "green peas" :hell "ketchup"} "Wrong bat")
+; => "Wrong bat"
+
+;; NOTE (to self): Try to utilizie the keyword as a function method over the 'get,' where appropriate!
+
+; ------------------------------------------------------------------------------
+; Vectors
+
+;; A vector is similar to an array, in that it's a 0-indexed data structure
+
+;; As with all other Clojure data structures, vectors, too, are immutable and persistent
+
+[6 6 6]
+
+(get [6 6 6] 12) ; => nil (no element at index 12)
+(get [6 6 6] 0) ; => 6 (element found at 0th index)
+(get-in [6 "six" {:most-metal-number {:num 666}}] [2 :most-metal-number :num])
+; => {:most-metal-number {:num 666}}
+
+;; NOTE: In the above, I combined index-based positioning with the 'get-in' method
+;; which I discovered was applicable to both maps and vectors (that is, any nested
+;; associative data structure). In reviewing the docs, it seems that the 'list'
+;; data structure would not work, because it is not associative. Using the nested
+;; properties of a vector, I supplied my argument as a vector containing '2' to grab the
+;; element at the 2-index, and then supplied two keywords (':most-metal-number' and
+;; ':num') to get the inner value of the nested hash-map at the 2-index
+
+;; To create a vector, use the 'vector' function, passing n-values
+(vector "like" "a" "rainbow" "in" "the")
+; => ["like" "a" "rainbow" "in" "the"]
+
+;; To add additional elements to a vector (IMPORTANT: added to the end!!!), use 'conj' function
+(conj ["like" "a" "rainbow" "in" "the"] "dark")
+; => [ "like" "a" "rainbow" "in" "the" "dark"]
+
+; ------------------------------------------------------------------------------
+; Lists


shorten poll interval

shorten poll interval

--- app/ws.cljs
+++ app/ws.cljs
@@ -16,8 +16,8 @@
     (when recording-id
       (let [cb (r {:type :get
                     :url (str "/recordings/" recording-id "/data")
-                    :data {:limit 100
-                             :start @start}})]
+                   :data {:limit 100
+                          :start @start}})]

         (go
           (let [res (<! cb)]
@@ -44,7 +44,7 @@
             (log/info l "resetting start timestamp")
             (reset! start 0)))
         (recur (<! e-chan))))
-    (js/setInterval fetch 2000 app-state out)
+    (js/setInterval fetch 500 app-state out)

     {:pub stdout
      :chan out}))


move parser to variable

move parser to variable


Dev server at Dropbox expected port

Dev server at Dropbox expected port

--- build.boot
+++ build.boot
@@ -23,7 +23,7 @@
   "The works"
   []
   (comp
-    (serve :dir "target")
+    (serve :dir "target" :port 8080)
     (watch)
     (reload)
     (cljs-repl)


more logging

more logging

--- src/babel/forest.cljc
+++ src/babel/forest.cljc
@@ -86,15 +86,10 @@
   (if (and (not (= :fail spec))
            (not (empty? (strip-refs spec))))
     (log/debug (str "lighting-bolt@" depth " spec: " (strip-refs spec))))
-  (log/trace (str "lighting-bolt@" depth " grammar:" (string/join ", " (map #(get-in % [:rule]) grammar))))
+  (if (not parent)
+    (log/warn (str "no parent for lightning-bolt@" depth " with spec: " (strip-refs spec))))
   (let [maxdepth 3 ;; maximum depth of a lightning bolt: H1 -> H2 -> H3 where H3 must be a lexeme, not a phrase.
-        index
-        #?(:clj (if (future? index) @index index))
-        #?(:cljs index)
-
-        lexicon
-        #?(:clj (if (future? lexicon) @lexicon lexicon))
-        #?(:cljs lexicon)
+        debug (log/debug (str "lightning-bolt@" depth " grammar:" (string/join ", " (map #(get-in % [:rule]) grammar))))

         depth (if depth depth 0)
         ;; TODO: unifyc is expensive: factor out into a let.
@@ -109,7 +104,8 @@

         debug (if (not (empty? candidate-parents))
                 (log/debug (str "candidate-parents: " (string/join "," (map #(get-in % [:rule])
-                                                                            candidate-parents)))))]
+                                                                            candidate-parents))))
+                (log/warn (str "candidate-parents are empty!")))]
     ;; TODO: remove or parameterize this hard-coded value.
     (if (> depth 5)
       (throw (exception (str "DEPTH IS GREATER THAN 5; HOW DID YOU END UP IN THIS TERRIBLE SITUATION? LOOK AT THE STACK. I'M OUTTA HERE."))))
@@ -152,9 +148,7 @@
                               (lightning-bolt grammar lexicon
                                               (get-in parent [:head])
                                               (+ 1 depth)
-                                              index parent morph)
-                              phrasal-children phrasal-children
-                              ]
+                                              index parent morph)]
                           (log/debug (str "calling overh with parent: [" (get-in parent [:rule]) "]" "'" (morph parent) "'"
                                           " and children: "
                                           (if phrasal-children
@@ -167,10 +161,14 @@
                                                        ))
                                                 phrasal-children))))
                           (if (empty? phrasal-children)
-                            (let [message (str "no phrasal children for for parent: " (morph parent) "(rule=" (get-in parent [:rule]) ")" )]
+                            (let [message (str "no phrasal children for parent: " (morph parent) "(rule=" (get-in parent [:rule]) ")" )]
                               (log/debug message))
                             ;; else; there are phrasal-children, so attach them below parent:
-                            (over/overh parent phrasal-children morph))))
+                            (do
+                              (log/debug (str "phrasal-children:" (map morph phrasal-children)))
+                              (over/overh parent phrasal-children morph)))
+                          )
+                        )
                        candidate-parents))]
         (if (= (rand-int 2) 0)
           (lazy-cat lexical phrasal)
@@ -221,7 +219,7 @@
               (filter (fn [result]
                         (not (fail? result)))
                       (map (fn [complement]
-                             (let [debug (log/debug (str "["
+                             (let [debug (log/debug (str "add complement ["
                                                          (get-in bolt [:rule]) " "
                                                          (morph bolt) "]: trying lexical complement:" (morph complement)
                                                          ))


Replace replace-task! with alter-var-root so macro does not get called.

--- build.boot
+++ build.boot
@@ -39,12 +39,10 @@
     (dev-env)
     (apply r xs)))

-(when (resolve 'lein-generate)
-  (replace-task!
-    [g lein-generate]
-    (fn [& xs]
-      (dev-env)
-      (apply g xs))))
+(when-let [v (resolve 'lein-generate)]
+  (alter-var-root v
+                  (fn [g]
+                    (fn [& xs] (dev-env) (apply g xs)))))

 (deftask deploy
          []


Note about bug in aurora pattern compiler

--- src/aurora/compiler.cljs
+++ src/aurora/compiler.cljs
@@ -128,7 +128,7 @@
                   ~(pattern->jsth index (:pattern branch) input)
                   ~@(for! [guard (:guards branch)]
                           (guard->jsth index guard))
-                  ~(action->jsth index (:action branch) id))
+                  ~(action->jsth index (:action branch) id)) ;; TODO this could throw match failure too
                 (catch ~(id->temp exception)
                   (if (== ~(id->temp exception) failure)
                     ~tail


added funcs

added funcs


CLJS-808: Warning from `find-classpath-lib` mistakenly included in generated source

--- src/clj/cljs/js_deps.clj
+++ src/clj/cljs/js_deps.clj
@@ -303,5 +303,9 @@
     (let [{:keys [provides] :as lib-info} (library-graph-node lib-resource)]
       (if (some #{(name lib)} provides)
         lib-info
-        (println (format "WARNING: JavaScript file found on classpath for library `%s`, but does not contain a corresponding `goog.provide` declaration: %s"
-                   lib lib-resource))))))
+        (binding [*out* *err*]
+          (println
+            (format
+              (str "WARNING: JavaScript file found on classpath for library `%s`, "
+                   "but does not contain a corresponding `goog.provide` declaration: %s")
+              lib lib-resource)))))))


multi-specs include dispatch values in path, fix for rep*

--- src/clj/clojure/spec.clj
+++ src/clj/clojure/spec.clj
@@ -298,7 +298,12 @@
   dispatch-tag that should return an appropriately retagged value.

   Note that because the tags themselves comprise an open set,
-  the tag keys cannot be :req in the specs.
+  the tag key spec cannot enumerate the values, but can e.g.
+  test for keyword?.
+
+  Note also that the dispatch values of the multimethod will be
+  included in the path, i.e. in reporting and gen overrides, even
+  though those values are not evident in the spec.
 "
   [mm retag]
   `(multi-spec-impl '~(res mm) (var ~mm) ~retag))
@@ -834,6 +839,7 @@
              (str "Multimethod :" form " does not contain nil-returning default method for :clojure.spec/invalid" ))
      (let [id (java.util.UUID/randomUUID)
            predx #(@mmvar %)
+           dval #((.dispatchFn ^clojure.lang.MultiFn @mmvar) %)
            tag (if (keyword? retag)
                  #(assoc %1 retag %2)
                  retag)]
@@ -845,21 +851,22 @@
                           (dt pred x form)
                           ::invalid))
         (explain* [_ path via in x]
-                  (if-let [pred (predx x)]
-                    (explain-1 form pred path via in x)
-                    {path {:pred form :val x :reason "no method" :via via :in in}}))
+                  (let [dv (dval x)
+                        path (conj path dv)]
+                    (if-let [pred (predx x)]
+                      (explain-1 form pred path via in x)
+                      {path {:pred form :val x :reason "no method" :via via :in in}})))
          (gen* [_ overrides path rmap]
               (if gfn
                 (gfn)
                 (let [gen (fn [[k f]]
                             (let [p (f nil)]
-                              (let [idk [id k]
-                                    rmap (inck rmap idk)]
-                                (when-not (recur-limit? rmap idk [idk] idk)
+                              (let [rmap (inck rmap id)]
+                                (when-not (recur-limit? rmap id path k)
                                   (gen/delay
                                    (gen/fmap
                                     #(tag % k)
-                                    (gensub p overrides path rmap (list 'method form k))))))))
+                                    (gensub p overrides (conj path k) rmap (list 'method form k))))))))
                       gs (->> (methods @mmvar)
                               (remove (fn [[k]] (= k ::invalid)))
                               (map gen)
@@ -1139,7 +1146,8 @@
             ::pcat (alt2 (pcat* {:ps (cons (deriv p0 x) pr), :ks ks, :forms forms, :ret ret})
                          (when (accept-nil? p0) (deriv (pcat* {:ps pr, :ks kr, :forms (next forms), :ret (add-ret p0 ret k0)}) x)))
             ::alt (alt* (map #(deriv % x) ps) ks forms)
-            ::rep (rep* (deriv p1 x) p2 ret splice forms)))))
+            ::rep (alt2 (rep* (deriv p1 x) p2 ret splice forms)
+                        (when (accept-nil? p1) (deriv (rep* p2 p2 (add-ret p1 ret nil) splice forms) x)))))))

 (defn- op-describe [p]
   (let [{:keys [::op ps ks forms splice p1 rep+] :as p} (reg-resolve p)]


Make vubis import robust against empty product_numbers

--- src/catalog/vubis.clj
+++ src/catalog/vubis.clj
@@ -356,7 +356,8 @@
                         ;; first try to decode the braille-music-grade. Next check if the product-number
                         ;; starts with "SS". Otherwise set the braille-grade to nil.
                        :braille-grade (or (braille-music-grade-raw-to-braille-grade braille-music-grade)
-                                          (when (re-find #"^SS\d{5,}" product-number) :schwarzschrift))
+                                          (when (and (string? product-number)
+                                                     (re-find #"^SS\d{5,}" product-number)) :schwarzschrift))
                        :volumes (parse-int volumes)
                        :accompanying-material accompanying-material))
       :taktilesbuch (-> item


Helper func emit-merged-lines.

Helper func emit-merged-lines.

--- src/cbfg/zgo/core.clj
+++ src/cbfg/zgo/core.clj
@@ -52,9 +52,10 @@
        (range beg (inc end))
        (subvec lines (dec beg) end)))

-(defn do-lines [lines beg end f] ; beg and end are 1-based.
-  (doseq [[i curr-line] (numbered-lines lines beg end)]
-    (f i curr-line)))
+(defn emit-merged-lines [out numbered-slines]
+  (doseq [[i line] numbered-slines]
+    (println "//" i line))
+  (println "out>>>" out))

 (defn emit [slines pmodel-in]
   (loop [last-line 0
@@ -62,11 +63,13 @@
     (when (seq pmodel)
       (let [[out [sline-beg sline-end]] (first pmodel)]
         (when (> sline-beg (inc last-line))
-          (do-lines slines (inc last-line) (dec sline-beg)
-                    #(println "//" %1 %2)))
-        (do-lines slines sline-beg sline-end
-                  #(println "//" %1 %2))
-        (println "out>>>" out)
+          (doseq [[i line] (numbered-lines slines
+                                           (inc last-line)
+                                           (dec sline-beg))]
+            (println "///" i line)))
+        (emit-merged-lines out (numbered-lines slines
+                                               sline-beg
+                                               sline-end))
         (recur sline-end
                (rest pmodel))))))


Fix execute case when query error is found

--- src/cfpb/qu/query.clj
+++ src/cfpb/qu/query.clj
@@ -94,7 +94,9 @@
       (assoc query :result
              (cond
               (seq (:errors query))
-               (sd/increment "qu.queries.invalid")
+               (do
+                 (sd/increment "qu.queries.invalid")
+                 [])

               (is-aggregation? query)
               (data/get-aggregation dataset collection (mongo-aggregation query))


Add docs for get-trip-reports.

Add docs for get-trip-reports.

--- project/scrape-trs/src/scrape_trs/core.clj
+++ project/scrape-trs/src/scrape_trs/core.clj
@@ -10,7 +10,11 @@
       sp/base-url (sp/->SPScrapeTripReport))))

 (defn get-trip-reports
-  ""
+  "implementation: type that implements scrape-trs.protocol/ScrapeTripReport
+  list-page: page (as a string) that lists trip reports and corresponds to the given implementation
+
+  Scrape all trip reports from the list-page, paging through pagination if
+  necessary, and return a sequence of scrape-trs.protocol/TripReport instances."
   [implementation list-page]
   (let [pager-urls (.extract-pager-urls implementation list-page)
         list-pages (if pager-urls (map slurp pager-urls) [list-page])


The board-view is now an agent

The board-view is now an agent

Signed-off-by: Stefan Marr <46f1a0bd5592a2f9244ca321b129902a06b53e03@stefan-marr.de>

--- Clojure/src/snake/board_view.clj
+++ Clojure/src/snake/board_view.clj
@@ -1,47 +1,55 @@
 (ns snake.board-view
   (:use snake.terminal)
+  (:use snake.agents-helpers)
   (:require [clojure.contrib.string :as string]))

 (defn create-view
   "Create a new board view"
-  [board]
-  :not-yet-implemented)
+  [{width :width height :height}]
+  (start-agent-and-initialize {:width  width
+                               :height height}))

 (defn draw-borders
   "Draws the surrounding border of the board."
-  [{width :width height :height}]
+  [board-view]
+  (let [{width  :width
+         height :height} board-view]
+    (println width)
+    (println height)
+    ; (println board-view)
+    (set-cursor 0 0)
+    (put "/")
+    (put (string/repeat width "-"))
+    (put "\\")

-  (set-cursor 0 0)
-  (put "/")
-  (put (string/repeat width "-"))
-  (put "\\")
+    (dotimes [i height]
+      (set-cursor 0           (+ i 1))
+      (put "|")
+      (set-cursor (+ width 1) (+ i 1))
+      (put "|"))

-  (dotimes [i height]
-    (set-cursor 0           (+ i 1))
-    (put "|")
-    (set-cursor (+ width 1) (+ i 1))
-    (put "|"))
+    (put "\n")

-  (put "\n")
-
-  (put "\\")
-  (put (string/repeat width "-"))
-  (put "/"))
+    (put "\\")
+    (put (string/repeat width "-"))
+    (put "/"))
+  (flush)
+  (println "down with borders"))

 (defmulti add-element :type)
   (defmethod add-element :apple
-    [{x :x y :y}]
+    [board-view {x :x y :y}]

     (set-cursor (+ x 1) (+ y 1))
     (put "o"))
   (defmethod add-element :snake
-    [{x :x y :y}]
+    [board-view {x :x y :y}]

     (set-cursor (+ x 1) (+ y 1))
     (put "#"))

 (defn remove-element
-  [{x :x y :y}]
+  [board-view {x :x y :y}]

   (set-cursor (+ x 1) (+ y 1))
   (put " "))


(SERVER-1772) Typos, small changes, formatting

--- src/puppetlabs/ezbake/core.clj
+++ src/puppetlabs/ezbake/core.clj
@@ -7,15 +7,14 @@
             [clj-time.local :as local-time]
             [stencil.core :as stencil]
             [leiningen.core.main :as lein-main]
+            [leiningen.core.project :as project]
+            [leiningen.core.classpath :as lein-classpath]
             [leiningen.deploy :as deploy]
-            [leiningen.core.classpath :as lein-classpath]
             [leiningen.uberjar :as uberjar]
             [schema.core :as schema]
-            [schema.utils :as schema-utils]
             [puppetlabs.ezbake.dependency-utils :as deputils]
             [puppetlabs.ezbake.exec :as exec]
-            [puppetlabs.config.typesafe :as ts]
-            [leiningen.core.project :as project]))
+            [puppetlabs.config.typesafe :as ts]))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Vars
@@ -196,7 +195,7 @@
          :manifest-string (deputils/generate-manifest-string lein-project)
          :dependency-tree (deputils/generate-dependency-tree-string lein-project)
          :additional-uberjar-info uberjar-info
-         :has-additional-uberjars (not (empty? additional-uberjars-info))}]
+         :has-additional-uberjars (not-empty additional-uberjars-info)}]
     (spit
      (fs/file staging-dir "ext" "ezbake.manifest")
      (stencil/render-string "
@@ -564,11 +563,10 @@
 (schema/defn get-additional-uberjars
   "Returns the list of additional uberjar dependencies from the given lein project"
   [lein-project]
-  (when-let [dependencies-vector (get-in lein-project [:lein-ezbake :additional-uberjars])]
-    dependencies-vector))
+  (get-in lein-project [:lein-ezbake :additional-uberjars]))

 (schema/defn resolve-dependency! :- File
-  "Resolves a single dependency and returns a File pointing to it's jar.
+  "Resolves a single dependency and returns a File pointing to its jar.

   This has the side effect of fetching the whole dependency tree for the given
   dependency, but we only care about the one jar"


Optimize template.cljs a little

Optimize template.cljs a little

--- src/reagent/impl/template.cljs
+++ src/reagent/impl/template.cljs
@@ -51,21 +51,29 @@
             (util/dash-to-camel k)))
     k))

+(defn ^boolean js-val? [x]
+  (not (identical? "object" (goog/typeOf x))))
+
+(declare convert-prop-value)
+
+(defn kv-conv [o k v]
+  (doto o
+    (aset (cached-prop-name k)
+          (convert-prop-value v))))
+
 (defn convert-prop-value [x]
-  (cond (or (string? x) (number? x) (fn? x)) x
+  (cond (js-val? x) x
         (named? x) (name x)
-        (map? x) (reduce-kv (fn [o k v]
-                              (doto o
-                                (aset (cached-prop-name k)
-                                      (convert-prop-value v))))
-                            #js{} x)
+        (map? x) (reduce-kv kv-conv #js{} x)
         (coll? x) (clj->js x)
-        (ifn? x) (fn [& args] (apply x args))
+        (ifn? x) (fn [& args]
+                   (apply x args))
         true (clj->js x)))

 (defn set-id-class [props id class]
   (let [p (if (nil? props) #js{} props)]
-    (when (and (some? id) (nil? (.' p :id)))
+    (when (and (some? id)
+               (nil? (.' p :id)))
       (.! p :id id))
     (when (some? class)
       (let [old (.' p :className)]
@@ -250,10 +258,11 @@
         (-> [(reagent-input) argv comp jsprops first-child]
             (with-meta (meta argv))
             as-element)
-        (let [p (if-some [key (some-> (meta argv) get-key)]
+        (let [key (some-> (meta argv) get-key)
+              p (if (nil? key)
+                  jsprops
                   (doto (if (nil? jsprops) #js{} jsprops)
-                    (.! :key key))
-                  jsprops)]
+                    (.! :key key)))]
           (make-element argv comp p first-child))))))

 (defn str-coll [coll]
@@ -297,12 +306,12 @@
 (declare expand-seq-check)

 (defn as-element [x]
-  (cond (string? x) x
+  (cond (js-val? x) x
         (vector? x) (vec-to-elem x)
         (seq? x) (if (dev?)
                    (expand-seq-check x)
                    (expand-seq x))
-        true x))
+        :else x))

 (defn expand-seq [s]
   (let [a (into-array s)]


CLJS-1085: Allow to pass test environment to cljs.test/run-all-tests

--- src/clj/cljs/test.clj
+++ src/clj/cljs/test.clj
@@ -294,9 +294,10 @@
   Optional argument is a regular expression; only namespaces with
   names matching the regular expression (with re-matches) will be
   tested."
-  ([] `(cljs.test/run-all-tests nil))
-  ([re]
-   `(cljs.test/run-tests (cljs.test/empty-env)
+  ([] `(cljs.test/run-all-tests nil (cljs.test/empty-env)))
+  ([re] `(cljs.test/run-all-tests ~re (cljs.test/empty-env)))
+  ([re env]
+   `(cljs.test/run-tests ~env
       ~@(map
           (fn [ns] `(quote ~ns))
           (cond->> (ana-api/all-ns)


don't disappear password so quickly

don't disappear password so quickly

--- src/cljs/pw/core.cljs
+++ src/cljs/pw/core.cljs
@@ -53,7 +53,7 @@
     om/IDidUpdate
     (did-update [_ _ _]
       (when (:pass fetched)
-        (let [timeout-chan (timeout 3000)]
+        (let [timeout-chan (timeout 60000)]
           (.focus (om/get-node owner "result"))
           (.select (om/get-node owner "result"))
           (go (let [_ (<! timeout-chan)]


expose key-equality clause creation

expose key-equality clause creation

--- src/er_cassandra/key.clj
+++ src/er_cassandra/key.clj
@@ -38,6 +38,15 @@
   ([key record-or-key-value {:keys [collection] :as opts}]
    (extract-key-value* key record-or-key-value opts)))

+(defn key-equality-clause
+  [key key-value]
+  (let [key (make-sequential key)
+        key-value (make-sequential key-value)]
+    (mapv (fn [k v]
+            [:= k v])
+          key
+          key-value)))
+
 (defn extract-key-equality-clause
   "returns a Hayt key equality clause for use in a (when...) form"

@@ -47,10 +56,7 @@
   ([key record-or-key-value opts]
    (let [key (make-sequential key)
          kv (extract-key-value key record-or-key-value opts)]
-     (mapv (fn [k v]
-             [:= k v])
-           key
-           kv))))
+     (key-equality-clause key kv))))

 (defn extract-collection-key-components
   [coll record-or-key-value]


Add docstrings for complicated spec-for-field multimethod

--- src/graphql_clj/spec.clj
+++ src/graphql_clj/spec.clj
@@ -267,30 +267,39 @@
 ;; Multimethod to decomplect getting base-spec and parent-type-name for fields

 (defmulti spec-for-field
+  "Handle children of fragments, lists, and root fields differently"
   (fn [{:keys [v/path v/parent]} parent-node s]
     (cond (#{:fragment-definition :inline-fragment} (:node-type parent))         :fragment-child
           (= :LIST (:kind parent-node))                                          :list-child
           (and (= (count path) 2) (or (= (first path) (:query-root-name s))
                                       (= (first path) (:mutation-root-name s)))) :root-field)))

-(defmethod spec-for-field :fragment-child [{:keys [v/path v/parent]} _ s]
+(defmethod spec-for-field :fragment-child
+  "Child fields of named and inline fragments jump out of the nesting path to the top level"
+  [{:keys [v/path v/parent]} _ s]
   (let [parent-type-name (name (:base-spec parent))
         spec             (named-spec s [parent-type-name (last path)])
         base-spec        (:spec (get-type-node spec s))]
     {:n spec :m {:base-spec base-spec :parent-type-name parent-type-name}}))

-(defmethod spec-for-field :list-child [{:keys [v/path]} parent-node s]
+(defmethod spec-for-field :list-child
+  "Child fields of list types need to be unwrapped to get to the parent and base types"
+  [{:keys [v/path]} parent-node s]
   (let [{:keys [type-name inner-type]} parent-node
         parent-type-name (or (:type-name inner-type) type-name) ;; TODO multiple levels of nesting?
         base-named-spec  (named-spec s [parent-type-name (last path)])
         base-spec        (:spec (get-type-node base-named-spec s))]
     {:n base-named-spec :m {:parent-type-name parent-type-name :base-spec base-spec}}))

-(defmethod spec-for-field :root-field [{:keys [v/path]} _ s]
+(defmethod spec-for-field :root-field
+  "Root fields smuggle their base types via metadata from visitor bootstrap"
+  [{:keys [v/path]} _ s]
   (let [base-spec (named-spec s [(last (resolve-path path))])] ;; Convert rootField => TypeName
     (register-idempotent s path base-spec {:parent-type-name (first path) :base-spec base-spec})))

-(defmethod spec-for-field :default [{:keys [v/path]} parent-node s]
+(defmethod spec-for-field :default
+  "By default, link this field to its parent object type path"
+  [{:keys [v/path]} parent-node s]
   (let [parent-type-name (:type-name parent-node)
         base-spec  (named-spec s (conj (:v/path parent-node) (last path)))]
     {:n base-spec :m {:parent-type-name parent-type-name :base-spec base-spec}}))


RR: limit 1km, 500m binning to zoom levels above 10

--- src/hatti/views/map.cljs
+++ src/hatti/views/map.cljs
@@ -396,15 +396,13 @@
       (let [{{old-map-data :data
               old-field :geofield
               {old-cell-width :cell-width} :hexbins
-              old-viewby :view-by
-              old-style :style} :map-page} (om/get-props owner)
+              old-viewby :view-by} :map-page} (om/get-props owner)
             {{new-map-data :data
               new-field :geofield
               {show-hexbins? :show?
                new-cell-width :cell-width
                hide-points? :hide-points?} :hexbins
-              new-viewby :view-by
-              new-style :style} :map-page} next-props
+              new-viewby :view-by} :map-page} next-props
             {:keys [mapboxgl-map layer-id geojson]} (om/get-state owner)
             {:keys [flat-form]} (om/get-shared owner)
             data-changed? (or (not= old-field new-field)
@@ -500,29 +498,34 @@
     (init-state [_]
       {:slider-value 0
        :zoom->bin? true
-       :value->size {0 500 1 250 2 100 3 50 4 25 5 10 6 5 7 1 8 0.5}})
+       :value->size {0 500 1 250 2 100 3 50 4 25 5 10 6 5 7 1 8 0.5}
+       :max-bin 6})
     om/IWillReceiveProps
     (will-receive-props [_ next-props]
-      (when (om/get-state owner :zoom->bin?)
-        (when-let [map (-> next-props :map-page :mapboxgl-map)]
-          (let [zoom (.getZoom map)
-                value (condp #(<= %2 %1) zoom
-                        -1 nil
-                        2  0
-                        5  1
-                        8  2
-                        11 3
-                        14 4
-                        17 5
-                        20 6
-                        nil)]
-            (om/set-state! owner :slider-value value)))))
+      (let [map (-> next-props :map-page :mapboxgl-map)
+            zoom (when map (.getZoom map))
+            value (condp #(<= %2 %1) zoom
+                    -1 nil
+                    2  0
+                    5  1
+                    8  2
+                    11 3
+                    14 4
+                    17 5
+                    20 6
+                    nil)]
+        (when (om/get-state owner :zoom->bin?)
+          (om/set-state! owner :slider-value value))
+      ;; allow 1km and 500m binning on zoom levels above 10
+        (if (> zoom 10)
+          (om/set-state! owner :max-bin 8)
+          (om/set-state! owner :max-bin 6))))
     om/IWillUpdate
     (will-update [_ _ {:keys [slider-value value->size]}]
       (om/update! cursor [:map-page :hexbins :cell-width]
                   (get value->size slider-value)))
     om/IRenderState
-    (render-state [_ {:keys [slider-value value->size]}]
+    (render-state [_ {:keys [slider-value value->size max-bin]}]
       "Render layer selector component w/css + expansion technique from
       leaflet layer control."
       (html
@@ -542,7 +545,7 @@
                (str (cond-> cell-size below-1km? (* 1000))
                     (if below-1km? " Meters" " Km"))]]
              [:input.slider#slider
-              {:type "range" :min "0" :max "8" :step "1"
+              {:type "range" :min "0" :max (str max-bin) :step "1"
                :value slider-value
                :on-change update-cell-width}]
              [:input.show-points#show-points


show home page

show home page

--- src/stonecutter_client/handler.clj
+++ src/stonecutter_client/handler.clj
@@ -7,6 +7,7 @@
             [scenic.routes :refer [scenic-handler]]
             [stonecutter-client.routes :refer [routes path]]
             [stonecutter-client.logging :as log-config]
+            [stonecutter-client.view.home :as home]
             [clojure.tools.logging :as log]))

 (defn html-response [s]
@@ -15,7 +16,7 @@
       (r/content-type "text/html")))

 (defn home [request]
- (html-response "Hello World!"))
+ (html-response (home/home-page request)))

 (defn not-found [request]
   (html-response "404 PAGE NOT FOUND"))


sync with ClojureScript master, IParseStacktrace now takes original error value

--- Clojure/src/ambly/repl/jsc.clj
+++ Clojure/src/ambly/repl/jsc.clj
@@ -186,7 +186,7 @@

 (defrecord JscEnv [host port socket response-promise]
   repl/IParseStacktrace
-  (-parse-stacktrace [this stacktrace opts]
+  (-parse-stacktrace [this stacktrace error opts]
     (raw-stacktrace->canonical-stacktrace stacktrace opts))
   repl/IJavaScriptEnv
   (-setup [this opts]


CMR-3991 PR comments

CMR-3991 PR comments

--- umm-spec-lib/src/cmr/umm_spec/test/iso19115_expected_conversion.clj
+++ umm-spec-lib/src/cmr/umm_spec/test/iso19115_expected_conversion.clj
@@ -346,7 +346,7 @@
     (-> person
         (assoc :FirstName (first names))
         (assoc :MiddleName (str/join " " (subvec names 1 (dec num-names))))
-        (update :MiddleName #(when (not (empty? %)) %)) ; nil if empty
+        (update :MiddleName #(when (seq %) %)) ; nil if empty
         (assoc :LastName (last names))))))

 (defn- expected-contact-person


Disable Publish button for non-Agora configs [GAWB-3105] (#1203)

--- src/cljs/main/broadfcui/page/workspace/method_configs/method_config_editor.cljs
+++ src/cljs/main/broadfcui/page/workspace/method_configs/method_config_editor.cljs
@@ -81,7 +81,8 @@
                    redacted? name-validation-errors? snapshots
                    editing? locked? loaded-config body-id parent]} props
            can-edit? (common/access-greater-than? access-level "READER")
-           config-id (ws-common/config->id (:methodConfiguration loaded-config))]
+           config-id (ws-common/config->id (:methodConfiguration loaded-config))
+           source-repo (:sourceRepo (:methodRepoMethod (:methodConfiguration loaded-config)))]
        [:div {:style {:flex "0 0 270px" :paddingRight 30}}
         (when (:show-delete-dialog? @state)
           [delete/DeleteDialog (merge (utils/restructure config-id workspace-id after-delete)
@@ -125,7 +126,7 @@
                   :text "Delete" :icon :delete
                   :disabled? (when locked? "The workspace is locked")
                   :onClick #(swap! state assoc :show-delete-dialog? true)}])
-              (when-not redacted?
+              (when (and (not redacted?) (= source-repo "agora"))
                 [buttons/SidebarButton
                  {:style :light :color :button-primary :margin (when can-edit? :top)
                   :text "Publish..." :icon :share


[#818] show user roles in users-list

[#818] show user roles in users-list

--- Dashboard/app/cljs/src/org/akvo/flow/dashboard/users/users_list.cljs
+++ Dashboard/app/cljs/src/org/akvo/flow/dashboard/users/users_list.cljs
@@ -43,8 +43,7 @@
           " / "
           [:a {:on-click #(om/set-state! owner :confirm-delete? false)} "No"]]
          [:span
-          [:a {:on-click #(do (dispatch :user-auth/fetch nil)
-                              (dispatch :roles/fetch nil)
+          [:a {:on-click #(do
                               (dispatch :projects/fetch nil)
                               (on-action user))}
            (b/icon :pencil) " Edit"]
@@ -52,7 +51,16 @@
           [:a {:on-click #( om/set-state! owner :confirm-delete? true)}
            (b/icon :remove) " Delete"]])))))

-(defn columns [owner]
+(defn user-roles [user user-auth-store roles-store]
+  (let [user-id (get user "keyId")
+        role-ids (map #(get % "roleId")
+                      (user-auth-store/get-by-user-id user-auth-store user-id))
+        role-names (->> role-ids
+                        (map #(store/get-role roles-store %))
+                        (map #(get % "name")))]
+    (s/join ", " role-names)))
+
+(defn columns [owner user-auth-store roles-store]
   (let [on-action (fn [user]
                     (om/set-state! owner :current-user-id (get user "keyId")))]
     [{:title "User name"
@@ -61,10 +69,8 @@
      {:title "Email"
       :cell-fn #(get % "emailAddress")
       :sort-by "emailAddress"}
-     {:title "Permission list"
-      :cell-fn #(if (= (get % "permissionList") "10")
-                  "Admin"
-                  "User")}
+     {:title "Roles"
+      :cell-fn #(user-roles % user-auth-store roles-store)}
      {:title "Actions"
       :component user-actions
       :component-data-fn (fn [user]
@@ -83,7 +89,9 @@

     om/IDidMount
     (did-mount [this]
-      (dispatch :fetch-users nil))
+      (dispatch :fetch-users nil)
+      (dispatch :user-auth/fetch nil)
+      (dispatch :roles/fetch nil))

     om/IRenderState
     (render-state [this {:keys [current-user-id] :as state}]
@@ -108,7 +116,7 @@
                      :on-range (fn [offset limit]
                                  (om/set-state! owner :pagination {:offset offset :limit limit}))
                      :key-fn #(get % "keyId")
-                     :columns (columns owner)})]]
+                     :columns (columns owner user-auth user_roles)})]]
         [:div.mypanel {:class (if current-user-id "opened" "closed")}
          [:div
           (om/build user-details {:user (if (or (nil? current-user-id)


update boot-reload

update boot-reload

--- recipes/boot-setup/build.boot
+++ recipes/boot-setup/build.boot
@@ -5,7 +5,7 @@
   :rsc-paths #{"html"}
   :dependencies '[[adzerk/boot-cljs "0.0-2371-27" :scope "test"]
                   [adzerk/boot-cljs-repl "0.1.6" :scope "test"]
-                  [adzerk/boot-reload "0.1.6" :scope "test"]
+                  [adzerk/boot-reload "0.1.7" :scope "test"]
                   [org.clojure/clojure "1.7.0-alpha4"]
                   [org.clojure/clojurescript "0.0-2371"]
                   [om "0.8.0-beta1"]])


Add function for retrieving an optional injection

--- src/io/aviso/rook.clj
+++ src/io/aviso/rook.clj
@@ -12,6 +12,12 @@
   {:added "0.1.11"}
   [request injection-key]
   (internals/get-injection request injection-key))
+
+(defn find-injection
+  "Retrieves an optional injected value from the request, returning nil if the value does not exist."
+  {:added "0.1.11"}
+  [request injection-key]
+  (get-in request [::injections injection-key]))

 (defn inject*
   "Merges the provided map of injectable argument values into the request. Keys should be keywords
@@ -96,7 +102,7 @@
         [[\"quux\"] 'example.quux special-middleware])."
   [options? & ns-specs]
   (dispatcher/compile-dispatch-table (if (map? options?) options?)
-    (apply dispatcher/namespace-dispatch-table options? ns-specs)))
+                                     (apply dispatcher/namespace-dispatch-table options? ns-specs)))

 (defn- convert-middleware-form
   [handler-sym metadata-sym form]


Atom generator tag fix

Atom generator tag fix

--- src/io/perun/atom.clj
+++ src/io/perun/atom.clj
@@ -27,7 +27,7 @@
        [:title site-title]
        (if (seq description)
          [:subtitle description])
-       [:generator {:url "https://perun.io/" :rel "self"} "Perun"]
+       [:generator {:uri "https://perun.io/" :rel "self"} "Perun"]
        [:link {:href (str base-url filename) :rel "self"}]
        [:link {:href base-url :type "text/html"}]
        [:updated (->> (take 10 posts)


Improve Readability of empty? Implementation

--- src/lens/reducers.clj
+++ src/lens/reducers.clj
@@ -38,7 +38,7 @@
           (:ret result))))))

 (defn empty? [coll]
-  (zero? (reduce + (r/take 1 (r/map (constantly 1) coll)))))
+  (clojure.core/empty? (into [] (r/take 1 coll))))

 (defn count [coll]
   (reduce + (r/map (constantly 1) coll)))


bump gyptis-usage dependency

bump gyptis-usage dependency

--- examples/gyptis-usage/project.clj
+++ examples/gyptis-usage/project.clj
@@ -7,4 +7,4 @@
                  [org.clojure/java.jdbc "0.4.2"]
                  [com.h2database/h2 "1.4.190"]
                  [clj-http "2.0.0"]
-                 [gyptis "0.1.0-SNAPSHOT"]])
+                 [gyptis "0.2.0"]])


Add type that generates hash collisions for faster failing tests

--- test/clojure/lean_map/test.clj
+++ test/clojure/lean_map/test.clj
@@ -81,8 +81,19 @@
   (let [kvm (->> (zipmap (range 100) (range 100)) (into lmu/empty))]
     (t/is (= nil (try (seq-iter-match kvm kvm) (catch Exception e e))))))

+(deftype BadHashNumber [num]
+  Object
+  (toString [_]
+    (str "BadHashNumber. " num))
+  clojure.lang.IHashEq
+  (hasheq [_]
+    1))
+
+(def gen-bad-hash
+  (gen/fmap (partial apply ->BadHashNumber) (gen/tuple gen/int)))
+
 (def gen-key
-  (gen/tuple gen/int))
+  (gen/tuple (gen/frequency [[9 gen/int] [1 gen-bad-hash]])))

 (def gen-value
   (gen/tuple gen/int))


Wait until we have the first instrument before starting the draw loop

--- src/playmary/one.cljs
+++ src/playmary/one.cljs
@@ -189,7 +189,7 @@
   (go
    (let [draw-ctx (util/get-ctx canvas-id)]
      (util/set-canvas-size! canvas-id (util/get-window-size))
-     (loop [instrument nil]
+     (loop [instrument (<! c-instrument)]
        (let [[data c] (alts! [c-instrument (timeout 16)])]
          (condp = c
            c-instrument (recur data)


Update tests

Update tests

--- test/micro_logic/core_test.clj
+++ test/micro_logic/core_test.clj
@@ -1,11 +1,12 @@
 (ns micro-logic.core-test
   (:require [clojure.test :refer :all]
+            [micro-logic.protocols :refer :all]
             [micro-logic.core :refer :all]
-            [micro-logic.protocols :refer :all]
+            [micro-logic.sequence :refer :all]
             ))

-(defonce a (lvar :a))
-(defonce b (lvar :b))
+(def a (lvar :a))
+(def b (lvar :b))

 (deftest micro-logic-tests
   (testing "walk"


put keys in function position

put keys in function position

--- src/jasons_game/core.clj
+++ src/jasons_game/core.clj
@@ -71,9 +71,9 @@
 (defmulti text
   "Extracts the text of a sentence, phrase, or word"
   :type)
-(defmethod text :sentence [sentence] (join " " (map text (sentence :elements))))
-(defmethod text :phrase [phrase] (join " " (map text (phrase :words))))
-(defmethod text :word [word] (word :text))
+(defmethod text :sentence [sentence] (join " " (map text (:elements sentence))))
+(defmethod text :phrase [phrase] (join " " (map text (:words phrase))))
+(defmethod text :word [word] (:text word))

 ;; Environment


multi arity

multi arity

--- src/scrabble/core.clj
+++ src/scrabble/core.clj
@@ -101,9 +101,13 @@
   "Return all possible valid words from the given letters"
   ([letters]
    (anagrams letters (count letters)))
+
   ([letters max-size]
+   (anagrams letters max-size 1))
+
+  ([letters max-size min-size]
    (apply clojure.set/union
-          (for [size (range  max-size 1 -1)]
+          (for [size (range  max-size min-size -1)]
             (let [perms-words (perms-with-length letters size)]
               (intersection (set perms-words) (set all-words)))))))


fix two bugs at once

fix two bugs at once

--- src/seathree/data.clj
+++ src/seathree/data.clj
@@ -213,8 +213,8 @@
 (defn store-tweets [cfg user-data tweets]
   (let [tkey    (tweets-key user-data)
         last-id (:id (redis cfg #(car/lindex tkey 0)))
-        tweets  (if last-id (filter (partial < last-id) tweets) tweets)]
-    (redis cfg #(apply (partial car/lpush tkey) tweets))))
+        tweets  (if last-id (filter #(< last-id (:id %)) tweets) tweets)]
+    (redis cfg #(apply (partial car/lpush tkey) (reverse tweets)))))

 (defn refresh-tweets!
   "Actually ask for new tweets from twitter for the given user map. If


(maint) Update metrics test mocks for new scheduler

The tk-scheduler returns an opaque value when scheduling a job, that
value can then be used to stop said job.

In our metrics tests we mock out scheduling so we can control the
sampling of metrics within our tests. The garbage values that our mock
creates are saved by the service and then used to try and stop any
scheduled job on test shutdown.

Invalid values before were silently ignored, however now the scheduler
throws an error when attempting to stop an invalid job. But since this
occurs during test teardown it does not cause a test error.

This patch mocks out the scheduler stop-job protocol as well so it will
ignore the garbage ids our mock scheduling creates.

--- test/integration/puppetlabs/services/jruby/jruby_metrics_service_test.clj
+++ test/integration/puppetlabs/services/jruby/jruby_metrics_service_test.clj
@@ -262,7 +262,8 @@
         ;; when the sampling occurs.  Otherwise these tests would be very racy.
         sampling-scheduled?# (atom false)
         mock-schedule-metrics-sampler# (fn [_# _# _#] (reset! sampling-scheduled?# true))]
-    (with-redefs [puppetlabs.services.jruby.jruby-metrics-core/schedule-metrics-sampler! mock-schedule-metrics-sampler#]
+    (with-redefs [puppetlabs.services.jruby.jruby-metrics-core/schedule-metrics-sampler! mock-schedule-metrics-sampler#
+                  puppetlabs.trapperkeeper.services.protocols.scheduler/stop-job (constantly true)]
       (bootstrap/with-app-with-config
         app#
         (jruby-testutils/add-mock-jruby-pool-manager-service


(maint) Organize requires in jruby-puppet-pool-int-test

--- test/integration/puppetlabs/services/jruby/jruby_puppet_pool_int_test.clj
+++ test/integration/puppetlabs/services/jruby/jruby_puppet_pool_int_test.clj
@@ -1,44 +1,44 @@
 (ns puppetlabs.services.jruby.jruby-puppet-pool-int-test
   (:require [clojure.test :refer :all]
+            [clojure.java.io :as io]
             [clojure.set :as set]
-            [clojure.java.io :as io]
+            [clojure.tools.logging :as log]
+            [me.raynes.fs :as fs]
             [schema.test :as schema-test]
+            [puppetlabs.http.client.metrics :as metrics]
+            [puppetlabs.http.client.sync :as http-client]
+            [puppetlabs.kitchensink.core :as ks]
+            [puppetlabs.kitchensink.testutils :as ks-testutils]
+            [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap]
+            [puppetlabs.puppetserver.testutils :as testutils :refer
+             [ca-cert localhost-cert localhost-key ssl-request-options]]
+            [puppetlabs.services.config.puppet-server-config-service :as ps-config]
+            [puppetlabs.services.jruby.jruby-metrics-service :as jruby-metrics-service]
+            [puppetlabs.services.jruby.jruby-puppet-core :as jruby-puppet-core]
             [puppetlabs.services.jruby.jruby-puppet-testutils :as jruby-testutils]
-            [puppetlabs.trapperkeeper.app :as tk-app]
-            [puppetlabs.trapperkeeper.services :as tk-services]
+            [puppetlabs.services.jruby-pool-manager.impl.jruby-agents :as jruby-agents]
+            [puppetlabs.services.jruby-pool-manager.jruby-core :as jruby-core]
+            [puppetlabs.services.jruby-pool-manager.jruby-schemas :as jruby-schemas]
             [puppetlabs.services.protocols.jruby-puppet :as jruby-protocol]
-            [puppetlabs.puppetserver.bootstrap-testutils :as bootstrap]
-            [puppetlabs.trapperkeeper.services.webserver.jetty9-service :as jetty9]
-            [puppetlabs.http.client.sync :as http-client]
-            [me.raynes.fs :as fs]
-            [puppetlabs.trapperkeeper.internal :as tk-internal]
-            [puppetlabs.trapperkeeper.core :as tk]
-            [puppetlabs.services.jruby.jruby-metrics-service :as jruby-metrics-service]
+            [puppetlabs.services.protocols.request-handler :as handler]
+            [puppetlabs.services.request-handler.request-handler-core :as handler-core]
             [puppetlabs.services.request-handler.request-handler-service :as handler-service]
             [puppetlabs.services.versioned-code-service.versioned-code-service :as vcs]
-            [puppetlabs.services.config.puppet-server-config-service :as ps-config]
-            [puppetlabs.services.protocols.request-handler :as handler]
-            [puppetlabs.services.request-handler.request-handler-core :as handler-core]
             [puppetlabs.ssl-utils.core :as ssl-utils]
-            [puppetlabs.kitchensink.testutils :as ks-testutils]
-            [puppetlabs.puppetserver.testutils :as testutils :refer
-             [ca-cert localhost-cert localhost-key ssl-request-options]]
+            [puppetlabs.trapperkeeper.app :as tk-app]
+            [puppetlabs.trapperkeeper.config :as tk-config]
+            [puppetlabs.trapperkeeper.core :as tk]
+            [puppetlabs.trapperkeeper.internal :as tk-internal]
+            [puppetlabs.trapperkeeper.services :as tk-services]
+            [puppetlabs.trapperkeeper.services.protocols.metrics :as metrics-protocol]
+            [puppetlabs.trapperkeeper.services.webserver.jetty9-service :as jetty9]
+            [puppetlabs.trapperkeeper.testutils.bootstrap :as tk-testutils]
             [puppetlabs.trapperkeeper.testutils.logging :as logging]
-            [puppetlabs.trapperkeeper.services.protocols.metrics :as metrics-protocol]
-            [clojure.tools.logging :as log]
-            [puppetlabs.trapperkeeper.testutils.bootstrap :as tk-testutils]
-            [puppetlabs.kitchensink.core :as ks]
-            [puppetlabs.services.jruby.jruby-puppet-core :as jruby-puppet-core]
-            [puppetlabs.services.jruby-pool-manager.jruby-core :as jruby-core]
-            [puppetlabs.services.jruby-pool-manager.impl.jruby-agents :as jruby-agents]
-            [puppetlabs.trapperkeeper.config :as tk-config]
-            [puppetlabs.http.client.metrics :as metrics]
-            [puppetlabs.services.jruby-pool-manager.jruby-schemas :as jruby-schemas]
             [puppetlabs.trapperkeeper.testutils.logging :as logutils])
-  (:import (org.jruby RubyInstanceConfig$CompileMode RubyInstanceConfig$ProfilingMode)
+  (:import (com.codahale.metrics MetricRegistry)
            (java.io ByteArrayOutputStream)
+           (org.jruby RubyInstanceConfig$CompileMode RubyInstanceConfig$ProfilingMode)
            (org.jruby.embed EvalFailedException)
-           (com.codahale.metrics MetricRegistry)
            (org.jruby.runtime Constants)))

 (def test-resources-dir


Specify an eviction policy for the cache eviction test

Setting a :max-entries with no eviction policy causes the policy to
default to :lirs, which appears to be broken in infinispan 7.2.3 (which
ships with WildFly 9.0.0.Final). Using :lru works, so we use that
instead.

--- caching/test/immutant/caching_test.clj
+++ caching/test/immutant/caching_test.clj
@@ -227,7 +227,7 @@
               getCacheConfiguration eviction maxEntries))))

 (deftest test-eviction
-  (let [c (new-cache :max-entries 2)]
+  (let [c (new-cache :max-entries 2 :eviction :lru)]
     (.put c :a 1)
     (.put c :b 2)
     (.put c :c 3)


fix optional param :truncate passed to generate/generate

--- src/babel/english.cljc
+++ src/babel/english.cljc
@@ -44,7 +44,7 @@
    (log/debug (str "generating with spec: " (strip-refs spec) " with max-total-depth: " max-total-depth))
    (let [result (generate/generate spec model
                                    :max-total-depth max-total-depth
-                                   :truncate-children truncate-children)]
+                                   :truncate truncate-children)]
      (if (keyword? result)
        (throw (Exception. (str "please don't send me a keyword :( : this is what you sent me: " result)))
        (conj {:surface (morph result)}


Sync before REPL stuff

Sync before REPL stuff

--- src/brevis/ui/core.clj
+++ src/brevis/ui/core.clj
@@ -9,6 +9,7 @@
            java.awt.Font)
   (:require
     [clojure.tools.nrepl :as nrepl]
+    [clojure.tools.nrepl.misc :as nrepl.misc]
     [leiningen.repl :as repl]
     [leiningen.core.project :as project]
     [leiningen.core.eval :as eval]
@@ -176,14 +177,16 @@
               (text! (:text-area @repl-output-window) (.toString (get-repl-outputstream)))
               (try
                 (let [startPosition 0
-                      line (.getText textArea startPosition (- (.getLength (.getDocument textArea)) startPosition 1))]
+                      line (.getText textArea startPosition (- (.getLength (.getDocument textArea)) startPosition 1))
+                      session-sender (nrepl/client-session @reply.eval-modes.nrepl/current-connection :session @reply.eval-modes.nrepl/current-session)]
                   (.setText textArea "")
-                  (println "Sending to repl:" line)
-                  (reply.eval-modes.nrepl/execute-with-client (:client @repl) #_@reply.eval-modes.nrepl/current-connection
-                            (assoc {}
-                                   :read-input-line-fn (partial reply.reader.simple-jline/safe-read-line {:no-jline true :prompt-string ""})
-                                   :interactive true)
-                            line)
+                  (println "Sending to repl:" line)
+                  (session-sender {:op "eval" :code line :id (nrepl.misc/uuid)})
+                  #_(reply.eval-modes.nrepl/execute-with-client (:client @repl) #_@reply.eval-modes.nrepl/current-connection
+                             (assoc {}
+                                    :read-input-line-fn (partial reply.reader.simple-jline/safe-read-line {:no-jline true :prompt-string ""})
+                                    :interactive true)
+                             line)
                   #_(java.io.ByteArrayInputStream.
                      (.getBytes "(println 'foobar)\nexit\n(println 'foobar)\n"))
                   #_(System/setIn (ByteArrayInputStream. (.getBytes (str line "\n") "UTF-8")))
@@ -205,41 +208,6 @@
        :text-area textArea
        :scroll-pane sp
        :menus menus}))
-
-#_(defn repl-output-window
-     "Make a REPL output window."
-     [params]
-     (let [
-           textArea (RSyntaxTextArea. 25 115)
-           ;textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
-           ;textArea.setCodeFoldingEnabled(true);
-           sp (RTextScrollPane. textArea)
-
-           a-new (action :handler a-new :name "New" :tip "Create a new file.")
-           a-open (action :handler a-open :name "Open" :tip "Open a file")
-           a-save (action :handler a-save :name "Save" :tip "Save the current file.")
-           a-exit (action :handler a-exit :name "Exit" :tip "Exit the editor.")
-           a-copy (action :handler a-copy :name "Copy" :tip "Copy selected text to the clipboard.")
-           a-paste (action :handler a-paste :name "Paste" :tip "Paste text from the clipboard.")
-           a-cut (action :handler a-cut :name "Cut" :tip "Cut text to the clipboard.")
-           a-save-as (action :handler a-save-as :name "Save As" :tip "Save the current file.")
-           menus (menubar
-                   :items [(menu :text "File" :items [a-save a-save-as a-exit])
-                           (menu :text "Edit" :items [a-copy a-cut a-paste])])
-           f (frame :title "Brevis - REPL Output" :menubar menus)]
-       (.setSyntaxEditingStyle textArea (cond (= (:language params) :java)
-                                              (SyntaxConstants/SYNTAX_STYLE_JAVA)
-                                              :else
-                                              (SyntaxConstants/SYNTAX_STYLE_CLOJURE)))
-       (.setCodeFoldingEnabled textArea true)
-       (display f sp)
-       (-> f pack! show!)
-       #_(println (.getLocation f))
-       (.setLocation f 850 680)
-       {:frame f
-        :text-area textArea
-        :scroll-pane sp
-        :menus menus}))

 (defn make-repl-output-window
    "Make an editor window."


fix docstring, cleanup refactoring and eliminate premature impl of uri-prefix matcher

--- src/calfpath/route.clj
+++ src/calfpath/route.clj
@@ -290,9 +290,19 @@
 ;; ----- ensure matcher in routes -----

-(def make-uri-matcher
-  "Given a route spec map containing :uri key with URI-pattern as value, return a matcher fn to match the URI. If the
-  route spec does not contain :uri key then it is left intact."
+(def ^{:arglists '([route-spec matchex])} ensure-matchex
+  "Given a route spec not containing the :matchex key, assoc specified matchex into the spec. If the route spec already
+  contains :matchex then leave it intact."
+  (make-ensurer :matchex
+    (fn [spec matchex]
+      (assoc spec :matchex matchex))))
+
+
+(def ^{:arglists '([route-spec uri-finder])} make-uri-matcher
+  "Given a route spec not containing the :matcher key and containing URI-pattern string as value (found by uri-finder),
+  create a URI matcher and add it under the :matcher key. If the route spec already contains the :matcher key or if it
+  does not contain URI-pattern then the route spec is left intact. When adding matcher also add matchex unless the
+  :matchex key already exists."
   (make-ensurer :matcher
     (fn [spec uri-finder]
       (when-not (map? spec)
@@ -300,11 +310,8 @@
       (if-let [uri-pattern (uri-finder spec)]  ; assoc matcher only if URI matcher is intended
         (do
           (when-not (string? uri-pattern)
-            (i/expected "URI pattern to be retrievable as a string value" spec))
-          (let [uri-template (i/parse-uri-template i/default-separator uri-pattern)
-                ensure-matchex (make-ensurer :matchex
-                                 (fn [spec x]
-                                   (assoc spec :matchex x)))]
+            (i/expected "URI pattern to be a string" spec))
+          (let [uri-template (i/parse-uri-template i/default-separator uri-pattern)]
             (-> spec
               (assoc :matcher (fn [request]
                                 (when-let [params (Util/matchURI ^String (:uri request) uri-template)]
@@ -315,16 +322,17 @@
         spec))))

-(def make-method-matcher
-  "Given a route spec map containing :method key with method keyword (or keyword set) as value, return a matcher fn to
-  match the method. If the route spec does not contain :method key then it is left intact."
+(def ^{:arglists '([route-spec method-finder])} make-method-matcher
+  "Given a route spec not containing the :matcher key and containing HTTP-method keyword (or keyword set) as value
+  (found by method-finder), create a method matcher and add it under the :matcher key. If the route spec already
+  contains the :matcher key or if it does not contain HTTP-method keyword/set then the route spec is left intact. When
+  adding matcher also add matchex unless the :matchex key already exists."
   (make-ensurer :matcher
     (fn [spec method-finder]
       (when-not (map? spec)
         (i/expected "route spec to be a map" spec))
       (if-let [method (method-finder spec)]  ; assoc matcher only if method matcher is intended
-        (let [ensure-matchex (make-ensurer :matchex (fn [spec x]
-                                                      (assoc spec :matchex x)))]
+        (do
           (when-not (or (keyword? method)
                       (and (set? method)
                         (every? keyword? method)))
@@ -345,46 +353,3 @@
                                                   `(when (~method (:request-method ~request))
                                                      {}))))))
         spec))))
-
-
-;; ----- manipulate nested routes -----
-
-
-(defn cons-matcher
-  "Given a bunch of routes, nest all of them under a specified matcher."
-  [matcher routes]
-  [{:matcher matcher :nested routes}])
-
-
-(defn cons-uri-prefix-matcher
-  "Given a bunch of routes, nest all of them under a URI-prefix matcher."
-  [^String prefix routes {:keys [strip? replace? original-key]
-                          :as options}]
-  (cons-matcher
-    (let [plen (.length prefix)]
-      (cond
-        (and strip? replace?)       (fn [request]
-                                      (let [^String uri (:uri request)]
-                                        (when (and (.startsWith uri prefix)
-                                                (> (.length uri) plen))
-                                          {:request (assoc request
-                                                      :uri         (.substring uri plen)
-                                                      original-key uri)})))
-        (and strip? (not replace?)) (fn [request]
-                                      (let [^String uri (:uri request)]
-                                        (when (and (.startsWith uri prefix)
-                                                (> (.length uri) plen))
-                                          {:request (assoc request
-                                                      :uri (.substring uri plen))})))
-        (and (not strip?) replace?) (fn [request]
-                                      (let [^String uri (:uri request)]
-                                        (when (and (.startsWith uri prefix)
-                                                (> (.length uri) plen))
-                                          {:request (assoc request
-                                                      original-key uri)})))
-        :otherwise                  (fn [request]
-                                      (let [^String uri (:uri request)]
-                                        (when (and (.startsWith uri prefix)
-                                                (> (.length uri) plen))
-                                          {})))))
-    routes))


First kvs no-op change test.

First kvs no-op change test.

--- src/cbfg/test/kvs.cljs
+++ src/cbfg/test/kvs.cljs
@@ -126,8 +126,25 @@
                                (e n res3
                                   (dissoc (merge m3 {:status :ok})
                                           :changes)
-                                  (atake tkvs res-ch3)))))))
-                    )
+                                  (atake tkvs res-ch3))))
+                           (let [noop-change (fn [kvs change-sq]
+                                               [kvs {:status :ok :foo :bar}])
+                                 res-ch4 (achan tkvs)
+                                 m4 {:opaque @n
+                                     :res-ch res-ch4
+                                     :op :multi-change
+                                     :kvs-ident (:kvs-ident open)
+                                     :changes [noop-change]}]
+                             (aput tkvs cmd-ch m4)
+                             (and
+                              (e n (atake tkvs res-ch4)
+                                 (dissoc (merge m4 {:status :ok :foo :bar})
+                                         :changes)
+                                 nil)
+                              (e n (atake tkvs res-ch4)
+                                 (dissoc (merge m4 {:status :ok})
+                                         :changes)
+                                 (atake tkvs res-ch4))))))))
            "pass"
            (str "FAIL: on test-lane #" @n)))))


Added own cmd-handlers for t2.

Added own cmd-handlers for t2.

--- src/cbfg/world/t2.cljs
+++ src/cbfg/world/t2.cljs
@@ -2,13 +2,16 @@
   (:require-macros [cbfg.act :refer [act act-loop achan achan-buf aput atake atimeout]])
   (:require [cbfg.world.t1 :refer [prog-base-now prog-curr-now prog-evt
                                    wait-done addr-override-xy]]
-            [cbfg.fence]
-            [cbfg.lane]
-            [cbfg.world.lane]))
+            [cbfg.world.base]))
+
+(def cmd-handlers
+  {"add"   (fn [c] (assoc c :rq #(cbfg.world.base/example-add % c)))
+   "sub"   (fn [c] (assoc c :rq #(cbfg.world.base/example-sub % c)))
+   "count" (fn [c] (assoc c :rq #(cbfg.world.base/example-count % c)))
+   "close-lane" (fn [c] (assoc c :op :close-lane))})

 (defn world-vis-init [el-prefix init-event-delay]
-  (cbfg.world.t1/world-vis-init-t "cbfg.world.t2"
-                                  cbfg.world.lane/cmd-handlers el-prefix
+  (cbfg.world.t1/world-vis-init-t "cbfg.world.t2" cmd-handlers el-prefix
                                   cbfg.world.t1/ev-msg init-event-delay))

 ; --------------------------------------------


Added automatic mimetypes to file outputs.

--- vendor/compojure.clj
+++ vendor/compojure.clj
@@ -37,6 +37,14 @@
         (when (pos? len)
           (. out (write buffer 0 len))
           (recur (. in (read buffer))))))))
+
+(def *default-mimetype* "application/octet-stream")
+
+(defn context-mimetype
+  "Get the mimetype of a filename using the ServletContext."
+  [context filename]
+  (or (. context (getMimeType filename))
+      *default-mimetype*))

 (defn re-escape
   "Escape all special regex chars in a string s."
@@ -97,6 +105,8 @@
     (instance? java.io.File update)
       (let [out (. response (getOutputStream))
             in  (new FileInputStream update)]
+        (. response (setHeader
+          "Content-Type" (context-mimetype context (str update))))
         (pipe-stream in out))))

 (def #^{:doc
@@ -116,12 +126,13 @@
   '(method    (. request (getMethod))
     full-path (. request (getPathInfo))
     param    #(. request (getParameter %))
-    header   #(. request (getHeader %))))
+    header   #(. request (getHeader %))
+    mime     #(context-mimetype (str %))))

 (defmacro pseudo-servlet
   "Create a pseudo-servlet from a resource. It's not quite a real
   servlet because it's a function, rather than an HttpServlet object."
-  [resource]
+  [& resource]
   `(fn ~'[route context request response]
      (let ~(apply vector *resource-bindings*)
        (update-response ~'context ~'response (do ~@resource)))))
@@ -133,6 +144,10 @@
     (cons [method (parse-route route) resource]
           *resources*)))

+(def *default-resource*
+  (pseudo-servlet
+    (str "Path: " full-path)))
+
 (defn find-resource
   "Find the first resource that matches the HttpServletRequest"
   [#^HttpServletRequest request response]
@@ -142,23 +157,25 @@
                     (if (= meth method)
                       (if-let route-params (match-route route path)
                         (partial resource route-params) nil)))]
-    (some matches? *resources*)))
+    (or
+      (some matches? *resources*)
+      (partial *default-resource* {}))))

 (defmacro GET "Creates a GET resource."
   [route & body]
-  `(add-resource "GET" ~route (pseudo-servlet ~body)))
+  `(add-resource "GET" ~route (pseudo-servlet ~@body)))

 (defmacro PUT "Creates a PUT resource."
   [route & body]
-  `(add-resource "POST" ~route (pseudo-servlet ~body)))
+  `(add-resource "POST" ~route (pseudo-servlet ~@body)))

 (defmacro POST "Creates a POST resource."
   [route & body]
-  `(add-resource "PUT" ~route (pseudo-servlet ~body)))
+  `(add-resource "PUT" ~route (pseudo-servlet ~@body)))

 (defmacro DELETE "Creates a DELETE resource."
   [route & body]
-  `(add-resource "DELETE" ~route (pseudo-servlet ~body)))
+  `(add-resource "DELETE" ~route (pseudo-servlet ~@body)))

 (def #^{:doc
   "A servlet that handles all requests into Compojure. Suitable for


get gasplan compiling again.

get gasplan compiling again.

--- src/angelic/search/action_set/gasplan.clj
+++ src/angelic/search/action_set/gasplan.clj
@@ -1,8 +1,12 @@
-(ns angelic.gasplan
+(ns angelic.search.action-set.gasplan
   (:require [edu.berkeley.ai.util :as util]
-            [edu.berkeley.ai.util  [graphs :as graphs] ]
-            [angelic [env :as env]  [hierarchy :as hierarchy]
-                 [sas :as sas] [sas-analysis :as sas-analysis]])
+            [edu.berkeley.ai.util.graphs :as graphs]
+            [angelic.env :as env]
+            [angelic.env.util :as env-util]
+            [angelic.env.state :as state]
+            [angelic.hierarchy :as hierarchy]
+            [angelic.sas :as sas]
+            [angelic.sas.analysis :as sas-analysis])
   (:import [java.util HashMap]))

@@ -55,7 +59,7 @@
   (assert (contains? effect-map target-var))
   (let [eval (effect-map target-var)
         pval? (contains? precond-map target-var)]
-    (env/env-util/make-factored-primitive
+    (env-util/make-factored-primitive
      [::AddAction name]
      (if pval? {(action-var target-var) nil, target-var (get precond-map target-var), (free-var target-var) false}
          {(action-var target-var) nil, (free-var target-var) false})
@@ -63,7 +67,7 @@
      reward)))

 (defn make-set-parent-var-action [p-var c-var]
-  (env/env-util/make-factored-primitive
+  (env-util/make-factored-primitive
    [::SetParent p-var c-var]
    {(free-var p-var) true}
    {(free-var p-var) false (parent-var p-var c-var) true}
@@ -82,7 +86,7 @@
                (every? #(state/get-var s (parent-var % effect-var)) unfree-pv))
         (util/assert-is (every? #(nil? (state/get-var s (action-var %))) precond-vars) ); "%s" [name effect-var (println s)])
         (util/assert-is (every? #(nil? (state/get-var s (action-var %))) effect-vars))
-        (env/env-util/make-factored-primitive
+        (env-util/make-factored-primitive
          [::GreedyFire name]
          (into precond-map
                (concat [[(action-var effect-var) factored-primitive]]
@@ -169,13 +173,13 @@

 ; Ideally, should prefer top-most top-down, bottom-most bottom-up, or something...

-(deftype GASPlanEnv [init actions-fn g-map]
+(defrecord GASPlanEnv [init actions-fn g-map]
   env/Env
-    (initial-state [_] init)
-    (actions-fn    [] actions-fn)
-    (goal-fn       [] #(when (state/state-matches-map? % g-map) (env/solution-and-reward %)))
+    (initial-state [this] init)
+    (actions-fn    [this] actions-fn)
+    (goal-fn       [this] #(when (state/state-matches-map? % g-map) (env/solution-and-reward %)))
   env/FactoredEnv
-    (goal-map      [] g-map))
+    (goal-map      [this] g-map))

 (defn make-gasplan-env [sas-problem]
   (def *add-count* (util/sref 0))
@@ -188,7 +192,7 @@
         dtgs          (sas-analysis/domain-transition-graphs sas-problem)
         simple-dtgs   (util/map-vals (fn [dtg] (for [[pval emap] dtg, [eval _] emap] [pval eval])) dtgs)
         acyclic-succ-fn (partial possibly-acyclic-successors (HashMap.) simple-dtgs)]
-    (GASPlanEnv
+    (GASPlanEnv.
      (expand-initial-state (env/initial-state sas-problem) child-var-map (goal-action dtgs))
      (fn gasplan-actions [s]
       (when-not (deadlocked? s child-var-map []);)


Take into account wrong input formatting from the websocket

--- src-cljs/photon/ui/ws.cljs
+++ src-cljs/photon/ui/ws.cljs
@@ -60,11 +60,12 @@
         (do
           (>! ws-channel {:ok true})
           (loop [elem (<! ws-channel)]
-            (when-not (or (nil? elem) (nil? (:projections (:message elem))))
+            (when-not (nil? elem)
               (if (contains? elem :error)
                 (do
                   #_(.log js/console (pr-str elem)))
-                (upd {:projections (:projections (:message elem))}))
+                (when-not (nil? (:projections (:message elem)))
+                  (upd {:projections (:projections (:message elem))})))
               (>! ws-channel {:ok true})
               (recur (<! ws-channel)))))
         (do (.log js/console "Error:" (pr-str error)))))))
@@ -84,26 +85,33 @@
                  previous-processed 0
                  previous-incoming 0
                  is-first? true]
-            (when-not (or (nil? elem) (nil? (:stats (:message elem))))
+            (when-not (nil? elem)
               (if (contains? elem :error)
                 (.log js/console (pr-str elem))
-                (let [stats-from-msg (:stats (:message elem))
-                      new-processed (get-chart-data (:processed stats-from-msg) previous-processed last-25-processed is-first?)
-                      new-incoming (get-chart-data (:incoming stats-from-msg) previous-incoming last-25-incoming is-first?)
-                      used-memory (- (:total-memory stats-from-msg) (:available-memory stats-from-msg))
-                      used-memory-percentage (int (* (/ used-memory (:total-memory stats-from-msg)) 100))
-                      new-memory (into [] (take-last 25 (conj last-25-memory used-memory-percentage)))
-                      new-timestamps (into [] (take-last 25 (conj timestamps (.getTime (js/Date.)))))
-                      stats (assoc stats-from-msg :last-25 {:processed new-processed
-                                                            :incoming new-incoming
-                                                            :memory new-memory
-                                                            :timestamps new-timestamps})]
-                  (when (< (last new-processed) 0) (println "SOMETHING WRONG!"))
-                  (when-not is-first? (upd {:stats stats}))
-                  (>! ws-channel {:ok true})
-                  (recur (<! ws-channel) new-processed new-incoming new-memory
-                         new-timestamps (:processed stats-from-msg) (:incoming stats-from-msg)
-                         false))))))
+                (if (nil? (:stats (:message elem)))
+                  (do
+                    (println "problem with" (:message elem))
+                    (>! ws-channel {:ok true})
+                    (recur (<! ws-channel) last-25-processed last-25-incoming
+                           last-25-memory timestamps previous-processed
+                           previous-incoming is-first?))
+                  (let [stats-from-msg (:stats (:message elem))
+                        new-processed (get-chart-data (:processed stats-from-msg) previous-processed last-25-processed is-first?)
+                        new-incoming (get-chart-data (:incoming stats-from-msg) previous-incoming last-25-incoming is-first?)
+                        used-memory (- (:total-memory stats-from-msg) (:available-memory stats-from-msg))
+                        used-memory-percentage (int (* (/ used-memory (:total-memory stats-from-msg)) 100))
+                        new-memory (into [] (take-last 25 (conj last-25-memory used-memory-percentage)))
+                        new-timestamps (into [] (take-last 25 (conj timestamps (.getTime (js/Date.)))))
+                        stats (assoc stats-from-msg :last-25 {:processed new-processed
+                                                              :incoming new-incoming
+                                                              :memory new-memory
+                                                              :timestamps new-timestamps})]
+                    (when (< (last new-processed) 0) (println "SOMETHING WRONG!"))
+                    (when-not is-first? (upd {:stats stats}))
+                    (>! ws-channel {:ok true})
+                    (recur (<! ws-channel) new-processed new-incoming new-memory
+                           new-timestamps (:processed stats-from-msg) (:incoming stats-from-msg)
+                           false)))))))
         (do
           (.log js/console "Error:" (pr-str error)))))))

@@ -116,12 +124,13 @@
         (do
           (>! ws-channel {:projection-name "__streams__"})
           (loop [elem (<! ws-channel)]
-            (when-not (or (nil? elem) (nil? (:current-value (:message elem))))
+            (when-not (nil? elem)
               (if (contains? elem :error)
                 (do #_(.log js/console (pr-str elem)))
-                (let [streams-proj (:message elem)]
-                  (upd {:streams
-                        (proj->streams (:current-value streams-proj))})))
+                (when-not (nil? (:current-value (:message elem)))
+                  (let [streams-proj (:message elem)]
+                    (upd {:streams
+                          (proj->streams (:current-value streams-proj))}))))
               (>! ws-channel {:projection-name "__streams__"})
               (recur (<! ws-channel)))))
         (do #_(.log js/console "Error:" (pr-str error)))))))


misnamed Order & Chaos cards correction

misnamed Order & Chaos cards correction

--- src/node/game/cards.cljs
+++ src/node/game/cards.cljs
@@ -527,6 +527,11 @@
    "Grappling Hook"
    {:abilities [{:msg "break all but 1 subroutine" :effect (effect (trash card))}]}

+   "Gravedigger"
+   {:events {:trash {:req (req (and (= (first (:zone target)) :servers) (= (:side target) "Corp")))
+                     :effect (effect (add-prop :runner card :counter 1))}}
+    :abilities [{:counter-cost 1 :cost [:click 1] :effect (effect (mill :corp))}]}
+
    "Green Level Clearance"
    {:effect (effect (gain :credit 3) (draw))}

@@ -571,11 +576,6 @@
    {:abilities [{:msg "access all cards in Archives"
                  :effect (effect (handle-access (:discard corp)) (trash card))}]}

-   "Harbinger"
-   {:events {:trash {:req (req (and (= (first (:zone target)) :servers) (= (:side target) "Corp")))
-                     :effect (effect (add-prop :runner card :counter 1))}}
-    :abilities [{:counter-cost 1 :cost [:click 1] :effect (effect (mill :corp))}]}
-
    "Hard at Work"
    {:events {:runner-turn-begins {:msg "gain 2 [Credits] and lose [Click]"
                                   :effect (effect (lose :click 1) (gain :credit 2))}}}
@@ -677,6 +677,9 @@
    {:abilities [{:counter-cost 1 :label "Add strength to a rezzed ICE"
                  :msg (msg "add " (:counter card) " strength to a rezzed ICE")}
                 {:cost [:click 1] :msg "add 1 counter" :effect (effect (add-prop card :counter 1))}]}
+
+   "I've Had Worse"
+   {:effect (effect (draw 3))}

    "Ixodidae"
    {:events {:corp-loss {:req (req (= (first target) :credit)) :msg "to gain 1 [Credits]"
@@ -1289,9 +1292,6 @@
    "Spooned"
    {:prompt "Choose a server" :choices (req servers) :effect (effect (run target))}

-   "Steelskin"
-   {:effect (effect (draw 3))}
-
    "Stim Dealer"
    {:events {:runner-turn-begins
              {:effect #(if (>= (:counter %3) 2)
@@ -1377,14 +1377,6 @@
    {:effect (effect (gain :link 2 :memory 2)) :leave-play (effect (lose :link 2 :memory 2))
     :recurring 2}

-   "Woman in the Red Dress"
-   {:events {:runner-turn-begins
-             {:msg (msg "reveal " (:title (first (:deck corp))) " on the top of R&D")
-              :optional {:prompt (msg "Draw " (:title (first (:deck corp))) "?")
-                         :msg (msg "draw " (:title (first (:deck corp))))
-                         :no-msg "doesn't draw with Woman in the Red Dress"
-                         :player :corp :effect (effect (draw))}}}}
-
    "Three Steps Ahead"
    {:end-turn {:effect (effect (gain :credit (* 2 (count (:successful-run runner-reg)))))
                :msg (msg "gain " (* 2 (count (:successful-run runner-reg))) " [Credits]")}}
@@ -1485,6 +1477,14 @@

    "Witness Tampering"
    {:effect (effect (lose :bad-publicity 2))}
+
+   "Woman in the Red Dress"
+   {:events {:runner-turn-begins
+             {:msg (msg "reveal " (:title (first (:deck corp))) " on the top of R&D")
+              :optional {:prompt (msg "Draw " (:title (first (:deck corp))) "?")
+                         :msg (msg "draw " (:title (first (:deck corp))))
+                         :no-msg "doesn't draw with Woman in the Red Dress"
+                         :player :corp :effect (effect (draw))}}}}

    "Wyldside"
    {:events {:runner-turn-begins {:msg "draw 2 cards and lose [Click]"


better subline in slogan

better subline in slogan

--- frontend/components/landing-b.cljs
+++ frontend/components/landing-b.cljs
@@ -36,11 +36,11 @@
                    (common/ico :logo)]]]
                 [:div.intro-slogan
                  [:h1.slogan-tagline {:title "Your org needs a hero."
-                                     :alt "We just need authorization first."}
+                                      :alt "We just need authorization first."}
                   "Your org needs a hero."]
-                 [:h3.slogan-subline {:title "Testing is hard. Help your team focus on product, we'll handle your"
+                 [:h3.slogan-subline {:title "You have a product to focus on, let Circle handle your"
                                       :alt "Why? Because signing up with your GitHub account lets Circle start your tests really fast."}
-                  "Testing is hard. Help your team focus on product, we'll handle your"]
+                  "You have a product to focus on, let Circle handle your"]
                  [:h3.slogan-subline {:title "Continuous Integration & Deployment."
                                       :alt "Note, without fine-grained scopes, GitHub requires us to request them in bulk."}
                   "Continuous Integration & Deployment."]]


remove extra/unnecessary bottom shelf

remove extra/unnecessary bottom shelf

--- frontend/components/landing_b.cljs
+++ frontend/components/landing_b.cljs
@@ -215,11 +215,7 @@
                   [:p
                    [:a.shopify-link
                     "See how Shopify does it"
-                    (common/ico :slim-arrow-right)]]]]
-                [:div.home-bottom-shelf
-                 [:a {:on-click #(put! controls-ch [:home-scroll-one-clicked])}
-                  "Learn more"
-                  (common/ico :chevron-down)]]]
+                    (common/ico :slim-arrow-right)]]]]]
                [:section.home-practice
                 [:div.practice-tools
                  [:article


don't set as much unnecessary state in the scroll handler

--- frontend/components/landing_b.cljs
+++ frontend/components/landing_b.cljs
@@ -42,7 +42,8 @@
                           (om/set-state! owner [:first-fig-animate] (< (.-bottom (.getBoundingClientRect purpose-article)) vh))
                           (om/set-state! owner [:second-fig-animate] (< (.-bottom (.getBoundingClientRect potential-article)) vh))
                           (om/set-state! owner [:header-bkg-scroller] (min (js/Math.abs (.-top (.getBoundingClientRect home-epilog)))
-                                                                           (js/Math.abs (- nav-height (.-bottom (.getBoundingClientRect home-prolog)))))))]
+                                                                           (js/Math.abs (- nav-height (.-bottom (.getBoundingClientRect home-prolog))))
+                                                                           nav-height)))]
     (om/set-state! owner [:scroll-key]
                    (goog.events/listen
                     js/window


Ensure client component is closed in feedback-exception!

--- src/onyx/test_helper.clj
+++ src/onyx/test_helper.clj
@@ -103,10 +103,15 @@
 (defn feedback-exception!
   "Feeds an exception that killed a job back to a client.
    Blocks until the job is complete."
-  [peer-config job-id]
-  (let [client (component/start (system/onyx-client peer-config))]
-    (when-not (onyx.api/await-job-completion peer-config job-id)
-      (throw (extensions/read-chunk (:log client) :exception job-id)))))
+  ([peer-config job-id]
+   (let [client (component/start (system/onyx-client peer-config))]
+     (try
+       (feedback-exception! peer-config job-id (:log client))
+       (finally
+         (component/stop client)))))
+  ([peer-config job-id log]
+   (when-not (onyx.api/await-job-completion peer-config job-id)
+     (throw (extensions/read-chunk log :exception job-id)))))

 (defrecord DummyInput []
   p-ext/Pipeline


Replace get-key-frame with animation-image

--- src/play_clj/core_2d.clj
+++ src/play_clj/core_2d.clj
@@ -69,8 +69,8 @@
                (utils/gdx-static-field :graphics :g2d :Animation
                                        ~(or (first args) :normal))))

-(defn get-key-frame
+(defn animation-image
   ([screen ^Animation animation]
-    (.getKeyFrame animation (:total-time screen) true))
+    (create-entity (.getKeyFrame animation (:total-time screen) true)))
   ([screen ^Animation animation is-looping?]
-    (.getKeyFrame animation (:total-time screen) is-looping?)))
+    (create-entity (.getKeyFrame animation (:total-time screen) is-looping?))))


casing failure

casing failure

--- src/frontend/proxy.clj
+++ src/frontend/proxy.clj
@@ -38,7 +38,7 @@
                     ;; fact that the backend was gzipped.
                     (dissoc "content-encoding")
                     ;; avoid setting two Dates!  httpkit here will insert another Date
-                    (dissoc "Date")
+                    (dissoc "date")
                     ;; The production server insists on secure cookies, but
                     ;; the development proxy does not support SSL.
                     strip-secure)]