what a nice test fix <3

what a nice test fix <3

--- test/metabase/api/meta/table_test.clj
+++ test/metabase/api/meta/table_test.clj
@@ -22,24 +22,17 @@

 ;; ## GET /api/meta/table?org
 ;; These should come back in alphabetical order and include relevant metadata
-(expect [{:description nil, :entity_type nil, :name "CATEGORIES", :rows 75, :entity_name nil, :active true,
-          :id (table->id :categories), :db_id @db-id}
-         {:description nil, :entity_type nil, :name "CHECKINS", :rows 1000, :entity_name nil, :active true,
-          :id (table->id :checkins), :db_id @db-id}
-         {:description nil, :entity_type nil, :name "USERS", :rows 15, :entity_name nil, :active true,
-          :id (table->id :users), :db_id @db-id}
-         {:description nil, :entity_type nil, :name "VENUES", :rows 100, :entity_name nil, :active true,
-          :id (table->id :venues), :db_id @db-id}
-         {:description nil, :entity_type nil, :name "categories", :rows 75, :entity_name nil, :active true,
-          :id (mongo-data/table-name->id :categories), :db_id @mongo-test-db-id}
-         {:description nil, :entity_type nil, :name "checkins", :rows 1000, :entity_name nil, :active true,
-          :id (mongo-data/table-name->id :checkins), :db_id @mongo-test-db-id}
-         {:description nil, :entity_type nil, :name "users", :rows 15, :entity_name nil, :active true,
-          :id (mongo-data/table-name->id :users), :db_id @mongo-test-db-id}
-         {:description nil, :entity_type nil, :name "venues", :rows 100, :entity_name nil, :active true,
-          :id (mongo-data/table-name->id :venues), :db_id @mongo-test-db-id}]
+(expect #{{:name "CATEGORIES", :rows 75,   :active true, :id (table->id :categories),                 :db_id @db-id}
+          {:name "CHECKINS",   :rows 1000, :active true, :id (table->id :checkins),                   :db_id @db-id}
+          {:name "USERS",      :rows 15,   :active true, :id (table->id :users),                      :db_id @db-id}
+          {:name "VENUES",     :rows 100,  :active true, :id (table->id :venues),                     :db_id @db-id}
+          {:name "categories", :rows 75,   :active true, :id (mongo-data/table-name->id :categories), :db_id @mongo-test-db-id}
+          {:name "checkins",   :rows 1000, :active true, :id (mongo-data/table-name->id :checkins),   :db_id @mongo-test-db-id}
+          {:name "users",      :rows 15,   :active true, :id (mongo-data/table-name->id :users),      :db_id @mongo-test-db-id}
+          {:name "venues",     :rows 100,  :active true, :id {mongo-data/table-name->id :venues},     :db_id @mongo-test-db-id}}
   (->> ((user->client :rasta) :get 200 "meta/table" :org @org-id)
-       (map #(dissoc % :db :created_at :updated_at)))) ; don't care about checking nested DB, and not sure how to compare `:created_at` / `:updated_at`
+       (map #(dissoc % :db :created_at :updated_at :entity_name :description :entity_type))
+       set))

 ;; ## GET /api/meta/table/:id
 (expect


fix up table api unit test.

fix up table api unit test.

--- test/metabase/api/meta/table_test.clj
+++ test/metabase/api/meta/table_test.clj
@@ -36,6 +36,7 @@
        :updated_at $
        :entity_name nil
        :active true
+       :pk_field nil
        :id (table->id :venues)
        :db_id (:id @test-db)
        :created_at $})
@@ -140,6 +141,7 @@
         :updated_at $
         :entity_name "Userz"
         :active true
+        :pk_field nil
         :id $
         :db_id @db-id
         :created_at $})


CMR-6499: Simplify feature validation

CMR-6499: Simplify feature validation

--- search-app/src/cmr/search/services/parameters/converters/shapefile.clj
+++ search-app/src/cmr/search/services/parameters/converters/shapefile.clj
@@ -49,6 +49,14 @@
   "The maximum number of points a shapefile can have"
   {:default 5000 :type Long})

+(defn winding-opts
+  "Get the opts for a call to `normalize-polygon-winding` based on file type"
+  [mime-type]
+  (case mime-type
+    "application/shapefile+zip" {:boundary-winding :cw}
+    "application/vnd.google-earth.kml+xml" {}
+    "application/geo+json" {:hole-winding :cw}))
+
 (defn unzip-file
   "Unzip a file (of type File) into a temporary directory and return the directory path as a File"
   [source]
@@ -114,6 +122,50 @@
         (errors/throw-service-error :bad-request (format "Cannot transform source CRS [%s] to WGS 84" src-crs-name))))
     geometry))

+(defn feature-point-count
+  "Get the number of points in the Feature"
+  [feature]
+  (let [crs (when (.getDefaultGeometryProperty feature)
+              (-> feature .getDefaultGeometryProperty .getDescriptor .getCoordinateReferenceSystem))
+        properties (.getProperties feature)
+        geometry-props (filter (fn [p] (geo/geometry? (.getValue p))) properties)
+        geometries (map #(-> % .getValue (transform-to-epsg-4326 crs)) geometry-props)]
+    (apply + (map geometry-point-count geometries))))
+
+(defn features-point-count
+  "Compute the number of points in a list of Features"
+  [features]
+  (reduce (fn [total feature] (+ total (feature-point-count feature)))
+          0
+          features))
+
+(defn validate-point-count
+  "Validate that the number of points in the features is greater than zero and less than the limit"
+  [features]
+  (let [point-count (features-point-count features)]
+    (if (= point-count 0)
+      "Shapefile has no points"
+      (when (> point-count (max-shapefile-points))
+        (format "Number of points in shapefile exceeds the limit of %d"
+          (max-shapefile-points))))))
+
+(defn- validate-feature-count
+  "Validates that the number of features is greater than zero and less than the limit"
+  [features]
+  (let [feature-count (count features)]
+    (if (= feature-count 0)
+      "Shapefile has no features"
+      (when (> feature-count (max-shapefile-features))
+        (format "Shapefile feature count [%d] exceeds the %d feature limit"
+          feature-count
+          (max-shapefile-features))))))
+
+(defn validate-features
+  "Validate this list of features in terms of shapefile limits"
+  [features]
+  (when-let [message (or (validate-feature-count features) (validate-point-count features))]
+    (errors/throw-service-error :bad-request message)))
+
 (defn feature->conditions
   "Process the contents of a Feature to return query conditions along with number of points in
   the processed Feature. The `context` map can be used to pass along additional info."
@@ -130,6 +182,20 @@
         conditions (mapcat (fn [g] (geometry->conditions g context)) geometries)]
     (debug (format "CONDITIONS: %s" conditions))
     [conditions point-count]))
+
+(defn features->conditions
+  "Converts a list of features into a vector of SpatialConditions"
+  [features mime-type]
+  (validate-features features)
+  (let [iterator (.iterator features)]
+    (loop [conditions []]
+      (if (.hasNext iterator)
+        (let [feature (.next iterator)
+              [feature-conditions _] (feature->conditions feature (winding-opts mime-type))]
+          (if (> (count feature-conditions) 0)
+            (recur (conj conditions (gc/or-conds feature-conditions)))
+            (recur conditions)))
+        conditions))))

 (defn error-if
   "Throw a service error with the given message if `f` applied to `item` is true.
@@ -278,31 +344,12 @@
           (throw e) ;; This was a more specific service error so just re-throw it
           (errors/throw-service-error :bad-request "Failed to parse KML file"))))))

-(defn winding-opts
-  "Get the opts for a call to `normalize-polygon-winding` based on file type"
-  [mime-type]
-  (case mime-type
-    "application/shapefile+zip" {:boundary-winding :cw}
-    "application/vnd.google-earth.kml+xml" {}
-    "application/geo+json" {:hole-winding :cw}))
-
 (defn in-memory->conditions-vec
   "Converts a group of features produced by simplification to a vector of SpatialConditions"
   [shapefile-info]
-  (try
-    (let [^ArrayList features (:tempfile shapefile-info)
-          mime-type (:content-type shapefile-info)
-          iterator (.iterator features)]
-      (loop [conditions []]
-        (if (.hasNext iterator)
-          (let [feature (.next iterator)
-                [feature-conditions _] (feature->conditions feature (winding-opts mime-type))]
-            (if (> (count feature-conditions) 0)
-              (recur (conj conditions (gc/or-conds feature-conditions)))
-              (recur conditions)))
-          conditions)))
-    (catch Exception e
-      (.printstackTrace e))))
+  (let [^ArrayList features (:tempfile shapefile-info)
+        mime-type (:content-type shapefile-info)]
+    (features->conditions features mime-type)))

 (defmulti shapefile->conditions
   "Converts a shapefile to query conditions based on shapefile format"
@@ -337,7 +384,7 @@
     (gc/or-conds (flatten conditions-vec))))

 (defmethod p/parameter->condition :shapefile
-  [_context concept-type param value options]
+  [_context _concept-type _param value _options]
   (if (enable-shapefile-parameter-flag)
     (shapefile->conditions value)
     (errors/throw-service-error :bad-request "Searching by shapefile is not enabled")))


Added saving and loading features for item groups.

--- yaw/yaw/world.clj
+++ yaw/yaw/world.clj
@@ -224,7 +224,7 @@

 ;; Save Tools for Items
 (defn meshToVector [mesh]
-	"Converts Meshes into a savable vector. Special Meshes not yet supported."
+	"Converts Meshes into a savable vector. Special Meshes not yet entirely supported."
 	(println "Mesh to vector called with " (.getClass mesh))
 	(if (= (.getClass mesh) gameEngine.meshs.Mesh) ;; If custom Mesh
 		(let [material (.getMaterial mesh)
@@ -243,7 +243,8 @@
 	"Converts a MyItem into a savable vector."
 	(let [rotation (.getRotation myItem)
 				translation (.getPosition myItem)]
-	(vector (.getScale myItem) (.x rotation) (.y rotation) (.z rotation) (.x translation) (.y translation) (.z translation))))
+	(vector (.getScale myItem) (.x rotation) (.y rotation) (.z rotation) (.x translation) (.y translation) (.z translation))
+	))

 (defn createMyItemVector [mesh itemListVec]
 	"Saves all MyItem in the given List (as vector) in EDN format."
@@ -261,6 +262,25 @@
 			(conj (saveMeshMap (pop meshMapVec)) (createMyItemVector (.getKey (last meshMapVec)) (vec (.getValue (last meshMapVec))))))
 	))

+;; Save Tools for Groups
+(defn createGroupVector [groupItemListVec allItemsList]
+	"Converts a GroupItem into a savable vector."
+	(if (= (.length groupItemListVec) 0)
+		(vector)
+		(if (= (.length groupItemListVec) 1)
+			(vector (.indexOf allItemsList (first groupItemListVec)))
+			(conj (createGroupVector (pop groupItemListVec) allItemsList) (.indexOf allItemsList (last groupItemListVec))))
+	))
+
+(defn saveGroupsList [groupsListVec allItemsList]
+	"Saves all groups of the given groupsList (as vector) in EDN format."
+	(if (= (.length groupsListVec) 0)
+		(vector)
+		(if (= (.length groupsListVec) 1)
+			(vector (createGroupVector (vec (.getItems (first groupsListVec))) allItemsList))
+			(conj (saveGroupsList (pop groupsListVec) allItemsList) (createGroupVector (vec (.getItems (last groupsListVec))) allItemsList)))
+	))
+
 ;; Save Tools for Cameras
 (defn cameraToVector [cam]
 	"Converts a Camera into a savable vector."
@@ -308,10 +328,14 @@
 ;; Save Functions
 (defn saveItems [world]
 	"Returns a vector containing all items of the given world in EDN format."
-	(let [sceneVertex (.getSceneVertex world)
-				meshMapVec (vec (.getMapMesh sceneVertex))]
+	(let [meshMapVec (vec (.getMapMesh (.getSceneVertex world)))]
 				(saveMeshMap meshMapVec)
 		))
+
+(defn saveGroups [world]
+	"Returns a vector containing all groups of the given world in EDN format."
+	(saveGroupsList (vec (.getListGroup world)) (.getListItems (.getSceneVertex world)))
+	)

 (defn saveCameras [world]
 	"Returns a vector containing all cameras of the given world in EDN format."
@@ -341,9 +365,10 @@
 (defn saveFile [filename world]
 	"Saves all items, cameras and lights of the given world into a file, in EDN format."
 	(let [itemsVector (saveItems world)
+				groupsVector (saveGroups world)
 				camerasVector (saveCameras world)
 				lightsVector (saveLights world)]
-		(spit filename (with-out-str (pr (vector itemsVector camerasVector lightsVector))))
+		(spit filename (with-out-str (pr (vector itemsVector groupsVector camerasVector lightsVector))))
 	))

 ;; Load Tools
@@ -364,7 +389,7 @@

 ;; Load Tools for Items
 (defn loadMesh [mesh]
-	"Loads a Mesh. Does not support subclasses of Mesh yet."
+	"Loads a Mesh. Does not support all subclasses of Mesh yet."
 	(if (= (get mesh 0) gameEngine.meshs.Mesh)
 		(gameEngine.meshs.Mesh. (float-array (get mesh 1)) (get mesh 2) (get mesh 3) (get mesh 4) (get mesh 5) (float-array (get mesh 6)) (int-array (get mesh 7)) (get mesh 8))
 		(gameEngine.meshGenerator.BlockGenerator/generate (get mesh 1) (get mesh 2) (get mesh 3) (get mesh 4) (get mesh 5) (get mesh 6) (get mesh 7)))
@@ -397,6 +422,38 @@
 				(loadMeshMap (pop meshMapVec) world)))
 	))

