It feels a bit cleaner to merge these protocol methods

--- src/cljs_rest/core.cljs
+++ src/cljs_rest/core.cljs
@@ -39,34 +39,31 @@
   (extend-protocol InfersRequestOptions
     MyTransitType
     (-opts [_] {:accept \"application/transit+json\"})
-    (-params-key [_] :transit-params)
-    (-params [this] this))"
+    (-params [this] {:transit-params this}))"

   (-opts [_] "Returns arbitrary request options for params type")
-  (-params-key [_] "Returns the cljs-http params key for request options")
-  (-params [_] "Returns the cljs-http params for request options"))
+  (-params [_] "Returns a map of cljs-http params for request options"))

 (extend-protocol InfersRequestOptions
   js/FormData
-  (-params-key [_] :body)
+  (-params [form-data] {:body form-data})

   nil
-  (-params-key [_] nil)
+  (-params [_] nil)

   default
   (-opts [x] (request-defaults x))
-  (-params-key [x]
+  (-params [x]
     ;; The conversion to JSON or similar serializations depends on `clj->js`,
     ;; which for our purposes is restricted to types satisfying ICollection.
-    (if (coll? x)
-        (collection-format->params-key (:collection-format @config) :params)
-        :params))
-  (-params [x] x))
+    (let [k (if (coll? x)
+                (collection-format->params-key (:collection-format @config) :params)
+                :params)]
+      {k x})))

 (defrecord MultipartParams []
   InfersRequestOptions
-  (-params-key [_] :multipart-params)
-  (-params [this] (seq this)))
+  (-params [this] {:multipart-params (seq this)}))

 (def multipart-params map->MultipartParams)

@@ -74,8 +71,7 @@
 ;; a specific order.
 (deftype OrderedMultipartParams [xs]
   InfersRequestOptions
-  (-params-key [_] :multipart-params)
-  (-params [_] xs))
+  (-params [_] {:multipart-params xs}))

 (defn ordered-multipart-params [xs]
   {:pre [(seqable? xs)]}
@@ -85,13 +81,11 @@
   (let [params (:params opts)
         base-opts (-opts params)
         opts* (merge base-opts opts)
-        k (-params-key params)
-        v (or (get opts* k) (-params params))]
+        params* (-params params)]
     (-> opts*
         (dissoc :params)
-        (assoc
-          k v
-          :url url)
+        (merge params*)
+        (assoc :url url)
         (dissoc nil))))

 (defn put-error! [opts error]


Add shapes support.

Add shapes support.

--- src/cljx/quil/core.cljx
+++ src/cljx/quil/core.cljx
@@ -3584,7 +3584,6 @@
     (let [mode (resolve-constant-key kind shader-modes)]
       (.shader (current-graphics) shader mode))))

-#+clj
 (defn
   ^{:requires-bindings true
     :processing-name "shape()"
@@ -3660,7 +3659,6 @@
   [angle]
   (.shearY (current-graphics) (float angle)))

-#+clj
 (defn ^{:requires-bindings true
         :processing-name "shapeMode()"
         :category "Shape"


Swap parameters of new-cons

Swap parameters of new-cons

--- src/cljx/revue/mem.cljx
+++ src/cljx/revue/mem.cljx
@@ -200,11 +200,22 @@
   "Allocate a new `VmCons` cell.  The `car` and `cdr` parameters have
   to be `StoredData`.  Return the new cons cell reference and the new
   store."
-  [[car cdr] store]
+  [store [car cdr]]
   (let [address (count store)
         new-store (conj store car cdr)]
     [(->VmCons address) new-store]))

+(defn cons-first [store xs]
+  "Return the first element of a `VmCons` cell."
+  (if (empty? xs)
+    ()
+    (nth store (-address xs store))))
+
+(defn cons-rest [store xs]
+  "Return the rest of a `VmCons` cell."
+  (if (empty? xs)
+    ()
+    (nth store (inc (-address xs store)))))

 ;;; A `VmVector` is a reference to a vector occupying a contiguous
 ;;; part of the heap.  Vectors correspond to arrays in C or vectors in
@@ -362,7 +373,7 @@
                                    [() store]
                                    this)]
       (reduce (fn [[vm-cons store] d]
-                (new-cons [d vm-cons] store))
+                (new-cons store [d vm-cons]))
               [() new-store]
               elts)))
   #+clj clojure.lang.PersistentVector #+cljs cljs.core/PersistentVector


bugfix: syntax that works with both lein 1.7 and lein 2.3

--- src/clojure/project.clj
+++ src/clojure/project.clj
@@ -11,6 +11,6 @@
                  [org.clojure/tools.cli "0.2.4"]
                  [clojurewerkz/cassaforte "1.1.0"]
                  [org.clojure/tools.logging "0.2.6"]
-                 [org.apache.zookeeper/zookeeper "3.4.5" :exclusions [[javax.jms/jms]
-                                                                      [com.sun.jmx/jmxri]
-                                                                      [com.sun.jdmk/jmxtools]]]])
+                 [org.apache.zookeeper/zookeeper "3.4.5" :exclusions [javax.jms/jms
+                                                                      com.sun.jmx/jmxri
+                                                                      com.sun.jdmk/jmxtools]]])


CMR-5260: Fixed existing intermittent failing spatial validation tests; minor code cleanup.

--- system-int-test/test/cmr/system_int_test/ingest/granule_validation_test.clj
+++ system-int-test/test/cmr/system_int_test/ingest/granule_validation_test.clj
@@ -328,55 +328,50 @@
             :errors errors}
            (select-keys response [:status :errors])))))