+;; Load Tools for Groups
+(defn createNGroups [n world]
+	"Creates n groups in the world."
+	(println "createNGroups called with " n world)
+	(if (= n 0)
+		nil
+		(do
+			(ItemManagement/createGroup world)
+			(createNGroups (- n 1) world))
+	))
+
+
+(defn addItemsToGroup [groupItemsList groupId world]
+	"Adds items from the groupItemsList vector to the group corresponding to the given groupId."
+	(println "addItemsToGroup called with " groupItemsList groupId world)
+	(cond (> (.size groupItemsList) 0)
+		(let [groupsList (.getListGroup world)
+					itemsList (.getListItems (.getSceneVertex world))]
+			(addItem (.get groupsList groupId) (.get itemsList (first groupItemsList)))
+			(addItemsToGroup (rest groupItemsList) groupId world))
+	))
+
+
+(defn addItemsToGroups [groupsList curId world]
+	"Adds items from the groupsList vector to corresponding groups."
+	(println "addItemsToGroups called with " groupsList curId world)
+	(cond (> (.length groupsList) 0)
+		(do
+			(addItemsToGroup (lazy-seq (last groupsList)) curId world)
+			(addItemsToGroups (pop groupsList) (- curId 1) world))
+	))
+
 ;; Load Tools for Cameras
 (defn addCameras [cameraList world index]
 	"Adds all cameras contained in the provided list to the World."
@@ -431,6 +488,15 @@
 	"Loads all MyItem objects from an EDN vector created with saveItems."
 	(loadMeshMap loadedItems world)
 	)
+
+(defn loadGroups [loadedGroups world]
+	"Loads all groups from an EDN vector created with saveGroups."
+	(println "loadGroups called with " loadedGroups world)
+	(cond (> (.size loadedGroups) 0)
+		(do
+			(createNGroups (.size loadedGroups) world)
+			(addItemsToGroups loadedGroups (- (.size loadedGroups) 1) world))
+	))

 (defn loadCameras [loadedCameras world]
 	"Loads all Camera objects from an EDN vector created with saveCameras."
@@ -445,12 +511,13 @@
 		(addPointLights (lazy-seq (get loadedLights 2)) sceneLight 0)
 		(addSpotLights (lazy-seq (get loadedLights 3)) sceneLight 0)
 	))
-
+
 (defn loadFile [filename world]
 	"Reinitializes the world and loads items, cameras and lights contained in the given file."
 		(let [loadedVector (read-string (slurp filename))]
 		(.init world)
 		(loadItems (get loadedVector 0) world)
-		(loadCameras (get loadedVector 1) world)
-		(loadLights (get loadedVector 2) world)
-	))
+		(loadGroups (get loadedVector 1) world)
+		(loadCameras (get loadedVector 2) world)
+		(loadLights (get loadedVector 3) world)
+	))


squash! squash! squash! Rework the way drivers are defined

--- src/metabase/driver/sync.clj
+++ src/metabase/driver/sync.clj
@@ -38,7 +38,7 @@

 ;; ## sync-database! and sync-table!

-(defn -sync-database! [{:keys [active-table-names], :as driver} database]
+(defn- -sync-database! [{:keys [active-table-names], :as driver} database]
   (let [start-time (System/currentTimeMillis)
         tracking-hash (str (java.util.UUID/randomUUID))]
     (log/info (u/format-color 'magenta "Syncing %s database '%s'..." (name (:engine database)) (:name database)))


Fix idle strategies broken by merge

Fix idle strategies broken by merge

--- src/onyx/messaging/aeron.clj
+++ src/onyx/messaging/aeron.clj
@@ -216,9 +216,8 @@
           external-addr (common/external-addr opts)
           port (opts->port opts)
           external-channel (aeron-channel external-addr port)
-          idle-strategy-config (arg-or-default :onyx.messaging.aeron/idle-strategy opts)
-          poll-idle-strategy-config (arg-or-default :onyx.messaging.aeron/poll-idle-strategy config)
-          offer-idle-strategy-config (arg-or-default :onyx.messaging.aeron/offer-idle-strategy config)
+          poll-idle-strategy-config (arg-or-default :onyx.messaging.aeron/poll-idle-strategy opts)
+          offer-idle-strategy-config (arg-or-default :onyx.messaging.aeron/offer-idle-strategy opts)
           send-idle-strategy (backoff-strategy poll-idle-strategy-config)
           receive-idle-strategy (backoff-strategy offer-idle-strategy-config)
           compress-f (or (:onyx.messaging/compress-fn opts) compress)


make sure note isnt blank

make sure note isnt blank

--- src/open_company/lib/bot.clj
+++ src/open_company/lib/bot.clj
@@ -38,9 +38,10 @@
        (apply merge)))

 (defn add-su-note [ctx]
-  (if-let [note (-> ctx :data :note)]
-    (assoc-in ctx [:stakeholder-update :note] note)
-    ctx))
+  (let [note (-> ctx :data :note)]
+    (if-not (string/blank? note)
+      (assoc-in ctx [:stakeholder-update :note] note)
+      ctx)))

 (defn add-origin [params ctx]
   (if-let [origin (get-in ctx [:request :headers "origin"])]


Squash - rule tuning

Squash - rule tuning

--- resources/rules/_1_post_identifier_merge/step_h_ice_to_bio/step_hd_bioentity_linking/instance_based_kr/goa/step_a/goa_molecular_function_ice_to_bio_instance_based.clj
+++ resources/rules/_1_post_identifier_merge/step_h_ice_to_bio/step_hd_bioentity_linking/instance_based_kr/goa/step_a/goa_molecular_function_ice_to_bio_instance_based.clj
@@ -5,7 +5,7 @@
   :description   "This rule creates a subclass of every molecular function and types it as a gene ontology molecular function concept identifier  (IAO_EXT_0000103)"
   :head          (
                    (?/molecular_function_instance rdfs/subClassOf ccp/temp_molecular_function)
-                   (?/molecular_function_instance ccp/temp_has_participant bioentity_instance)
+                   (?/molecular_function_instance ccp/temp_has_participant ?/bioentity_instance)

                    (?/molecular_function_instance rdf/type ?/molecular_function)
                    (?/bioentity_instance rdf/type ?/participating_bioentity)


Rename another macroj

Rename another macroj

--- src/play_clj/g2d_physics.clj
+++ src/play_clj/g2d_physics.clj
@@ -104,13 +104,9 @@

 ; fixtures

-(defn fixture*
-  []
-  (FixtureDef.))
-
-(defmacro fixture
-  [& options]
-  `(let [^FixtureDef object# (fixture*)]
+(defmacro fixture-def
+  [& options]
+  `(let [^FixtureDef object# (FixtureDef.)]
      (u/fields! object# ~@options)
      object#))


Canonicalize the name of the method, too.

--- src/useful/experimental/delegate.clj
+++ src/useful/experimental/delegate.clj
@@ -1,4 +1,5 @@
 (ns useful.experimental.delegate
+  (:use useful.debug)
   (:require [useful.ns :as ns]))

 (defn canonical-name
@@ -24,7 +25,7 @@
   (loop [ret {}, curr-key nil, decls decls]
     (if-let [[x & xs] (seq decls)]
       (if (seq? x)
-        (recur (assoc-in ret [curr-key (first x)] x),
+        (recur (assoc-in ret [curr-key (symbol (name (first x)))] x),
                curr-key, xs)
         (let [interface-name (canonical-name x)]
           (recur (update-in ret [interface-name] #(or % {})),


Add total-pages field to projects in the dashboard (#16)

--- src/uxbox/ui/dashboard/projects.cljs
+++ src/uxbox/ui/dashboard/projects.cljs
@@ -169,7 +169,7 @@
       [:div.project-th-actions
        [:div.project-th-icon.pages
         i/page
-        [:span "0"]]
+        [:span (:total-pages project)]]
        #_[:div.project-th-icon.comments
         i/chat
         [:span "0"]]


각주링크 추가

각주링크 추가


Remove debug println on shapes and canvas.

--- frontend/uxbox/ui/workspace/canvas.cljs
+++ frontend/uxbox/ui/workspace/canvas.cljs
@@ -130,7 +130,6 @@
   [own shape selected]
   (let [{:keys [id x y width height] :as shape} shape
         selected? (contains? selected id)]
-    (println "shape-render" id)
     (letfn [(on-mouse-down [event]
               (let [local (:rum/local own)]
                 (dom/stop-propagation event)
@@ -212,7 +211,6 @@

 (defn- canvas-render
   [own {:keys [width height id] :as page}]
-  (println "canvas-render" id)
   (let [workspace (rum/react wb/workspace-state)
         shapes-by-id (rum/react shapes-by-id)
         workspace-selected (:selected workspace)


Require cljsjs.react.dom

Require cljsjs.react.dom

--- src/re_view_hiccup/core.cljs
+++ src/re_view_hiccup/core.cljs
@@ -1,5 +1,6 @@
 (ns re-view-hiccup.core
   (:require [cljsjs.react]
+            [cljsjs.react.dom]
             [clojure.string :as string]
             [re-view-hiccup.react.attrs :as react-html]))


add user starred rendering

add user starred rendering

--- src/clj/hsm/controllers/user.clj
+++ src/clj/hsm/controllers/user.clj
@@ -3,6 +3,7 @@
             [clojure.java.io              :as io]
             [cheshire.core                :refer :all]
             [ring.util.response           :as resp]
+            [hiccup.def                   :refer [defhtml]]
             [hsm.actions                  :as actions]
             [hsm.pipe.event               :as event-pipe]
             [hsm.views                    :refer [layout panel panelx]]
@@ -16,6 +17,39 @@
   (let [id (id-of request)
         user (actions/load-user db id)]
     (json-resp user)))
+
+(defhtml user-part
+  [id user admin? c-star c-follow c-followers]
+  (panel (:login user)
+    [:img.img-responsive.img-rounded {:src (:image user)}]
+    [:h3 [:span (:login user)]
+      [:a.pad10 {:href (str "https://github.com/" (:login user))} [:i.fa.fa-github]]]
+    [:h5 [:span (:name user)]]
+    [:p [:a {:href (:blog user)}(:blog user)]]
+    [:p (:company user)]
+    [:p (:location user)]
+    [:p (:type user)]
+    [:a {:href (str "mailto://" (:email user))} (:email user)]
+    [:p (format "%s %s %s" c-star c-follow c-followers)]
+    (when admin?
+      [:a.btn.btn-danger.btn-sm {:href (format "/user2/%s?force-sync=1" id)} "Synchronize"])
+    ))
+
+(defhtml render-repos
+  [repos]
+  [:table.table (for [repo repos]
+    [:tbody
+      [:tr
+        [:td {:rowspan 2} [:span (:watchers repo)]]
+        [:td
+          [:a {:href (str "/p/" (:full_name repo))}
+          (:full_name repo)
+          [:span.label (:stars repo)]
+          [:span.label (:forks repo)]
+          ]]]
+      [:tr
+          [:td
+          [:p.gray (:description repo)]]]])])

 (defn get-user2
   [[db event-chan] request]
@@ -39,20 +73,7 @@
           (json-resp user)
           (layout host
               [:div.col-lg-3
-                (panel (:login user)
-                  [:img.img-responsive.img-rounded {:src (:image user)}]
-                  [:h3 [:span (:login user)]
-                    [:a.pad10 {:href (str "https://github.com/" (:login user))} [:i.fa.fa-github]]]
-                  [:h5 [:span (:name user)]]
-                  [:p [:a {:href (:blog user)}(:blog user)]]
-                  [:p (:company user)]
-                  [:p (:location user)]
-                  [:p (:type user)]
-                  [:a {:href (str "mailto://" (:email user))} (:email user)]
-                  [:p (format "%s %s %s" c-star c-follow c-followers)]
-                  (when admin?
-                    [:a.btn.btn-danger.btn-sm {:href (format "/user2/%s?force-sync=1" id)} "Synchronize"])
-                  )
+                (user-part id user admin? c-star c-follow c-followers)
                 (when-not org?
                   (panel [:a {:href (format "/user2/%s/following" (:login user))} (str "Following: " c-follow)]
                     [:ul (for [star (:following user-extras)] [:li [:a {:href (str "/user2/" star)} star]])])
@@ -63,22 +84,11 @@
               (when-not org?
                 [:div.col-lg-6
                 (panel [:a {:href (format "/user2/%s/starred" (:login user))} (str "Starred " c-star) ]
-                  [:ul (for [star (:starred user-extras)] [:li [:a {:href (str "/p/" star)} star]])])])
+                  [:ul (for [star (take 10 (:starred user-extras))]
+                    [:li [:a {:href (str "/p/" star)} star]])])])
               [:div.col-lg-6
               (panelx "User Repos" ["no-pad"]
-                [:table.table (for [repo user-repos]
-                  [:tbody
-                  [:tr
-                    [:td {:rowspan 2} [:span (:watchers repo)]]
-                    [:td
-                      [:a {:href (str "/p/" (:full_name repo))}
-                      (:full_name repo)
-                      [:span.label (:stars repo)]
-                      [:span.label (:forks repo)]
-                      ]]]
-                  [:tr
-                      [:td
-                      [:p.gray (:description repo)]]]])]
+                (render-repos user-repos)
                 )]]))))))

 (defn sync-user2
@@ -137,7 +147,28 @@
   [{:keys [db event-chan redis]} request])

 (defn user2-starred
-  [{:keys [db event-chan redis]} request])
+  [{:keys [db event-chan redis]} request]
+  (let [id (id-of request)
+        host (host-of request)
+        user (actions/load-user2 db id)
+        user-extras (actions/user-extras db id)
+        admin? true
+        is-json (type-of request :json)
+        c-star (count (:starred user-extras))
+        c-follow (count (:following user-extras))
+        c-followers (count (:followers user-extras))
+        org? (= (:type user) "Organization")]
+    (if is-json
+          (json-resp user)
+          (layout host
+              [:div.col-lg-3
+                (user-part id user admin? c-star c-follow c-followers)]
+              [:div.col-lg-9
+              (when-not org?
+                [:div.col-lg-6
+                (panel [:a {:href (format "/user2/%s/starred" (:login user))} (str "Starred " c-star) ]
+                  (render-repos (reverse (sort-by :watchers (actions/load-projects-by-id db (vec (:starred user-extras))))))
+                  )])]))))

 (defn user2-contrib
   [{:keys [db event-chan redis]} request])


remove recursive user load

remove recursive user load

--- src/clj/hsm/controllers/user.clj
+++ src/clj/hsm/controllers/user.clj
@@ -48,7 +48,7 @@
     [:h3 [:a {:href (str "/user2/" id "/followers")} c-followers ]" followers "]

     (when admin?
-      [:a.btn.btn-danger.btn-sm {:href (format "/user2/%s?force-sync=1" id)} "Synchronize"])
+      [:a.btn.btn-danger.btn-sm {:href (format "/user2/%s?force-sync=1" id) :rel "nofollow"} "Synchronize"])
     ))

 (defhtml render-repos
@@ -78,7 +78,9 @@
     (if (or force-sync (not (:full_profile user)))
       (do
         (gh/find-n-update db id conf)
-        (redirect (str "/user2/" id)))
+        ; (redirect (str "/user2/" id))
+        (json-resp {:ok 1})
+        )
       (let [user-extras (actions/user-extras db id)
             user-repos (reverse (sort-by :watchers (actions/load-projects-by-id db (vec (:repos user-extras)))))
             c-star (count (:starred user-extras))


refactor shell-step for better readability

--- src/clj/lambdacd/steps/shell.clj
+++ src/clj/lambdacd/steps/shell.clj
@@ -33,25 +33,28 @@
     (.readLine reader)
     (catch IOException e nil)))

+(defn- read-and-print-shell-output [proc-result ctx]
+  (let [out-reader (io/reader (:out proc-result))
+        printer (support/new-printer)]
+    (loop []
+      (let [line (safe-read-line out-reader)]
+        (if line
+          (do
+            (support/print-to-output ctx printer line)
+            (recur)))))
+    (support/printed-output printer)))
+
 (defn- mysh [cwd cmd  ctx]
   (let [result-ch (:result-channel ctx)
         x (sh/proc "bash" "-c" cmd :dir cwd)
         proc (:process x)
-        out-reader (io/reader (:out x))
         was-killed (atom false)
         kill-switch (:is-killed ctx)
         watch-ref (UUID/randomUUID)
         _ (add-kill-handling ctx proc was-killed watch-ref)
-        printer (support/new-printer)
-        out (loop []
-              (let [v (safe-read-line out-reader)]
-                  (if v
-                    (do
-                      (support/print-to-output ctx printer v)
-                      (recur))
-                    (support/printed-output printer))))
-          exit-code (sh/exit-code x)
-          status (exit-code->status exit-code @was-killed)]
+        out (read-and-print-shell-output x ctx)
+        exit-code (sh/exit-code x)
+        status (exit-code->status exit-code @was-killed)]
     (async/close! result-ch)
     (remove-watch kill-switch watch-ref)
     {:exit exit-code :status status :out out}))


Fail softer on clojuredocs dependency conflicts

--- src/clj/reply/initialization.clj
+++ src/clj/reply/initialization.clj
@@ -82,9 +82,13 @@

     (in-ns '~'user)

-    ; assumes cd-client is on the execution classpath by now
-    (require '[cd-client.core])
-    (~'reply.exports/intern-with-meta '~'user '~'clojuredocs #'cd-client.core/pr-examples)
+    (try
+      (require '[cd-client.core])
+      (let [pr-exes# (ns-resolve '~'cd-client.core '~'pr-examples)]
+        (~'reply.exports/intern-with-meta '~'user '~'clojuredocs pr-exes#))
+      (catch Exception e#
+        (println "Warning: Could not load the ClojureDocs client, so `clojuredocs` will be unavailable")
+        (println "  Details:" e# "\n")))

     (~'help)
     nil))


parse json only if same response type specified

#20

--- src/clj/swarmpit/docker/http.clj
+++ src/clj/swarmpit/docker/http.clj
@@ -3,9 +3,9 @@
   (:require [clj-http.conn-mgr :as conn-mgr]
             [clj-http.client :as client]
             [cheshire.core :refer [parse-string generate-string]]
-            [swarmpit.config :refer [config]])
-  (:import (org.apache.http.conn.socket PlainConnectionSocketFactory)
-           (org.apache.http.config RegistryBuilder)
+            [swarmpit.config :refer [config]]
+            [clojure.string :as str])
+  (:import (org.apache.http.config RegistryBuilder)
            (swarmpit.socket UnixSocketFactory)
            (org.apache.http.impl.conn BasicHttpClientConnectionManager)
            (java.io IOException)
@@ -52,9 +52,10 @@
                       :query-params       params
                       :body               (generate-string payload)
                       :retry-handler      (fn [& args] false)})
-          body (-> response :body (parse-string true))
-          code (-> response :status)]
-      body)
+          response-type (-> response :headers :Content-Type)]
+      (if (str/includes? response-type "application/json")
+        (-> response :body (parse-string true))
+        (-> response :body)))
     (catch IOException exception
       (throw (let [error (.getMessage exception)]
                (ex-info (str "Docker failure: " error) {:message error}))))


Add a menu entry for addition

Add a menu entry for addition

--- src/cljs/hyphen_keeper/core.cljs
+++ src/cljs/hyphen_keeper/core.cljs
@@ -313,6 +313,9 @@
     [:div#navbar-collapse.navbar-collapse.collapse
      [:ul.nav.navbar-nav.navbar-right
       [:li
+       (if (= active :insert) {:class "active"} {})
+       [:a {:href "/"} (tr [:add])]]
+      [:li
        (if (= active :edit) {:class "active"} {})
        [:a {:href "/edit"} (tr [:edit])]]]]]])


move template funcs to dynamic var *fns*

--- src/cljs/om_lette/templater.cljs
+++ src/cljs/om_lette/templater.cljs
@@ -19,6 +19,7 @@
   [l v]
   (.log js/console l)
   (.log js/console (clj->js v))
+  (.log js/console v)
   v)

 (defn dbg2->
@@ -27,11 +28,22 @@

 (defonce template-cache (atom {}))

+(def ^:dynamic *fns* {"=>" (fn [source dest]
+                             (mapv #(assoc state dest %)
+                                   source))
+                      "identity" identity
+                      "vector" vector
+                      "hashmap" hash-map
+                      "set" set
+                      "resolve-symbol" (fn [state symb] (or (get *fns* symb)
+                                                            (get state symb "[empty]")))
+                      "template" #(render-template % %2)})
+
 (defn render-template
   [tname state & {:keys [fns]}]
-  (dbg2 "render-template state" state)
-  (sab/html  (cached-template->hiccup tname
-                                      (update-in state [:fns] merge fns))))
+  (binding [*fns* (merge *fns* fns)]
+    (sab/html (cached-template->hiccup tname
+                                       state))))

 (defn has-all-keys? [m keys]
   (apply = (map count [keys (select-keys m keys)])))
@@ -115,8 +127,7 @@
                                  eval-func (eval-parsed-cljs-code func state)]
                              (if (fn? eval-func)
                                eval-func
-                               (get-in state
-                                       [:fns eval-func])))
+                               (get *fns* eval-func)))
                            (mapv #(eval-parsed-cljs-code % state)
                                  (rest c)))
         :default c))
@@ -152,8 +163,6 @@

 (defn eval-om-if-expr
   [x state]
-  (dbg2 "om-if x = " x)
-  (dbg2 "om-if state = " state)
   (get state (apply str (mapcat second x))))

 (defn html->template
@@ -223,32 +232,18 @@

 (defn template->hiccup
   [tmplt state]
-  (let [s (update-in state
-                     [:fns]
-                     (fn [fns] (merge {"=>" (fn [source dest]
-                                              (mapv #(assoc state dest %)
-                                                   source))
-                                       "identity" identity
-                                       "vector" vector
-                                       "hashmap" hash-map
-                                       "set" set
-                                       "resolve-symbol" #(or (get-in % [:fns %2])
-                                                             (dbg2 "r-s =" (get % (dbg2 "r-s %2 =" %2) "[empty]")))
-                                       "template" #(render-template % (dbg2 "template %2= " %2) :fns (:fns state))}
-                                      fns)))]
-    (->> tmplt
-         (walk/prewalk (fn [h]
-                         (reduce (fn [current [pred proc-fn]]
-                                   (if-let [r (pred current)]
-                                     (proc-fn r)
-                                     current))
-                                 h
-                                 (processors s))))
-         (walk/postwalk flatten-out))))
+  (->> tmplt
+       (walk/prewalk (fn [h]
+                       (reduce (fn [current [pred proc-fn]]
+                                 (if-let [r (pred current)]
+                                   (proc-fn r)
+                                   current))
+                               h
+                               (processors state))))
+       (walk/postwalk flatten-out)))

 (defn cached-template->hiccup
   [tname state]
-  (dbg2 "cached-template->hiccup state =" state)
   (let [r (template->hiccup (get @template-cache tname) state)]
     r))


Add constructors

Add constructors

--- src/clojure_fabric/grpc_core.clj
+++ src/clojure_fabric/grpc_core.clj
@@ -29,7 +29,7 @@
 (ns clojure-fabric.grpc-core
   (:require [clojure-fabric.crypto-suite :as crypto-suite]
             [clojure-fabric.utils :as utils]
-            [clojure-fabric.wrappers :as proto]
+            [clojure-fabric.proto :as proto]
             [clojure.core.async :as async])
   (:import [com.google.protobuf ByteString Timestamp]
            io.grpc.ManagedChannel
@@ -41,7 +41,8 @@
            org.bouncycastle.util.encoders.Hex
            [org.hyperledger.fabric.protos.common Common$ChannelHeader Common$Header Common$HeaderType Common$SignatureHeader]
            org.hyperledger.fabric.protos.msp.Identities$SerializedIdentity
-           [org.hyperledger.fabric.protos.peer Chaincode$ChaincodeID Chaincode$ChaincodeInput Chaincode$ChaincodeInvocationSpec Chaincode$ChaincodeSpec Chaincode$ChaincodeSpec$Type EndorserGrpc ProposalPackage$ChaincodeHeaderExtension ProposalPackage$ChaincodeProposalPayload ProposalPackage$Proposal ProposalPackage$SignedProposal]))
+           [org.hyperledger.fabric.protos.peer Chaincode$ChaincodeID Chaincode$ChaincodeInput Chaincode$ChaincodeInvocationSpec Chaincode$ChaincodeSpec Chaincode$ChaincodeSpec$Type EndorserGrpc ProposalPackage$ChaincodeHeaderExtension ProposalPackage$ChaincodeProposalPayload ProposalPackage$Proposal ProposalPackage$SignedProposal]
+           ))

 (defonce ^:dynamic *grpc-configuration*
   ;; From Java SDK
@@ -62,34 +63,13 @@
   [k]
   (*grpc-configuration* k))

-(defn make-chaincode-id
-  ([name]
-   (make-chaincode-id name {}))
-  ([name {:keys [version path] :or {version "" path ""}}]
-   (-> (Chaincode$ChaincodeID/newBuilder)
-       (.setName name)
-       (.setVersion version)
-       (.setPath path)
-       (.build))))
-
-(defn make-chaincode-input
-  ([args]
-   (-> (Chaincode$ChaincodeInput/newBuilder)
-       (.addAllArgs args)
-       (.build)))
-  ;; FIXME: can't find deatails on decorations
-  #_
-  ([args decorations]
-   (-> (Chaincode$ChaincodeInput/newBuilder)
-       (.addAllArgs args))))
-
 (defn make-chaincode-spec
   ([chaincode-id input]
-   (-> (Chaincode$ChaincodeSpec/newBuilder)
-       (.setType Chaincode$ChaincodeSpec$Type/GOLANG)
-       (.setChaincodeId ^Chaincode$ChaincodeID chaincode-id)
-       (.setInput ^Chaincode$ChaincodeInput input)
-       (.build)))
+   (-> (proto/new-builder Chaincode$ChaincodeSpec)
+       (proto/set-type Chaincode$ChaincodeSpec$Type/GOLANG)
+       (proto/set-chaincode-id ^Chaincode$ChaincodeID chaincode-id)
+       (proto/set-input ^Chaincode$ChaincodeInput input)
+       (proto/build)))
   ;; FIXME: use of timeout
   #_
   ([type chaincode-id input timeout]
@@ -101,10 +81,10 @@
        (.build))))

 (defn make-chaincode-invocation-spec
-  ([^Chaincode$ChaincodeSpec chaincode-spec]
-   (-> (Chaincode$ChaincodeInvocationSpec/newBuilder)
-       (.setChaincodeSpec chaincode-spec)
-       (.build)))
+  ([chaincode-spec]
+   (-> (proto/new-builder Chaincode$ChaincodeInvocationSpec)
+       (proto/set-chaincode-spec chaincode-spec)
+       (proto/build)))
   ;; FIXME: setIdGenerationAlg
   #_
   ([^Chaincode$ChaincodeSpec chaincode-spec id-generation-alg]
@@ -115,14 +95,16 @@
 (defn make-chaincode-header-extention
   ([chaincode-id]
    (make-chaincode-header-extention chaincode-id ByteString/EMPTY))
-  ([^Chaincode$ChaincodeID chaincode-id payload-visibility]
-   (-> (ProposalPackage$ChaincodeHeaderExtension/newBuilder)
-       (.setChaincodeId chaincode-id)
+  ([chaincode-id payload-visibility]
+   (-> (proto/new-builder ProposalPackage$ChaincodeHeaderExtension)
+       (proto/set-chaincode-id chaincode-id)
        ;; NOTE: payload-visibility is ByteString
        ;; Currently only full visibility
-       (.setPayloadVisibility payload-visibility)
-       (.build))))
-
+       (proto/set-payload-visibility payload-visibility)
+       (proto/build))))
+
+;; FIXME: Timestamp is primitive of com.google.protobuf
+;;      No idea yet how to make it nice
 (defn make-current-grpc-timestamp
   []
   (let [now (System/currentTimeMillis)]
@@ -134,23 +116,24 @@
 (defn make-channel-header
   ([type version channel-id tx-id epoch]
    (make-channel-header type version channel-id tx-id epoch ByteString/EMPTY))
-  ([^Common$HeaderType type version channel-id tx-id epoch extension]
+  ([type version channel-id tx-id epoch extension]
    (let [now (System/currentTimeMillis)]
-    (-> (Common$ChannelHeader/newBuilder)
-        (.setType (.getNumber type))
-        (.setVersion version)
-        (.setTimestamp ^Timestamp (make-current-grpc-timestamp))
-        (.setChannelId ^Chaincode$ChaincodeID channel-id)
-        (.setTxId tx-id)
-        (.setEpoch epoch)
-        (.setExtension (.toByteString ^ProposalPackage$ChaincodeHeaderExtension extension))
-        (.build)))))
+    (-> (proto/new-builder Common$ChannelHeader)
+        (proto/set-type type)
+        (proto/set-version version)
+        (proto/set-timestamp (make-current-grpc-timestamp))
+        (proto/set-channel-id channel-id)
+        (proto/set-tx-id tx-id)
+        (proto/set-epoch epoch)
+        (proto/set-extension #_ extension
+          (.toByteString ^ProposalPackage$ChaincodeHeaderExtension extension))
+        (proto/build)))))

 (defn make-serialized-identity [user]   ; i.e. user-context
-  (-> (Identities$SerializedIdentity/newBuilder)
-      (.setIdBytes (ByteString/copyFromUtf8 (:certificate user)))
-      (.setMspid (:msp-id user))
-      (.build)))
+  (-> (proto/new-builder Identities$SerializedIdentity)
+      (proto/set-id-bytes (ByteString/copyFromUtf8 (:certificate user)))
+      (proto/set-mspid (:msp-id user))
+      (proto/build)))

 (defn make-identity-byte-string [user]
   (.toByteString ^Identities$SerializedIdentity (make-serialized-identity user)))
@@ -174,8 +157,8 @@
   default-epoch)

 (defn make-chaincode-header
-  [^Chaincode$ChaincodeID chaincode-id channel-id tx-id epoch]
-  (make-channel-header Common$HeaderType/ENDORSER_TRANSACTION ; type
+  [chaincode-id channel-id tx-id epoch]
+  (make-channel-header (proto/get-number Common$HeaderType/ENDORSER_TRANSACTION) ; type
                        1                ; version
                        channel-id
                        tx-id
@@ -186,27 +169,27 @@

 (defn make-signature-header
   [creator nonce]
-  (-> (Common$SignatureHeader/newBuilder)
-      (.setCreator creator)
-      (.setNonce nonce)
-      (.build)))
+  (-> (proto/new-builder Common$SignatureHeader)
+      (proto/set-creator creator)
+      (proto/set-nonce nonce)
+      (proto/build)))

 (defn make-header
   [^Common$ChannelHeader channel-header ^Common$SignatureHeader signature-header]
-  (-> (Common$Header/newBuilder)
-      (.setChannelHeader (.toByteString channel-header))
-      (.setSignatureHeader (.toByteString signature-header))
-      (.build)))
+  (-> (proto/new-builder Common$Header)
+      (proto/set-channel-header (.toByteString channel-header))
+      (proto/set-signature-header (.toByteString signature-header))
+      (proto/build)))

 (defn make-proposal
   ([header payload]
    (make-proposal header payload ByteString/EMPTY))
-  ([header payload extension]
-   (-> (ProposalPackage$Proposal/newBuilder)
-       (.setHeader (.toByteString ^Common$Header header))
-       (.setPayload (.toByteString ^ProposalPackage$ChaincodeProposalPayload payload))
-       (.setExtension extension)
-       (.build))))
+  ([^Common$Header header ^ProposalPackage$ChaincodeProposalPayload payload extension]
+   (-> (proto/new-builder ProposalPackage$Proposal)
+       (proto/set-header (.toByteString header))
+       (proto/set-payload (.toByteString payload))
+       (proto/set-extension extension)
+       (proto/build))))

 (defn make-chaincode-proposal-payload
   ([chaincode-id fcn args]
@@ -222,21 +205,21 @@
               (make-chaincode-spec chaincode-id)
               (make-chaincode-invocation-spec))]

-     (-> (ProposalPackage$ChaincodeProposalPayload/newBuilder)
-         (.setInput (.toByteString chaincode-invocation-spec))
-         (.putAllTransientMap transient-map)
-         (.build)))))
+     (-> (proto/new-builder ProposalPackage$ChaincodeProposalPayload)
+         (proto/set-input (.toByteString chaincode-invocation-spec))
+         (proto/put-all-transient-map transient-map)
+         (proto/build)))))

 (defn make-signed-proposal
   [^ProposalPackage$Proposal proposal user]
-  (-> (ProposalPackage$SignedProposal/newBuilder)
-      (.setProposalBytes (.toByteString proposal))
-      (.setSignature (-> (.toByteArray proposal)
-                         #^bytes (crypto-suite/sign
-                                  (:private-key user)
-                                  {:algorithm (:key-algorithm (:crypto-suite user))})
-                         (ByteString/copyFrom)))
-      (.build)))
+  (-> (proto/new-builder ProposalPackage$SignedProposal)
+      (proto/set-proposal-bytes (.toByteString proposal))
+      (proto/set-signature (-> (.toByteArray proposal)
+                               #^bytes (crypto-suite/sign
+                                        (:private-key user)
+                                        {:algorithm (:key-algorithm (:crypto-suite user))})
+                               (ByteString/copyFrom)))
+      (proto/build)))

 ;;;