-;; This tests that UMM type validations are applied during collection ingest.
-;; Thorough tests of UMM validations should go in cmr.umm.test.validation.core and related
-;; namespaces.
-(deftest granule-umm-validation-test
-  (testing "Spatial validation"
-    (testing "geodetic polygon"
-      ;; Invalid points are caught in the schema validation
-      (assert-invalid-spatial
-        :geodetic
-        "GEODETIC"
-        [(polygon 180 90, -180 90, -180 -90, 180 -90, 180 90)]
-        ["Spatial validation error: The shape contained duplicate points. Points 1 [lon=180 lat=90] and 2 [lon=-180 lat=90] were considered equivalent or very close."
-         "Spatial validation error: The shape contained duplicate points. Points 3 [lon=-180 lat=-90] and 4 [lon=180 lat=-90] were considered equivalent or very close."
-         "Spatial validation error: The shape contained consecutive antipodal points. Points 2 [lon=-180 lat=90] and 3 [lon=-180 lat=-90] are antipodal."
-         "Spatial validation error: The shape contained consecutive antipodal points. Points 4 [lon=180 lat=-90] and 5 [lon=180 lat=90] are antipodal."]))
-    (testing "geodetic polygon with holes"
-      ;; Hole validation is not supported yet. See CMR-1173.
-      ;; Holes are ignored during validation for now.
-      (assert-valid-spatial
-        :geodetic
-        "GEODETIC"
-        [(poly/polygon [(umm-s/ords->ring 1 1, -1 1, -1 -1, 1 -1, 1 1)
-                        (umm-s/ords->ring 0,0, 0.00004,0, 0.00006,0.00005, 0.00002,0.00005, 0,0)])]))
-    (testing "cartesian polygon"
-      ;; The same shape from geodetic is valid as a cartesian.
-      ;; Cartesian validation is not supported yet. See CMR-1172
-      (assert-valid-spatial :cartesian "CARTESIAN"
-                            [(polygon 180 90, -180 90, -180 -90, 180 -90, 180 90)]))
-
-    (testing "geodetic line"
-      (assert-invalid-spatial
-        :geodetic
-        "GEODETIC"
-        [(l/ords->line-string :geodetic [0,0,1,1,2,2,1,1])]
-        ["Spatial validation error: The shape contained duplicate points. Points 2 [lon=1 lat=1] and 4 [lon=1 lat=1] were considered equivalent or very close."]))
-
-    (testing "cartesian line"
-      ;; Cartesian line validation isn't supported yet. See CMR-1172
-      (assert-valid-spatial
-        :cartesian
-        "CARTESIAN"
-        [(l/ords->line-string :cartesian [180 0, -180 0])]))
-
-    (testing "bounding box"
-      (assert-invalid-spatial
-        :geodetic
-        "GEODETIC"
-        [(m/mbr -180 45 180 46)]
-        ["Spatial validation error: The bounding rectangle north value [45] was less than the south value [46]"]))))
+(deftest granule-geodetic-spatial-validation-test
+  (testing "geodetic polygon"
+    ;; Invalid points are caught in the schema validation
+    (assert-invalid-spatial
+     :geodetic
+     "GEODETIC"
+     [(polygon 180 90, -180 90, -180 -90, 180 -90, 180 90)]
+     ["Spatial validation error: The shape contained duplicate points. Points 1 [lon=180 lat=90] and 2 [lon=-180 lat=90] were considered equivalent or very close."
+      "Spatial validation error: The shape contained duplicate points. Points 3 [lon=-180 lat=-90] and 4 [lon=180 lat=-90] were considered equivalent or very close."
+      "Spatial validation error: The shape contained consecutive antipodal points. Points 2 [lon=-180 lat=90] and 3 [lon=-180 lat=-90] are antipodal."
+      "Spatial validation error: The shape contained consecutive antipodal points. Points 4 [lon=180 lat=-90] and 5 [lon=180 lat=90] are antipodal."]))
+
+  (testing "geodetic polygon with holes"
+    (assert-valid-spatial
+     :geodetic
+     "GEODETIC"
+     [(poly/polygon [(umm-s/ords->ring 1 1, -1 1, -1 -1, 1 -1, 1 1)
+                     (umm-s/ords->ring 0,0, 0.00004,0, 0.00006,0.00005, 0.00002,0.00005, 0,0)])]))
+
+  (testing "geodetic line"
+    (assert-invalid-spatial
+     :geodetic
+     "GEODETIC"
+     [(l/ords->line-string :geodetic [0,0,1,1,2,2,1,1])]
+     ["Spatial validation error: The shape contained duplicate points. Points 2 [lon=1 lat=1] and 4 [lon=1 lat=1] were considered equivalent or very close."]))
+
+  (testing "bounding box"
+    (assert-invalid-spatial
+     :geodetic
+     "GEODETIC"
+     [(m/mbr -180 45 180 46)]
+     ["Spatial validation error: The bounding rectangle north value [45] was less than the south value [46]"])))
+
+(deftest granule-cartesian-spatial-validation-test
+  (testing "cartesian polygon"
+    ;; The same shape from geodetic is valid as a cartesian.
+    (assert-valid-spatial :cartesian "CARTESIAN"
+                          [(polygon 180 90, -180 90, -180 -90, 180 -90, 180 90)]))
+
+  (testing "cartesian line"
+    (assert-valid-spatial
+     :cartesian
+     "CARTESIAN"
+     [(l/ords->line-string :cartesian [180 0, -180 0])])))

 (deftest inappropriate-spatial-coverage-test
   (testing "granule with spatial but parent collection does not"
@@ -435,30 +430,29 @@
    `(cmr.metadata-db.services.concept-constraints/set-enforce-granule-ur-constraint! true)))

 (def ^:private coll-file
-  "temp file for collection metadata"
-  "collection.xml")
+  "temp file for collection metadata in multipart request"
+  "cmr_5260_collection.xml")

 (def ^:private granule-file
-  "temp file for granule metadata"
-  "granule.json")
+  "temp file for granule metadata in multipart request"
+  "cmr_5260_granule.json")

 (defn- validate-granule-multipart
-  "Returns the validation result of the granule with the given collection and granule
-  through multiparts request."
+  "Returns the granule validataion result for the given collection and granule
+  via multipart granule validation request."
   [granule-concept coll-concept]
   ;; clj-http does not work with content-type that contains semicolons
   ;; (e.g. application/vnd.nasa.cmr.umm+json; version=1.4)
   ;; So we execute curl command directly from shell for UMM-G granule validation requests
-  (let [coll-fiile ""])
   (try
     (spit coll-file (:metadata coll-concept))
     (spit granule-file (:metadata granule-concept))
     (let [{:keys [provider-id native-id]} granule-concept
           validate-url (url/validate-url provider-id :granule native-id)
           coll-form (format "collection=<%s;type=%s" coll-file (:format coll-concept))
-          granule-form (format "granule=<%s;type=%s" granule-file (:format granule-concept))]
-      (let [{:keys [out]} (shell/sh "curl" "-i" "-F" granule-form "-F" coll-form validate-url)]
-        out))
+          granule-form (format "granule=<%s;type=%s" granule-file (:format granule-concept))
+          {:keys [out]} (shell/sh "curl" "-i" "-F" granule-form "-F" coll-form validate-url)]
+      out)
     (finally
       (io/delete-file coll-file)
       (io/delete-file granule-file))))
@@ -478,29 +472,28 @@
        (validate-granule-multipart granule-concept coll-concept))))

 (deftest validation-umm-g-granule-test
-  (testing "with collection as additional parameter"
-    (let [collection-attrs {:EntryTitle "correct"
-                            :ShortName "S1"
-                            :Version "V1"}
-          collection-ref-attrs {:entry-title "correct"
-                                :short-name "S1"
-                                :version-id "V1"}
-          collection (data-umm-c/collection collection-attrs)
-          coll-concept (d/umm-c-collection->concept collection :iso-smap)
-          coll-concept-id (:concept-id collection)]
-      (testing "valid UMM-G granule"
-        (let [granule (assoc (dg/granule-with-umm-spec-collection collection nil)
-                             :collection-ref
-                             (umm-g/map->CollectionRef collection-ref-attrs))
-              granule-concept (d/item->concept granule :umm-json)]
-          (validate-granule-multipart-ok? granule-concept coll-concept)))
-
-      (testing "invalid UMM-G granule"
-        (let [granule (assoc (dg/granule-with-umm-spec-collection collection nil)
-                             :collection-ref
-                             (umm-g/map->CollectionRef (merge collection-ref-attrs {:entry-title "wrong"})))
-              granule-concept (d/item->concept granule :umm-json)
-              expected-err-msg (str "Collection Reference Entry Title \\[wrong\\] does not match "
-                                    "the Entry Title of the parent collection \\[correct\\]")]
-          (validate-granule-multipart-failed?
-           granule-concept coll-concept 422 expected-err-msg))))))
+  (let [collection-attrs {:EntryTitle "correct"
+                          :ShortName "S1"
+                          :Version "V1"}
+        collection-ref-attrs {:entry-title "correct"
+                              :short-name "S1"
+                              :version-id "V1"}
+        collection (data-umm-c/collection collection-attrs)
+        coll-concept (d/umm-c-collection->concept collection :iso-smap)]
+    (testing "valid UMM-G granule"
+      (let [granule (assoc (dg/granule-with-umm-spec-collection collection nil)
+                           :collection-ref
+                           (umm-g/map->CollectionRef collection-ref-attrs))
+            granule-concept (d/item->concept granule :umm-json)]
+        (validate-granule-multipart-ok? granule-concept coll-concept)))
+
+    (testing "invalid UMM-G granule"
+      (let [granule (assoc (dg/granule-with-umm-spec-collection collection nil)
+                           :collection-ref
+                           (umm-g/map->CollectionRef
+                            (merge collection-ref-attrs {:entry-title "wrong"})))
+            granule-concept (d/item->concept granule :umm-json)
+            expected-err-msg (str "Collection Reference Entry Title \\[wrong\\] does not match "
+                                  "the Entry Title of the parent collection \\[correct\\]")]
+        (validate-granule-multipart-failed?
+         granule-concept coll-concept 422 expected-err-msg)))))


Only filter containers to failed when the build changes (#1780)

--- src-cljs/frontend/controllers/api.cljs
+++ src-cljs/frontend/controllers/api.cljs
@@ -260,7 +260,7 @@
 (defn maybe-set-containers-filter!
   "Depending on the status and outcome of the build, set active
   container filter to failed."
-  [state comms]
+  [state comms build-changed?]
   (let [build (get-in state state/build-path)
         containers (get-in state state/containers-path)
         build-running? (not (build-model/finished? build))
@@ -273,7 +273,8 @@
     ;; set filter
     (when (and (not build-running?)
                (seq failed-containers)
-               failed-filter-valid?)
+               failed-filter-valid?
+               build-changed?)
       (put! controls-ch [:container-filter-changed {:new-filter :failed
                                                     :containers failed-containers}]))))

@@ -300,7 +301,8 @@
         {:keys [build-num project-name]} context
         {:keys [org repo vcs_type]} (state/navigation-data current-state)
         {:keys [read-settings]} scopes
-        plan-url (gstring/format "/api/v1.1/project/%s/%s/plan" vcs_type project-name)]
+        plan-url (gstring/format "/api/v1.1/project/%s/%s/plan" vcs_type project-name)
+        build-changed? (not (= (-> previous-state :current-build-data) (-> current-state :current-build-data)))]
     ;; This is slightly different than the api-event because we don't want to have to
     ;; convert the build from steps to containers again.
     (analytics/track {:event-type :view-build
@@ -341,7 +343,7 @@
                (= project-name (vcs-url/project-name (get-in args [:resp :vcs_url]))))
       (fetch-visible-output current-state comms build-num (get-in args [:resp :vcs_url]))
       (frontend.favicon/set-color! (build-model/favicon-color (get-in current-state state/build-path)))
-      (maybe-set-containers-filter! current-state comms))))
+      (maybe-set-containers-filter! current-state comms build-changed?))))

 (defmethod api-event [:cancel-build :success]
   [target message status {:keys [context resp]} state]


delete test code comment

delete test code comment

--- sample/_config.clj
+++ sample/_config.clj
@@ -12,9 +12,6 @@
  ;;     "/"    => "/YYYY-MM/POST.html"
  ;;     "/foo" => "/foo/YYYY-MM/POST.html"
  :url-base     "/"
-; :url-base     "/u/14918307/misaki-mac-sample/"
-
- :index-name "index.html"

  ;; dev server port
  ;;   default value: 8080
@@ -31,9 +28,6 @@
                      "/css/main.css"]
         :device-css ["/css/smartphone.css"]
         :js         ["/js/main.js"]}
-;                     "/u/14918307/misaki-mac-sample/css/main.css"]
-;        :device-css ["/u/14918307/misaki-mac-sample/css/smartphone.css"]
-;        :js         ["/u/14918307/misaki-mac-sample/js/main.js"]}

  ;; post file compile hook
  :compile-with-post ["index.html.clj" "atom.xml.clj"]


remove unused namespaces

remove unused namespaces

--- src/crucible/values.clj
+++ src/crucible/values.clj
@@ -1,7 +1,6 @@
 (ns crucible.values
   (:require [clojure.spec :as s]
-            [crucible.encoding.keys :as keys]
-            [crucible.pseudo :as pseudo]))
+            [crucible.encoding.keys :as keys]))

 (s/def ::ref keyword?)
 (s/def ::att keyword?)


Add projection to containers

Add projection to containers

--- src/databinder/core.clj
+++ src/databinder/core.clj
@@ -55,14 +55,17 @@
   {:projector
    (fn [uri binding active url meta vals]
      (let [s (apply str vals)]
-       (hic/html [:li  {:class (if active "active" "")
-
-                        :data-uri uri}
-                  [:a.projector-binding {
-                                         :href url
-                                         :data-uri uri
-                                         :data-binding binding
-                                         } (if (re-matches #"^\s*$" s) "untitled" s)]])))
+       (hic/html [:a.projector-binding {
+                                        :href url
+                                        :data-uri uri
+                                        :data-binding binding
+                                        } (if (re-matches #"^\s*$" s) "untitled" s)])))
+   :list-item
+   (fn [uri binding active url meta vals]
+     (hic/html [:li  {:class (if active "active" "")
+
+                      :data-uri uri}
+                vals]))
    :column8
    (fn [uri binding active url meta vals]
      (hic/html [:div.span8 vals]))
@@ -272,7 +275,7 @@
                          (relation-getter data resource))
                current (if mypath (get (parse-uri url) mypath))
                active (if mypath (= current (.getURI resource)))
-               myurl (if mypath (str built-url mypath "/" (.getURI resource) "/"))
+               built-url (or (if mypath (str built-url mypath "/" (.getURI resource) "/")) built-url)
                vals (if (empty? sub-calls)
                    (map literalize related)
                    (map seq (apply map vector (map (fn [sub-call]
@@ -285,7 +288,7 @@
              (func (.getURI resource) ;; apply the bound function to the thing, the binding that points at the funtion, meta-data, and the finished children (should be ordered by now).
                    (.getURI binding)
                    active
-                   (or myurl built-url)
+                   built-url
                    meta-data
                    vals)))))
      (contains? types (db :container)) ;;TODO make it so we can project from a container.
@@ -295,14 +298,18 @@
                   projected (if (and p (res p))
                               (if (.containsResource data (res p))
                                 (res p)))
-                  ]
+
+                  current (if mypath (get (parse-uri url) mypath))
+
+                  active (if mypath (= current (.getURI resource)))
+                  built-url (or (if mypath (str built-url mypath "/" (.getURI resource) "/")) built-url)]

               (if ppath
                 (if projected
                   (func
                    (.getURI resource)
                    (.getURI binding)
-                   nil
+                   active
                    built-url
                    meta-data
                    (map (fn [sub-call] (sub-call data nil projected url (str built-url ppath "/" (.getURI resource) "/"))) sub-calls))
@@ -310,7 +317,7 @@
                 (func
                  (.getURI resource)
                  (.getURI binding)
-                 nil
+                 active
                  built-url
                  meta-data
                  (map (fn [sub-call] (sub-call data nil resource url built-url)) sub-calls))
@@ -358,18 +365,18 @@
            (map (fn [child] (qb child model uri)) children)
            '())
          (map (fn [child] (qb child model uri)) children))]
-    (println types "=" (db :container) " or " (db :relator))
+
     (cond (contains? types (db :relator))
           (let [statement (get-bound binding model)
                 binder (.getURI (.getPredicate statement))
                 predicate (.asResource (.getObject statement)) ;;TODO handle type thing with path thing
                 reverse (= binder (db :binds))]
-            (println "got here 1")
+
             [{:pred (.getURI predicate) :rev reverse :path onpath} subs])

           (contains? types (db :container))
-          (do (println "got here 2")
-            subs)
+
+          subs
           )))

@@ -460,7 +467,7 @@
     (.add qm "root" (res "http://logangilmour.com/example-ontology#person"))  ;; TODO DIRTY DIRTY HACKS

     (let [done (.toString (new ParameterizedSparqlString s qm))]
-      (println (render-query query false) "\n\n\n" (render-graph query) "\n\n\n" done)
+
       (.execConstruct
        (. QueryExecutionFactory sparqlService
           "http://localhost:8000/sparql/"
@@ -533,6 +540,7 @@
                                                         (res (:root db))
                                                         (prop (:haschild db)))))]

+
         (fn [data resource uri]
           ((s-rec root inf []) data nil resource uri "/view/"))
         ))
@@ -638,15 +646,19 @@
   data:binds rdf:type ;
   dc:title \"List of People\" ;
   dc:description \"A list of people contained within the application\" ;
-  data:haschild ex:person-projector .
+  data:haschild ex:person-item .
+
+ex:person-item
+  rdf:type w:list-item ;
+  data:path \"test\" ;
+  data:haschild ex:person-projector ;
+  data:projects ex:person-container .

 ex:person-projector
   rdf:type w:projector ;
-  data:path \"test\" ;
   data:bindo ont:name ;
   dc:title \"select\" ;
-  dc:description \"choose a person\" ;
-  data:projects ex:person-container .
+  dc:description \"choose a person\" .

 ex:person-container
   rdf:type w:column8 ;
@@ -701,6 +713,8 @@
 w:row rdfs:subClassOf data:container .

 w:list rdfs:subClassOf data:relator .
+
+w:list-item rdfs:subClassOf data:container .

 w:deleter rdfs:subClassOf data:relator .


capture a new unbound case and protect cogroup-transform

--- src/datasplash/core.clj
+++ src/datasplash/core.clj
@@ -51,8 +51,9 @@
          nss (list)]
     (let [{:keys [message trace-elems cause] :as current-ex} todo]
       (if message
-        (if (re-find #"clojure\.lang\.Var\$Unbound|call unbound fn|dynamically bind non-dynamic var" message)
+        (if (re-find #"clojure\.lang\.Var\$Unbound|call unbound fn|dynamically bind non-dynamic var|Unbound:" message)
           (let [[_ missing-ns] (or (re-find #"call unbound fn: #'([^/]+)/" message)
+                                   (re-find #"Unbound: #'([^/]+)/" message)
                                    (re-find #"Can't dynamically bind non-dynamic var: ([^/]+)/" message))
                 ns-to-add (->> trace-elems
                                (filter #(:clojure %))
@@ -1315,75 +1316,77 @@
      (ptransform
       :cogroup
       [^GroupSpecs group-specs]
-      (let [root-name (if nam (name nam) "cogroup")
-            pcolls (for [[idx [pcoll f {:keys [drop-nil?] :as opts}]]
-                         (map-indexed (fn [idx s] (if (instance? PCollection s)
-                                                    [idx [s nil nil]] [idx s])) (:specs group-specs))]
-                     (let [local-name (str root-name "-" (if pcoll (.getName pcoll) "pcoll"))
-                           op (if f
-                                (with-keys f {:name (str local-name "-group-by")} pcoll)
-                                pcoll)]
-                       (if drop-nil?
-                         (dfilter (if f
-                                    (fn [^KV kv] (not (nil? (.getKey kv))))
-                                    (fn [v] (not (nil? v))))
-                                  {:name (str local-name "-drop-nil")
-                                   :without-coercion-to-clj true}
-                                  op)
-                         op)))
-            pcolltuple (make-keyed-pcollection-tuple pcolls)
-            ordered-tags (->> pcolltuple
-                              (.getKeyedCollections)
-                              (map #(.getTupleTag %))
-                              (sort-by #(.getId %)))
-            rel (apply-transform pcolltuple (CoGroupByKey/create) base-schema opts)
-            required-set (->> (:specs group-specs)
-                              (map-indexed (fn [idx [_ _ {:keys [type]}]]
-                                             (when (= type :required) idx)))
-                              (remove nil?)
-                              (into #{}))
-            required-count (count required-set)
-            final-rel (pardo
-                       (fn [^DoFn$ProcessContext c]
-                         (let [^KV kv (.element c)
-                               k (.getKey kv)
-                               ^CoGbkResult raw-values (.getValue kv)]
-                           ;; skip if a required part of the group is empty
-                           (when-not (some identity
-                                           (map-indexed (fn [idx tag]
-                                                          (if (required-set idx)
-                                                            (not (-> (.getAll raw-values tag)
-                                                                     (.iterator)
-                                                                     (.hasNext)))
-                                                            false))
-                                                        ordered-tags))
-                             (if (and (not join-nil?) (nil? k))
-                               (cond
-                                 (= required-count 0) (doseq [[idx tag]
-                                                              (map-indexed
-                                                               (fn [idx tag] [idx tag]) ordered-tags)]
-                                                        (greedy-emit-cogbkresult
-                                                         raw-values (count ordered-tags) idx tag c))
-                                 (= required-count 1) (greedy-emit-cogbkresult
-                                                       raw-values
-                                                       (count ordered-tags)
-                                                       (first required-set)
-                                                       (nth ordered-tags
-                                                            (first required-set))
-                                                       c)
-                                 :else nil)
-                               (let [values (mapv
-                                             (fn [tag]
-                                               (greedy-read-cogbkresult raw-values tag))
-                                             ordered-tags)]
-                                 (.output c (make-kv k values)))))))
-                       (assoc opts
-                              :name (str root-name "-apply-requirements")
-                              :without-coercion-to-clj true
-                              :coder (make-kv-coder (.getKeyCoder (.getCoder rel))
-                                                    (make-nippy-coder)))
-                       rel)]
-        final-rel)))))
+      (safe-exec-cfg
+       options
+       (let [root-name (if nam (name nam) "cogroup")
+             pcolls (for [[idx [pcoll f {:keys [drop-nil?] :as opts}]]
+                          (map-indexed (fn [idx s] (if (instance? PCollection s)
+                                                     [idx [s nil nil]] [idx s])) (:specs group-specs))]
+                      (let [local-name (str root-name "-" (if pcoll (.getName pcoll) "pcoll"))
+                            op (if f
+                                 (with-keys f {:name (str local-name "-group-by")} pcoll)
+                                 pcoll)]
+                        (if drop-nil?
+                          (dfilter (if f
+                                     (fn [^KV kv] (not (nil? (.getKey kv))))
+                                     (fn [v] (not (nil? v))))
+                                   {:name (str local-name "-drop-nil")
+                                    :without-coercion-to-clj true}
+                                   op)
+                          op)))
+             pcolltuple (make-keyed-pcollection-tuple pcolls)
+             ordered-tags (->> pcolltuple
+                               (.getKeyedCollections)
+                               (map #(.getTupleTag %))
+                               (sort-by #(.getId %)))
+             rel (apply-transform pcolltuple (CoGroupByKey/create) base-schema opts)
+             required-set (->> (:specs group-specs)
+                               (map-indexed (fn [idx [_ _ {:keys [type]}]]
+                                              (when (= type :required) idx)))
+                               (remove nil?)
+                               (into #{}))
+             required-count (count required-set)
+             final-rel (pardo
+                        (fn [^DoFn$ProcessContext c]
+                          (let [^KV kv (.element c)
+                                k (.getKey kv)
+                                ^CoGbkResult raw-values (.getValue kv)]
+                            ;; skip if a required part of the group is empty
+                            (when-not (some identity
+                                            (map-indexed (fn [idx tag]
+                                                           (if (required-set idx)
+                                                             (not (-> (.getAll raw-values tag)
+                                                                      (.iterator)
+                                                                      (.hasNext)))
+                                                             false))
+                                                         ordered-tags))
+                              (if (and (not join-nil?) (nil? k))
+                                (cond
+                                  (= required-count 0) (doseq [[idx tag]
+                                                               (map-indexed
+                                                                (fn [idx tag] [idx tag]) ordered-tags)]
+                                                         (greedy-emit-cogbkresult
+                                                          raw-values (count ordered-tags) idx tag c))
+                                  (= required-count 1) (greedy-emit-cogbkresult
+                                                        raw-values
+                                                        (count ordered-tags)
+                                                        (first required-set)
+                                                        (nth ordered-tags
+                                                             (first required-set))
+                                                        c)
+                                  :else nil)
+                                (let [values (mapv
+                                              (fn [tag]
+                                                (greedy-read-cogbkresult raw-values tag))
+                                              ordered-tags)]
+                                  (.output c (make-kv k values)))))))
+                        (assoc opts
+                               :name (str root-name "-apply-requirements")
+                               :without-coercion-to-clj true
+                               :coder (make-kv-coder (.getKeyCoder (.getCoder rel))
+                                                     (make-nippy-coder)))
+                        rel)]
+         final-rel))))))

 (defn cogroup-by-transform
   [{:keys [collector] :as options}]


Update a message copied from Eastwood that was no longer appropriate

--- src/dolly/namespace.clj
+++ src/dolly/namespace.clj
@@ -254,8 +254,8 @@
        (println (format "    should have namespace: %s" recommended-namespace))
        (println (format "    or should be in file : %s" recommended-fname)))
      (println "
-No other linting checks will be performed until these problems have
-been corrected.
+No other operations will be performed until these problems have been
+corrected.

 The 'should have namespace' and 'should be in file' messages above are
 merely suggestions.  It may be better in your case to rename both the


Fix guitar example

Fix guitar example

--- src/examples/guitar.clj
+++ src/examples/guitar.clj
@@ -15,8 +15,8 @@
 ; Checkout the built-in fx in overtone/studio/fx.clj

 ; add fx to an instrument chain with inst-fx
-(inst-fx guitar fx-distortion2)
-(inst-fx guitar fx-reverb2)
+(inst-fx! guitar fx-distortion2)
+(inst-fx! guitar fx-reverb2)

 ; keep an fx instance id if you want to control it later
 (def lowpass (inst-fx guitar fx-rlpf))


Fix tests of `wrap-json-body`

Fix tests of `wrap-json-body`

--- test/com/nomistech/clojure_the_language/c_800_libraries/s_800_web/ss_020_ring.clj
+++ test/com/nomistech/clojure_the_language/c_800_libraries/s_800_web/ss_020_ring.clj
@@ -1,8 +1,27 @@
 (ns com.nomistech.clojure-the-language.c-800-libraries.s-800-web.ss-020-ring
-  (:require [midje.sweet :refer :all]
+  (:require [clojure.string :as str]
+            [midje.sweet :refer :all]
             [ring.middleware.json :refer [wrap-json-body
                                           wrap-json-response]]
             [ring.util.response :refer [response]]))
+
+;;;; ___________________________________________________________________________
+;;;; ---- Request test helpers ----
+
+(defn string->stream
+  ([s] (string->stream s "UTF-8"))
+  ([s encoding]
+   (-> s
+       (.getBytes encoding)
+       (java.io.ByteArrayInputStream.))))
+
+;; NOTES
+;; - content-type must be lower case.
+;;   - but `wrap-json-response` produces "Content-Type". WTF?
+
+(defn json->request [string]
+  {:headers {"content-type" "application/json; charset=utf-8"}
+   :body (string->stream string)})

 ;;;; ___________________________________________________________________________
 ;;;; ---- wrap-json-response ----
@@ -29,7 +48,7 @@
 ;;;; ---- wrap-json-body ----

 (defn handler-002 [request]
-  (let [user (get-in request [:body "user"])]
+  (let [user (get-in request [:body :user] "<no user specified>")]
     (response (str "Uploaded '" user "'."))))

 (def app-002
@@ -37,13 +56,13 @@
                                :bigdecimals? true}))

 (fact
-  (handler-002 {:body {"user" "Fred"}})
+  (handler-002 {:body {:user "Fred"}})
   => {:status 200
       :headers {}
       :body "Uploaded 'Fred'."})

 (fact
-  (app-002 {:body {"user" "Fred"}})
+  (app-002 (json->request "{\"user\":\"Fred\"}"))
   => {:status 200
       :headers {}
       :body "Uploaded 'Fred'."})


action code moved into signal leading to rename: :navigate -> :set-visibility

--- src/frontend/todos.cljs
+++ src/frontend/todos.cljs
@@ -66,7 +66,14 @@
          :on-connect (dispatch :sample-action)

          ; will come from router middleware
-         [::routing/on-navigate token] (dispatch [:navigate token])
+         [::routing/on-navigate token]
+         (do
+           ;(println "    token =" (pr-str token))
+           (when-let [match (->> -visibility-spec
+                               (filter #(= (:token %) token))
+                               first)]
+             ;(println "      route match =" (pr-str match))
+             (dispatch [:set-visibility (:key match)])))

          ; will come from devtools
          ::devtools/on-did-replay nil
@@ -89,17 +96,8 @@
          ; do nothing, only for a demo
          :sample-action model

-         [:navigate token]
-         (do
-           ;(println "    token =" (pr-str token))
-           (if-let [match (->> -visibility-spec
-                               (filter #(= (:token %) token))
-                               first)]
-             (do
-               ;(println "      route match =" (pr-str match))
-               (assoc model :visibility (:key match)))
-
-             model))
+         [:set-visibility key]
+         (assoc model :visibility key)

          [:update-field val]
          (assoc model :field val)


Refactor

Refactor

--- src/greenyet/status.clj
+++ src/greenyet/status.clj
@@ -5,18 +5,15 @@

 (defn- status-color-from-components [components]
   (let [colors (map :color components)
-        status-color (if (or (empty? colors)
-                             (some #(= % :red) colors))
-                       :red
-                       (if (some #(= % :yellow) colors)
-                         :yellow
-                         :green))]
+        status-color (cond
+                       (or (some #(= % :red) colors) (empty? colors)) :red
+                       (some #(= % :yellow) colors) :yellow
+                       :else :green)]
     [status-color nil]))

 (defn- overall-status-color [json config components]
-  (if-let [color (parse/color json config)]
-    color
-    (status-color-from-components components)))
+  (or (parse/color json config)
+      (status-color-from-components components)))

 (defn- status-from-json [json config]
   (let [[components components-error] (parse/components json config)


Fix thing->def

Fix thing->def

--- src/grimoire/things.clj
+++ src/grimoire/things.clj
@@ -322,7 +322,4 @@
   returns that value. Otherwise returns nil."
   [t]
   {:pre [(thing? t)]}
-  (if-not (def? t)
-    (when t
-      (recur (thing->parent t)))
-    t))
+  (if (def? t) t nil))


Fix bug in integration, fix coefficieant of lift for cambered foils

--- src/hydrofoil/model.clj
+++ src/hydrofoil/model.clj
@@ -106,6 +106,24 @@
     (* (/ max-camber (Math/pow (- position-camber 1) 2))
        (+ (* -1 1) (* 2 position-camber) (* 1 (Math/cos theta-not))))))

+(defn GFPCos
+  [individual theta-not]
+  (let [position-camber (individual :corrected-position-camber)
+        max-camber (individual :corrected-max-camber)]
+    (let [position-camber (individual :corrected-position-camber)
+        max-camber (individual :corrected-max-camber)]
+    (* (/ max-camber (Math/pow position-camber 2))
+       (+ -1 (* 2 position-camber) (* 1 (Math/cos theta-not)))
+       (Math/cos theta-not)))))
+
+(defn GAPCos
+  [individual theta-not]
+  (let [position-camber (individual :corrected-position-camber)
+        max-camber (individual :corrected-max-camber)]
+    (* (/ max-camber (Math/pow (- position-camber 1) 2))
+       (+ (* -1 1) (* 2 position-camber) (* 1 (Math/cos theta-not)))
+       (Math/cos theta-not))))
+
 (defn theta-switch
   "The angle at which the coefficient-of-lift calculation will switch from one integration to another
   arccos(1 - 2P)"
@@ -129,46 +147,50 @@

 (defn left-rule
   "Creates a lazy seque of points to evaluate a function at for a left rule riemann sum
-  Takes a number of particians"
-  [pieces]
-  (range 0 1 (/ 1 pieces)))
+  Takes a number of particians.
+  n defines how many elements in the lazy squence
+  low defines the lower bound of the range
+  high defines the upper bound of the range"
+  [n low high]
+  (range low high (/ (- high low) n)))

 (defn right-rule
   "Creates a lazy seque of points to evaluate a function at for a right rule riemann sum
-  Takes a number of particians"
-  [pieces]
-  (range (/ 1 pieces) (+ (/ 1 pieces) 1) (/ 1 pieces)))
+  Takes a number of particians
+  n defines how many elements in the lazy squence
+  low defines the lower bound of the range
+  high defines the upper bound of the range"
+  [n low high]
+  (range (/ (- high low) n) (+ high (/ (- high low) n)) (/ (- high low) n)))

 (defn middle-rule
   "Creates a lazy seque of points to evaluate a function at for a right middle riemann sum
   Takes a number of particians"
-  [pieces]
-  (range (/ 1 (* 2 pieces))
-         1
-         (/ 1 pieces)))
+  [n low high]
+  (range (/ (- high low) (* 2 n)) high (/ (- high low) n)))

 (defn integral-abstracted
   "Will do a riemann sum on the function:
   State will be a function, either left, right, or middle, based on the style of riemann sum.
   Pices is how boxes it makes, aka the resolution of the riemann sum"
-  [individual function state pieces]
-  (reduce #(+ %1 (* (/ 1 pieces) (function individual %2))) 0 (state pieces)))
+  [individual function state low high n]
+  (reduce #(+ %1 (* (/ (- high low) n) (function individual %2))) 0 (state n low high)))

 (defn integral-production
   "same as riemann sum but it might be faster, you need to figure out left, right, middle
-  functions on your own"
+  functions on your own. ONLY WORKS FROM RANGE 0 TO 1"
   [individual function start-x end-x increment pieces]
   (reduce #(+ %1 (* (/ 1 pieces) (function individual %2))) 0 (range start-x end-x increment)))

 (defn trapazoid-integral
-  [individual function pieces]
-  (* 0.5 (+ (integral-abstracted individual function left-rule pieces)
-            (integral-abstracted individual function right-rule pieces))))
+  [individual function low high n]
+  (* 0.5 (+ (integral-abstracted individual function left-rule low high n)
+            (integral-abstracted individual function right-rule low high n))))

 (defn simpson-integral
-  [individual function pieces]
-  (+ (/ (trapazoid-integral individual function (/ pieces 2)) 3)
-     (/ (* 2 (integral-abstracted individual function middle-rule (/ pieces 2))) 3)))
+  [individual function low high n]
+  (+ (/ (trapazoid-integral individual function low high (/ n 2)) 3)
+     (/ (* 2 (integral-abstracted individual function middle-rule low high (/ n 2))) 3)))

 (defn adjusted-upper-function
   "   /////   upper-surface-y-function * d/dx(upper-surface-x-function) /////
@@ -195,8 +217,8 @@
   The integral multiplies by the derivative of the x function because the functions are
   paremetric."
   [individual]
-  (- (simpson-integral individual adjusted-upper-function 90)
-     (simpson-integral individual adjusted-lower-function 90)))
+  (- (simpson-integral individual adjusted-upper-function 0 1 90)
+     (simpson-integral individual adjusted-lower-function 0 1 90)))

 ;;;---------------- Coefficantof lift ----------------
 (defn symetric-coefficient-of-lift
@@ -211,15 +233,15 @@
         theta-switch-constant (theta-switch individual)]
     (- attack-angle
        (* (/ 1 Math/PI)
-          (+ (integral-production individual gradient-forward-polar-function 0 theta-switch-constant (/ theta-switch-constant 90) 90)
-             (integral-production individual gradient-aft-polar-function theta-switch-constant Math/PI (/ (- Math/PI theta-switch-constant) 90) 90))))))
+          (+ (integral-abstracted individual gradient-forward-polar-function middle-rule 0 theta-switch-constant 600)
+             (integral-abstracted individual gradient-aft-polar-function left-rule theta-switch-constant Math/PI 600))))))

 (defn A-1
   [individual run-constants]
   (let [theta-switch-constant (theta-switch individual)]
     (* (/ 2 Math/PI)
-       (+ (integral-production individual gradient-forward-polar-function 0 theta-switch-constant (/ theta-switch-constant 90) 90)
-          (integral-production individual gradient-aft-polar-function theta-switch-constant Math/PI (/ (- Math/PI theta-switch-constant) 90) 90)))))
+       (+ (integral-abstracted individual GFPCos middle-rule 0 theta-switch-constant 850)
+          (integral-abstracted individual GAPCos left-rule theta-switch-constant Math/PI 850)))))

 (defn cambered-coefficient-of-lift
@@ -250,3 +272,18 @@
 ;;(integral-abstracted (hash-map :corrected-max-camber 0 :corrected-position-camber 0 :corrected-thickness 0.45) upper-surface-y-function left-rule 100)

 ;;(upper-surface-y-function (hash-map :corrected-max-camber 0 :corrected-position-camber 0.5 :corrected-thickness 0.45) 0)
+
+(* (integral-production (NACA-design 2 4 12) gradient-forward-polar-function 0 1.369 (/ 1.369 200) 200) 1.369)
+
+(integral-abstracted (NACA-design 2 4 12) gradient-forward-polar-function middle-rule 0 (theta-switch (NACA-design 2 4 12)) 200)
+
+(trapazoid-integral (NACA-design 2 4 12) gradient-forward-polar-function 0 (theta-switch (NACA-design 2 4 12)) 10000)
+
+(simpson-integral (NACA-design 2 4 12) gradient-forward-polar-function 0 (theta-switch (NACA-design 2 4 12)) 1000)
+
+(integral-abstracted (NACA-design 2 4 12) gradient-aft-polar-function left-rule (theta-switch (NACA-design 2 4 12)) (Math/PI) 200)
+
+(simpson-integral (NACA-design 2 4 12) gradient-aft-polar-function (theta-switch (NACA-design 2 4 12)) (Math/PI) 200)
+
+
+


Cleanup Clojure code with argument destructuring

--- clojure/src/biotool/core.clj
+++ clojure/src/biotool/core.clj
@@ -11,21 +11,18 @@

 (defn update_stats
   "Update stats accumulator with information from the next sequence"
-  [old_stats this_record]
-  (let [old_num_sequences (old_stats :num_sequences)
-        old_num_bases (old_stats :num_bases)
-        old_min_sequence_length (old_stats :min_sequence_length)
-        old_max_sequence_length (old_stats :max_sequence_length)
-        this_sequence (:sequence this_record)
-        this_sequence_length (count this_sequence)]
-       {:num_sequences (inc old_num_sequences)
-        :num_bases (+ old_num_bases this_sequence_length)
-        :min_sequence_length (if old_min_sequence_length
-                                 (min old_min_sequence_length this_sequence_length)
-                                 this_sequence_length)
-        :max_sequence_length (if old_max_sequence_length
-                                 (max old_max_sequence_length this_sequence_length)
-                                 this_sequence_length)}))
+  [stats record]
+  (let [{:keys [num_sequences num_bases min_sequence_length max_sequence_length]} stats
+        sequence (:sequence record)
+        sequence_length (count sequence)]
+       {:num_sequences (inc num_sequences)
+        :num_bases (+ num_bases sequence_length)
+        :min_sequence_length (if min_sequence_length
+                                 (min min_sequence_length sequence_length)
+                                 sequence_length)
+        :max_sequence_length (if max_sequence_length
+                                 (max max_sequence_length sequence_length)
+                                 sequence_length)}))

 (def header "FILENAME\tTOTAL\tNUMSEQ\tMIN\tAVG\tMAX")

@@ -33,24 +30,17 @@
   "Display the computed stats in pretty fashion on the standard output"
   [filename stats]
   (println header)
-  (let [this_num_sequences (:num_sequences stats)
-        this_num_bases (:num_bases stats)
-        this_min_sequence_length (:min_sequence_length stats)
-        this_max_sequence_length (:max_sequence_length stats)
-        average (if (> this_num_sequences 0)
-                    (double (/ this_num_bases this_num_sequences))
+  (let [{:keys [num_sequences num_bases min_sequence_length max_sequence_length]} stats
+        average (if (> num_sequences 0)
+                    (double (/ num_bases num_sequences))
                     nil)
         average_str (if average (str average) "-")
-        num_sequences_str (str this_num_sequences)
-        num_bases_str (str this_num_bases)
+        num_sequences_str (str num_sequences)
+        num_bases_str (str num_bases)
         min_sequence_length_str
-          (if this_min_sequence_length
-              (str this_min_sequence_length)
-              "-")
+          (if min_sequence_length (str min_sequence_length) "-")
         max_sequence_length_str
-          (if this_max_sequence_length
-              (str this_max_sequence_length)
-              "-")
+          (if max_sequence_length (str max_sequence_length) "-")
         output_str (str filename "\t"
                         num_sequences_str "\t"
                         num_bases_str "\t"


http: handle body params as well.

http: handle body params as well.

--- src/io/cyanite/http.clj
+++ src/io/cyanite/http.clj
@@ -74,9 +74,17 @@

 (defn ->params
   [^QueryStringDecoder dx]
-  (for [[k vlist] (.parameters dx)
-        :let [vs (seq vlist)]]
-    [(keyword (str k)) (if (< 1 (count vs)) vs (first vs))]))
+  (reduce
+   merge {}
+   (for [[k vlist] (.parameters dx)
+         :let [vs (seq vlist)]]
+     [(keyword (str k)) (if (< 1 (count vs)) vs (first vs))])))
+
+(defn body-params
+  [^FullHttpRequest msg headers body]
+  (when-let [content-type (:content-type headers)]
+    (when (.startsWith content-type "application/x-www-form-urlencoded")
+      (QueryStringDecoder. body false))))

 (defn request-handler
   "Capture context and msg and yield a closure
@@ -85,13 +93,19 @@
    The closure may be called at once or submitted to a pool."
   [f ^ChannelHandlerContext ctx ^FullHttpRequest msg]
   (fn []
-    (let [dx   (QueryStringDecoder. (.getUri msg))
-          req  {:uri            (.path dx)
-                :params         (reduce merge {} (->params dx))
-                :request-method (method->data (.getMethod msg))
-                :version        (-> msg .getProtocolVersion .text)
-                :headers        (headers (.headers msg))
-                :body           (bb->string (.content msg))}
+    (let [headers (headers (.headers msg))
+          body    (bb->string (.content msg))
+          dx      (QueryStringDecoder. (.getUri msg))
+          p1      (->params dx)
+          p2      (some-> msg (body-params headers body) ->params)
+          req     {:uri            (.path dx)
+                   :get-params     p1
+                   :body-params    p2
+                   :params         (merge p1 p2)
+                   :request-method (method->data (.getMethod msg))
+                   :version        (-> msg .getProtocolVersion .text)
+                   :headers        headers
+                   :body           body}
           resp (data->response (f req) (.getProtocolVersion msg))]
       (-> (.writeAndFlush ctx resp)
           (.addListener ChannelFutureListener/CLOSE)))))


Avoid crash when no beat sync info has been seen

--- src/afterglow/midi.clj
+++ src/afterglow/midi.clj
@@ -465,7 +465,7 @@
   Traktor controller mapping."
   []
   (set (for [[k v] @clock-sources]
-         (when (< (- (now) (:traktor-beat-phase v)) 300) k))))
+         (when (< (- (now) (:traktor-beat-phase v 0)) 300) k))))

 (defn sync-to-midi-clock
   "Returns a sync function that will cause the beats-per-minute


Fix crash for devices with nil descriptions.

Also make filter-devices public, since I plan on enhancing its
capability.

--- src/afterglow/midi.clj
+++ src/afterglow/midi.clj
@@ -750,7 +750,7 @@
     ""
     (str "matching " (with-out-str (clojure.pprint/write-out name-filter)) " ")))

-(defn- filter-devices
+(defn filter-devices
   "Return only those devices whose name and/or description match the
   specified pattern. name-filter can either be a Pattern, or a string
   which will be turned into a pattern which matches in a
@@ -761,8 +761,8 @@
     (let [pattern (if (= (class name-filter) Pattern)
                     name-filter
                     (Pattern/compile (Pattern/quote (str name-filter)) Pattern/CASE_INSENSITIVE))]
-      (filter #(or (re-find pattern (:name %1))
-                   (re-find pattern (:description %1)))
+      (filter #(or (re-find pattern (or (:name %1) ""))
+                   (re-find pattern (or (:description %1) "")))
               devices))))

 (defn current-clock-sources


going all primitive

going all primitive

--- src/kmp_search/core.clj
+++ src/kmp_search/core.clj
@@ -12,18 +12,19 @@

 (defn matcher [^bytes pattern]
   (let [length (alength pattern)
-        failure (long-array length)
-        compute-failure (fn [[i j] b]
-                          (let [j (loop [j j p (aget pattern j)]
-                                    (if (and (pos? j) (not= p b))
-                                      (recur (aget failure (dec j))
-                                             (aget pattern j))
-                                      (if (= p b)
-                                        (inc j)
-                                        j)))]
-                            (aset-long failure i j)
-                            [(inc i) j]))
-        _ (reduce compute-failure [1 0] (drop 1 pattern))]
+        failure (long-array length)]
+    (loop [i 1 j 0]
+      (when (< i length)
+        (let [b (aget pattern i)
+              ^long j (loop [j j]
+                        (let [p (aget pattern j)]
+                          (if (and (pos? j) (not= p b))
+                            (recur (aget failure (dec j)))
+                            (if (= p b)
+                              (inc j)
+                              j))))]
+          (aset-long failure i j)
+          (recur (inc i) j))))
     {:pattern pattern
      :length length
      :failure failure


:bug: Fix paste image in prod mode

:bug: Fix paste image in prod mode

--- frontend/src/uxbox/util/webapi.cljs
+++ frontend/src/uxbox/util/webapi.cljs
@@ -75,12 +75,12 @@
   [data]
   (assert (string? data) "`data` should be string")
   (let [cboard (unchecked-get js/navigator "clipboard")]
-    (.writeText cboard data)))
+    (.writeText ^js cboard data)))

 (defn- read-from-clipboard
   []
   (let [cboard (unchecked-get js/navigator "clipboard")]
-    (rx/from (.readText cboard))))
+    (rx/from (.readText ^js cboard))))

 (defn- read-image-from-clipboard
   []
@@ -91,7 +91,7 @@
                       (if img-type
                         (rx/from (.getType item img-type))
                         (rx/empty))))]
-    (->> (rx/from (.read cboard)) ;; Get a stream of item lists
+    (->> (rx/from (.read ^js cboard)) ;; Get a stream of item lists
          (rx/mapcat identity)     ;; Convert each item into an emission
          (rx/switch-map read-item))))


[#532] Map client aggregation function names to pg aggregate functions (partial list for now)

--- backend/src/akvo/lumen/lib/pivot_impl.clj
+++ backend/src/akvo/lumen/lib/pivot_impl.clj
@@ -20,7 +20,6 @@
        rest
        (map first)))

-;; TODO filter
 (defn source-sql [table-name
                   {:keys [category-column
                           row-column
@@ -135,7 +134,14 @@
   {:category-column (find-column columns (get query "categoryColumn"))
    :row-column (find-column columns (get query "rowColumn"))
    :value-column (find-column columns (get query "valueColumn"))
-   :aggregation (get query "aggregation")
+   :aggregation (condp = (get query "aggregation")
+                  "mean" "avg"
+                  "sum" "sum"
+                  "min" "min"
+                  "max" "max"
+                  "count" "count"
+                  (throw (ex-info "Unsupported aggregation function"
+                                  {:aggregation (get query "aggregation")})))
    :filters (get query "filters")})

 (defn valid-query? [query]


initialize with new game only

initialize with new game only

--- cartagena-web/src/cartagena_web/main.cljs
+++ cartagena-web/src/cartagena_web/main.cljs
@@ -142,7 +142,7 @@
                          :discard-pile []}
   )

-(defonce app-state (atom initial-game-state))
+(defonce app-state (atom nil))

 (defn to-scale [n]
   (* 1.65 n))
@@ -238,12 +238,19 @@
    {:x 400 :y 240}
    ])

-(defn pirate-click [game-state color from-space-index]
+;; TODO: duplicated from server code
+(defn active-player
+  "Returns the active player from the players collection by name."
+  [game-state]
+  (first (filter #(= (:current-player game-state) (:name %)) (:players game-state))))
+
+(defn pirate-click [color from-space-index]
   (if-let [selected-card (:selected-card @app-state)]
-    (do
-      (println "moving" color "from" from-space-index "to" selected-card "; call the server and get the new game state back")
-      (reset! app-state (dissoc @app-state :selected-card)))
-    (println "moving" color "from" from-space-index "backward; call the server and get the new game state back")))
+    (when (= color (:color (active-player @app-state)))
+      (do
+        (println "moving" color "from" from-space-index "to" selected-card "; call the server and get the new game state back")
+        (reset! app-state (dissoc @app-state :selected-card)))
+      (println "moving" color "from" from-space-index "backward; call the server and get the new game state back"))))

 (defn jail []
   (when-let [jail (get-in @app-state [:board 0])]
@@ -263,7 +270,7 @@
                        :r (to-scale 4)
                        :fill color-name
                        :on-click (fn jail-click [e]
-                                   (pirate-click @app-state pirate-color 0))}]))))))))
+                                   (pirate-click pirate-color 0))}]))))))))

 ;; TODO: this looks almost exactly like jail
 (defn ship []
@@ -284,7 +291,7 @@
                        :r (to-scale 4)
                        :fill color-name
                        :on-click (fn ship-click [e]
-                                   (pirate-click @app-state pirate-color 37))}]))))))))
+                                   (pirate-click pirate-color 37))}]))))))))

 (defn normal-space [x y]
   [:rect
@@ -311,13 +318,8 @@
                [space image]
                )))))

-;; TODO: duplicated from server code
-(defn active-player
-  "Returns the active player from the players collection by name."
-  [game-state]
-  (first (filter #(= (:current-player game-state) (:name %)) (:players game-state))))
-
-(defn card-click [game-state card]
+
+(defn card-click [card]
   (do
     (println "card-click" card)
     (reset! app-state (assoc @app-state :selected-card card))))
@@ -350,47 +352,48 @@
           :width (to-scale 501)
           :height (to-scale 301)}]
         (into (static-board))
+        (into (normal-spaces))
         (into (jail))
-        (into (normal-spaces))
         (into (ship))
         )]
-   (let [{:keys [color cards] player-name :name} (active-player @app-state)
-         card-groups (frequencies cards)]
-     [:div
-      [:table
-       {:class "t1"}
-       [:tbody
-        [:tr
-         [:td "Player"]
-         [:td player-name]]]
-       [:tr
-        [:td "Color"]
-        [:td
-         [:svg
-          {:width (to-scale 20)
-           :height (to-scale 20)}
-          [:circle
-           {:cx (to-scale 10)
-            :cy (to-scale 10)
-            :r (to-scale 7)
-            :fill (name color)}]]
-         [:span {:style {:color (name color)}} (name color)]]]
-       [:tr
-        [:td "Actions Remaining"]
-        [:td (:actions-remaining @app-state)]]
-       [:tr
-        [:td "Cards"]
-        [:td (for [[card num] card-groups]
-               ^{:key card}
-               [:span {:style {:float "left"}}
-                [:figure
-                 [:img
-                  {:src (card icon-images)
-                   :width (to-scale 30)
-                   :height (to-scale 30)
-                   :on-click (fn ship-click [e]
-                               (card-click @app-state card))}]
-                 [:center [:figcaption num]]]])]]]])])
+   (when-let [active-player (active-player @app-state)]
+     (let [{:keys [color cards] player-name :name} active-player
+           card-groups (frequencies cards)]
+       [:div
+        [:table
+         {:class "t1"}
+         [:tbody
+          [:tr
+           [:td "Player"]
+           [:td player-name]]]
+         [:tr
+          [:td "Color"]
+          [:td
+           [:svg
+            {:width (to-scale 20)
+             :height (to-scale 20)}
+            [:circle
+             {:cx (to-scale 10)
+              :cy (to-scale 10)
+              :r (to-scale 7)
+              :fill (name color)}]]
+           [:span {:style {:color (name color)}} (name color)]]]
+         [:tr
+          [:td "Actions Remaining"]
+          [:td (:actions-remaining @app-state)]]
+         [:tr
+          [:td "Cards"]
+          [:td (for [[card num] card-groups]
+                 ^{:key card}
+                 [:span {:style {:float "left"}}
+                  [:figure
+                   [:img
+                    {:src (card icon-images)
+                     :width (to-scale 30)
+                     :height (to-scale 30)
+                     :on-click (fn ship-click [e]
+                                 (card-click card))}]
+                   [:center [:figcaption num]]]])]]]]))])

 (defn ^:export main []


(SERVER-797) Removed bogus legacy-routes-test assertion

This commit removes an assertion from one of the legacy-routes-tests
which was never actually exercised anyway so long as the test passes
and, therefore, seems irrelevant.

--- test/integration/puppetlabs/services/legacy_routes/legacy_routes_test.clj
+++ test/integration/puppetlabs/services/legacy_routes/legacy_routes_test.clj
@@ -97,8 +97,7 @@
              we should never get to the HTTP request, but if that's the case, the
              assertion is weird and confusing."
              app
-             {:web-router-service {::master-service/master-service {:foo "/bar"}}}
-             (is (= 200 (:status (http-get "/puppet/v3/node/localhost?environment=production"))))))))))
+             {:web-router-service {::master-service/master-service {:foo "/bar"}}}))))))

 (deftest ^:integration legacy-ca-routes-disabled
   (testing (str "(SERVER-759) The legacy CA routes are not forwarded when the "


fixed validation middleware

fixed validation middleware

--- examples/todomvc/src/app/middleware/schema.cljs
+++ examples/todomvc/src/app/middleware/schema.cljs
@@ -11,6 +11,7 @@
       (update :on-start helpers/after-do
               (fn [model _dispatch-signal]
                 (run!
-                  ; using console log for better printing in Chrome console
-                  (.log js/console "Validation problems:" (s/check schema @model))
-                  (throw (ex-info "Model validation failed. See more info above." {})))))))+                  (when-let [problems (s/check schema @model)]
+                    ; using console log for better printing in Chrome console
+                    (.log js/console "Validation problems:" problems)
+                    (throw (ex-info "Model validation failed. See more info above." {}))))))))


added explicit `refer`

added explicit `refer`

--- exercises/minesweeper/test/minesweeper_test.clj
+++ exercises/minesweeper/test/minesweeper_test.clj
@@ -1,7 +1,7 @@
 (ns minesweeper-test
-  (:require [clojure.test :refer :all]
+  (:require [clojure.test :refer [deftest is]]
             [clojure.string :refer [join]]
-            [minesweeper :refer :all]))
+            [minesweeper :refer [draw]]))

 (deftest zero-size-board
   (is (= (draw "") "")))


Use more width for attribute columns, and render lists of references to other data better

--- src/cljs/org/broadinstitute/firecloud_ui/common/table.cljs
+++ src/cljs/org/broadinstitute/firecloud_ui/common/table.cljs
@@ -254,7 +254,8 @@
      (let [attribute-keys (apply union
                             (map #(set (keys (% "attributes")))
                               (filter #(= (% "entityType") (:selected-entity-type @state))
-                                (:entities props))))]
+                                (:entities props))))
+           attr-col-width (max 100 (min 400 (int (/ 1000 (count attribute-keys)))))]
        [Table
         (merge props
           {:key (:selected-entity-type @state)
@@ -262,16 +263,25 @@
                       [{:header "Entity Type" :starting-width 100
                         :content-renderer (or (:entity-type-renderer props)
                                             (fn [entity] (entity "entityType")))}
-                       {:header "Entity Name" :starting-width 100
+                       {:header "Entity Name" :starting-width 200
                         :content-renderer (or (:entity-name-renderer props)
                                             (fn [entity] (entity "name")))}]
-                      (map (fn [k] {:header k :starting-width 100
+                      (map (fn [k] {:header k :starting-width attr-col-width
                                     :content-renderer
                                     (fn [attr-value]
-                                      (if (and (map? attr-value)
-                                            (= (set (keys attr-value)) #{"entityType" "entityName"}))
+                                      (cond
+                                        ;; for attributes referring to a single other entity
+                                        ;; e.g. samples referring to participants
+                                        (and (map? attr-value)
+                                             (= (set (keys attr-value)) #{"entityType" "entityName"}))
                                         (attr-value "entityName")
-                                        ((:attribute-renderer props) attr-value)))})
+                                        ;; for attributes referring to a list of entities
+                                        ;; e.g. sample sets referring to samples
+                                        (and (sequential? attr-value)
+                                             (map? (first attr-value)) ;; we'll just assume homogeneous lists
+                                             (= (set (keys (first attr-value))) #{"entityType" "entityName"}))
+                                        (clojure.string/join ", " (map (fn [refr] (refr "entityName")) attr-value))
+                                        :else ((:attribute-renderer props) attr-value)))})
                         attribute-keys))
            :filters (mapv (fn [key] {:text key :pred #(= key (% "entityType"))})
                       (:entity-types props))


Only text email for now.

Only text email for now.

--- src/oc/email/mailer.clj
+++ src/oc/email/mailer.clj
@@ -76,10 +76,10 @@
                       (assoc :subject subject)
                       (assoc :source (str default-inviter " <" default-reply-to ">")))]
     (try
-      (spit html-file (invite/html invitation)) ; create the email in a tmp file
-      (shell/sh "juice" html-file inline-file) ; inline the CSS
-      (email invitation {:text (invite/text invitation)
-                         :html (slurp inline-file)}) ; email it to the recipients
+      ;(spit html-file (invite/html invitation)) ; create the email in a tmp file
+      ;(shell/sh "juice" html-file inline-file) ; inline the CSS
+      (email invitation {:text (invite/text invitation)})
+                         ;:html (slurp inline-file)}) ; email it to the recipients
       (finally
         ; remove the tmp files
         (io/delete-file html-file true)


fix notifications

fix notifications

--- src/ci3/agent/core.clj
+++ src/ci3/agent/core.clj
@@ -102,20 +102,21 @@
 (defn notify [st build & text]
   (telegram/notify (str st " build " (get-in build [:repository]) "/n"
                         (get-in build [:commit :message]) " \n"
-                        "by " (or (get-in build [:author :raw]) (get-in build [:author :name])) " /n"
+                        "by " (or (get-in build [:author :raw]) (get-in build [:author :name])) " \n"
                         base-url "builds/" (get-in build [:metadata :name])
                         (when text (str " \n ```" (str/join text) "```") ))))

 (defn error [build res]
   (println build)
   (when-not (:test build)
-    (notify "Success" build))
+    (notify "Fail" build))
   (update-status (assoc build :status "failed")))

 (defn success [build]
   (println build)
+  (notify "Success" build)
   (when-not (:test build)
-    (notify "Fail" build))
+    (notify "Success" build))
   (update-status (assoc build :status "success")))

 (defmethod u/*fn


Don't print out unhandled events

Don't print out unhandled events

--- src/clj/onyx_dashboard/http/server.clj
+++ src/clj/onyx_dashboard/http/server.clj
@@ -56,7 +56,7 @@
                                          (:job (:?data event)))
             :chsk/uidport-close (swap! tracking od/stop-tracking! user-id)
             :chsk/ws-ping nil
-            (println "Dunno what to do with: " event)))
+            nil #_(println "Dunno what to do with: " event)))
         (recur)))))

 (defn send-mult-fn [send-fn! connected-uids msg]


Add room outlines and special corner rooms

--- src/cljc/robinson/dungeons/temple.cljc
+++ src/cljc/robinson/dungeons/temple.cljc
@@ -80,13 +80,18 @@
 (defn room-to-cellsxy
   "Convert the bounds of a room into a list of points that represent the room."
   [min-x min-y max-x max-y]
-  (let [top    [(map (fn [x] [x min-y {:type :horizontal-wall}]) (range min-x (inc max-x)))]
-        bottom [(map (fn [x] [x max-y {:type :horizontal-wall}]) (range min-x (inc max-x)))]
+  (let [alternate-corners? (> 0.5 (rand))
+        corners [[[min-x min-y {:type (if alternate-corners? :upper-left-2 :upper-left-1)}]
+                  [max-x min-y {:type (if alternate-corners? :upper-right-2 :upper-right-1)}]
+                  [min-x max-y {:type (if alternate-corners? :bottom-left-2 :bottom-left-1)}]
+                  [max-x max-y {:type (if alternate-corners? :bottom-right-2 :bottom-right-1)}]]]
+        top    [(map (fn [x] [x min-y {:type :horizontal-wall}]) (range (inc min-x) max-x))]
+        bottom [(map (fn [x] [x max-y {:type :horizontal-wall}]) (range (inc min-x) max-x))]
         middle-line (concat [[min-x {:type :vertical-wall}]]
                             (vec (map (fn [x] [x {:type :floor}]) (range (inc min-x) max-x)))
                             [[max-x {:type :vertical-wall}]])
         middle-lines (vec (map (fn [y] (map (fn [[x cell]] [x y cell]) middle-line)) (range (inc min-y) max-y)))
-        lines (concat top middle-lines bottom)]
+        lines (concat corners top middle-lines bottom)]
     (apply concat lines)))

 (defn points-to-fully-connected-graph
@@ -148,6 +153,19 @@
                                        edges))
     (take 5 edges)))

+(defn find-junction-rooms [edges]
+  "Return 2 junction room centers. Candidate junction rooms have atleast 3 edges connected to them."
+  (let [counts (reduce (fn [m [from to]]
+                         (-> m
+                         (update from (fn [v] (inc (or v 0))))
+                         (update from (fn [v] (inc (or v 0))))))
+                       {}
+                       edges)
+       junctions (keys (into {} (filter (fn [[_ connections]] (> connections 2))
+                                        counts)))]
+    (println "junctions" junctions)
+    (set (take 2 junctions))))
+
 (defn vertical-or-horizontally-aligned?
   [& xys]
   (some (partial apply =) (apply map vector xys)))
@@ -210,7 +228,8 @@
     (= y max-y)
       :horizontal
     :else
-      (assert false (format "Unknown wall type %d %d %d %d %d %d" min-x min-y max-x max-y x y))))
+      (rand-nth [:vertical :horizontal])
+      #_(assert false (format "Unknown wall type %d %d %d %d %d %d" min-x min-y max-x max-y x y))))

 (defn multi-part-segment
   [from from-type to to-type]
@@ -227,13 +246,17 @@
     (= from-type :vertical)
       (horizontal-corner-segment from to)))

-(defn make-corridor-points [cells room-centers-to-room-bounds start end]
+(defn make-corridor-points [cells room-centers-to-room-bounds junction-room-centers start end]
   "Finds a list of `[x y]`s comprising a corridor from `start` to `end`.
    `room-centers-to-room-bounds` is a map with `[x y]` keys and `[min-x min-y max-x max-y]` values."
   (let [start-room-bounds (get room-centers-to-room-bounds start)
         end-room-bounds   (get room-centers-to-room-bounds end)
-        door-xy-1         (find-door start-room-bounds start end)
-        door-xy-2         (find-door end-room-bounds end start)]
+        door-xy-1         (if (contains? junction-room-centers start)
+                            start
+                            (find-door start-room-bounds start end))
+        door-xy-2         (if (contains? junction-room-centers end)
+                            end
+                            (find-door end-room-bounds end start))]
     (println "start" start)
     (println "start-room-bounds" start-room-bounds)
     (println "end" end)
@@ -256,85 +279,27 @@
         lines    (map (fn [line] (map last (group-by first line))) lines-xy)]
     lines))

-(defn cellsxy-to-ascii [cells-xy]
-  "Convert a grid of cells into a list of string that can be rendered."
-  (let [contents (map (fn [line] (clojure.string/join
-                                      (map (fn [[x y cell]]
-                                        (if (nil? cell)
-                                            \
-                                            (case (cell :type)
-                                              :floor \.
-                                              :vertical-wall \|
-                                              :horizontal-wall \-
-                                              \?)))
-                                       line))) cells-xy)]
-    contents))
-
 (defn merge-cells
   "When merging cells, given their types, determine
    the type of the resulting cell."
   [cell1 cell2]
-  (case (cell1 :type)
-    :floor (case (cell2 :type)
-             :floor :floor
-             :horizontal-wall :floor
-             :vertical-wall :floor
-             :corridor :close-door
-             :close-door :floor
-             :up-stairs :up-stairs
-             :down-stairs :down-stairs
-             :nil :floor)
-    :horizontal-wall (case (cell2 :type)
-             :floor :floor
-             :horizontal-wall :horizontal-wall
-             :vertical-wall :horizontal-wall
-             :corridor :close-door
-             :close-door :close-door
-             :up-stairs :up-stairs
-             :down-stairs :down-stairs
-             :nil :horizontal-wall)
-    :vertical-wall (case (cell2 :type)
-             :floor :floor
-             :horizontal-wall :horizontal-wall
-             :vertical-wall :vertical-wall
-             :corridor :close-door
-             :close-door :close-door
-             :up-stairs :up-stairs
-             :down-stairs :down-stairs
-             :nil :vertical-wall)
-    :corridor (case (cell2 :type)
-             :floor :floor
-             :horizontal-wall :close-door
-             :vertical-wall :close-door
-             :corridor :corridor
-             :close-door :close-door
-             :up-stairs :up-stairs
-             :down-stairs :down-stairs
-             :nil :corridor)
-    :close-door (case (cell2 :type)
-             :floor :floor
-             :horizontal-wall :close-door
-             :vertical-wall :close-door
-             :corridor :corridor
-             :close-door :close-door
-             :up-stairs :up-stairs
-             :down-stairs :down-stairs
-             :nil :close-door)
-    :up-stairs (case (cell2 :type)
-             :floor :up-stairs
-             :horizontal-wall :up-stairs
-             :vertical-wall :up-stairs
-             :corridor :up-stairs
-             :close-door :up-stairs
-             :nil :up-stairs)
-    :down-stairs (case (cell2 :type)
-             :floor :down-stairs
-             :horizontal-wall :down-stairs
-             :vertical-wall :down-stairs
-             :corridor :down-stairs
-             :close-door :down-stairs
-             :nil :down-stairs)
-    :nil (cell2 :type)))
+  (println "merging cells" cell1 "," cell2)
+  (let [cell1-type (get cell1 :type)
+        cell2-type (get cell2 :type)]
+    (cond
+      (or (and (= cell1-type :corridor)
+               (contains? #{:horizontal-wall :vertical-wall :close-door} cell2-type))
+          (and (= cell2-type :corridor)
+               (contains? #{:horizontal-wall :vertical-wall :close-door} cell1-type)))
+        :close-door
+      (= cell1-type :nil)
+        cell2-type
+      (= cell2-type :nil)
+        cell1-type
+      (= cell1-type cell2-type)
+        cell1-type
+      :else
+        (assert false (format "Trying to merge %s %s" (str cell1-type) (str cell2-type))))))

 (defn merge-with-canvas
   "Merge a grid of `[x y cell]` into an existing grid. The result is a merged grid
@@ -353,6 +318,11 @@
 (defn rand-int-range [min max]
   (+ (rand-int (- max min)) min))

+(defn room-bounds-to-center
+  [[x1 y1 x2 y2]]
+  [(int (/ (+ x1 x2) 2))
+   (int (/ (+ y1 y2) 2))])
+
 (defn random-place
   "Create a grid of random rooms with corridors connecting them and doors
    where corridors connect to rooms."
@@ -374,13 +344,11 @@
                                       [x y (+ x width) (+ y height)]))
                                     (range columns)))
                              (range rows))
-        rooms        (mapcat #(apply room-to-cellsxy %) room-bounds)
+        ;rooms        (mapcat #(apply room-to-cellsxy %) room-bounds)
         room-centers-to-room-bounds
                      (reduce (fn [m room-bounds]
-                               (let [[x1 y1 x2 y2] room-bounds]
-                                 (assoc m [(int (/ (+ x1 x2) 2))
-                                           (int (/ (+ y1 y2) 2))]
-                                          room-bounds)))
+                               (assoc m (room-bounds-to-center room-bounds)
+                                        room-bounds))
                              {}
                              room-bounds)
         room-centers (keys room-centers-to-room-bounds)
@@ -389,12 +357,24 @@
         g            (graph-to-minimum-spanning-tree fcg)
         more-edges   (additional-edges min-width min-height room-centers g)
         g            (concat g more-edges)
-        ;; reduce over g
+        ;; set of room centers that are junction rooms
+        junction-rooms (find-junction-rooms g)
+        ;; merge room cells to canvas, skipping junction rooms
+        cells        (reduce (fn [cells room-bound]
+                               (println "room-bound" room-bound)
+                               (if (contains? junction-rooms (room-bounds-to-center room-bound))
+                                 cells
+                                 (let [room-cellsxy (apply room-to-cellsxy room-bound)]
+                                   (println "room-cellsxy" room-cellsxy)
+                                   (apply merge-with-canvas cells room-cellsxy))))
+                             (canvas width height)
+                             room-bounds)
+        ;; reduce over g, merging corridor cells to canvas
         cells        (reduce (fn [cells [start goal]]
-                               (let [points (make-corridor-points cells room-centers-to-room-bounds start goal)]
+                               (let [points (make-corridor-points cells room-centers-to-room-bounds junction-rooms start goal)]
                                  (println "corridor points" points)
                                  (apply merge-with-canvas cells (points-to-corridor points))))
-                             (apply merge-with-canvas (canvas width height) rooms)
+                             cells
                              g)
         upstairs     (conj [(first room-centers)] {:type :up-stairs})
         downstairs   (conj [(last room-centers)] {:type :down-stairs})]
@@ -416,11 +396,19 @@
                                         (if (nil? cell)
                                             \
                                             (case (cell :type)
-                                              :floor \.
-                                              :vertical-wall \|
-                                              :horizontal-wall \-
+                                              :floor \·
+                                              :corridor \#
+                                              :vertical-wall \║
+                                              :horizontal-wall \═
+                                              :upper-left-1 \╔
+                                              :upper-right-1 \╗
+                                              :bottom-left-1 \╚
+                                              :bottom-right-1 \╝
+                                              :upper-left-2 \◙
+                                              :upper-right-2 \◙
+                                              :bottom-left-2 \◙
+                                              :bottom-right-2 \◙
                                               :close-door \+
-                                              :corridor \#
                                               :up-stairs \<
                                               :down-stairs \>
                                               (str (cell :type)))))


Checks if handler is a vector and combines all handlers

--- src/clojure/catacumba/impl/routing.clj
+++ src/clojure/catacumba/impl/routing.clj
@@ -71,7 +71,7 @@
   [^Chain chain [_ handlersmap]]
   {:pre [(map? handlersmap)]}
   (letfn [(attach [^Context ctx ^ByMethodSpec spec [method handler]]
-            (let [^Handler handler (hs/adapter handler)
+            (let [^Handler handler (if (vector? handler) (combine-handlers handler) (hs/adapter handler))
                   ^Block block (hp/fn->block #(.handle handler ctx))]
               (case method
                 :get (.get spec block)


ignore functions beginning with '.' in inner trace

--- src/com/billpiel/sayid/deep_trace2.clj
+++ src/com/billpiel/sayid/deep_trace2.clj
@@ -523,6 +523,12 @@
                                     path
                                     parent-path)))

+(defn dot-sym?
+  [sym]
+  (-> sym
+       str
+       (.startsWith ".")))
+
 (defn xpand-form
   [form src-map fn-meta & [path parent-path]]
   (let [path' (or path [])]
@@ -537,7 +543,9 @@

           (= 'if head) (xpand-if form src-map fn-meta path' parent-path)

-          (special-symbol? head) (xpand-all form src-map fn-meta path' parent-path)
+          (or (special-symbol? head)
+              (dot-sym? head)) ;; TODO better way to detect these?
+          (xpand-all form src-map fn-meta path' parent-path)

           :else (xpand-fn head form src-map fn-meta path' parent-path)))

@@ -608,8 +616,11 @@
                         macroexpand
                         get-fn
                         (xpand-fn* meta'))]
-    (util/eval-in-ns (-> ns' str symbol)
-                     traced-form)))
+    (try (util/eval-in-ns (-> ns' str symbol)
+                          traced-form)
+         (catch Exception e
+           (clojure.pprint/pprint traced-form)
+           (throw e)))))

 (defn ^{::trace/trace-type :deep-fn} composed-tracer-fn
   [m _]


Typo fix

Typo fix

--- src/overseer/worker.clj
+++ src/overseer/worker.clj
@@ -29,7 +29,7 @@
             (raven.interface/stacktrace ex))]
     (try (raven/capture dsn ex-map)
       (catch Exception ex'
-        (timbre/error "Senry exception handler failed")
+        (timbre/error "Sentry exception handler failed")
         (timbre/error ex')))))

 (defn ->default-exception-handler


Breaking change - control-bus-get may now return a sequence of vals.

Modify control-bus-get to return multiple vals when getting a multi-channel
control bus. If passed a numeric index, functionality remains unchanged.

Add new function control-but-get-channel which will only ever return a
single value.

--- src/overtone/sc/bus.clj
+++ src/overtone/sc/bus.clj
@@ -163,17 +163,19 @@
        (snd "/c_set" id val)
        val)))

-(defn control-bus-get
-  "Synchronously get the current value of a control bus.
-
-   An optional offset may be supplied to access values within
-   multi-channel buses."
-  ([bus] (control-bus-get bus 0))
+(defn control-bus-get-channel
+  "Syncronously get the current value of an individual channel of a
+   control bus. Always returns a single value. For a multi-channel bus,
+   defaults to first channel.
+
+   An optional offset may be specified."
+  ([bus]
+     (control-bus-get-channel bus 0))
   ([bus offset]
+     (when (control-bus? bus)
+       (ensure-valid-bus-offset! bus offset))
      (let [id (to-sc-id bus)
            id (+ offset id)]
-       (when (control-bus? bus)
-         (ensure-valid-bus-offset! bus offset))
        (let [p  (server-recv "/c_set" (fn [info] (= id (first (:args info))))) ]
          (snd "/c_get" id)
          (second (:args (deref! p (str "attempting to read the current value of bus "
@@ -216,6 +218,17 @@
        (drop 2 (:args (deref! p (str "attempting to get a range of consecutive control bus values of length "
                                      len " from bus " (with-out-str (pr bus)))))))))

+(defn control-bus-get
+  "Synchronously get the current value of a control bus. If a
+   control-bus record is passed in, all channels are returned.
+
+   An optional offset may be supplied to access values within
+   multi-channel buses."
+  ([bus] (control-bus-get bus 0))
+  ([bus offset]
+     (if (control-bus? bus)
+       (control-bus-get-range bus (:n-channels bus) offset)
+       (control-bus-get-channel bus offset))))
 (defn- create-monitor-group
   "Creates a group for the audio bus monitor synths. Designed to be
    called in a dependency callback after :foundation-groups-created."


check mongo-status

check mongo-status

--- src/clj/ceres/core.clj
+++ src/clj/ceres/core.clj
@@ -126,10 +126,11 @@
   (timbre/set-config! [:shared-appender-config :spit-filename] (:logfile @server-state))
   (info "Starting twitter collector...")
   (when (:init? @server-state)
-    (collector/init-mongo)
-    (curator/backup-tweets (:backup-folder @server-state))
-    (curator/backup-articles (:backup-folder @server-state))
-    (curator/backup-origins (:backup-folder @server-state)))
+    (doall
+     (collector/init-mongo)
+     (try
+       (curator/backup-tweets (:backup-folder @server-state))
+       (catch Exception e (error (str "Caught exception" (.getMessage e)))))))
   (info @server-state)
   (when (:http-server? @server-state)
     (run-server (site #'all-routes) {:port (:port @server-state) :join? false}))


Modified stuff in rain, so we're currently generating all indices -- we can pair these against each rain month.

--- src/clj/forma/rain.clj
+++ src/clj/forma/rain.clj
@@ -172,11 +172,38 @@
         sample (+ line index)]
     [sample line]))

+;; TODO -- comment, get rid of the 720.
 (defn rain-index
-  "INCOMPLETE. Returns the index inside a rain data vector for the
-  given inputs."
   [mod-h mod-v sample line res]
-  (geo-coords mod-h mod-v sample line res))
+  (let [[lat lon] (geo-coords mod-h mod-v sample line res)
+        [row col] (indy lat lon)]
+    (+ (* row 720) col)))
+
+;; TODO -- rename this, docstring.
+(defn index [res x]
+  (int (floor (* x (/ res)))))
+
+;; TODO -- rename this. rename in rain-ndex above.
+;; Also, get these 720s, and the forma-res, out of there!
+(defn indy [lat lon]
+  (let [forma-idx (partial index forma-res)
+        lon-idx (forma-idx (abs lon))
+        lat-idx (forma-idx (+ lat 90))]
+    (vector lat-idx
+            (if (neg? lon)
+              (- (dec 720) lon-idx)
+              lon-idx))))
+
+;; TODO -- rename this from resample.
+;; TODO -- can we just return index, here?  Then, we could have, for
+;; an input of chunk size, data, resolution -- we'd actually just need
+;; chunk-size and resolution as inputs.  mod-h, mod-v, chunk,
+;; chunk-seq. But the chunk-seq would actually be the proper indices
+;; within the data!  So the results of this would be a huge business
+;; of those four parameters. Every months would need them all.
+;;
+;;It would take ALL of those and a given month -- and return all of
+;; the samples. But we'd be able to split these between everything.

 (defn resample
   "Takes in a month's worth of PREC/L rain data, and returns a lazy
@@ -184,10 +211,13 @@
   [data res mod-h mod-v chunk chunk-size]
   (let [rain (vec data)]
     (for [pixel (range chunk-size)]
-      (let [[sample line] (tile-position chunk pixel chunk-size)
-            index (rain-index mod-h mod-v sample line res)]
-        (rain index)))))
-
+      (let [[sample line] (tile-position chunk pixel chunk-size)]
+        (rain-index mod-h mod-v sample line res)))))
+
+;; TODO -- this query currents generates all chunks for a specific
+;; rain month. We want to convert this so that it generates the MAPS
+;; of all chunks! Then, we'll feed this whole business in with each
+;; month, and (map month-data idx-seq).
 (defmapcatop [rain-chunks [chunk-size]]
   ^{:doc "Takes in data for a single month of rain data, and resamples
   it to the MODIS sinusoidal grid at the supplied resolution. Returns
@@ -198,5 +228,5 @@
           mod-v (range v-tiles)
           chunk (range (/ (sqr edge-length) chunk-size))
           :when (valid-modis? mod-h mod-v)]
-      (let [chunk-seq (resample data res mod-h mod-v chunk chunk-size)]
-        [mod-h mod-v chunk chunk-seq]))))+      (let [idx-seq (resample data res mod-h mod-v chunk chunk-size)]
+        [mod-h mod-v chunk idx-seq]))))


Do not read resources/config.clj when compiling.

Fixes lein jar and lein uberjar.

--- src/clojars/config.clj
+++ src/clojars/config.clj
@@ -1,4 +1,4 @@
 (ns clojars.config
   (:require [clojure.java.io :as io]))

-(def config (read-string (slurp (io/resource "config.clj"))))+(def config (when-not *compile-files* (read-string (slurp (io/resource "config.clj")))))


cassandra: error message typo

cassandra: error message typo

--- src/er_cassandra/model/alia/upsert.clj
+++ src/er_cassandra/model/alia/upsert.clj
@@ -280,7 +280,7 @@
               :upsert/require-explicit-select-upsert
               {:message (str "this entity has foreign keys, "
                              "so requires the previous version "
-                             "to upsert. either use select-upsert"
+                             "to upsert. either use select-upsert "
                              "or change")
                :entity (with-out-str (pprint entity))
                :record record


be more careful with serialization and deserialization

serialise everything before applying to db,
deserialise afterwards

--- src/er_cassandra/model/alia/upsert.clj
+++ src/er_cassandra/model/alia/upsert.clj
@@ -186,15 +186,15 @@
               (= (t/extract-uber-key-value entity old-record)
                  (t/extract-uber-key-value entity record))))

-  (ddo [:let [opts (ts/default-timestamp-opt opts)
-
-              record-keys (-> record keys set)]
-
-
-        record-bs (t/run-callbacks session entity :before-save record opts)
-
-        :let [record-bs-keys (-> record-bs keys set)
-              removed-keys (set/difference record-keys record-bs-keys)
+  (ddo [:let [opts (ts/default-timestamp-opt opts)]
+
+        ;; serialize the old-record and record
+        old-record-ser (t/run-callbacks session entity :before-save old-record opts)
+        record-ser (t/run-callbacks session entity :before-save record opts)
+
+        :let [record-keys (-> record keys set)
+              record-ser-keys (-> record-ser keys set)
+              removed-keys (set/difference record-keys record-ser-keys)

               ;; if the op is an insert, then old-record will be nil,
               ;; and we will need to return nil values for any removed keys
@@ -205,33 +205,44 @@
                                       [k nil]))
                                (into {}))]

-        [updated-record-with-keys
+        [updated-record-with-keys-ser
          acquire-failures] (unique-key/upsert-primary-record-and-update-unique-keys
                             session
                             entity
-                            old-record
-                            record-bs
+                            old-record-ser
+                            record-ser
                             opts)

-        _ (monad/when updated-record-with-keys
+        _ (monad/when updated-record-with-keys-ser
             (update-secondaries-and-lookups session
                                             entity
-                                            old-record
-                                            updated-record-with-keys
+                                            old-record-ser
+                                            updated-record-with-keys-ser
                                             opts))
+
+        ;; construct the response and deserialise
+        response-record-raw (merge nil-removed
+                                   old-record
+                                   updated-record-with-keys-ser)
+        response-record (t/run-callbacks
+                         session
+                         entity
+                         :after-load
+                         response-record-raw
+                         opts)

         ;; do any :after-save actions
         _ (t/run-callbacks
            session
            entity
            :after-save
-           updated-record-with-keys
+           response-record
            opts)]

     (return
      ;; merge the updated-record-with-keys with the old-record, so any
      ;; cols not included in the update are in the response
-     (pair (merge nil-removed old-record updated-record-with-keys)
+     (pair response-record
            acquire-failures))))

 (s/defn upsert*


CMR-1307: Address review comments

CMR-1307: Address review comments

--- system-int-test/src/cmr/system_int_test/data2/opendata.clj
+++ system-int-test/src/cmr/system_int_test/data2/opendata.clj
@@ -90,21 +90,18 @@
    :results {:conformsTo odrh/OPENDATA_SCHEMA
              :dataset (map collection->expected-opendata collections)}})

-(defn- map-with-sequentials->map-with-sets
-  "Converts all of the collections within a map to sets. This allows maps to be compared such that
-  the order of elements in a collection is ignored."
-  [m]
-  (into #{} (for [v m]
-              (util/map-values #(if (sequential? %) (set %) %) v))))
+(defn- opendata-results-map->opendata-results-map-using-sets
+  "Converts all of the collections within an opendata results map to sets. This allows maps to be
+  compared such that the order of elements in a collection is ignored."
+  [opendata-results-map]
+  (update-in opendata-results-map [:results :dataset]
+             (fn [dataset]
+               (into #{} (for [field dataset]
+                           (util/map-values #(if (sequential? %) (set %) %) field))))))

 (defn assert-collection-opendata-results-match
   "Returns true if the opendata results are for the expected items"
   [collections actual-result]
-  (is (= (-> (collections->expected-opendata collections)
-             (update-in [:results :dataset] set)
-             (update-in [:results :dataset]
-                        #(map-with-sequentials->map-with-sets %)))
-         (-> actual-result
-             (update-in [:results :dataset] set)
-             (update-in [:results :dataset]
-                        #(map-with-sequentials->map-with-sets %))))))
+  (is (= (opendata-results-map->opendata-results-map-using-sets
+           (collections->expected-opendata collections))
+         (opendata-results-map->opendata-results-map-using-sets actual-result))))


CMR-694: Added test of deleting a concept with native id with slashes.

--- test/cmr/system_int_test/ingest/collection_ingest_test.clj
+++ test/cmr/system_int_test/ingest/collection_ingest_test.clj
@@ -166,4 +166,8 @@
     (is (= 200 (:status response)))
     (is (ingest/concept-exists-in-mdb? concept-id revision-id))
     (is (= 1 revision-id))
-    (is (= "Name/With/Slashes" (:native-id ingested-concept)))))
+    (is (= "Name/With/Slashes" (:native-id ingested-concept)))
+
+    (testing "delete"
+      (let [delete-result (ingest/delete-concept ingested-concept)]
+        (is (= 200 (:status delete-result)))))))


prettier type handling

prettier type handling

--- src/latte_compiler/static_analysis.clj
+++ src/latte_compiler/static_analysis.clj
@@ -466,7 +466,7 @@
   (= (get-type x) [:int]))

 (defn- annotate-erel
-  [vars lexpr rexpr relop location]
+  [glob-state vars lexpr rexpr relop location]
   (match [lexpr rexpr relop]
     [(lexpr :guard #(is-str %)) (rexpr :guard #(is-str %)) [:eq]]
     (succ [vars (with-type [:eapp [:ident "_eqStrings"] [lexpr rexpr]] [:bool])])
@@ -478,11 +478,11 @@
     (succ [vars (with-type [:erel lexpr relop rexpr] [:bool])])

     [lexpr rexpr (:or [:eq] [:ieq])]
-    (if (= (get-type lexpr)
+    (if (check-types-helper glob-state (get-type lexpr)
           (get-type rexpr))
       (succ [vars (with-type [:erel lexpr relop rexpr] [:bool])])
-      (err (str "expr invalid; expected " (get-type lexpr) ", found " (get-type rexpr)
-             " in: " location))
+      (err (str "expr invalid; expected " (print-type (get-type lexpr)) ", found "
+             (print-type (get-type rexpr)) " in: " location))
       )

     :else
@@ -644,7 +644,7 @@
               [[vars1 lexpr] (annotate-expr glob-state vars (second expr))
                [vars2 rexpr] (annotate-expr glob-state vars1 (fourth expr))
                op (m-result (third expr))
-               res (annotate-erel vars2 lexpr rexpr op location)
+               res (annotate-erel glob-state vars2 lexpr rexpr op location)
                ]
               res)
       :emul (domonad phase-m