trying to get this dumb event-processor stuff better

--- src/cljs/reagent_demo/views/about_page.cljs
+++ src/cljs/reagent_demo/views/about_page.cljs
@@ -1,15 +1,29 @@
 (ns reagent_demo.views.about_page)

 (defn main []
-  [:div [:h2 "About "]
-    [:div [:a {:href "#/"} "go to the home page"]]])
+  [:div [:a {:href "#/"} "go to the home page"]])

 (def ac (new window/AudioContext))
+(def int-array (new js/Uint8Array 2048))
+
+(defn event-processor [event]
+  (let [input-buffer (.-inputBuffer event)
+        output-buffer (.-outputBuffer event)
+        input-data-0 (.getChannelData input-buffer 0)
+        output-data-0 (.getChannelData output-buffer 0)
+        ]
+    (for [x (range (.-length input-buffer))]
+      (aset (.getChannelData output-buffer 0) x (aget input-data-0 x))
+    )
+  )
+)

 (defn play-clip [url position duration rate gain reverse]
   (let [xhr (new window/XMLHttpRequest)
         source (.createBufferSource ac)
+        analize-node (.createAnalyser ac)
         gain-node (.createGain ac)
+        process-node (.createScriptProcessor ac 4096 2 1)
         biquad-node (.createBiquadFilter ac)]
     (.open xhr "get" url true)
     (set! (.-responseType xhr) "arraybuffer")
@@ -19,34 +33,45 @@
           (when reverse
             (js/Array.prototype.reverse.call (.getChannelData buffer 0))
             (js/Array.prototype.reverse.call (.getChannelData buffer 1)))
-          ; (.linearRampToValueAtTime (.-gain gain-node) 1 0)
-          ; (.linearRampToValueAtTime (.-gain gain-node) 0 5)
+          ; (.linearRampToValueAtTime (.-gain gain-node) 1 position)
+          ; (.linearRampToValueAtTime (.-gain gain-node) 0 0)
           (set! (.-buffer source) buffer)
           (set! (.-value (.-gain gain-node)) gain)
           (set! (.-value (.-playbackRate source)) rate)
+          (set! (.-onaudioprocess process-node) event-processor)
           ; (set! (.-Q biquad-node) 1)
           ; (set! (.-gain biquad-node) 1)
           ; (set! (.-type biquad-node) "notch")
           ; (set! (.-value (.-frequency biquad-node)) 1000)
-          (.connect source biquad-node)
+          (.connect source analize-node)
+          (.connect analize-node process-node)
+          ; (.connect analize-node biquad-node)
+          (.connect process-node biquad-node)
           (.connect biquad-node gain-node)
           (.connect gain-node (aget ac "destination"))
-          (.start source (.-currentTime ac) position)
+          (.start source 0 position)
+          (js/setInterval #(do
+              (.getByteTimeDomainData analize-node int-array)
+              ; (.log js/console (aget int-array 0)))
+              )
+            50)
           (js/setTimeout
             #(.stop source 0)
             (* duration 1000))))))
     (.send xhr)))

 (def url "http://static.kevvv.in/sounds/callmemaybe.mp3")
+(def url2 "https://ia600805.us.archive.org/27/items/NeverGonnaGiveYouUp/jocofullinterview41.mp3")
+
+(play-clip url 15 15 1 1 false)
+

 (defn n-loops [times seconds func]
   (when (< 0 times)
     (func times)
     (js/setTimeout
       #(n-loops (dec times) seconds func)
-      (* 1000 seconds)
-    )
-  )
-)
+      (* 1000 seconds))))

-(n-loops 15 5 #(play-clip url (- 16 %) 10 % 1 (odd? %)))
+; (n-loops 16 3 #(play-clip url (- 20 %) 5 (if (even? %) 2 0.5) 1 (odd? %)))
+; (n-loops 16 3 #(play-clip url2 (- 20 %) 5 (if (even? %) 2 0.5) 1 (odd? %)))


4clojure: implementing a predicate that checks the validity of a binary-tree

--- src/clojure_learning/4clojure-exercises.clj
+++ src/clojure_learning/4clojure-exercises.clj
@@ -1287,3 +1287,43 @@
 (smaller-than-sum-of-squared-digs (range 10)) ;8
 (smaller-than-sum-of-squared-digs (range 100)) ;50
 (smaller-than-sum-of-squared-digs (range 1000)) ;50
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; To Tree, or not to Tree
+;; Trees: easy
+;; Write a predicate which checks whether or not a given sequence represents a binary tree.
+;; Each node in the tree must have a value, a left child, and a right child.
+;; in short: binary trees are the trees which have NO MORE than 3 nodes:
+;; -> 1 value, 1 left-branch, 1 right-branch
+;; (= true (__ '(:a (:b nil nil) nil))
+;; (= false (__ '(:a (:b nil nil)))
+;; (= false (__ [1 [2 [3 [4 false nil] nil] nil] nil])
+
+(defn binary-tree?
+  [xs]
+    (let [valid-node? #(= 3 (count %))
+          node? #(and (or (seq? %) (vector? %)))]
+    (->> xs
+       (reduce (fn [acc composite]
+              (if (node? composite)
+                (conj acc ((comp not empty?) composite) (binary-tree? composite))
+                (conj acc (and (valid-node? xs) composite))))  [])
+       flatten
+       (filter false?)
+       empty?)))
+
+
+;; demo:
+(binary-tree? '(:a (:b nil nil) nil))                  ; true
+(binary-tree? [1 [2 [3 [4 false nil] nil] nil] nil])   ; false
+(binary-tree? [1 [2 nil nil] [3 nil nil] [4 nil nil]]) ; false
+(binary-tree? '(:a nil ()))                            ; false
+
+(doc seq?) ; -> returns true if x implements ISeq
+(class ()) ; EmptyList
+(seq? ()) ; true
+(empty? ()); true
+(if-let [c (seq ())] c) ; nil
+
+;; TODO: take the time, to implement this solution using low-level recursion ONLY


fix: speedup slower timeline

fix: speedup slower timeline

--- src/main/clojure/pdok/featured/timeline.clj
+++ src/main/clojure/pdok/featured/timeline.clj
@@ -278,13 +278,12 @@
        (log/with-logs ['pdok.featured.timeline :error :error] (j/print-sql-exception-chain e))))))

 (defn- load-current-feature-cache-sql [dataset n]
-  (str "WITH last_version AS (
-   SELECT collection, feature_id, feature,
-    ROW_NUMBER() OVER (PARTITION BY collection, feature_id ORDER BY version DESC, valid_from DESC) as rk
-    FROM " (qualified-timeline dataset) ")
-    SELECT * FROM last_version WHERE rk = 1
-     AND collection = ? AND feature_id in ("
-       (clojure.string/join "," (repeat n "?")) ")"))
+  (str "SELECT DISTINCT ON (feature_id)
+    collection, feature_id, feature
+    FROM " (qualified-timeline dataset)
+    " WHERE collection = ? AND feature_id in ("
+       (clojure.string/join "," (repeat n "?")) ")
+      ORDER BY feature_id ASC, version DESC, valid_from DESC"))

 (defn- load-current-feature-cache [db dataset collection ids]
   (try (j/with-db-connection [c db]


Added fpins translation of 3.24 - now moving onto trees

--- src/fpinscala/datastructures.clj
+++ src/fpinscala/datastructures.clj
@@ -349,5 +349,20 @@
           (not (every? false? res))
           (recur (next isup) (conj res pass)))))))
 ;fpins
-;TODO translate fpins solution
+(defn starts-with [l prefix]
+  (if (nil? prefix)
+    true
+    (let [[h1 & t1] l [h2 & t2] prefix]
+      (if (= h1 h2)
+        (recur t1 t2)
+        false))))
+(defn has-subsequence-fpins [sup sub]
+  (if (empty? sup)
+    (empty? sub)
+    (if (starts-with sup sub)
+      true
+      (let [[h & t] sup]
+        (if (and (not (nil? h)) (not (empty? t)))
+          (recur t sub)
+          false)))))
 ;-----------------------------------------------------------------------


Handle nested ns-specs without explicit middleware in canonicalize-ns-specs

--- src/io/aviso/rook/dispatcher.clj
+++ src/io/aviso/rook/dispatcher.clj
@@ -604,9 +604,11 @@
                 :as ns-spec]]
             (let [context-pathvec (if (vector? context-pathvec?)
                                     context-pathvec?)
-                  middleware      (if context-pathvec
-                                    middleware?
-                                    ns-sym)
+                  middleware      (let [mw? (if context-pathvec
+                                              middleware?
+                                              ns-sym)]
+                                    (if-not (vector? mw?)
+                                      mw?))
                   ns-sym          (if context-pathvec
                                     ns-sym
                                     context-pathvec?)


using timbre-refer

using timbre-refer

--- src/aws/networking.clj
+++ src/aws/networking.clj
@@ -13,6 +13,7 @@
   "AWS networking functions"
   (:import com.amazonaws.services.ec2.model.AssociateAddressRequest)
   (:require
+    [taoensso.timbre :as timbre]
     [amazonica.aws.ec2 :as ec2]
     [slingshot.slingshot :refer  [throw+]]
     [celestial.model :refer (hypervisor)]
@@ -21,6 +22,8 @@
     [clojure.string :refer (join)]
     [aws.common :refer (with-ctx instance-desc)]
     [celestial.persistency.systems :as s]))
+
+(timbre/refer-timbre)

 (defn pub-dns [endpoint instance-id]
   (instance-desc endpoint instance-id :public-dns-name))
@@ -79,9 +82,8 @@

 (defn assoc-pub-ip [endpoint instance-id {:keys [machine aws] :as spec}]
    (let [{:keys [ip]} machine {:keys [subnet-id allocation-id]} aws]
-      (if-not subnet-id
-        (with-ctx ec2/associate-address {:instance-id instance-id :public-ip ip})
-        (attach-vpc-ip endpoint instance-id spec)
-        )))
+     (if-not subnet-id
+       (with-ctx ec2/associate-address {:instance-id instance-id :public-ip ip})
+       (attach-vpc-ip endpoint instance-id spec))))


Clear out prog-hover on time-travel rollback.

--- src/cbfg/world/t1.cljs
+++ src/cbfg/world/t1.cljs
@@ -57,12 +57,13 @@
   ; Time-travel to the past if snapshot is available.
   (when-let [ago-ss (get @prog-ss ss-ts)]
     (ago-restore (actx-agw (:world @prog-base)) ago-ss)
-    (swap! prog-history #(vec (filter (fn [[s & _]] (<= s ss-ts)) %)))
-    (swap! prog-ss #(into {} (filter (fn [[s _]] (<= s ss-ts)) %)))
     ; TODO: This prog-frame deref is strange, as it turned into a
     ; om.core/MapCursor somehow during the event handler rather than
     ; an expected prog-frame dict.
     (reset! prog-curr @prog-frame)
+    (reset! prog-hover nil)
+    (swap! prog-history #(vec (filter (fn [[s & _]] (<= s ss-ts)) %)))
+    (swap! prog-ss #(into {} (filter (fn [[s _]] (<= s ss-ts)) %)))
     (cbfg.world.base/render-client-hist (:reqs @prog-curr))))

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


Need mysterious deref during on-prog-frame-restore.

--- src/cbfg/world/t1.cljs
+++ src/cbfg/world/t1.cljs
@@ -51,9 +51,12 @@
 (defn on-prog-frame-restore [ts label prog-frame]
   ; Time-travel to the past if snapshot is available.
   (when-let [ago-ss (get @prog-ss ts)]
-    (reset! prog-curr prog-frame)
+    (ago-restore (actx-agw (:world @prog-base)) ago-ss)
     (swap! prog-history #(vec (take (+ ts 1) %)))
-    (ago-restore (actx-agw (:world @prog-base)) ago-ss)))
+    ; TODO: This prog-frame deref is strange, as it turned into a
+    ; om.core/MapCursor somehow during the event handler rather
+    ; an the expected prog-frame dict.
+    (reset! prog-curr @prog-frame)))

 (defn on-prog-frame-focus [ts label prog-frame]
   (reset! prog-hover prog-frame)


try to repull agetn

try to repull agetn

--- src/ci3/build/core.clj
+++ src/ci3/build/core.clj
@@ -21,7 +21,7 @@
                       {:key "account" :path "account.json"}]}}]
    :containers
    [{:name "agent"
-     :image "healthsamurai/ci3:latest"
+     :image "healthsamurai/ci3"
      :imagePullPolicy "Always"
      :args ["agent"]
      :volumeMounts
@@ -36,6 +36,7 @@
                 :prefix "CI3_SECRET_"}]
      :env
      [{:name "BUILD_ID" :value (get-in res [:metadata :name])}
+      {:name "REDEPLOY_HASH" :value (System/currentTimeMillis)}
       {:name "BOTO_CONFIG" :value "/gsutil/.boto"}
       {:name "REPOSITORY" :value (get-in res [:repository])}
       {:name "DOCKER_KEY" :valueFrom {:secretKeyRef {:name "docker-registry" :key "key"}}}


Changed resource loader class to System

Changed resource loader class to System

--- ring-core/src/ring/util/response.clj
+++ ring-core/src/ring/util/response.clj
@@ -60,9 +60,9 @@
   Options:
     :root - take the resource relative to this root"
   [path & [opts]]
-  (let [path   (str (:root opts "") "/" path)
-        path   (.replace path "//" "/")]
-    (if-let [resource (.getResourceAsStream (class file-response) path)] ; any Ring fn will do here
+  (let [path (str (:root opts "") "/" path)
+        path (.replace path "//" "/")]
+    (if-let [resource (.getResourceAsStream System path)]
       (response resource))))

 (defn status


Minor updates to basic table collection methods.


add mis lib ref

add mis lib ref

--- src/clj/hsm/schema.clj
+++ src/clj/hsm/schema.clj
@@ -1,5 +1,6 @@
 (ns hsm.schema
-  (:require
+  (:require
+    [clojure.tools.logging :as log]
     [clojurewerkz.cassaforte.cql  :as cql]
     [clojurewerkz.cassaforte.query :as cq]
     [qbits.hayt.dsl.statement :as hs]))


refactoring

refactoring

--- src/notehub/storage.clj
+++ src/notehub/storage.clj
@@ -79,9 +79,6 @@
 (defn short-url-exists? [url]
   (= 1 (redis :hexists :short-url url)))

-(defn get-short-url [noteID]
-  (redis :hget :short-url noteID))
-
 (defn resolve-url [url]
   (let [value (redis :hget :short-url url)]
     (when value ; TODO: necessary?


Remove duplicate filename

Remove duplicate filename

--- src/video_server/handler.clj
+++ src/video_server/handler.clj
@@ -15,7 +15,7 @@
             [compojure.route :refer [not-found resources]]
             [ring.middleware.gzip :refer [wrap-gzip]]
             [ring.middleware.stacktrace :refer [wrap-stacktrace]]
-            [video-server.android :refer [android-version]]
+            [video-server.android :refer [android-version apk-filename]]
             [video-server.html :refer [downloads-template title-page titles-template]]
             [video-server.library :refer [current-titles title-for-id title-listing video-listing]]
             [video-server.util :refer :all]))
@@ -51,7 +51,7 @@
 (defn downloads
   "Returns the downloads page."
   []
-  (html-response (downloads-template @base-url "video-client-release.apk")))
+  (html-response (downloads-template @base-url (apk-filename))))

 (defn videos-api
   "Responds with a list of available videos."


Use the limited fields for display

Use the limited fields for display

--- src/wishlistd/models/sql.clj
+++ src/wishlistd/models/sql.clj
@@ -42,8 +42,8 @@
       (values neu))))

 (defn read-wishlist [code]
-  (select wishlist
-    (with wish)
+  (select wishlist (wishlist-fields)
+    (with wish (wish-fields))
     (where {:code code})))

 (defn update-wishlist [{:keys [code] :as wl}]


Making a 90 second cooldown between games the default.

--- src/server/core.cljs
+++ src/server/core.cljs
@@ -76,7 +76,7 @@
 (def game-settings
   "Game timer settings."
   (atom {:duration 300 ; Length in seconds of a multiplayer round. Default is 5 minutes.
-         :cooldown 0})) ; Length in seconds before automatically starting a new game. Default (0) requires manual start.
+         :cooldown 90})) ; Length in seconds before automatically starting a new game. Setting 0 requires manual start.

 (def leaders
   "The leaders in the current game."


Running tests for 'diff' against 'diff*' (doesn't swallow exceptions).

--- test/flare/core_test.clj
+++ test/flare/core_test.clj
@@ -1,5 +1,6 @@
 (ns flare.core-test
-  (:require [flare.core :refer :all]
+  (:require [flare.core :refer [diff* generate-reports* report flatten-keys diff-match-patch-string
+                                generate-report-for-keyed-diff]]
             [clojure.test.check :as tc]
             [clojure.test.check.clojure-test :refer [defspec]]
             [clojure.test.check.generators :as gen]
@@ -7,6 +8,8 @@
             [clojure.test :refer [is deftest testing]])
   (:import [flare.core AtomDiff SetDiff MapKeysDiff SequentialSizeDiff StringDiff]))

+(def diff diff*)
+

 (deftest flatten-keys-test


Remove debug commentary

Remove debug commentary

--- integration-tests/apps/caching/counter/test/counter/test/locking.clj
+++ integration-tests/apps/caching/counter/test/counter/test/locking.clj
@@ -14,16 +14,13 @@
 (defn work
   [{:keys [name key]}]
   (let [cache (get caches name)]
-    (log/info "JC: work start" name cache)
     (loop [v (get cache key)]
-      (log/info "JC: v=" name v)
       (if (csh/put-if-replace cache key v (inc v))
         (msg/publish "/queue/done" name)
         (recur (get cache key))))))

 (use-fixtures :each (fn [f]
                       (let [listener (msg/listen "/queue/work" work :concurrency 10)]
-                        (log/info "JC: listener for /queue/work set")
                         (f)
                         (msg/unlisten listener))))

@@ -31,16 +28,12 @@
   (csh/put (:pessimistic caches) :count 0)
   (is (= 0 (:count (:pessimistic caches))))
   (dotimes [_ 10] (msg/publish "/queue/work" {:name :pessimistic :key :count}))
-  (log/info "JC: published 10 messages")
   (is (every? (partial = :pessimistic) (take 10 (msg/message-seq "/queue/done" :timeout 60000))))
-  (log/info "JC: pessimistic done" (:count (:pessimistic caches)))
   (is (= 10 (:count (:pessimistic caches)))))

 (deftest correct-counting-with-optimistic-locking
   (csh/put (:optimistic caches) :count 0)
   (is (= 0 (:count (:optimistic caches))))
   (dotimes [_ 3] (msg/publish "/queue/work" {:name :optimistic :key :count}))
-  (log/info "JC: published 3 messages")
   (is (every? (partial = :optimistic) (take 3 (msg/message-seq "/queue/done" :timeout 60000))))
-  (log/info "JC: optimistic done" (:count (:optimistic caches)))
   (is (= 3 (:count (:optimistic caches)))))


cleanup

cleanup

--- src/voke/events.cljs
+++ src/voke/events.cljs
@@ -3,9 +3,8 @@
   (:require [voke.schemas :refer [EventType]])
   (:require-macros [schema.core :as sm]))

-; A map of {event-name -> [event-handler-fn]}.
+; A map of {EventType -> [event-handler-fn]}.
 (def ^:private registry (atom {}))
-; TODO rename :event-type to :type

 (sm/defn publish-event [event]
   (doseq [handler (@registry (event :type))]


Before allowing options maps with some switches in main.

--- src/zprint/main.cljc
+++ src/zprint/main.cljc
@@ -35,7 +35,7 @@
           "java -jar zprint-filter-"
           (second (clojure.string/split (:version (get-options)) #"-")))
      ""
-     " <options-map> is a Clojure map containing zprint options."
+     " <options-map> is a Clojure map containing zprint options. Must be first."
      "               Note that since it contains spaces, it must be"
      "               wrapped in quotes, for example:"
      "               '{:width 120}'"
@@ -43,7 +43,7 @@
      "               Use the -e switch to see the total options"
      "               map, which will show you what is configurable."
      ""
-     " <switches> which do no formatting:"
+     " <switches> which do no formatting, only one allowed:"
      ""
      "  -h  --help         Output this help text."
      "  -v  --version      Output the version of zprint."
@@ -54,21 +54,41 @@
      ""
      "  -d  --default      Accept no configuration input."
      "  -u  --url URL      Load options from URL."
-     "      --url-only URL Load only options found from URL, ignore all others."
-     ""
-     " <switches> which format named files:  May follow a configuration switch"
-     "                                       or an options map, but not both"
+     "      --url-only URL Load only options found from URL,"
+     "                     ignore all .zprintrc, .zprint.edn files."
+     ""
+     " <switches> which process named files:  May follow a configuration switch"
+
+     "                                        or an options map, but not both!"
      ""
      "  -w  --write FILE                read, format, and write to FILE (or FILEs),"
      "                                  -w *.clj is supported."
-     "  -lw  --list-write FILE          like -w, but indicate which files processed."
-     "  -cw  --changed-write FILE       like -w, but indicate which files changed."
-     "  -lcw --list-changed-write FILE  like -w, but indicate files both processed"
-     "                                  and changed."
-     ""
-     " The -w switch is the only switch where you may also have an options map!"
+     "  -c  --check FILE                read and check format of FILE (or FILEs)"
+     "                                  -c *.clj is supported."
+     ""
+     " Variations on -w, --write and -c, -check:"
+     ""
+     "  -lw  --list-write      FILE  like -w, but indicate which files processed."
+     "  -fw  --formatted-write FILE  like -w, but indicate which files changed."
+     "  -sw  --summary-write   FILE  like -w, but include a summary of the number"
+     "                               of files processed and how many required a"
+     "                               format change, as well as any errors."
+     ""
+     " Combinations are allowed, w/write and c/check must always be last,"
+     " and order matters for -- switches.  Examples:"
+     ""
+     "   -lfw, -lfsw, -fsw, -flw, -sflw, etc."
+     "   --list-formatted-write, --list-formatted-summary-write, etc."
+     ""
+     " All combinations of -w and --write switches are also allowed "
+     " with -c and --check switches:"
+     ""
+     "   -lfc, -lfsc, -fsc, -flc, -sflc, etc."
+     "   --list-formatted-check, --list-formatted-summary-check, etc."
+     ""
+     " The -w and -c switches are the only switches where you may also"
+     " have an options map!"
      ""]))
-

 (defn write-to-stderr
   "Take a string, and write it to stderr."
@@ -78,60 +98,71 @@
     (.flush w)))

 (defn format-file
-  "Take a single argument, a filename string, and format it.
-  Read from the file, then rewrite the file with the formatted source.
-  Return an exit-status, either 0 if successful, or 1 if there were
-  problems.  In the event of problems, don't change the contents of
-  the file, but output text describing the problem to stderr."
-  [filename list? changed?]
-  (let [[exit-status in-str format-str format-stderr]
-          (as-> [0 nil nil nil] running-status
-            (let [[exit-status in-str format-str format-stderr] running-status]
+  "Take a single argument, a filename string, and format it.  Read
+  from the file, then rewrite the file with the formatted source.
+  Return [exit-status required-format], where exit-status is
+  either 0 if successful, or 1 if there were problems, and
+  required-format is 0 if not, 1 if it did.  In the event of
+  problems, don't change the contents of the file, but output text
+  describing the problem to stderr."
+  [filename check? list? formatted?]
+  (let [[exit-status required-format in-str format-str format-stderr]
+          (as-> [0 0 nil nil nil] running-status
+            (let [[exit-status required-format in-str format-str format-stderr]
+                    running-status]
               (when list? (write-to-stderr (str "Processing file " filename)))
-              (try [0 (slurp filename) nil nil]
+              (try [0 0 (slurp filename) nil nil]
                    (catch Exception e
-                     [1 nil nil
+                     [1 0 nil nil
                       (str "Failed to open file " filename " because: " e)])))
-            (let [[exit-status in-str format-str format-stderr] running-status]
+            (let [[exit-status required-format in-str format-str format-stderr]
+                    running-status]
               (if (= exit-status 1)
                 ; We are done, move on
                 running-status
-                (try [0 in-str (zprint-file-str in-str filename) nil]
+                (try [0 0 in-str (zprint-file-str in-str filename) nil]
                      (catch Exception e
-                       [1 nil nil
+                       [1 0 nil nil
                         (str "Failed to format file: " filename
                              " because " e)]))))
             ;
             ; See comment in -main about graalVM issues with this code
             ;
             ; Write whatever is supposed to go to stdout
-            (let [[exit-status in-str format-str format-stderr] running-status]
+            (let [[exit-status required-format in-str format-str format-stderr]
+                    running-status]
               (if (= exit-status 1)
                 ; We are done, move on
                 running-status
                 ; Did we actually change anything?
                 (if (not= in-str format-str)
                   ; Yes, write it out
-                  (try
-                    (let [^java.io.Writer w (clojure.java.io/writer filename)]
-                      (.write w (str format-str))
-                      (.flush w)
-                      (.close w)
-                      (when changed?
-                        (write-to-stderr (str "Formatted file " filename)))
-                      [0 nil nil nil])
-                    (catch Exception e
-                      [1 nil nil
-                       (str "Failed to write output file: " filename
-                            " because " e)]))
-                  ; No, just move on
-                  [0 nil nil nil])))
+                  (if check?
+                    (do (when formatted?
+                          (write-to-stderr (str "Formatting required in file "
+                                                filename)))
+                        [0 1 nil nil nil])
+                    (try
+                      (let [^java.io.Writer w (clojure.java.io/writer filename)]
+                        (.write w (str format-str))
+                        (.flush w)
+                        (.close w)
+                        (when formatted?
+                          (write-to-stderr (str "Formatted file " filename)))
+                        [0 1 nil nil nil])
+                      (catch Exception e
+                        [1 1 nil nil
+                         (str "Failed to write output file: " filename
+                              " because " e)])))
+                  ; No, we didn't actually change anything, just move on
+                  [0 0 nil nil nil])))
             ; Write whatever is supposed to go to stderr, if anything
-            (let [[exit-status in-str format-str format-stderr] running-status]
+            (let [[exit-status required-format in-str format-str format-stderr]
+                    running-status]
               (when format-stderr (write-to-stderr format-stderr))
               ; We don't change the running-status because we wrote to stderr
               running-status))]
-    exit-status))
+    [exit-status required-format]))

 (defn elements-before-last-switch
   "Given the args from the command line, find the last arg that
@@ -154,6 +185,11 @@
              "count-before-last-switch" count-before-last-switch)
     count-before-last-switch))

+(defn pair-sum
+  "Sum two vector pairs."
+  [[a b] [c d]]
+  [(+ a c) (+ b d)])
+
 ;;
 ;; # Main
 ;;
@@ -168,36 +204,47 @@
   (let [before-last-switch (elements-before-last-switch args)
         last-switch-in-seq (when before-last-switch
                              (nthnext args before-last-switch))
-        possible-write-switch (when before-last-switch
-                                (first last-switch-in-seq))
-        write? (#{"-w" "--write" "-lw" "-cw" "-lcw" "-clw"
-                  "--list-changed-write" "--changed-list-write" "--list-write"
-                  "--changed-write"}
-                possible-write-switch)
-        changed? (when write?
-                   (clojure.string/includes? possible-write-switch "c"))
-        list? (when write? (clojure.string/includes? possible-write-switch "l"))
-        files (when write? (next last-switch-in-seq))
-        args (if write? (take before-last-switch args) args)
-        #_#_options?
-          (and (first args)
-               (clojure.string/starts-with? (clojure.string/trim (first args))
-                                            "{"))
-        #_#_write-switch (if options? (second args) (first args))
-        #_#_write? (or (= "-w" write-switch) (= "--write" write-switch))
-        #_#_files (when write? (if options? (nnext args) (next args)))
-        ; Now that we have the --write/-w stuff out of the way, process
-        ; switches and options, having first removed the --write/-w stuff,
-        ; if any
-        #_#_args (if write? (if options? (take 1 args) nil) args)
+        possible-wc-switch (when before-last-switch
+                             (clojure.string/trim (first last-switch-in-seq)))
+        write-set #{"-w" "-lw" "-lfw" "-lsw" "-lfsw" "-fw" "-fsw" "-sw" "-flw"
+                    "-flsw" "-fslw" "-sfw" "-slw" "-sflw" "-slfw" "--write"
+                    "--list-write" "--list-formatted-write"
+                    "--list-format-write" "--list-formatted-summary-write"
+                    "--formatted-write" "--list-format-summary-write"
+                    "--format-write" "--formatted-summary-write"
+                    "--summary-write" "--format-summary-write"}
+        check-set #{"-c" "-lc" "-lfc" "-lsc" "-lfsc" "-fc" "-fsc" "-sc" "-flc"
+                    "-flsc" "-fslc" "-sfc" "-slc" "-sflc" "-slfc" "--check"
+                    "--list-check" "--list-formatted-check"
+                    "--list-format-check" "--list-formatted-summary-check"
+                    "--formatted-check" "--list-format-summary-check"
+                    "--format-check" "--formatted-summary-check"
+                    "--format-summary-check" "--summary-check"}
+        write? (write-set possible-wc-switch)
+        check? (check-set possible-wc-switch)
+        [list? formatted? summary?]
+          (when (or write? check?)
+            (if (clojure.string/starts-with? possible-wc-switch "--")
+              [(clojure.string/includes? possible-wc-switch "list")
+               (or (clojure.string/includes? possible-wc-switch "formatted")
+                   (clojure.string/includes? possible-wc-switch "format"))
+               (clojure.string/includes? possible-wc-switch "summary")]
+              [(clojure.string/includes? possible-wc-switch "l")
+               (clojure.string/includes? possible-wc-switch "f")
+               (clojure.string/includes? possible-wc-switch "s")]))
+        files (when (or write? check?) (next last-switch-in-seq))
+	; Remove write or check switch and files, if any
+        args (if (or write? check?) (take before-last-switch args) args)
         options (first args)
         _ (prn "args:" args)
         _ (println)
         _ (prn "before-last-switch:" before-last-switch
-               "possible-write-switch:" possible-write-switch
+               "possible-wc-switch:" possible-wc-switch
                "write?" write?
+               "check?" check?
                "list?" list?
-               "changed?" changed?
+               "formatted?" formatted?
+               "summary?" summary?
                "files:" files)
         ; Some people wanted a zprint that didn't take configuration.
         ; If you say "--default" or "-d", that is what you get.
@@ -245,7 +292,7 @@
                 running-status
                 ; Do we have a options, and if so, is that all?
                 (if (and options
-		         (not (clojure.string/starts-with? options "-"))
+                         (not (clojure.string/starts-with? options "-"))
                          (not arg-count-ok?))
                   ; No, we have something that could be options, and other
                   ; stuff after it, which is not allowed.  If we had -w
@@ -430,14 +477,41 @@
           #_(shutdown-agents)
           #_(System/exit exit-status))
       ; Do whatever formatting we should do
-      (if write?
+      (if (or write? check?)
         ; We have one or more filenames to deal with
-        (let [total-exit-status
-                (reduce #(+ %1 (format-file %2 list? changed?)) 0 files)]
-          #_(prn "total-exit-status:" total-exit-status)
+        (let [[total-exit-status total-required-format]
+                (reduce #(pair-sum %1 (format-file %2 check? list? formatted?))
+                  [0 0]
+                  files)
+              file-count (count files)]
+          (prn "total-exit-status:" total-exit-status
+               "total-required-format:" total-required-format)
+          (when summary?
+            (write-to-stderr
+              (str
+                "Processed "
+                file-count
+                " file"
+                (if (> file-count 1) "s, " ", ")
+                (if (pos? total-exit-status)
+                  (str "with "
+                       total-exit-status
+                       " error"
+                       (if (> total-exit-status 1) "s" "")
+                       ", ")
+                  "")
+                (if (pos? total-required-format) total-required-format "none")
+                " of which "
+                (if check? "require" "required")
+                " formatting.")))
           ;;;  NOTE FIX THIS ONE TOO
           #_(shutdown-agents)
-          #_(System/exit (if (> total-exit-status 0) 1 0)))
+          #_(System/exit (if write?
+                           (if (> total-exit-status 0) 1 0)
+                           ; For check? we return the number of files that
+                           ; needed formatting, even though we didn't
+                           ; actually format them, and the errors as well
+                           (+ total-required-format total-exit-status))))
         ; We are operating on stdin and stdout
         (let [in-str (slurp *in*)
               [format-status stdout-str format-stderr]


Added test for mark-as-completed command

--- test/kmg/domain_test.clj
+++ test/kmg/domain_test.clj
@@ -146,3 +146,11 @@
     (let [db-after (db)]
           (is (= (spec-ids db-after #(vector (user-current-goal db-after "user2")))
            #{"spec1"})))))
+
+(deftest test-mark-as-completed
+  (let [db-before (db)]
+    (is (not (is-media-complete? db-before (media-dbid-by-id db-before "book5") "user1")))
+    )
+    (mark-as-completed-command "user1" "spec1_book5")
+    (let [db-after (db)]
+      (is (is-media-complete? db-after (media-dbid-by-id db-after "book5") "user1"))))


now also for existing ...

now also for existing ...

--- integration/dda/pallet/crate/dda_user_crate/instantiate_existing.clj
+++ integration/dda/pallet/crate/dda_user_crate/instantiate_existing.clj
@@ -31,10 +31,9 @@
    :private-key ssh-priv-key})

 (def domain-config
-  {:user-name "USERNAME_TO_BE_CREATED"
-   :encrypted-password  "USER_PASSWORD"
-   :authorized-keys [ssh-pub-key]
-   :personal-key ssh-key-pair})
+  {:test {:encrypted-password  "USER_PASSWORD"
+          :authorized-keys [ssh-pub-key]
+          :personal-key ssh-key-pair}})

 (def provisioning-ip
     "TARGET_IP")


Rename function

Rename function

--- src/discuss/views.cljs
+++ src/discuss/views.cljs
@@ -170,7 +170,7 @@
                                          :onClick   #(com/dispatch-add-action statement (lib/get-selection))}
                                     "Submit"))))))

-(defn template-dispatcher
+(defn view-dispatcher
   "Dispatch current template in main view by the app state."
   [data]
   (let [view (lib/current-view)]
@@ -188,7 +188,7 @@
                     (dom/br nil)
                     (dom/strong nil (get-in data [:issues :info])))
            (vlib/panel-wrapper
-             (template-dispatcher data))
+             (view-dispatcher data))
            (when (get-in data [:layout :add?])
              (om/build add-element {}))))


Remove empty function.

Remove empty function.

--- src/onyx/log/commands/common.clj
+++ src/onyx/log/commands/common.clj
@@ -87,8 +87,6 @@
       (let [n (mod message-id (count peers))]
         (= (nth peers n) id)))))

-(defn allocated-to-job [replica args id])
-
 (defn should-seal? [replica job-id state message-id]
   (let [allocated-to-job? (= job-id (:job (peer->allocated-job (:allocations replica) (:id state))))]
     (and allocated-to-job?


Test for covered.

Test for covered.

--- src/onyx/log/commands/common.clj
+++ src/onyx/log/commands/common.clj
@@ -335,6 +335,9 @@
   (fn [old new diff state]
     (:job-scheduler old)))

+(defn job-covered? [replica job]
+  (seq (remove seq (vals (get-in replica [:allocations job])))))
+
 (defn any-coverable-jobs? [replica]
   (seq
    (filter


Cosmetic.

Cosmetic.

--- src/onyx/peer/task_lifecycle.clj
+++ src/onyx/peer/task_lifecycle.clj
@@ -691,7 +691,6 @@
                            :onyx.core/peer-replica-view peer-replica-view
                            :onyx.core/state state}

-
             pipeline (build-pipeline task-map pipeline-data)
             pipeline-data (assoc pipeline-data :onyx.core/pipeline pipeline)


Fix secretbox benchmarks some more

Fix secretbox benchmarks some more

--- test/caesium/crypto/secretbox_benchmark.clj
+++ test/caesium/crypto/secretbox_benchmark.clj
@@ -9,27 +9,31 @@

 ;; secretbox to-buf! macros vs fn vs no casts with indirect byte bufs

+(def random-direct-byte-buf (comp bc/->direct-byte-buf randombytes))
+(def random-indirect-byte-buf (comp bc/->indirect-byte-buf randombytes))
+
 (deftest ^:benchmark to-buf!-benchmarks
-  (let [key (bc/->direct-byte-buf (randombytes s/keybytes))
-        sizes (map (partial bit-shift-left 1) [6 8 10 12 20 24])]
+  (let [sizes (map (partial bit-shift-left 1) [6 8 10 12 20 24])]
     (println "secretbox to-buf! macros vs fn vs no casts with direct bufs")
     (println "these bufs already exist, so there is no allocation")
-    (doseq [[size message] (map (juxt identity randombytes) sizes)
+    (doseq [[size msg] (map (juxt identity random-direct-byte-buf) sizes)
             f [s/secretbox-easy-to-direct-byte-bufs-with-macros!
                s/secretbox-easy-to-direct-byte-bufs!
                s/secretbox-easy-to-byte-bufs-nocast!]]
       (println f (fmt-bytes size))
-      (let [nonce (bc/->direct-byte-buf (randombytes s/noncebytes))
+      (let [key (random-direct-byte-buf s/keybytes)
+            nonce (random-direct-byte-buf s/noncebytes)
             out (ByteBuffer/allocateDirect (+ s/macbytes size))]
-        (bench (f out message nonce key))))
+        (bench (f out msg nonce key))))

     (println "secretbox to-buf! macros vs fn vs no casts with indirect bufs")
     (println "these bufs already exist, so there is no allocation")
-    (doseq [[size message] (map (juxt identity randombytes) sizes)
+    (doseq [[size msg] (map (juxt identity random-indirect-byte-buf) sizes)
             f [s/secretbox-easy-to-indirect-byte-bufs-with-macros!
                s/secretbox-easy-to-indirect-byte-bufs!
                s/secretbox-easy-to-byte-bufs-nocast!]]
       (println f (fmt-bytes size))
-      (let [nonce (bc/->indirect-byte-buf (randombytes s/noncebytes))
+      (let [key (random-indirect-byte-buf s/keybytes)
+            nonce (random-indirect-byte-buf s/noncebytes)
             out (ByteBuffer/allocate (+ s/macbytes size))]
-        (bench (f out message nonce key))))))
+        (bench (f out msg nonce key))))))


correct typo

correct typo

--- test/clj_money/models/transactions_test.clj
+++ test/clj_money/models/transactions_test.clj
@@ -484,7 +484,7 @@
                               (map #(select-keys % [:index :amount :balance])))]
     (testing "transaction item balances are correct"
       (is (= expected-checking actual-checking)
-          "Check items should have the correct values after update")
+          "Checking items should have the correct values after update")
       (is (= expected-groceries actual-groceries)
           "Groceries items should have the correct values after update"))
     (testing "account balances are correct"


Fixed issue #24

Fixed issue #24

--- src/frontend/core.cljs
+++ src/frontend/core.cljs
@@ -23,7 +23,8 @@
                           :download-slots default-download-slots
                           :num-of-uploads 0
                           :num-of-downloads 0
-                          :download-progress {}}))
+                          :download-progress {}
+                          :download-status {}}))

 (enable-console-print!)

@@ -114,6 +115,8 @@
 (defn request-file-download [track-id]
   (if (nil? (get (:music-files @app-state) track-id))
     (do
+      (swap! app-state assoc :download-status (merge (:download-status @app-state)
+                                                     {track-id :in-progress}))
       (swap! app-state assoc :music-files (merge (:music-files @app-state)
                                                  {track-id (new js/Blob)}))
       (swap! app-state assoc :num-of-downloads (inc (:num-of-downloads @app-state)))
@@ -124,8 +127,11 @@
 (defn indices [pred coll]
   (keep-indexed #(when (pred %2) %1) coll))

+(defn is-track-downloading? [track-id]
+  (= :in-progress (get (:download-status @app-state) track-id)))
+
 (defn is-track-downloaded? [track-id]
-  (not (nil? (get (:music-files @app-state) track-id))))
+  (= :complete (get (:download-status @app-state) track-id)))

 (defn get-next-track-to-download []
   (let [track-order (:track-order @app-state)
@@ -133,7 +139,8 @@
                                           track-order))
         not-downloaded-tracks (filter #(not (nil? %1))
                                       (map (fn [id]
-                                             (if-not (is-track-downloaded? id)
+                                             (if-not (or (is-track-downloading? id)
+                                                         (is-track-downloaded? id))
                                                id))
                                            track-order))
         nearest-tracks (sort (fn [a b]
@@ -234,6 +241,9 @@
     (.on stream "end"
       (fn []
         (println "Download complete!")
+        (swap! app-state assoc :download-status (merge (:download-status @app-state)
+                                                       {track-id :complete}))
+
         (swap! app-state assoc :num-of-downloads (dec (:num-of-downloads @app-state)))
         (swap! app-state assoc :download-progress (dissoc (:download-progress @app-state) track-id))

@@ -263,7 +273,8 @@

       (if-not (is-track-downloaded? track-id)
         (request-file-download track-id)
-        (.emit socket "ready-to-start" sound-id))))
+        (if-not (is-track-downloading? track-id)
+          (.emit socket "ready-to-start" sound-id)))))

 (.on socket "pause"


cleanup

cleanup

--- src/frontend/core.cljs
+++ src/frontend/core.cljs
@@ -6,7 +6,7 @@
 (defonce room (str "room:" room-id))
 (defonce socket (js/io "http://localhost:3001"))
 (defonce app-state (atom {:users []
-                          :messages ["H" "A" "B"]}))
+                          :messages []}))

 (defn user-view [user owner]
   (reify


refactor

refactor

--- src/clj/salava/badge/endorsement.clj
+++ src/clj/salava/badge/endorsement.clj
@@ -1,10 +1,10 @@
 (ns salava.badge.endorsement
   (:require [yesql.core :refer [defqueries]]
-            [salava.core.util :refer [get-db md->html get-full-path]]
+            [salava.core.util :refer [get-db md->html get-full-path plugin-fun get-plugins]]
             [slingshot.slingshot :refer :all]
             [clojure.tools.logging :as log]
             [salava.badge.main :refer [send-badge-info-to-obf]]
-            [salava.user.db :as user]))
+            #_[salava.user.db :as user]))

 (defqueries "sql/badge/main.sql")

@@ -25,7 +25,8 @@
   (try+
     (if (badge-owner? ctx user-badge-id user-id)
       (throw+ {:status "error" :message "User cannot endorse himself"})
-      (let [endorser-info (user/user-information ctx user-id)]
+      (let [endorser-info-fn (first (plugin-fun (get-plugins ctx) "db" "user-information"))
+             endorser-info (endorser-info-fn ctx user-id)#_(user/user-information ctx user-id)]
         (when-let [id (->> (insert-user-badge-endorsement<! {:user_badge_id user-badge-id
                                                              :external_id (generate-external-id)
                                                              :issuer_id user-id


add order-by functionality

add order-by functionality

--- src/cljs/phonecat_re_frame/core.cljs
+++ src/cljs/phonecat_re_frame/core.cljs
@@ -33,6 +33,7 @@
    (reaction (:order-prop @db))))

 (re-frame/register-handler
+<<<<<<< HEAD
  :initialise-db             ;; usage: (dispatch [:initialise-db])
  (fn
    [_ _]                   ;; Ignore both params (db and v).
@@ -41,12 +42,22 @@
              {:name "Motoral Xoom" :snippet "The Next, Next Generation tablet."}]
     :search-input ""
     :order-prop "name"}))
+=======
+   :initialise-db             ;; usage: (dispatch [:initialise-db])
+   (fn
+     [_ _]                   ;; Ignore both params (db and v).
+     {:phones [{:name "Nexus S" :snippet "Fast just got faster with Nexus S."}
+               {:name "Motorola XOOM™ with Wi-Fi" :snippet "The Next, Next Generation tablet."}
+               {:name "Motoral Xoom" :snippet "The Next, Next Generation tablet."}]
+      :search-input ""}))
+>>>>>>> 0720b58... add order-by functionality

 (defn handle-search-input-entered
   [app-state [_ search-input]]
   (assoc-in app-state [:search-input] search-input))

 (re-frame/register-handler
+<<<<<<< HEAD
  :search-input-entered
  handle-search-input-entered)


Fix more texture atlas

Fix more texture atlas

--- src/cljs/robinson/webglterminal.cljs
+++ src/cljs/robinson/webglterminal.cljs
@@ -22,7 +22,9 @@

 (def characters
   (map identity
-       (concat "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$%^&*()_-+=[]{}|:;,./<>?'\""
+       (concat "abcdefghijklmnopqrstuvwxyz"
+               "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+               "~!@#$%^&*()_-+=[]{}|:;,./<>?'\""
                "\u00A7"
                "\u039B"
                "\u03B1"
@@ -46,13 +48,14 @@
                "\u2500"
                "\u2500"
                "\u2500"
-               "\u2500")))
+               "\u2500"
+)))

 ;; A sequence of [\character x y] where [x y] is the position in the character atlas.
 (def character-layout
-  (let [character-matrix (partition (int (inc (.sqrt js/Math (count characters)))) characters)]
-      (mapv concat
+  (let [character-matrix (partition-all (int (inc (.sqrt js/Math (count characters)))) characters)]
+        (mapv concat
         (map-indexed (fn [y line]
                        (map-indexed (fn [x c]
                                       [c (* x 12) (* y 16)])
@@ -74,6 +77,8 @@
             (assoc m c [x y (+ x 12) (+ y 16)]))
           {}
           character-layout))
+
+(log/info (str character-layout))

 ;; Adjust canvas to fit character atlas size
 (let [width (* 12 (count (first character-layout)))
@@ -90,15 +95,17 @@
                                       (-> ctx
                                         (canvas/fill-style "#191d21")
                                         (canvas/fill-rect val)))))
-  (doseq [[[c x y]] character->pos]
-    (canvas/add-entity character-canvas (keyword (str :char- c))
+  (doseq [line character-layout]
+    (doseq [[c x y] line]
+    (log/info c x y)
+    (canvas/add-entity character-canvas (keyword (str :char- (int x) (int y)))
                        (canvas/entity {:c c :x x :y y :w 12 :h 16}   ; val
                                       nil                       ; update function
                                       (fn [ctx {:keys [c x y]}]             ; draw function
                                         #_(log/info "Drawing char" c "@" x y)
                                         (-> ctx
                                           (canvas/fill-style "#f9fdf1")
-                                          (canvas/text {:text (str c) :x x :y y})))))))
+                                          (canvas/text {:text (str c) :x x :y (+ 16 y)}))))))))


show full image when complete

show full image when complete

--- src/cljs/salava/metabadge/ui/my.cljs
+++ src/cljs/salava/metabadge/ui/my.cljs
@@ -26,13 +26,14 @@

 (defn metabadge-element [milestone state]
   (let [{:keys [badge name min_required required_badges completion_status]} milestone
-        completed (if (> completion_status 100) 100 completion_status)]
+        completed (if (> completion_status 100) 100 completion_status)
+        image-class (if (= 100 completion_status) "" " opaque")]
     [:div.media.grid-container
      [:div.media-content
       [:a {:href "#" :on-click #(mo/open-modal [:metabadge :metadata] milestone)}
        (if (:image badge)
          [:div.media-left
-          [:img.badge-img.opaque {:src (:image badge)}]
+          [:img.badge-img {:src (:image badge) :class image-class}]
           ])
        [:div.media-body
         [:div.media-heading


Fix vcard URI prefixer to use the right prefix.

--- src/grafter/rdf/ontologies/vcard.clj
+++ src/grafter/rdf/ontologies/vcard.clj
@@ -2,7 +2,7 @@
   "Convenience terms for the VCard vocabulary."
   (:use [grafter.rdf.ontologies.util]))

-(def vcard (prefixer "http://www.w3.org/2006/vcard/ns"))
+(def vcard (prefixer "http://www.w3.org/2006/vcard/ns#"))

 (def vcard:Address (vcard "Address"))


Update documentation namespaces

Update documentation namespaces

--- src/main/clojure/conexp/util/doc.clj
+++ src/main/clojure/conexp/util/doc.clj
@@ -91,6 +91,7 @@
    file '[conexp.main
           conexp.util.exec
           conexp.util.doc
+          conexp.util.profiler
           conexp.layouts
           conexp.layouts.base
           conexp.layouts.common
@@ -99,10 +100,7 @@
           conexp.layouts.layered
           conexp.layouts.util
           conexp.contrib.draw
-          conexp.contrib.factor-analysis
-          conexp.contrib.gui
-          conexp.contrib.profiler
-          ]))
+          conexp.gui]))

 ;;;


Making quick fix to add revision date back to umm json results.

--- search-app/src/cmr/search/results_handlers/umm_json_results_handler.clj
+++ search-app/src/cmr/search/results_handlers/umm_json_results_handler.clj
@@ -18,7 +18,7 @@
    "entry-id"
    "short-name"
    "version-id"
-   "revision-date2"
+   "revision-date"
    "deleted"
    "metadata-format"])

@@ -32,7 +32,7 @@
          [entry-id] :entry-id
          [short-name] :short-name
          [version-id] :version-id
-         [revision-date] :revision-date2
+         [revision-date] :revision-date
          [deleted] :deleted
          [metadata-format] :metadata-format} (:fields elastic-result)
         revision-date (when revision-date (str/replace (str revision-date) #"\+0000" "Z"))


logging fixes

logging fixes

--- src/name_bazaar/server/watchdog.cljs
+++ src/name_bazaar/server/watchdog.cljs
@@ -8,6 +8,7 @@
     [district0x.server.effects :as d0x-effects]
     [district0x.server.state :as state :refer [*server-state*]]
     [name-bazaar.server.db-sync :as db-sync]
+    [taoensso.timbre :refer-macros [log trace debug info warn error]]
     [name-bazaar.server.emailer.listeners :as email-listeners])
   (:require-macros [cljs.core.async.macros :refer [go go-loop]]))

@@ -18,25 +19,25 @@
   (swap! server-state assoc-in [:node-watchdog :enabled?] true)
   (let [shortcircuit? (get-in @server-state [:config :shortcircuit-node-watchdog?])]
     (if shortcircuit?
-      (println "Shortcircuit watcher")
-      (println "Starting watcher"))
+      (warn "Shortcircuit watcher")
+      (info "Starting watcher"))
     (go-loop []
       (let [node-watchdog (:node-watchdog @server-state)]
         (<! (timeout (:timeout node-watchdog)))
-        ;; (println "Check?")
+        (info "Check?")
         (let [state (or shortcircuit?
                         (web3/connected? (state/web3 @server-state)))]
           (when (and
                  on-down-fn
                  (:online? node-watchdog)
                  (not state))
-            ;; (println "down")
+            (warn "Node is offline")
             (on-down-fn))
           (when (and
                  on-up-fn
                  (not (:online? node-watchdog))
                  state)
-            ;; (println "up")
+            (warn "Node is online")
             (on-up-fn))
           (swap! server-state assoc-in [:node-watchdog :online?] state))
         (when (:enabled? node-watchdog)


ENV specific KMS URLs (#1319)

ENV specific KMS URLs (#1319)

* adding code to change the version value used when talking to KMS in SIT and UAT

--- transmit-lib/src/cmr/transmit/kms.clj
+++ transmit-lib/src/cmr/transmit/kms.clj
@@ -39,6 +39,21 @@
    :related-urls :uuid
    :granule-data-format :uuid})

+(comment
+ "The following map contains code used for trasitioning CMR from SIT->UAT->PROD
+  and keeping in step with KMS changes. These three envirments all talk to
+  production KMS due to AWS->EBNET network limitations. Because of of this we
+  need to be able to publish data for all three envirments with one host. while
+  not ideal, it was decided to use the different 'version' capabilities in KMS
+  to isolate production from the other two envirments. Specificly: rucontenttype
+  is a three level tree in SIT, but not PROD. This process is only needed durring
+  the transition and should be deleted once in production."
+ )
+
+ (def production?
+   "Return true if CMR is not currently in production."
+   (= "prod" (System/getenv "ENVIRONMENT")))
+
 (def keyword-scheme->gcmd-resource-name
   "Maps each keyword scheme to the GCMD resource name"
   {:providers "providers?format=csv"
@@ -51,7 +66,8 @@
    :measurement-name "measurementname?format=csv"
    :concepts "idnnode?format=csv"
    :iso-topic-categories "isotopiccategory?format=csv"
-   :related-urls "rucontenttype?format=csv"
+   :related-urls (if production? "rucontenttype?format=csv"
+                   "rucontenttype?format=csv&version=DRAFT")
    :granule-data-format "granuledataformat?format=csv"})

 (def keyword-scheme->field-names


A test for remote sending to client

A test for remote sending to client

--- web/test/immutant/websocket_test.clj
+++ web/test/immutant/websocket_test.clj
@@ -16,7 +16,8 @@
   (:require [clojure.test :refer :all]
             [immutant.web :refer :all]
             [immutant.websocket :refer :all]
-            [gniazdo.core :as ws]))
+            [gniazdo.core :as ws]
+            [clojure.string :refer [upper-case]]))

 (defn test-websocket
   [create-handler]
@@ -46,3 +47,14 @@
 (deftest jsr-356-websocket
   (let [expected [:open "hello" 1000]]
     (is (= expected (test-websocket create-servlet)))))
+
+(deftest remote-sending-to-client
+  (let [result (promise)
+        server (run (create-handler {:on-message (fn [c m] (send! c (upper-case m)))}))
+        socket (ws/connect "ws://localhost:8080" :on-receive #(deliver result %))]
+    (try
+      (ws/send-msg socket "hello")
+      (is (= "HELLO" (deref result 2000 "goodbye")))
+      (finally
+        (ws/close socket)
+        (stop server)))))