Actually commit compander docstring updates

--- src/overtone/sc/ugen/metadata/compander.clj
+++ src/overtone/sc/ugen/metadata/compander.clj
@@ -2,7 +2,8 @@
   (:use [overtone.sc.ugen common constants]))

 (def specs
-     [
+  [
+;;amplitude
       {:name "Amplitude"
        :args [{:name "in"
                :default 0.0
@@ -24,6 +25,7 @@
        :sclang-location "Compander"
        :auto-rate true}

+;;compander
       {:name "Compander",
        :args [{:name "in"
                :default 0.0
@@ -38,32 +40,44 @@
               {:name "thresh"
                :default 0.5
                :modulatable true
-               :doc "Control signal amplitude threshold, which determines the break point between slopeBelow and slopeAbove. Usually 0..1. The control signal amplitude is calculated using RMS."}
+               :doc "Control signal amplitude threshold, which determines the break point between slope-below and slope-above. Typically a value between 0 and 1. "}

               {:name "slope-below"
                :default 1.0
                :modulatable true
-               :doc "Slope of the amplitude curve below the threshold. If this slope > 1.0, the amplitude will drop off more quickly the softer the control signal gets; when the control signal is close to 0 amplitude, the output should be exactly zero -- hence, noise gating. Values < 1.0 are possible, but it means that a very low-level control signal will cause the input signal to be amplified, which would raise the noise floor."}
+               :doc "Slope of the amplitude curve below the threshold. A value of 1 means the output amplitude will match the control signal amplitude."}

               {:name "slope-above"
                :default 1.0
                :modulatable true
-               :doc "Same thing, but above the threshold. Values < 1.0 achieve compression (louder signals are attenuated); > 1.0, you get expansion (louder signals are made even louder). For 3:1 compression, you would use a value of 1/3 here."}
+               :doc "Slope of the amplitude curve above the threshold. A value of 1 means the output amplitude will match the control signal amplitude."}

               {:name "clamp-time"
                :default 0.01
                :modulatable true
-               :doc "The amount of time it takes for the amplitude adjustment to kick in fully. This is usually pretty small, not much more than 10 milliseconds (the default value)."}
+               :doc "Time taken for the amplitude adjustment to kick in fully (in seconds). This is usually pretty small, not much more than 10 milliseconds (the default value). Also known as the time of the attack phase."}

               {:name "relax-time"
                :default 0.1
                :modulatable true
-               :doc "The amount of time for the amplitude adjustment to be released. Usually a bit longer than clamp-time; if both times are too short, you can get some (possibly unwanted) artifacts."}]
-       :summary "General purpose (hard-knee) dynamics processor."
+               :doc "The amount of time for the amplitude adjustment to be released. Usually a bit longer than clamp-time; if both times are too short, you can get some (possibly unwanted) artifacts. Also known as the time of the release phase."}]
+       :summary "General purpose hard-knee dynamic range processor."
        :scsynth-location "FilterUgens"
        :sclang-location "Compander"
        :rates #{:ar}
-       :doc "May be used to define: compressers, expanders, limiters, gates and duckers"}
+       :doc "The compander will modify the amplitude of the in signal based on an analysis of the control signal. Typically the in and control signals are the same. The amplitude of the control signal is calcuated using RMS (Root Mean Square) and the final amplitude of the in signal is calculated as a function of the amplitude threshold, and slopes either side (below and above) with some temporal modifications in terms of attack and release phases. It is a hard-knee processor which means that the response curve is a sharp angle rather than a rounded edge.
+
+If the control amplitude is less than the threshold, the slope below is used to calculate the amplitude modification. If this is steep (greater than 1) this will reduce the amplitude of quiet signals (the quieter the control amplitude the greater the reduction affect).  Values < 1.0 are possible, but it means that a very low-level control signal will cause the input signal to be amplified, which would raise the noise floor.
+
+If the control amplitude is greater than the threshold, the slope above is used to calculate the amplitude modification. If this is steep (greater than 1) this will create expansion - loud signals will be made louder). Less than 1 will achieve compressions (louder signals are attenuated).
+
+The clamp and relax times modify when the amplitude modification takes place and ends.
+
+May be used to define: compressers, expanders, limiters, gates and duckers.
+
+For more information see: http://en.wikipedia.org/wiki/Audio_level_compression
+"}
+

       ;; Normalizer : UGen {
       ;;   var buffer;


Catches I/O Exceptions, prints exception.

I mean, yeah, just dumping the exceptions out there isn't great but this
is a tool for my personal use. I can deal.

--- comment-breaker/src/comment_breaker/core.clj
+++ comment-breaker/src/comment_breaker/core.clj
@@ -44,8 +44,10 @@
 	      (assoc p-map :out-file (suffix-file (:in-file p-map) "-broken"))
 	    :else p-map))))

-;; Should catch exceptions on I/O!
 (defn -main
   [& args]
   (let [cli-map (get-args args)]
-    (spit (:out-file cli-map) (process-file (slurp (:in-file cli-map))))))+    (try
+      (spit (:out-file cli-map) (process-file (slurp (:in-file cli-map))))
+	  (catch java.io.IOException e
+	    (prn (.toString e))))))


CMR-4363: Increase max request size we can accept in Jetty from 5MB to 50MB so that large humanizer reports can be saved in cubby.

--- common-lib/src/cmr/common/api/web_server.clj
+++ common-lib/src/cmr/common/api/web_server.clj
@@ -41,10 +41,10 @@
   ONE_MB)

 (def MAX_REQUEST_BODY_SIZE
- "The maximum size of a request to body. This is set to 500KB prevent large requests coming in
-  that cause out of memory exceptions. A large ISO document like AST_L1A can be 120K characters which
-  would take up about 240KB in Java. This value is set to 5 MB."
- (* 5 ONE_MB))
+ "The maximum request body size which the application will accept. This is set to prevent large,
+  invalid requests coming in that cause out of memory exceptions. Requests to save the humanizer
+  report in Cubby can be in the 5 to 10 MB range."
+ (* 50 ONE_MB))

 (defn- routes-fn-verify-size
   "Takes the passed in routes function and wraps it with another function that will verify request


shufflefn: check for null before trying to shuffle

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -20,7 +20,7 @@
 ;;(def ^:const shufflefn (fn [x] x))

 ;; nondeterministic generation
-(def ^:const shufflefn (fn [x] (lazy-seq (shuffle x))))
+(def ^:const shufflefn (fn [x] (and x (lazy-seq (shuffle x)))))

 (def ^:const randomize-lexemes-before-phrases
 ;;  false)


mapcat over bolt groups

mapcat over bolt groups

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -59,24 +59,24 @@
                            each-path-through-trellis))
                  (apply combo/cartesian-product (vals each-bolt-and-comps)))))
      (filter #(not (empty? %)))
-     (map (fn [bolt-group]
-            (->> bolt-group
-                 (map (fn [bolt-and-comps]
-                        (apply unify
-                               (let [bolt (get bolt-and-comps [])
-                                     paths-and-comps (dissoc bolt-and-comps [])
-                                     paths (keys paths-and-comps)]
-                                 (cons bolt
-                                       (map (fn [path]
-                                              (let [result (assoc-in bolt path (get paths-and-comps path))]
-                                                (if (= true truncate)
-                                                  (dissoc-paths result [path])
-                                                  result)))
-                                            paths))))))
-                 (filter #(not (= :fail %))))))
-;     (map (fn [expression]
-;            (do-defaults expression model)))
-;     (filter not-fail?)
+     (mapcat (fn [bolt-group]
+               (->> bolt-group
+                    (map (fn [bolt-and-comps]
+                           (apply unify
+                                  (let [bolt (get bolt-and-comps [])
+                                        paths-and-comps (dissoc bolt-and-comps [])
+                                        paths (keys paths-and-comps)]
+                                    (cons bolt
+                                          (map (fn [path]
+                                                 (let [result (assoc-in bolt path (get paths-and-comps path))]
+                                                   (if (= true truncate)
+                                                     (dissoc-paths result [path])
+                                                     result)))
+                                               paths))))))
+                    (filter #(not (= :fail %))))))
+     (map (fn [expression]
+            (do-defaults expression model)))
+     (filter not-fail?)
 ;     (map (fn [final]
 ;            (log/trace (str "final: " ((:morph-ps model) final)))
 ;            final))


added utility function to check for search expression in field

--- src/hatti/ona/forms.cljs
+++ src/hatti/ona/forms.cljs
@@ -6,8 +6,7 @@
             [clojure.string :as string]
             [hatti.constants :refer [_submission_time
                                      _submitted_by
-                                     _last_edited]]
-            [hatti.utils.helpers :refer [uses-search-expression?]]))
+                                     _last_edited]]))

 ;; CONSTANTS
 (def currency-regex #"£|$")
@@ -202,6 +201,12 @@
     (if (contains? (-> label keys set) language)
       (label language)
       (label (-> label keys sort first)))))
+
+(defn uses-search-expression?
+    "Checks if the appearance-value has the search expression"
+    [appearance-value]
+    (and (string? appearance-value)
+         (re-matches #"^search\(.*\)$" appearance-value)))

 (defn format-answer
   "String representation for a particular field datapoint (answer).


Show created component in current search if it matches filter

--- src/warehouse/core.cljs
+++ src/warehouse/core.cljs
@@ -205,13 +205,15 @@
                   change-set-data
                   (range (count change-set-data) 0 -1))])

+(defn update-filter [val]
+  (swap! app-state assoc :filter {:val val
+                                  :search (js->clj (.search index val))}))
+
 (defn search []
   [:label "Search: "
    [:input {:name "search",
             :type "search"
-            :on-change (m/handler-fn
-                         (swap! app-state assoc :filter {:val (.-target.value e)
-                                                         :search (js->clj (.search index (.-target.value e)))}))}]])
+            :on-change (m/handler-fn (update-filter (.-target.value e)))}]])

 (defn export []
   [:a {:href (->> @app-state
@@ -289,7 +291,9 @@
                         :tags (:tags component)})))

 (add-watch app-state :indexer (fn [k r os ns]
-                                (update-index index ns)))
+                                (when-not (identical? (:components os) (:components ns))
+                                  (update-index index ns)
+                                  (update-filter (get-in ns [:filter :val])))))

 (defn on-js-reload []
   ;; optionally touch your app-state to force rerendering depending on


add a homepage endpoint for the web api

add a homepage endpoint for the web api

--- src/wb_es/web/index.clj
+++ src/wb_es/web/index.clj
@@ -64,6 +64,8 @@
       (wrap-routes web-integration/wrap-random)))

 (defroutes app
+  (GET "/" []
+       (response {:message "Welcome to the search API."}))
   api-lite-routes
   (context "/integration" []
            integration-routes


admin? function

admin? function

--- src/celestial/roles.clj
+++ src/celestial/roles.clj
@@ -1,6 +1,5 @@
 (ns celestial.roles
-  "celetial roles"
- )
+  "celetial roles")

 (def ^{:doc "roles string to keyword map"}
   roles-m {"admin" ::admin "user" ::user "anonymous" ::anonymous})
@@ -13,3 +12,5 @@

 (def admin #{::admin})

+(defn admin? [{:keys [roles] :as user}]
+  (clojure.set/subset? admin roles))


add optional metrics console reporting

add optional metrics console reporting

--- elephantdb-server/src/clj/elephantdb/keyval/core.clj
+++ elephantdb-server/src/clj/elephantdb/keyval/core.clj
@@ -4,6 +4,7 @@
   (:use [elephantdb.common.domain :only (loaded?)]
         [metrics.timers :only (timer time! time-fn!)]
         [metrics.meters :only (meter mark!)]
+        [metrics.core :only (report-to-console)]
         [elephantdb.common.graphite :only (report-to-graphite)])
   (:require [jackknife.core :as u]
             [jackknife.logging :as log]
@@ -253,8 +254,11 @@
       (db/prepare)
       (db/launch-updater! (:update-interval-s conf-map)))
     (when-let [graphite-conf (:graphite-conf local-config)]
-      (log/info "Graphite reporter started.")
+      (log/info "Metrics graphite reporter started.")
       (report-to-graphite (:host graphite-conf) (:port graphite-conf)))
+    (when-let [metrics-reporting-interval-s (:metrics-reporting-interval-s local-config)]
+      (log/info "Metrics console reporter started.")
+      (report-to-console metrics-reporting-interval-s))
     (thrift/launch-server! kv-processor
                            (kv-service database)
                            (:port conf-map))))


Remove deprecated primary application fn. Replaced by start!.

--- src/clj/aspire/core.clj
+++ src/clj/aspire/core.clj
@@ -29,11 +29,6 @@
   (.stop (:jetty-instance system))
   (dissoc system :sql-db-pool :jetty-instance))

-#_(defn aspire [{:keys [conf-sql-db] :as conf}]
-  (println :aspire "Do it. Do it now." (dissoc conf-sql-db :password))
-  (println (a-sqldb/select! {:select [:*] :from [:comp] :limit 2}))
-  (a-web/run!))
-
 (defn get-conf! [args]
   (let [opts (a-cli/get-opts args)
         conf (a-conf/getconf a-conf/configs opts)]


Update to allow developer workflow using tools.namespace.

--- src/clj/aspire/core.clj
+++ src/clj/aspire/core.clj
@@ -6,29 +6,62 @@
             [aspire.sqldb :as a-sqldb]
             [aspire.web :as a-web]))

-(defn aspire [{:keys [conf-sql-db] :as conf}]
+(defn system
+  "http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-reloaded"
+  [conf]
+  (println :hi)
+  {:conf conf})
+
+(defn start!
+  "Performs side effects to initialize the system, acquire resources,
+  and start it running. Returns an updated instance of the system."
+  [system]
+  (assoc system
+    :sql-db-pool
+    (a-sqldb/default-connection! (get-in system [:conf :conf-sql-db]))
+    :jetty-instance
+    (a-web/run! (get-in system [:conf :conf-web]))))
+
+(defn stop!
+  "Performs side effects to shut down the system and release its
+  resources. Returns an updated instance of the system."
+  [system]
+  (.close (:datasource @(:sql-db-pool system)))
+  (.stop (:jetty-instance system))
+  (dissoc system :sql-db-pool :jetty-instance))
+
+#_(defn aspire [{:keys [conf-sql-db] :as conf}]
   (println :aspire "Do it. Do it now." (dissoc conf-sql-db :password))
-  (a-sqldb/default-connection! conf-sql-db)
   (println (a-sqldb/select! {:select [:*] :from [:comp] :limit 2}))
-  (a-web/run))
+  (a-web/run!))
+
+(defn get-conf! [args]
+  (let [opts (a-cli/get-opts args)
+        conf (a-conf/getconf a-conf/configs opts)]
+    [opts conf]))

 (defn -main [& args]
   ;; work around dangerous default behaviour in Clojure
   (alter-var-root #'*read-eval* (constantly false))

-  (let [opts (a-cli/get-opts args)
-        conf (a-conf/getconf a-conf/configs opts)
-        db (:conf-sql-db conf)]
-    (a-util/output! :opts opts :conf conf :db db)
+  (let [[opts conf] (get-conf! args)
+        db (:conf-sql-db conf)
+        system (system conf)]
+    (a-util/output! :system system :conf conf :db db)

     (cond
      (:init-sql opts) (a-sqldb-ddl/init! db)
      (:zero-out-sql-db opts) (a-sqldb-ddl/print-drop-sql!)
-     :else (aspire conf))))
+     :else (start! system))))

 (comment

-  (-main "--conf-sql-db" (format "%s/.aspire/conf-sql-db.edn" (System/getProperty "user.home")))
+  (def home (System/getProperty "user.home"))
+  (def mydir (format "%s/.aspire/" home))
+  (def args ["--verbose"
+             "--conf-sql-db" (format "%s/conf-sql-db.edn" mydir)
+             "--conf-web" (format "%s/conf-web.edn" mydir)])
+  (def system (apply -main args))

   )


Docs for find-record.

Docs for find-record.

--- src/clj_record/core.clj
+++ src/clj_record/core.clj
@@ -79,6 +79,8 @@
     (find-by-sql model-name (apply vector select-query values))))

 (defn find-record
+  "Returns the first matching record. This is just (first (find-records ...)).
+  Note that at the moment there's no optimization to prevent the entire result set being read and converted into records."
   [model-name attributes-or-where-params]
   (first (find-records model-name attributes-or-where-params)))


CLJS-290: use transient vector in vec

CLJS-290: use transient vector in vec

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -3002,7 +3002,10 @@
                  (persistent! out))))))))

 (defn vec [coll]
-  (reduce conj cljs.core.PersistentVector/EMPTY coll))
+  (-persistent!
+   (reduce -conj!
+           (-as-transient cljs.core.PersistentVector/EMPTY)
+           coll)))

 (defn vector [& args] (vec args))


remove fn call from cljs.core.PersistentVector/EMPTY_NODE construction

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -3202,7 +3202,7 @@
       (RSeq. coll (dec cnt) nil)
       ())))

-(set! cljs.core.PersistentVector/EMPTY_NODE (pv-fresh-node nil))
+(set! cljs.core.PersistentVector/EMPTY_NODE (VectorNode. nil (make-array 32)))

 (set! cljs.core.PersistentVector/EMPTY
   (PersistentVector. nil 0 5 cljs.core.PersistentVector/EMPTY_NODE (array) 0))


* src/cljs/cljs/core.cljs: fix docstring location for identical? and nil?. docstring for =

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -198,15 +198,22 @@
   (-remove-watch [this key]))

 ;;;;;;;;;;;;;;;;;;; fundamentals ;;;;;;;;;;;;;;;
-(defn identical? [x y]
+(defn identical?
   "Tests if 2 arguments are the same object"
+  [x y]
   (cljs.core/identical? x y))

-(defn = [x y]
+(defn =
+  "Equality. Returns true if x equals y, false if not. Compares
+  numbers and collections in a type-independent manner.  Clojure's immutable data
+  structures define -equiv (and thus =) as a value, not an identity,
+  comparison."
+  [x y]
   (-equiv x y))

-(defn nil? [x]
+(defn nil?
   "Returns true if x is nil, false otherwise."
+  [x]
   (identical? x nil))

 (defn type [x]


the default should not report anything

the default should not report anything

--- src/cljs/cljs/test.cljs
+++ src/cljs/cljs/test.cljs
@@ -283,8 +283,7 @@
      :dynamic true}
   report (fn [m] [(:reporter (get-current-env)) (:type m)]))

-(defmethod report :default [m]
-  (prn m))
+(defmethod report :default [m])

 (defmethod report [::default :pass] [m]
   (inc-report-counter! :pass))


Add support for copy() function.

Add support for copy() function.

--- src/cljx/quil/core.cljx
+++ src/cljx/quil/core.cljx
@@ -1034,7 +1034,6 @@
     (constrain-float amt low high))
   #+cljs (.constrain (current-applet) amt low high))

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


Add dry-run as default run for inbox dismiss script, use -f or --force-update instead.

--- src/oc/storage/util/import_inbox_dismiss.clj
+++ src/oc/storage/util/import_inbox_dismiss.clj
@@ -2,9 +2,17 @@
   "
   For every read we have in DynamoDB, create a dismiss-at record in the corresponding entry.

-  Usage:
+  Dry run:

   lein run -m oc.storage.util.import-inbox-dismiss
+
+  To actualy update
+
+  lein run -m oc.storage.util.import-inbox-dismiss -f
+
+  or
+
+  lein run -m oc.storage.util.import-inbox-dismiss --force-update
   "
   (:require [clojure.string :as s]
             [clojure.tools.cli :refer (parse-opts)]
@@ -24,7 +32,7 @@
 ;; ----- CLI -----

 (def cli-options
-  [])
+  [["-f" "--force-update"]])

 (defn error-msg [errors]
   (str "The following errors occurred while parsing your command:\n\n"
@@ -53,7 +61,8 @@
                                              next-user-visibility)))
                         updated-entry (assoc e :user-visibility entry-user-vis)]
                     (println "Updating entry" (:uuid e) "with:" entry-user-vis)
-                    (entry/update-entry-no-user! conn (:uuid e) updated-entry))))))))
+                    (when (:force-update options)
+                      (entry/update-entry-no-user! conn (:uuid e) updated-entry)))))))))
       (catch Exception e
         (println e)
-        (exit 1 "Exception migrating follow<->unfollow.")))))+        (exit 1 "Exception migrating read->dimiss-at.")))))


Clean up.

Clean up.

--- src/onyx/scheduling/common_job_scheduler.clj
+++ src/onyx/scheduling/common_job_scheduler.clj
@@ -7,26 +7,6 @@
             [onyx.extensions :as extensions]
             [onyx.scheduling.common-task-scheduler :as cts]
             [taoensso.timbre]))
-
-(defn unbounded-jobs [replica balanced]
-  (filter
-   (fn [[job _]]
-     (= (get-in replica [:saturation job]) Double/POSITIVE_INFINITY))
-   balanced))
-
-(defn adjust-with-overflow [replica balanced]
-  (reduce
-   (fn [result [job n]]
-     (let [sat (or (get-in replica [:saturation job]))
-           extra (- n sat)]
-       (if (pos? extra)
-         (-> result
-             (update-in [:overflow] + extra)
-             (update-in [:jobs] conj [job sat]))
-         (-> result
-             (update-in [:jobs] conj [job n])))))
-   {:overflow 0 :jobs []}
-   balanced))

 (defn at-least-one-active? [replica peers]
   (->> peers
@@ -90,9 +70,13 @@
          (cts/drop-peers replica job overflow))))
    (:jobs replica)))

-(defmulti select-job
-  (fn [{:keys [args]} replica]
-    (:job-scheduler replica)))
+(defn reconfigure-cluster-workload [replica]
+  (let [job-offers (job-offer-n-peers replica)
+        job-claims (job->task-claims replica job-offers)
+        spare-peers (apply + (vals (merge-with - job-offers job-claims)))
+        max-utilization (claim-spare-peers replica job-claims spare-peers)
+        peers-to-displace (find-displaced-peers replica max-utilization)]
+    (reallocate-peers replica peers-to-displace max-utilization)))

 (defn exempt-from-acker? [replica job task args]
   (or (some #{task} (get-in replica [:exempt-tasks job]))
@@ -112,178 +96,10 @@
           (update-in [:ackers job] vec))
       replica)))

-(defmethod select-job :default
-  [_ replica]
-  (throw (ex-info
-           (format "Job scheduler %s not recognized. Check that you have not supplied a task scheduler instead."
-                   (:job-scheduler replica))
-           {:replica replica})))
-
-(defmulti volunteer-via-new-job?
-  (fn [old new diff state]
-    (:job-scheduler old)))
-
-(defmulti volunteer-via-killed-job?
-  (fn [old new diff state]
-    (:job-scheduler old)))
-
-(defmulti volunteer-via-sealed-output?
-  (fn [old new diff state]
-    (:job-scheduler old)))
-
-(defmulti volunteer-via-accept?
-  (fn [old new diff state]
-    (:job-scheduler old)))
-
-(defmulti volunteer-via-leave?
-  (fn [old new diff state]
-    (:job-scheduler old)))
-
-(defmulti reallocate-from-job?
-  (fn [scheduler old new state]
-    scheduler))
-
-(defmulti job-offer-n-peers :job-scheduler)
+(defmulti job-offer-n-peers
+  (fn [replica]
+    (:job-scheduler replica)))

 (defmulti claim-spare-peers
   (fn [replica jobs n]
     (:job-scheduler replica)))
-
-(def replica-g {:job-scheduler :onyx.job-scheduler/greedy
-              :jobs [:j1 :j2]
-              :tasks {:j1 [:t1 :t2 :t3]
-                      :j2 [:t4 :t5]}
-              :task-schedulers {:j1 :onyx.task-scheduler/balanced
-                                :j2 :onyx.task-scheduler/balanced}
-              :saturation {:j1 3}
-              :peers [:p1 :p2 :p3 :p4 :p5]})
-
-(def job-offers-g (job-offer-n-peers replica-g))
-
-(def job-claims-g
-  (reduce-kv
-   (fn [all j claim]
-     (assoc all j (cts/task-claim-n-peers replica-g j claim)))
-   {}
-   job-offers-g))
-
-(def spare-peers-g (apply + (vals (merge-with - job-offers-g job-claims-g))))
-
-(def max-utilization-g (claim-spare-peers replica-g job-claims-g spare-peers-g))
-
-(def task-distribution-g (cts/task-distribute-peer-count replica-g :j1 (:j1 max-utilization-g)))
-
-
-(def replica-b {:job-scheduler :onyx.job-scheduler/balanced
-                :jobs [:j1 :j2]
-                :tasks {:j1 [:t1 :t2 :t3 :g :h :i :j :k :l :m :n :o]
-                        :j2 [:t4 :t5 :t6]}
-                :saturation {:j1 3 :j2 Double/POSITIVE_INFINITY}
-                :task-schedulers {:j1 :onyx.task-scheduler/balanced
-                                  :j2 :onyx.task-scheduler/balanced}
-                :task-saturation {:j2 {:t4 2}}
-                :peers [:p1 :p2 :p3 :p4 :p5 :p6 :p7]})
-
-(def job-offers-b (job-offer-n-peers replica-b))
-
-(def job-claims-b
-  (reduce-kv
-   (fn [all j claim]
-     (assoc all j (cts/task-claim-n-peers replica-b j claim)))
-   {}
-   job-offers-b))
-
-(def spare-peers-b (apply + (vals (merge-with - job-offers-b job-claims-b))))
-
-(def max-utilization-b (claim-spare-peers replica-b job-claims-b spare-peers-b))
-
-(def task-distribution-b (cts/task-distribute-peer-count replica-b :j2 (:j2 max-utilization-b)))
-
-
-
-
-(def replica-p {:job-scheduler :onyx.job-scheduler/percentage
-                :jobs [:j1 :j2]
-                :tasks {:j1 [:t1 :t2 :t3]
-                        :j2 [:t4 :t5 :t6]}
-                :task-schedulers {:j1 :onyx.task-scheduler/balanced
-                                  :j2 :onyx.task-scheduler/balanced}
-                :saturation {:j1 3 :j2 Double/POSITIVE_INFINITY}
-                :peers [:p1 :p2 :p3 :p4 :p5 :p6 :p7 :p8 :p9 :p10]
-                :percentages {:j1 40 :j2 60}})
-
-(def job-offers-p (job-offer-n-peers replica-p))
-
-(def job-claims-p
-  (reduce-kv
-   (fn [all j claim]
-     (assoc all j (cts/task-claim-n-peers replica-p j claim)))
-   {}
-   job-offers-p))
-
-(def spare-peers-p (apply + (vals (merge-with - job-offers-p job-claims-p))))
-
-(def max-utilization-p (claim-spare-peers replica-p job-claims-p spare-peers-p))
-
-(def task-distribution-p (cts/task-distribute-peer-count replica-p :j2 (:j2 max-utilization-p)))
-
-
-
-(def replica-pt {:job-scheduler :onyx.job-scheduler/percentage
-                 :jobs [:j1 :j2]
-                 :tasks {:j1 [:t1 :t2 :t3]
-                         :j2 [:t4 :t5 :t6]}
-                 :task-schedulers {:j1 :onyx.task-scheduler/percentage
-                                   :j2 :onyx.task-scheduler/percentage}
-                 :saturation {:j1 0 :j2 Double/POSITIVE_INFINITY}
-                 :peers [:p1 :p2 :p3 :p4 :p5 :p6 :p7 :p8 :p9 :p10]
-                 :percentages {:j1 40 :j2 60}
-                 :task-percentages {:j1 {:t1 20 :t2 30 :t3 50}
-                                    :j2 {:t4 50 :t5 20 :t6 30}}})
-
-(def job-offers-pt (job-offer-n-peers replica-pt))
-
-(def job-claims-pt
-  (reduce-kv
-   (fn [all j claim]
-     (assoc all j (cts/task-claim-n-peers replica-pt j claim)))
-   {}
-   job-offers-pt))
-
-(def spare-peers-pt (apply + (vals (merge-with - job-offers-pt job-claims-pt))))
-
-(def max-utilization-pt (claim-spare-peers replica-pt job-claims-pt spare-peers-pt))
-
-(def task-distribution-pt (cts/task-distribute-peer-count replica-pt :j2 (:j2 max-utilization-pt)))
-
-
-(def replica-c {:job-scheduler :onyx.job-scheduler/percentage
-                :jobs [:j1 :j2]
-                :tasks {:j1 [:t1 :t2 :t3]
-                        :j2 [:t4 :t5 :t6]}
-                :task-schedulers {:j1 :onyx.task-scheduler/balanced
-                                  :j2 :onyx.task-scheduler/balanced}
-                :saturation {:j1 3 :j2 Double/POSITIVE_INFINITY}
-                :peers [:p1 :p2 :p3 :p4 :p5 :p6 :p7 :p8 :p9 :p10]
-                :percentages {:j1 40 :j2 60}
-                :allocations {:j1 {:t1 [] :t2 [] :t3 []}
-                              :j2 {:t4 [:p1 :p2 :p3 :p4]
-                                   :t5 [:p5 :p6 :p7]
-                                   :t6 [:p8 :p9 :p10]}}})
-
-(def job-offers-c (job-offer-n-peers replica-c))
-
-(def job-claims-c (job->task-claims replica-c job-offers-c))
-
-(def spare-peers-c (apply + (vals (merge-with - job-offers-c job-claims-c))))
-
-(def max-utilization-c (claim-spare-peers replica-c job-claims-c spare-peers-c))
-
-(def task-distribution-c (cts/task-distribute-peer-count replica-c :j2 (:j2 max-utilization-c)))
-
-(def current-job-allocations-c (current-job-allocations replica-c))
-
-(def current-task-allocations-c (current-task-allocations replica-c))
-
-(def peers-to-displace (find-displaced-peers replica-c max-utilization-c))
-


[skip ci] Property based testing: do not generate float schema in cljs

--- src/test/cljc/mikron/runtime/generators.cljc
+++ src/test/cljc/mikron/runtime/generators.cljc
@@ -73,6 +73,7 @@
                   (compound-schema-generator schema inner-generator)))
            (tc.gen/one-of)))
     (->> (compiler.schema/leaf-children compiler.schema/extended-hierarchy :scalar)
+         #?(:cljs (remove #{:float}))
          (map scalar-schema-generator)
          (tc.gen/one-of))))


add a test for input validation

add a test for input validation

--- test/clj/conference_rating/handler_test.clj
+++ test/clj/conference_rating/handler_test.clj
@@ -51,10 +51,15 @@
       (let [conferences (json-body-for db (request :get "/api/conferences"))]
         (is (= 1 (count conferences)))
         (is (= "some description" (:description (first conferences))))
-        (is (= "some name" (:name (first conferences)))))))))
+        (is (= "some name" (:name (first conferences))))))))
+  (testing "should fail if incomplete data is written to ratings"
+    (let [db (create-mock-db)
+          response ((app db) (-> (request :post "/api/conferences/someConferenceId/ratings")
+                                 (body (json/write-str {:some "random value"}))
+                                 (header :content-type "application/json")))]
+      (is (= 500 (:status response))))))

-
-(deftest backwards-compatibility-test
+  (deftest backwards-compatibility-test
   (testing "that we get valid ratings even if there is crap in the db"
     (let [db (create-mock-db)
           conference-id (ObjectId.)


Remove random file

Remove random file


Add select button and handlers for actions

--- src-cljs/photon/ui/frontend.cljs
+++ src-cljs/photon/ui/frontend.cljs
@@ -976,6 +976,21 @@
         iv (condp = (:action m) :group-by "{}" "[]")]
     [iv (str "(fn [prev next]\n" action ")")]))

+(def action-mappings {:group-by "Group by"
+                      :select "Select"})
+
+(defn action-item [data owner]
+  (reify
+    om/IRender
+    (render [_]
+      (dom/p nil (str (get action-mappings (key (first data)))
+                      " " (val (first data))) " "
+             (dom/a #js {:href "#"} "[X]")))))
+
+(defn action-list->actions [action-list]
+  (mapcat (fn [k] (map #(hash-map k %) (get action-list k)))
+          (keys action-list)))
+
 (defn var-actions [data owner]
   (reify
     om/IInitState
@@ -984,7 +999,8 @@
         (loop [elem (<! (:ch data))]
           (om/update-state! owner (fn [old] (assoc old :var elem)))
           (recur (<! (:ch data)))))
-      {:var nil})
+      {:var nil
+       :action-list {}})
     om/IRenderState
     (render-state [_ state]
       (if (nil? (:var state))
@@ -992,17 +1008,32 @@
         (let [node (js->clj (:var state) :keywordize-keys true)
               sch (-> node :node :original :schema)
               path (clojure.string/join "." (:path sch))
-              [iv code] (construct-code state)]
+              [iv code] (construct-code state)
+              upd (fn [k v]
+                    (om/update-state! owner (fn [o] (assoc o k v))))]
           (dom/div
            nil
            (dom/p nil (str "Selected variable: " path))
            (dom/button
-            #js {:onClick (fn [ev]
-                            (om/update-state! owner
-                                              (fn [old]
-                                                (assoc old :action :group-by))))}
+            #js {:onClick
+                 (fn [ev]
+                   (om/update-state!
+                    owner
+                    (fn [old] (update-in old [:action-list :group-by]
+                                         #(conj (into #{} %) path)))))}
             "Group by")
-           (dom/br nil)
+           (dom/button
+            #js {:onClick
+                 (fn [ev]
+                   (om/update-state!
+                    owner
+                    (fn [old] (update-in old [:action-list :select]
+                                         #(conj (into #{} %) path)))))}
+            "Select")
+           (apply dom/div
+                  nil
+                  (map #(om/build action-item %)
+                       (action-list->actions (:action-list state))))
            (dom/label nil "Initial value")
            (om/build code-block iv)
            (dom/label nil "Code")


label a little smarter so that the short solution is early

--- src/adventofcode1/twentyfour.clj
+++ src/adventofcode1/twentyfour.clj
@@ -86,6 +86,7 @@
 ;;([1 1] [1 3] [1 5] [1 9] [1 5] [3 5] [3 3] [3 1] [5 1] [5 5] [5 6] [5 9] [3 9] [3 7])
 ;;([1 1] [1 3] [1 1] [1 3] [1 5] [1 9] [3 9] [3 7] [3 9] [5 9] [5 6] [5 5] [3 5] [3 3])
 ;;([1 1] [1 3] [1 1] [1 3] [1 5] [1 9] [1 5] [3 5] [3 3] [3 5] [5 5] [5 6] [5 9] [3 9] [3 7])
+

 (def sample3
   "###########
@@ -518,17 +519,22 @@
   (= (count digits)(count (:dp puzzle))))

 (s/fdef path->breadcrump-alts
-        :args (s/cat :current ::from :paths (s/coll-of ::path))
+        :args (s/cat  :breadcrumbs ::breadcrumbs :paths (s/coll-of ::path))
         :ret  (s/coll-of ::from))

 (defn path->breadcrump-alts
-  [current paths]
-  (map
-   (fn [{:keys [from to]}]
-     (if (= current from)
-       to
-       from))
-   paths))
+  [breadcrumbs paths]
+  (let [current (first breadcrumbs)
+        bread-ext
+        (map
+         (fn [{:keys [from to]}]
+           (let [next (if (= current from) to from)]
+             [next
+              ;; make the visited path be last
+              (not (mw.utils/in? breadcrumbs next))]))
+         paths)]
+    (map first (sort bread-ext))))
+

 (s/fdef possibilites
         :args (s/cat :breadcrumbs ::breadcrumbs :digits ::digits :puzzle ::puzzle)
@@ -539,8 +545,9 @@
   [breadcrumbs digits puzzle]
   (let [current (first breadcrumbs)
         p (-> puzzle :all (get current))
-        breadcrumb (path->breadcrump-alts current p)]
+        breadcrumb (path->breadcrump-alts breadcrumbs p)]
     breadcrumb))
+


Move to child-lists from n-ary relations

--- src/databinder/core.clj
+++ src/databinder/core.clj
@@ -31,7 +31,7 @@

 (defn make-map [f1 f2 coll]
-  (apply hash-map (flatten (map (fn [val] [(f1 val) (f2 val)]) coll))))
+  (apply hash-map (apply concat (map (fn [val] [(f1 val) (f2 val)]) coll))))

 (defn prop [uri]
   (if uri
@@ -46,6 +46,12 @@

 (defn uris [base & resources]
   (apply assoc {} (flatten (map (fn [resource] [resource (str base (name resource))]) resources))))
+
+(defn write-out [model]
+  (with-open [out (io/output-stream "/Users/logangilmour/test.rdf")]
+    (.write model out "TURTLE"))
+
+  nil)

 (defn literalize [res]
   (if res
@@ -164,7 +170,7 @@
 (def dc (uris "http://purl.org/dc/elements/1.1/" :title :description))

-(def bind (uris "http://logangilmour.com/data-binder#" :js :debug :index :rank :root :application :subject :object :child :container :from :path :view :base :param :end :name :binding :compiled))
+(def bind (uris "http://logangilmour.com/data-binder#" :js :debug :index :root :application :subject :object :children :container :from :path :view :base :param :name :binding :compiled))

@@ -214,8 +220,8 @@
 :component :param :root .
 :component :param :path .
 :component :param :from .
-:component :param :rank .
 :component :param :index .
+:component :param :children .

 :index :name \"index\" .

@@ -223,8 +229,8 @@
 :object rdfs:domain :binding .
 :subject rdfs:domain :binding .

-:child rdfs:domain :component .
-:child rdfs:range :component .
+:children rdfs:domain :component .
+:children rdfs:range rdfs:List .

 :binding :param :subject .
 :binding :param :object .
@@ -235,8 +241,6 @@

 :view rdfs:subClassOf :component .

-:application rdfs:subClassOf :view .
-

@@ -262,17 +266,14 @@
   :js \"emit(list(this));\" .

 pl:list rdfs:subClassOf :view ;
-  :param pl:binding, dc:title, :root ;
-  :end pl:ending ;
+  :param pl:binding, dc:title, :root, :children;
   :base [a w:list ;
          :root :root ;
-         :debug \"thing\";
          dc:title dc:title;
-         :child pl:binding] .
-
-pl:binding :child pl:ending.
-
-pl:ending a w:li .
+         :children (pl:binding)] .
+
+pl:binding :children ([a w:li;
+                       :children :children]).

 w:li rdfs:subClassOf :container ;
   :js \"emit(li(this));\" .
@@ -283,80 +284,56 @@
   :js \"emit(listItem(this));\" .

 w:list-item rdfs:subClassOf :view ;
-  :param w:item-url ;
-  :end w:item-end ;
+  :param :path, :children ;
   :base [a w:list-item- ;
-         :path w:item-url ;
-         :child [a w:active ;
-                 w:check-path w:item-url ;
-                 :rank 1 ],
-                w:item-end] .
-
-w:item-end a w:projector ;
-  :rank 2 .
+         :path :path;
+         :children (
+                 [a w:active ;
+                  :from :path]
+                 [a w:projector;
+                  :children :children])] .

 w:link-list rdfs:subClassOf :view ;
-  :param w:list-path, w:list-binding, w:list-title;
-  :end w:list-end ;
+  :param :path, w:list-binding, dc:title, :children;
   :base
     [a w:list ;
-     dc:title w:list-title ;
-     :child w:list-binding].
-
-w:list-binding :child w:list-end .
-
-w:list-end a w:list-item;
-  w:item-url w:list-path.
-
+     dc:title dc:title ;
+     :children (w:list-binding)].
+
+w:list-binding :children (
+  [a w:list-item;
+   :path :path;
+   :children :children]) .

 tm:type-manager rdfs:subClassOf :view ;
-:param tm:type, tm:title, tm:item , tm:path;
-:end tm:ending;
+:param tm:type, dc:title, tm:item , :path, :children;
 :base
   [a w:row ;
   :root tm:type ;
-  :child
+  :children (
     [a w:column4 ;
-     :rank 1 ;
-     :child
+     :children (
       [a w:link-list ;
-       :rank 1 ;
-       w:list-title tm:title ;
-       w:list-binding [:object rdf:type ] ;
-       :child tm:item ;
-       w:list-path tm:path] ,
+       dc:title dc:title ;
+       w:list-binding [:object rdf:type] ;
+       :children (tm:item) ;
+       :path :path]
       [a w:creator ;
-       :rank 2;
-       :child [:object rdf:type]]] ,
-      tm:ending].
-
-tm:ending a w:column4;
-:from tm:path ;
-:rank 2.
-
-
-
+       :children ([:object rdf:type])])]
+    [a w:column4;
+     :from :path;
+     :children :children])].

 cb:relator rdfs:subClassOf :view ;
   :param cb:binding , cb:path ;
   :base [a w:checkbox ;
-         :child cb:binding ,
-                [a w:value ; :from cb:path ; :rank 2 ]] .
-
-cb:binding
-  :from cb:path ;
-  :rank 1 ;
-
-  :child [a w:value] .
-
-
-
-w:item :rank 2 .
-
-
-w:activating-list-item rdfs:subClassOf :view .
+         :children (cb:binding
+                [a w:value ; :from cb:path])] .
+
+cb:binding :from cb:path ;
+  :children ([a w:value]) .

 w:deleter
   rdfs:subClassOf :container ;
@@ -421,58 +398,23 @@
   :js \"if(this.vals==this.uri){emit('active')}else{emit('')};\" .

 w:active rdfs:subClassOf :view ;
-  :param w:check-path ;
+  :param :from ;
   :base [a w:active-test ;
-         :child [a w:value ; :from w:check-path] ] .
+         :children ([a w:value ; :from :from]) ] .
 "

               ))
-
-
-(comment (def params
-    (apply assoc {} (flatten (map (fn [statement]
-                                    [(.getURI (.getSubject statement))
-                                     (.getString (.getObject statement))])
-                                  (doall (iterator-seq
-                                          (.listStatements widgets
-                                                           nil
-                                                           (prop (bind :parameter))
-                                                           nil))))))))
-
-(comment (defn get-params [resource model]
-    (apply assoc {}
-           (flatten
-            (map (fn [pr]
-                   (let [p (prop pr)]
-                     (let [param (first (relate-right model p resource))]
-                       (if param
-                         [(get params pr) (.getString param)]
-                         [(get params pr) nil]))))
-                 (keys params)
-                 )))))

 (defn parse-uri [uri]
   (vec (filter (comp not (partial re-matches #"^\s*$")) (clojure.string/split uri #"/"))))

 (defn types [model binding]
-  (println "Trying to deal with " binding)
-  (if binding
-    (set (map #(.toString %) (relate-right model (prop "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") binding)))
+
+  (if (and binding (.isResource binding))
+    (set (map #(.toString %)
+              (relate-right model (prop "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") binding)))
     (set [])))
-
-(defn get-subs [model binding] ;;TODO make this deep.
-  (filter #(not (contains? (types model %) (bind :container))) (relate-right model (prop (bind :child)) binding)))
-
-
-(defn rdf->str [resource]
-  (cond
-   (.isResource resource)
-   (.getURI resource)
-   (.isLiteral resource)
-   (.getString resource)
-   :default
-   (.toString resource)))

 (defn get-property [model resource property]
   (filter identity (map #(if % (.getURI %))
@@ -484,33 +426,59 @@

 (defn named-params [model context]
-  (into {} (keep #(if (first %) %) (make-map #(literalize (first (relate-right model (prop (bind :name)) (res %))))
-                           #(literalize ( get context %))
+  (into {} (keep #(if (first %) %)
+                 (make-map #(literalize (first (relate-right model (prop (bind :name)) (res %))))
+                           #(let [property (get context %)]
+                              (if (seq? property)
+                                (doall (map (fn [p] (literalize p)) property))
+                                (literalize property)))
                            (keys context)))))

-(defn relate-lookup [model context predicate resource]
-  (map #(or (get context (literalize %)) %) (iterator-seq (.listObjectsOfProperty model resource predicate))))
-
-(defn build-context [model parent-context binding]
-  (let [params (get-property model binding (prop (bind :param)))
-
-        context (make-map identity
-                          #(first (relate-lookup model parent-context (prop %) binding)) params)
-        ] ;;TODO these could be parameters themselves
-    context))
+(defn resolve-property [model context resource]
+  (if (contains? (set (keys context)) (literalize resource))
+    (get context (literalize resource))
+    resource))
+
+(defn resolve-list [model property]
+  (if (contains? (types model property) (rdfs :List))
+                (doall (rdf-seq model property))
+                property))
+
+(defn build-context [model binding]
+  (let [params (get-property model binding (prop (bind :param)))]
+    (make-map identity
+              #(resolve-list model (first (relate-right model (prop %) binding)))
+                          params)))
+
+(defn resolve-context [model parent-context context]
+  (make-map identity
+            (fn [key]
+              (let [property (get context key)]
+                (if (seq? property)
+                  property
+                  (resolve-property model parent-context property))))
+            (keys context)))

 (defn copy-context [model local-context node]
   (doseq [param (keys local-context)]
-    (if (get local-context param)
-      (.add model (.createStatement model node (prop param) (get local-context param))))))
+    (let [property (get local-context param)]
+      (if property
+        (.add model (.createStatement model node (prop param)
+                                      (if (seq? property)
+
+                                        (make-seq model property)
+                                        property)))))))

 (defn merge-context [parent-context context]
-  (let [tits (merge parent-context
-                    (into {} (keep (fn [[key val :as pair]] (if (not (get parent-context key)) pair))
-                                   context)))]
-
-    tits))
+  (merge-with
+   (fn [parent child]
+     (if (and (seq? parent) (seq? child))
+       (doall (concat parent child))
+       child))
+   parent-context
+   (into {} (keep (fn [[key val :as pair]] (if (not (get parent-context key)) pair))
+                        context))))

 (defn debug [message context]
   (if (get context (bind :debug)) (println "\n" message ", " (get context (bind :debug)) ", " context)))
@@ -518,11 +486,11 @@

 (defn url-index [model node index] ;;end end-children
   (if (contains? (types model node) (bind :compiled))
-    (let [context (build-context model {} node)
+    (let [context (build-context model node)

           children (doall
                     (filter (fn [child] (empty? (relate-right model (prop (bind :from)) child)))
-                     (relate-right model (prop (bind :child)) node)))
+                     (get context (bind :children))))

           path (get context (bind :path))

@@ -537,21 +505,25 @@
         (doseq [onlooker onlookers] ;;end end-children
           (url-index model onlooker (+ index 1)))))))

-(defn generics [model node parent-context parent-children local-part] ;;end end-children
-  (let [local-context (build-context model parent-context node)
-
-        local-context (if parent-children (merge-context local-part local-context) local-context)
-
-        context (merge parent-context local-context)
-
-        thing (println "\n\n1: " parent-context "\n\n2: " local-context "\n\n3: " context)
+(defn generics [model node parent-context local-part] ;;end end-children
+  (let [local-context (build-context model node)
+
+        ;;thing (println "\n\n1: " parent-context "\n\n2: " local-context)

         ;; children (doall (relate-right model (prop (bind :child)) node))
-        children
-        (map #(generics model % parent-context nil nil)
-             (rdf-seq model (get parent-context (bind :children)))) ;;TODO holy shit I'm here
-
-        children (if parent-children (concat parent-children children) children)
+        children (get local-context (bind :children))
+
+        local-context
+        (if (seq? children)
+          (assoc local-context (bind :children) (doall (map #(generics model % parent-context nil) children)))
+          local-context
+          )
+
+        local-context (resolve-context model parent-context local-context)
+
+        local-context (if local-part (merge-context local-part local-context) local-context)
+
+        ann (debug (str  "thing: " parent-context) local-context)

         base (res (first (get-property model node (prop (bind :base)))))

@@ -559,14 +531,19 @@

         clone (res (uuid))

+
+
         subbed (get parent-context (literalize node))
+
         ;;fuck (debug (str "Hmm: " child-map "\n\n" new-end "\n\n") local-context)
         ]
+
+
     (cond
      subbed
-     (generics model subbed context children local-context) ;;end end-children
+     (generics model subbed parent-context local-context) ;;end end-children
      (contains? types (bind :view))
-     (generics model base context nil local-context) ;;(conj end new-end) (conj end-children children)
+     (generics model base (merge parent-context local-context) nil) ;;(conj end new-end) (conj end-children children)
      :default
      (do

@@ -581,18 +558,14 @@

 (defn s-rec [binding model]

-  (let [context (build-context model {} binding)
+  (let [context (build-context model binding)

         params (named-params model context)
-        children (sort-by (fn [resource]
-                            (let [p (.getProperty model resource (prop (bind :rank)))]
-                              (if p
-                                (.getString (.asLiteral (.getObject p)))
-                                "")))
-                          (relate-right model (prop (bind :child)) binding))
-        bindings (clojure.string/join ", "
-                                      (map #(.getURI %)
-                                           (get-subs model binding)))
+        children (get context (bind :children))
+        bindings (clojure.string/join
+                  ", "
+                  (map #(.getURI %)
+                       (filter #(not (contains? (types model %) (bind :container))) children)))

         from (get context (bind :from))

@@ -623,7 +596,7 @@

          (let [url-parts (parse-uri url)
                my-part (get url-parts (- index 1))
-               fuck (println "Mine: " my-part " at index " index " of " url)
+               ;;fuck (println "Mine: " my-part " at index " index " of " url)
                my-res (res my-part)

                my-res (if my-res
@@ -707,7 +680,7 @@

 (defn prepare [view widgets]
   (let [model (. ModelFactory createRDFSModel (.union view widgets))
-        root (generics model (res (bind :application)) {} nil nil {})]
+        root (generics model (res (bind :application)) {} nil)]
     (url-index model root 0)
     {:root root :model model}))

@@ -1021,7 +994,7 @@

-(def example-view (to-model
+(def example-view-small (to-model
                    "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
 @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
 @prefix : <http://logangilmour.com/data-binder#> .
@@ -1040,34 +1013,11 @@
  [a pl:list;
     :root foaf:Person;
     dc:title \"Butt\";
-    :debug \"the list\";
     pl:binding [:object rdf:type];
-    :child [:subject foaf:givenName]].
-
-
- #[a tm:type-manager ;
- # tm:type foaf:Person ;
- # tm:title \"People\" ;
- # tm:item ex:fullName ;
- # tm:path \"person\" ;
- # :child
- #  [dc:title \"Remove\" ;                     :rank 0 ;
- #    a w:deleter ;
- #    :child [:subject rdf:type]],
-#
-#   [dc:title \"Given Name\" ;                 :rank 1 ;
-#     a w:text-field ;
-#     :child [:subject foaf:givenName]] ,
-#
-#    [dc:title \"Family Name\" ;               :rank 2 ;
-#     a w:text-field ;
-#     :child [:subject foaf:familyName]]]
-
-
-
+    :children ([:subject foaf:givenName])].
 "))

-(def example-view-large (to-model
+(def example-view (to-model
                    "
 @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
 @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@@ -1086,55 +1036,55 @@
 :base
  [a tm:type-manager;
   tm:type foaf:Person;
-  tm:title \"People\";
+  dc:title \"People\";
   tm:item ex:fullName;
-  tm:path \"person\";
-  :child
-   [dc:title \"Remove\";                     :rank 0;
+  :path \"person\";
+  :children (
+   [dc:title \"Remove\";
      a w:deleter;
-     :child [:subject rdf:type]],
-
-   [dc:title \"Given Name\";                 :rank 1;
+     :children ([:subject rdf:type])]
+
+   [dc:title \"Given Name\";
      a w:text-field;
-     :child [:subject foaf:givenName]],
-
-    [dc:title \"Family Name\";               :rank 2;
+     :children ([:subject foaf:givenName])]
+
+    [dc:title \"Family Name\";
      a w:text-field;
-     :child [:subject foaf:familyName]],
-
-    [dc:title \"Birthday\";                  :rank 3;
+     :children ([:subject foaf:familyName])]
+
+    [dc:title \"Birthday\";
      a w:datepicker;
-     :child [:subject foaf:birthday]],
-
-    [dc:title \"Status\";                    :rank 4;
+     :children ([:subject foaf:birthday])]
+
+    [dc:title \"Status\";
      a w:text-field;
-     :child [:subject foaf:status]],
-
-    [a pl:list;                              :rank 5;
+     :children ([:subject foaf:status])]
+
+    [a pl:list;
      dc:title \"Knows\";
      pl:binding [:subject foaf:knows];
-     :child ex:fullName],
-
-    [a w:popup;                               :rank 6;
+     :children (ex:fullName)]
+
+    [a w:popup;
      dc:title \"Edit Known...\";
-     :child
-       [a pl:list;
+     :children
+       ([a pl:list;
         dc:title \"All\";
         :root foaf:Person;
         pl:binding [:object rdf:type];
-        :child
-          ex:fullName,
+        :children (
+          ex:fullName
           [a cb:relator;
            cb:binding [:object foaf:knows];
-           cb:path \"person\"]]]].
+           cb:path \"person\"] ) ] ) ] ) ].

 ex:fullName a w:join-text;
   w:join-with \" \";
-  :child
-    [a w:text;                               :rank 1;
-     :child [:subject foaf:givenName]],
-    [a w:text;                               :rank 2;
-     :child [:subject foaf:familyName]].
+  :children (
+    [a w:text;
+     :children ([:subject foaf:givenName])]
+    [a w:text;
+     :children ([:subject foaf:familyName])]).

 "))

@@ -1226,4 +1176,4 @@

-;;(do (use 'databinder.core) (def stop! (-main)) (defn reload [] (stop!) (use 'databinder.core :reload) (def stop! (-main))))
+;;(do (use 'databinder.core :reload) (def stop! (-main)) (defn reload [] (stop!) (use 'databinder.core :reload) (def stop! (-main))))


on F12 activate debug mode

on F12 activate debug mode

--- desktop/src-common/con_world/screen-main.clj
+++ desktop/src-common/con_world/screen-main.clj
@@ -87,12 +87,14 @@
                 (create-player-entity screen)]))

            :on-render
-
-           (fn [screen entities]
+           (fn [{:keys [debug-physics?] :as screen} entities]

              (clear!)

              (let [[screen entities] (may-spawn-enemy screen entities)]
+
+               (when debug-physics?
+                 (draw-phisics-bodies screen))

                (if (player-dead? entities)

@@ -109,9 +111,12 @@
                       (render! screen)))))

            :on-key-down
-           (fn [{:keys [key]} entities]
+           (fn [{:keys [key] :as screen} entities]
              (when-let [direction (key->direction key)]
-               (on-key-move-cell entities direction)))
+               (on-key-move-cell entities direction))
+             (when (= 255 key)
+               (update! screen :debug-physics? true)
+               entities))

            :on-resize
            (fn [screen _]


CMR-4986: Added testing data for new variable bounds.

--- test/cmr/opendap/tests/unit/ous/variable.clj
+++ test/cmr/opendap/tests/unit/ous/variable.clj
@@ -55,6 +55,17 @@
        {:Name "lon"
         :Size 36000
         :Type "LONGITUDE_DIMENSION"}]}})
+
+(def ummvar-1-2-bounds
+  {:umm
+    {:Characteristics
+      {:Bounds
+        {:LowerLeft
+          {:Lat -90
+           :Lon -180}
+         :UpperRight
+          {:Lat 90
+           :Lon 180}}}}})

 (deftest lon-dim
   (is (nil? (variable/lon-dim (variable/extract-dimensions no-spatial-dims))))


Don't return archived cards for other card listing options :sad:

--- src/metabase/api/card.clj
+++ src/metabase/api/card.clj
@@ -38,17 +38,17 @@
 (defn- cards:all
   "Return all `Cards`."
   []
-  (sel :many Card, (k/order :name :ASC)))
+  (sel :many Card, :archived false, (k/order :name :ASC)))

 (defn- cards:mine
   "Return all `Cards` created by current user."
   []
-  (sel :many Card, :creator_id *current-user-id*, (k/order :name :ASC)))
+  (sel :many Card, :creator_id *current-user-id*, :archived false, (k/order :name :ASC)))

 (defn- cards:fav
   "Return all `Cards` favorited by the current user."
   []
-  (->> (hydrate (sel :many [CardFavorite :card_id], :owner_id *current-user-id*)
+  (->> (hydrate (sel :many [CardFavorite :card_id], :owner_id *current-user-id*, :archived false)
                 :card)
        (map :card)
        (sort-by :name)))
@@ -56,19 +56,19 @@
 (defn- cards:database
   "Return all `Cards` belonging to `Database` with DATABASE-ID."
   [database-id]
-  (sel :many Card (k/order :name :ASC), :database_id database-id))
+  (sel :many Card (k/order :name :ASC), :database_id database-id, :archived false))

 (defn- cards:table
   "Return all `Cards` belonging to `Table` with TABLE-ID."
   [table-id]
-  (sel :many Card (k/order :name :ASC), :table_id table-id))
+  (sel :many Card (k/order :name :ASC), :table_id table-id, :archived false))

 (defn- cards-with-ids
-  "Return `Cards` with CARD-IDS.
+  "Return unarchived `Cards` with CARD-IDS.
    Make sure cards are returned in the same order as CARD-IDS`; `[in card-ids]` won't preserve the order."
   [card-ids]
   {:pre [(every? integer? card-ids)]}
-  (let [card-id->card (sel :many :field->obj [Card :id], :id [in card-ids])]
+  (let [card-id->card (sel :many :field->obj [Card :id], :id [in card-ids], :archived false)]
     (filter identity (map card-id->card card-ids))))

 (defn- cards:recent
@@ -112,8 +112,8 @@
    :popular  (u/drop-first-arg cards:popular)
    :archived (u/drop-first-arg cards:archived)})

-(defn- card-has-label? [label card]
-  (contains? (set (map :slug (:labels card))) label))
+(defn- card-has-label? [label-slug card]
+  (contains? (set (map :slug (:labels card))) label-slug))

 (defn- cards-for-filter-option [filter-option model-id label]
   (let [cards (-> ((filter-option->fn (or filter-option :all)) model-id)


Implement macro for defining command trees.

Help command is still broken in at least some cases.

--- src/mvxcvi/vault/tool.clj
+++ src/mvxcvi/vault/tool.clj
@@ -1,5 +1,6 @@
 (ns mvxcvi.vault.tool
-  (:require [clojure.tools.cli :refer [cli]])
+  (:require [clojure.string :as string]
+            [clojure.tools.cli :refer [cli]])
   (:gen-class :main true))

 ;; Vault commands need to know:
@@ -17,25 +18,14 @@
 ;; $ vault object ...
 ;; $ vault group ...

-;; So what's the algorithm?
-;; - scan arguments for first occurrance of subcommand key
-;;   NOTE: this means that an argument to an option CANNOT be any subcommand name!
-;;   e.g. $ vault --some-option blob --another-option foo group show ...
-;;        $ vault [--some-option] [blob --another-option foo ...]
-;;
-;; - run cli with the specs for this node on the pre-command args
-;; - if the subcommand is 'help', change it to :help true in the opts map and recur
-;; - if a subcommand was chosen, recurse with the subcommand node, the subcommand args, and the merged option map
-;; - if no subcommand was chosen and :help is set, print the help message for this node
-;; - if no subcommand was chosen and the node has an :action, execute the action with the opts and remaining args
-;; - otherwise, error.

+;; COMMAND TREE STRUCTURE

-
-; command node:
+; command nodes look like this:
 #_
-{:usage "vault [global opts] <command> [command args]"
+{:name "vault"
+ :usage "vault [global opts] <command> [command args]"
  :desc "Command-line tool for the vault data store."
  :specs [["--blob-store" "Path to blob-store configuration." ...]]
  :init (fn [opts] ...)
@@ -43,7 +33,52 @@
  :action (fn [opts args] ...)}

-(defn handle-command
+(def ^:private ^:dynamic *command-branch*
+  "Vector containing the command names on the current branch."
+  [])
+
+
+(defmacro ^:private command
+  "Simple macro for building readable command trees."
+  [usage desc & more]
+  (let [[cname usage] (string/split usage #" " 2)
+        [specs more] (split-with vector? more)
+        command {:name cname
+                 :usage `(string/join " " (concat *command-branch* [~usage]))
+                 :desc desc
+                 :specs (vec specs)}
+        elements (group-by first (filter list? more))]
+    (when (> (count (elements 'init)) 1)
+      (throw (IllegalArgumentException.
+               (str "Multiple `init` elements in command definition: " (elements 'init)))))
+    (when (> (count (elements 'action)) 1)
+      (throw (IllegalArgumentException.
+               (str "Multiple `action` elements in command definition: " (elements 'action)))))
+    (when (and (elements 'command) (elements 'action))
+      (throw (IllegalArgumentException.
+               (str "Command definition contains both `command` and `action` elements: " more))))
+    (let [assoc-fn (fn [cmd [k & body]]
+                     (if k
+                       (if (symbol? (first body))
+                         (assoc cmd (keyword k) (first body))
+                         (assoc cmd (keyword k) `(fn ~@body)))
+                       cmd))
+          command (reduce assoc-fn command
+                          [(first (elements 'init))
+                           (first (elements 'action))])]
+      (if-let [subcommands (elements 'command)]
+        `(binding [*command-branch* (conj *command-branch* ~(:name command))]
+           (->>
+             ~(vec subcommands)
+             (map (juxt :name identity))
+             (into {})
+             (assoc ~command :commands)))
+        `(binding [*command-branch* (conj *command-branch* ~(:name command))]
+           ~command)))))
+
+
+(defn- handle-command
+  "Handles a sequence of arguments following a command tree structure."
   [command opts args]
   (let [subcommand-names (into #{} (cons "help" (keys (:commands command))))

@@ -66,66 +101,48 @@
                @new-opts
                subcommand-args)) ; NOTE: ignores unknown args before the subcommand
       (cond (:help opts) (do (println banner) (System/exit 0))
-            (:action command) ((:action command) opts command-args)
+            (:action command) ((:action command) @new-opts command-args)
             :else (do (println banner) (System/exit 1))))))
-
-
-#_
-(command "vault [global opts] <command> [command args]"
-  "Command-line tool for the vault data store."
-
-  ["--blob-store" "Path to blob-store configuration."
-   :default "~/.config/vault/blob-store.edn"]
-  ["-v" "--verbose" "Show extra debugging messages."
-   :flag true :default false]
-  ["-h" "--help" "Show usage information."
-   :flag true :default false]
-
-  (init [opts]
-    (-> opts
-        (assoc :blob-store (slurp (:blob-store opts)))))
-
-  (command "blob [opts] <action> [args]"
-    "Blob storage command."
-
-    (command "list [opts]"
-      "Enumerate the stored blobs."
-      ; ... filtering/range options
-      (action blob-tool/list-blobs))
-
-    (command "info <blobref>"
-      "Show information about a stored blob."
-      (action blob-tool/blob-info))
-
-    (command "get <blobref>"
-      "Print the contents of a blob to stdout."
-      (action blob-tool/get-blob))
-
-    (command "put"
-      "Store a blob of data and print the resulting blobref."
-      (action blob-tool/put-blob))))

 ;; COMMAND LINE INTERFACE

+(def command-tree
+  (command "vault [global opts] <command> [command args]"
+    "Command-line tool for the vault data store."
+
+    ["--blob-store" "Path to blob-store configuration."
+     :default "~/.config/vault/blob-store.edn"]
+    ["-v" "--verbose" "Show extra debugging messages."
+     :flag true :default false]
+    ["-h" "--help" "Show usage information."
+     :flag true :default false]
+
+    #_ (init [opts]
+      (-> opts
+          (assoc :blob-store (slurp (:blob-store opts)))))
+
+    (command "blob [opts] <action> [args]"
+      "Blob storage command."
+
+      (command "list [opts]"
+        "Enumerate the stored blobs."
+        ; ... filtering/range options
+        (action vector #_ blob-tool/list-blobs))
+
+      (command "info <blobref>"
+        "Show information about a stored blob."
+        (action vector #_ blob-tool/blob-info))
+
+      (command "get <blobref>"
+        "Print the contents of a blob to stdout."
+        (action vector #_ blob-tool/get-blob))
+
+      (command "put"
+        "Store a blob of data read from stdin and print the resulting blobref."
+        (action vector #_ blob-tool/put-blob)))))
+
+
 (defn -main [& args]
-  (let [[opts args banner]
-        (cli
-          args
-          "Usage: vault [global opts] <system> <command> [command args]"
-          ["--blob-store" "Path to blob-store configuration."
-           :default "~/.config/vault/blob-store.edn"]
-          ["-v" "--verbose" "Show extra debugging messages."
-           :flag true :default false]
-          ["-h" "--help"    "Show usage information."
-           :flag true :default false])]
-    (when (:help opts)
-      (println banner)
-      (System/exit 0))
-    ;; TODO: command-line processing
-    (println "Opts: " opts)
-    (let [[system action & args] args]
-      (println "System: " system)
-      (println "Action: " action)
-      (println "Args: " args))))
+  (handle-command command-tree {} args))


Renamed a var

Renamed a var

--- src/cia/stores/sql/judgement.clj
+++ src/cia/stores/sql/judgement.clj
@@ -40,7 +40,7 @@
   (transform/db-relationship->schema-relationship
    judgement-indicator-relationship-map))

-(def entities->db-indicators
+(def judgements->db-indicators
   (transform/entities->db-relationships
    judgement-indicator-relationship-map))

@@ -54,7 +54,7 @@
                                select/judgement-entity-values
                                (map transform/to-db-observable)
                                (map transform/to-db-valid-time)))
-     (c/insert @judgement-indicator (entities->db-indicators judgements)))
+     (c/insert @judgement-indicator (judgements->db-indicators judgements)))
     realized-judgements))

 (defn select-judgements [filter-map]


implement Bazaar

implement Bazaar

--- src/clj/game/cards-resources.clj
+++ src/clj/game/cards-resources.clj
@@ -88,6 +88,19 @@
                               (handle-end-run state side)
                               (when (= target (:counter card))
                                 (trash state :runner card {:unpreventable true})))}]}
+
+   "Bazaar"
+   {:events
+    {:runner-install
+     {:req (req (is-type? target "Hardware"))
+      :effect (req (let [hw (:title target)]
+                     (resolve-ability state side
+                       {:optional {:req (req (some #(when (= (:title %) hw) %) (:hand runner)))
+                                   :prompt (msg "Install another copy of " hw "?")
+                                   :msg (msg "install another copy of " hw)
+                                   :yes-ability {:effect (req (when-let [c (some #(when (= (:title %) hw) %)
+                                                                                (:hand runner))]
+                                                                 (runner-install state side c)))}}} card nil)))}}}

    "Beach Party"
    {:in-play [:hand-size-modification 5]


Modified Aesop's to use cid instead of title when checking that it's not targeting itself.

--- src/clj/game/cards-resources.clj
+++ src/clj/game/cards-resources.clj
@@ -23,9 +23,12 @@

    "Aesops Pawnshop"
    {:flags {:runner-phase-12 (req (>= 2 (count (all-installed state :runner))))}
-    :abilities [{:msg (msg "trash " (:title target) " and gain 3 [Credits]")
-                 :choices {:req #(and (= (:side %) "Runner") (:installed %) (not= (:title %) "Aesop's Pawnshop"))}
-                 :effect (effect (gain :credit 3) (trash target {:unpreventable true}))}]}
+    :abilities [{:effect (req (resolve-ability
+                                state side
+                                {:msg (msg "trash " (:title target) " and gain 3 [Credits]")
+                                 :choices {:req #(and (= (:side %) "Runner") (:installed %) (not= (:cid card) (:cid %)))}
+                                 :effect (effect (gain :credit 3) (trash target {:unpreventable true}))}
+                               card nil))}]}

    "Always Be Running"
    {:abilities [{:once :per-turn


Log action id if it fails.

Log action id if it fails.

--- src/clj/hatnik/worker/worker.clj
+++ src/clj/hatnik/worker/worker.clj
@@ -60,21 +60,25 @@
     (doseq [action actions
             :when (and (= (:library action) library)
                        (ver/first-newer? ver (:last-processed-version action)))]
-      (let [proj (stg/get-project db (:project-id action))
-            user (stg/get-user-by-id db (:user-id proj))
-            error (perform-action action user
-                                  {:library library
-                                   :version ver
-                                   :previous-version (:last-processed-version action)
-                                   :project (:name proj)}
-                                  utils)]
-        (if-not error
-          (do (timbre/debug "Action completed sucessfully. Updating library version in action.")
-              (stg/update-action! db (:id user)
-                                  (:id action) (assoc action
-                                                 :last-processed-version ver))
-              (timbre/debug "Action updated."))
-          (timbre/warn "Error while performing action: " error "Not updating the action."))))))
+      (try
+        (let [proj (stg/get-project db (:project-id action))
+              user (stg/get-user-by-id db (:user-id proj))
+              error (perform-action action user
+                                    {:library library
+                                     :version ver
+                                     :previous-version (:last-processed-version action)
+                                     :project (:name proj)}
+                                    utils)]
+          (if-not error
+            (do (timbre/debug "Action completed sucessfully. Updating library version in action.")
+                (stg/update-action! db (:id user)
+                                    (:id action) (assoc action
+                                                   :last-processed-version ver))
+                (timbre/debug "Action updated."))
+            (timbre/warn "Error while performing action: " error "Not updating the action.")))
+        (catch Exception e
+          (timbre/error "Error in action" (:id action))
+          (throw e))))))

 (defn update-all-actions
   "Runs update for all actions by checking latest versions of corresponding


Update log message.

Update log message.

--- src/clj/hatnik/worker/worker.clj
+++ src/clj/hatnik/worker/worker.clj
@@ -88,7 +88,7 @@
   (let [actions (stg/get-actions db)
         libraries (group-by :library actions)]
     (timbre/info "Total actions:" (count actions)
-                 "Libraries to update:" (keys libraries))
+                 ", libraries to update:" (keys libraries))
     (doseq [[library actions] libraries]
       (check-library-and-perform-actions library actions db
                                          perform-action utils))


better flow

better flow

--- src/clj_gamification/handler.clj
+++ src/clj_gamification/handler.clj
@@ -35,17 +35,22 @@
    [:form#newGroupForm {:action "/team"}
     [:button.btn {:type "sumbit"} "Start a new team!"]]))

-(defn page-team-idea [team-id idea]
+(defn page-team-idea [team-id idea published]
   "Form to submit name of team's gamification idea"
   (page
    "Idea"                               ; TODO better title
+   (when published
+     [:p.text-success "Your idea has been published"])
    [:form {:action (str "/team/" team-id "/idea"), :method "post"}
     [:label (str "Publish team " team-id "'s gamification idea:")
      [:br]
      [:input {:type "text", :name "idea", :value idea,
               :autofocus "true",
               :title "Describe your idea"}]]
-    [:button.btn {:type "submit"} "Publish"]]))
+    [:button.btn {:type "submit"} "Publish"]]
+   [:p "Or "
+    [:a {:href "/await-vote"} "await voting for the best idea"]
+    " to be started"]))

 (defn page-teams [teams]
   "Overveiw of all teams and their ideas"
@@ -89,8 +94,9 @@
       xhr.send();
 "))

-(defn page-gamemaster []
+(defn page-gamemaster
   "Control page for the GameMaster: 1. task info, 2. show task to others, 3. start brainstorming?, 4. start voting, 5. show number voted, 6. show voting results"
+  []
   (page
    "GameMaster Control"
    [:h1 "You control the game!"]
@@ -106,6 +112,16 @@
      (button "start-brainstorming" "2. Start brainstorming")
      (button "start-voting" "3. Start voting")
      (button "show-voting-results" "4. Show voting results")])))
+
+(defn page-await-vote [referer]
+  (page "Awaiting voting..."
+        [:p "Do "
+         [:a {:href "/vote"} "vote for the best idea"]
+         " once voting is opened"]
+        (when referer
+          [:p "(Or "
+           [:a {:href referer} "go back"]
+           " where you came from.)"])))

 (defn has-voted? [{:keys [remote-addr session]}]
   (or
@@ -152,14 +168,14 @@
               (GET "/" [] (redirect (let [id (swap! team-counter inc)] ; TODO assign picture/name of an animal
                                       (swap! teams assoc id "")
                                       (str "/team/" id))))
-              (GET "/:id" [id]
+              (GET "/:id" [id published]
                    (let [id (toint id)
                          idea (get @teams id)]
-                     (page-team-idea id idea)))
+                     (page-team-idea id idea published)))
               (POST "/:id/idea" [id idea]
                     (let [id (toint id)]
                       (swap! teams assoc id idea) ; TODO notify visibly that the idea has been published; notify /teams page
-                      (redirect (str "/team/" id)))))
+                      (redirect (str "/team/" id "?published=true")))))
      (GET "/teams" []
           (page-teams @teams))
      (POST "/vote" [teamid :as req]
@@ -172,7 +188,11 @@
                (swap! voter-ips conj (:remote-addr req))
                {:session {:voted? true},
                 :status 201
-                :body (str "Thank you for voting for team " teamid "!")})))
+                :body (page "Voted" [:p "Thank you for voting for team " teamid "!"])})))
+     (GET "/await-vote" [:as req]
+          (if (= :voting state)
+            (redirect "/vote")
+            (page-await-vote (get-in req [:headers "referer"]))))
      (GET "/vote" [] "Sorry, you can only POST to this page")
      (GET "/vote-results" [] (page-vote-results @teams @votes))
      (GET "/projector" []


Add lancaster stemmer.

Add lancaster stemmer.

--- src/cljs-nlp/stem/lancaster.cljs
+++ src/cljs-nlp/stem/lancaster.cljs
@@ -1,4 +1,5 @@
-(ns cljs-nlp.stem.lancaster)
+(ns cljs-nlp.stem.lancaster
+  (:use [clojure.string :only [lower-case]]))

 (def rules [{"continuation" false "intact" true "pattern" "ia" "size" "2"}
             {"continuation" false "intact" true "pattern" "a" "size" "1"}
@@ -114,4 +115,57 @@
             {"appendage" "t" "continuation" true "intact" false "pattern" "ncy" "size" "2"}
             {"continuation" true "intact" false "pattern" "acy" "size" "3"}
             {"continuation" true "intact" false "pattern" "iz" "size" "2"}
-            {"appendage" "s" "continuation" false "intact" false "pattern" "yz" "size" "1"}])+            {"appendage" "s" "continuation" false "intact" false "pattern" "yz" "size" "1"}])
+
+(defn group-rules [coll]
+  (let [alpha (comp last "pattern")]
+    (group-by alpha coll)))
+
+(defn contains-vowel? [s]
+  (if-let [candidate (first s)]
+    (if (#{"a" "e" "i" "o" "u" "y"} candidate)
+      true
+      (recur (rest s)))
+    false))
+
+(defn acceptable? [stemmed-word]
+  (let [length (count stemmed-word)
+        first-letter (first stemmed-word)]
+    (if (contains-vowel? first-letter)
+      (>= length 2)
+      (if (>= length 3)
+        (contains-vowel? stemmed-word)
+        false))))
+
+(defn apply-stem-rule [word rule]
+  (let [stem-size (rule "size")
+        stemmed-word (subs word 0 (- (count word) stem-size))
+        appendage (rule "appendage")
+        result (str stemmed-word appendage)]
+    (when (acceptable? stemmed-word)
+      result)))
+
+(defn process-rules [word rules intact?]
+  (if-let [rule (first rules)]
+    (let [word-length (count word)
+          intact-flag (rule "intact")
+          pattern (rule "pattern")
+          pattern-length (count pattern)]
+      (if (and (or intact? (not intact-flag)) (= (subs word (- word-length pattern-length)) pattern))
+        (if-let [stemmed-word (apply-stem-rule word rule)]
+          (if (rule "continuation")
+            (stem stemmed-word false)
+            stemmed-word)
+          (recur word (rest rules) intact?))
+        (recur word (rest rules) intact?)))
+    word))
+
+(defn stem
+  ([word] (stem word true))
+  ([word intact?] (stem word intact? (group-rules rules)))
+  ([word intact? dict]
+   (let [last-letter (last word)
+         rules (last-letter dict)]
+     (if-not (nil? rules)
+       (process-rules word rules intact?)
+       word))))


utcnow-midnight: Return current time, UTC, floored to midnight

--- src/karmanaut/utils.clj
+++ src/karmanaut/utils.clj
@@ -1,7 +1,10 @@
 (ns karmanaut.utils
   (:gen-class)
   (:require [clojure.java.io :as io])
-  (:import [java.util Date]))
+  (:import [java.util Calendar
+                      Date
+                      GregorianCalendar
+                      TimeZone]))

 (defn env [key default]
   (get (System/getenv) key default))
@@ -14,6 +17,17 @@
 (defn utcnow []
   (Date.))

+(defn utcnow-midnight []
+  (let [tz (TimeZone/getTimeZone "UTC")
+        c (GregorianCalendar. tz)]
+    (doto c
+      (.set Calendar/HOUR_OF_DAY 0)
+      (.set Calendar/MINUTE 0)
+      (.set Calendar/SECOND 0)
+      (.set Calendar/MILLISECOND 0))
+    (.getTime c)))
+
+
 (defn long-to-date
   "Reddit timestamps are the number of seconds since the
   Unix epoch, in UTC."


Fix Issue with Queue Name

Fix Issue with Queue Name

--- src/lens/amqp_async.clj
+++ src/lens/amqp_async.clj
@@ -19,7 +19,7 @@

 (defn- declare-queue [amqp-ch {:keys [queue-name]}]
   (if queue-name
-    (lqu/declare amqp-ch queue-name {:exclusive true})
+    (do (lqu/declare amqp-ch queue-name {:exclusive true}) queue-name)
     (lqu/declare-server-named amqp-ch)))

 (defn chan
@@ -37,7 +37,7 @@
          _ (lb/qos amqp-ch n)
          ch (async/chan n xform)
          queue (declare-queue amqp-ch opts)]
-     (debug {:action :subscribe})
+     (debug {:action :subscribe :queue queue})
      (lco/subscribe amqp-ch queue (delivery-fn ch) (select-keys opts [:consumer-tag]))
      (reify
        ReadPort


Remove generated file.

Remove generated file.

--- src/om_event_bus/core.clj
+++ src/om_event_bus/core.clj
@@ -1,6 +0,0 @@
-(ns om-event-bus.core)
-
-(defn foo
-  "I don't do a whole lot."
-  [x]
-  (println x "Hello, World!"))


Can't be emitted or drained.

Can't be emitted or drained.

--- src/onyx/plugin/kafka.clj
+++ src/onyx/plugin/kafka.clj
@@ -201,7 +201,7 @@
                      kpartitions))
           resuming-tps (reduce-kv
                         (fn [all k v]
-                          (if (not= v :emitted)
+                          (if (not (some #{v} #{:emitted :drained}))
                             (conj all (TopicPartition. topic v))
                             all))
                         []


Fix js include

Fix js include

--- src/orbitingnews/core.clj
+++ src/orbitingnews/core.clj
@@ -6,7 +6,8 @@
             [compojure.route :as route]
             [orbitingnews.config :as config]
             [orbitingnews.twitter :as twitter]
-            [hiccup.core :as dom])
+            [hiccup.core :as dom]
+            [hiccup.page :as page])
   (:gen-class))

 (defn handler [req]
@@ -31,7 +32,7 @@
   [:html
     [:head
       [:title "Houston we have a problem"]
-      (include-js "/js/main.js")]
+      (page/include-js "/js/main.js")]
     [:body
       [:h1 "Orbiting News"]
       [:h2 "Houston we have a problem"]


CV Generator

CV Generator

--- src/cv_generator/docx_writer.clj
+++ src/cv_generator/docx_writer.clj
@@ -20,6 +20,7 @@
   (let [target-directory (str path "/target/" filename "/docx")
         source-directory (str path "/resources/templates/docx")
         document (str target-directory "/word/document.xml")]
+    (fs/delete-dir target-directory)
     (fs/copy-dir source-directory target-directory)
     (with-open [w (io/writer document)]
       (.write w (mustache/render-file "templates/docx" (cv/convert-to-data-map cv filter))))


Fixed line number and file information for sent expressions

--HG--
branch : bleeding-edge

--- src/de/kotka/vimclojure/repl.clj
+++ src/de/kotka/vimclojure/repl.clj
@@ -101,7 +101,7 @@
   everything, but allows to specify an offset as initial line."
   [reader offset]
   (proxy [LineNumberingPushbackReader] [reader]
-    (getLineNumber []  (+ offset (proxy-super getLineNumber)))))
+    (getLineNumber [] (+ offset (proxy-super getLineNumber) -1))))

 (defn with-repl*
   "Calls thunk in the context of the Repl with the given id. id may be -1
@@ -121,8 +121,9 @@
                    line)]
     (try
       (Var/pushThreadBindings
-        {Compiler/SOURCE        file
-         Compiler/LINE          line
+        {Compiler/LINE          line
+         Compiler/SOURCE        (.getName (java.io.File. file))
+         Compiler/SOURCE_PATH   file
          #'*in*                 (make-reader *in* line)
          #'*ns*                 (if nspace nspace (the-repl :ns))
          #'*warn-on-reflection* (the-repl :warn-on-reflection)


Updating rebuild dropdown status based on the selected action.

--- src-cljs/frontend/components/build_head.cljs
+++ src-cljs/frontend/components/build_head.cljs
@@ -1213,36 +1213,46 @@
   (reify
     om/IInitState
     (init-state [_]
-      (let [rebuild-args  {:build-id  (build-model/id build)
-                           :vcs-url   (:vcs_url build)
-                           :build-num (:build_num build)}
-            rebuild!      #(do (raise! owner %)
-                               (om/set-state! owner [:actions :rebuild :text] "Rebuilding"))]
-        {:actions
+      (let [rebuild-args    {:build-id  (build-model/id build)
+                             :vcs-url   (:vcs_url build)
+                             :build-num (:build_num build)}
+            update-status!  #(om/set-state! owner [:rebuild-status] %)
+            rebuild!        #(raise! owner %) ]
+        {:rebuild-status "Rebuild"
+         :actions
          {:rebuild
           {:text  "Rebuild with cache"
            :title "Retry the same tests"
-           :action #(rebuild! [:retry-build-clicked (merge rebuild-args {:no-cache? false})])}
+           :action #(do (rebuild! [:retry-build-clicked (merge rebuild-args {:no-cache? false})])
+                        (update-status! "Rebuilding with cache"))}

           :without_cache
           {:text  "Rebuild without cache"
            :title "Retry without cache"
-           :action #(rebuild! [:retry-build-clicked (merge rebuild-args {:no-cache? true})])}
+           :action #(do (rebuild! [:retry-build-clicked (merge rebuild-args {:no-cache? true})])
+                        (update-status! "Rebuilding without cache"))}

           :with_ssh
           {:text  "Rebuild with SSH"
            :title "Retry with SSH in VM",
-           :action #(rebuild! [:ssh-build-clicked rebuild-args])}}}))
+           :action #(do (rebuild! [:ssh-build-clicked rebuild-args])
+                        (update-status! "Rebuilding with SSH"))}}}))
+
+    om/IWillUpdate
+    (will-update [_ {:keys [build]} _]
+      (when (build-model/running? build)
+        (om/set-state! owner [:rebuild-status] "Rebuild")))
+
+
     om/IRenderState
-    (render-state [_ {:keys [actions]}]
+    (render-state [_ {:keys [actions rebuild-status]}]
       (let [text-for    #(-> actions % :text)
             action-for  #(-> actions % :action)]
         (html
           [:div.dropdown.rebuild
            [:button.btn.dropdown-toggle {:data-toggle "dropdown"}
-            "Rebuild"
+            rebuild-status
             [:img {:src (common/icon-path "UI-ArrowChevron")}]]
-
            [:ul.dropdown-menu
             [:li
              [:a {:on-click (action-for :rebuild)} (text-for :rebuild)]]
@@ -1271,7 +1281,7 @@
                                   (get-in data state/project-scopes-path))]
         (html
           [:div.build-actions-v2
-           (when true #_(and (build-model/can-cancel? build) has-write-settings?)
+           (when (and (build-model/can-cancel? build) has-write-settings?)
              (forms/managed-button
                [:a.build-action
                 {:data-loading-text "Canceling"


add queued explanation specific to Enterprise

--- src-cljs/frontend/components/build_head.cljs
+++ src-cljs/frontend/components/build_head.cljs
@@ -62,6 +62,15 @@
        "Add Containers"]
       " to run more builds concurrently."]]))

+(defn queued-explanation-text []
+  (if (not (enterprise?))
+    "We're sorry; this is our fault. Typically you should only see this when load spikes overwhelm our auto-scaling; waiting to acquire containers should be brief and infrequent."
+    [:span
+     "Typically, this means you have more builds scheduled to be run than available capacity in the fleet. "
+     (if (-> js/window (aget "renderContext") (aget "current_user") utils/js->clj-kw :admin)
+       [:span "Check " [:a {:href "/admin/fleet-state"} "Fleet State"] " for details and potentially start new builders"]
+       "Ask CircleCI Enterprise administrator to check fleet state and launch new builder machines")]))
+
 (defn build-queue [data owner]
   (reify
     om/IWillMount
@@ -91,7 +100,7 @@
                " acquiring containers for this build."])
             (when (< 10000 (build-model/run-queued-time build))
               [:p#circle_queued_explanation
-               "We're sorry; this is our fault. Typically you should only see this when load spikes overwhelm our auto-scaling; waiting to acquire containers should be brief and infrequent."])
+               (queued-explanation-text)])

             (when (seq builds)
               (list
@@ -138,7 +147,7 @@

              (when (< 10000 (build-model/run-queued-time build))
                [:span#circle_queued_explanation
-                " We're sorry; this is our fault. Typically you should only see this when load spikes overwhelm our auto-scaling; waiting to acquire containers should be brief and infrequent."])
+                (str " " (queued-explanation-text))])
              (when (seq builds)
                [:span
                 " This build " (if usage-queued? "has been" "was")


Use agents for actions on topics (publish and done) to respect order

--- src/pubsure_ws/source.clj
+++ src/pubsure_ws/source.clj
@@ -7,7 +7,8 @@
             [clj-wamp.server :as wamp]
             [clojure.string :refer (split)]
             [cheshire.core :as json]
-            [taoensso.timbre :as timbre])
+            [taoensso.timbre :as timbre]
+            [clojure.core.cache :as cache])
   (:import [java.net InetAddress URI]
            [java.util UUID]))
 (timbre/refer-timbre)
@@ -20,9 +21,9 @@
   function takes three parameters: the topic, the size and whether to
   receive the cache items as a response or as published messsages. The
   cache data is availabe in the source state record."
-  [{:keys [cache] :as source} topic size publish?]
+  [{:keys [topics] :as source} topic size publish?]
   (debug "Requested to send " size "items from cache for" topic "to" wamp/*call-sess-id*)
-  (let [messages (reverse (take size (get @cache topic)))
+  (let [messages (reverse (take size (:cache @(get @topics topic))))
         cnt (count messages)]
     (if publish?
       (do (debug "Sending" cnt "cached message for" topic "to" wamp/*call-sess-id* "as events.")
@@ -36,9 +37,9 @@
 (defn- send-summary
   "Sends a summary of the published messages, built by the optional
   summary function given at source creation."
-  [{:keys [summary-fn summaries] :as source} topic]
+  [{:keys [config summaries] :as source} topic]
   (debug "Requested to send summary of" topic "to" wamp/*call-sess-id*)
-  (if summary-fn
+  (if (:summary-fn config)
     (let [summary (get @summaries topic)]
       (debug "Sending summary of" topic "to" wamp/*call-sess-id*)
       (trace "Summary is" summary)
@@ -84,51 +85,74 @@

 ;;; Source implementation.

-;; topics = (ref #{"topic"})
-;; cache = (atom {"topic" (msg-3 msg-2 msg-1)})
+(defn- publish-action
+  [{:keys [topic registered? cache summaries dirwriter] :as data} config message]
+  (let [uuid (UUID/randomUUID)]
+    (debug "Requested to publishing message" uuid "on" topic)
+    (trace "Message" uuid "-" message)
+
+    (when-not registered?
+      (api/add-source dirwriter topic (:uri config))
+      (debug "Registered" (:uri config) "for topic" topic "in directory service."))
+
+    (wamp/send-event! topic message)
+
+    (when-let [summary-fn (:summary-fn config)]
+      (swap! summaries update-in [topic] (fn [current] (summary-fn current message))))
+
+    (let [new-data (merge data
+                          {:cache (take (:cache-size config) (conj cache message))
+                           :registered? true})]
+      (debug "Message " uuid "published and cached.")
+      (trace "Data for" topic "after message" uuid "is:" new-data)
+      new-data)))
+
+
+(defn- done-action
+  [{:keys [topic registered? cache summaries dirwriter] :as data} config]
+  (debug "Initiated 'done' for" topic)
+
+  (when-let [done-payload (:done-payload config)]
+    (debug "Sending done payload to" topic)
+    (wamp/send-event! topic done-payload))
+
+  (when registered?
+    (api/remove-source dirwriter topic (:uri config))
+    (debug "Unregistered" (:uri config) "for topic" topic "in directory service."))
+
+  (when (:clean-summary-on-done config)
+    (swap! summaries dissoc topic))
+
+  (let [new-data (merge data
+                        {:cache (when-not (:clean-cache-on-done config) cache)
+                         :registered? false})]
+    (debug "Done for topic" topic "processed.")
+    (trace "Data for" topic "after done is:" new-data)
+    new-data))
+
+
+;; topics = (ref {"topic" agent})
 ;; open = (atom boolean)
-;; config = {:cache-size long, :clean-cache-on-done boolean, :clean-summary-on-done boolean}
-;; summaries (atom {"topic", summary})
-(defrecord WebsocketSource [dirwriter stop-fn open topics cache uri config summary-fn summaries]
+;; config = {:cache-size long, :clean-cache-on-done boolean, :clean-summary-on-done boolean,
+;;           :uri URI, :summary-fn nil/fn}
+(defrecord WebsocketSource [dirwriter stop-fn open topics config summaries]
   Source
   (publish [this topic message]
-    (let [uuid (UUID/randomUUID)]
-      (debug "Requested to publishing message" uuid "on" topic)
-      (trace "Message" uuid "-" message)
-      (when @open
-        (when (dosync
-                (when-not (get @topics topic)
-                  (alter topics conj topic)))
-          (when @open
-            (api/add-source dirwriter topic uri)
-            (debug "Registered" uri "for topic" topic "in directory service.")))
-        (wamp/send-event! topic message)
-        (let [new-cache (swap! cache update-in [topic]
-                               (fn [c] (take (config :cache-size) (conj c message))))]
-          (debug "Message " uuid "published and cached.")
-          (trace "Cache for" topic "after message" uuid "is:" (get new-cache topic)))
-        (when summary-fn
-          (let [new-summaries (swap! summaries update-in [topic] summary-fn message)]
-            (debug "Summary for" topic "updated with message" uuid)
-            (trace "Summary for" topic "after message" uuid "is:" (get new-summaries topic)))))))
+    (if @open
+      (let [topic-agent (get (dosync
+                               (if-not (get @topics topic)
+                                 (alter topics assoc topic
+                                        (agent {:topic topic, :registered? false
+                                                :summaries summaries, :dirwriter dirwriter}))
+                                 @topics))
+                             topic)]
+        (send topic-agent publish-action config message))
+      (warn "Trying to 'publish' after the source is closing or closed.")))

   (done [this topic]
-    (debug "Initiated 'done' for" topic)
-    (when @open
-      (when (dosync (when (get @topics topic)
-                      (alter topics disj topic)))
-        (when @open
-          (when-let [done-payload (:done-payload config)]
-            (debug "Sending done payload to" topic)
-            (wamp/send-event! topic done-payload))
-          (api/remove-source dirwriter topic uri)
-          (debug "Unregistered" uri "for topic" topic "in directory service."))
-        (when (:clean-cache-on-done config)
-          (swap! cache dissoc topic)
-          (debug "Cleaned cache for" topic))
-        (when (and summary-fn (:clean-summary-on-done config))
-          (swap! summaries dissoc topic)
-          (debug "Cleaned summary for" topic))))))
+    (if-let [topic-agent (get @topics topic)]
+      (send topic-agent done-action config)
+      (warn "Trying to 'done' on topic that never published."))))

 (defn start-source
@@ -191,12 +215,13 @@
   (info "Starting websocket source with directory writer" directory-writer "and config" config)
   (let [uri (or uri (URI. (str "ws://" (. (InetAddress/getLocalHost) getHostName) ":" port)))
         stop-fn (atom nil)
-        config (assoc config :cache-size cache-size)
-        summaries (if (< 0 summary-ttl)
-                    (cache/ttl-cache-factory {} :ttl summary-ttl)
-                    {})
-        source (WebsocketSource. directory-writer stop-fn (atom true) (ref #{}) (atom {}) uri
-                                 config summary-fn (atom {}))
+        config (assoc config :cache-size cache-size :uri uri)
+        summaries (when summary-fn
+                    (if (< 0 summary-ttl)
+                      (cache/ttl-cache-factory {} :ttl summary-ttl)
+                      {}))
+        source (WebsocketSource. directory-writer stop-fn (atom true) (ref {}) config
+                                 (atom summaries))
         app (make-app source)
         wrapped-app (if wrap-fn (wrap-fn app) app)]
     (reset! stop-fn (http/run-server wrapped-app {:port port}))
@@ -207,15 +232,10 @@
   "Given the return value of `start-source`, this stops the Websocket
   server and removes every topic for this source from the directory
   service."
-  [{:keys [stop-fn open uri dirwriter topics config] :as source}]
+  [{:keys [stop-fn open dirwriter topics config] :as source}]
   (when @open
     (info "Stopping websocket source, using state" source)
     (reset! open false)
-    (@stop-fn :timeout 100)
-    (let [done-payload (:done-payload config)]
-      (dosync (doseq [topic @topics]
-                (when done-payload
-                  (debug "Sending done payload to" topic)
-                  (wamp/send-event! topic done-payload))
-                (debug "Unregistering" uri "for topic" topic "in directory service.")
-                (api/remove-source dirwriter topic uri))))))
+    (doseq [topic-agent (vals @topics)]
+      (send topic-agent done-action config))
+    (@stop-fn :timeout 100)))


Keep cue var scroll buttons white when pressed.

--- src/afterglow/controllers/ableton_push_2.clj
+++ src/afterglow/controllers/ableton_push_2.clj
@@ -1614,7 +1614,7 @@
                                      (captured-controls [this] #{note})
                                      (captured-notes [this] #{})
                                      (adjust-interface [this _]
-                                       (swap! (:next-top-pads controller) assoc (inc (* 2 x)) amber-color)
+                                       (swap! (:next-top-pads controller) assoc (inc (* 2 x)) white-color)
                                        true)
                                      (handle-control-change [this message]
                                        (when (and (= (:note message) note) (zero? (:velocity message)))


fix UI at home

fix UI at home

--- src/cljs/daveconservatoire/site/ui_dave.cljs
+++ src/cljs/daveconservatoire/site/ui_dave.cljs
@@ -38,17 +38,6 @@
               "Welcome to Dave Conservatoire")))))))

 (def hero (om/factory Hero))
-
-(om/defui ^:once Testcomp
-  Object
-  (render [this]
-    (let [{:keys []} (om/props this)]
-      (dom/div #js {:className "test"}
-        "my Div"))))
-
-(def testcomp (om/factory Testcomp))
-
-#_(declare footer)

 (om/defui ^:once Homeboxes
   Object
@@ -168,13 +157,13 @@
           (dom/div #js {:className "inner_content"}
             (dom/div #js {:className "pad30"})
             (dom/h1 #js {:className "title"} title)
-            (dom/h1 #js {:className "intro"} intro)))))))
+            (dom/h1 #js {:className "intro" :dangerouslySetInnerHTML #js {:__html intro}})))))))

 (def course-banner (om/factory CourseBanner))

 (om/defui ^:once HomeCourseTopic
   static om/IQuery
-  (query [_] [:topic/title :url/slug])
+  (query [_] [:db/id :topic/title :url/slug])

   static om/Ident
   (ident [_ props] (u/model-ident props))
@@ -183,15 +172,15 @@
   (render [this]
     (let [{:keys [topic/title url/slug]} (om/props this)]
       (dom/li #js {:className "span4", :style #js {"marginBottom" 5}}
-        (link {:className "btn btn-large btn-block dc-btn-yellow" ::r/handler ::r/topic ::r/params {::r/slug slug}}
+        (link {:className "btn btn-large btn-block dc-btn-yellow" ::r/handler ::r/topic ::r/params {::r/slug slug} :react-key "link"}
           (dom/h3 nil
             title))))))

-(def home-course-topic (om/factory HomeCourseTopic))
+(def home-course-topic (om/factory HomeCourseTopic {:keyfn :db/id}))

 (om/defui ^:once CourseWithTopics
   static om/IQuery
-  (query [_] [:course/title
+  (query [_] [:db/id :course/title :course/description
               {:course/topics (om/get-query HomeCourseTopic)}])

   static om/Ident
@@ -199,9 +188,9 @@

   Object
   (render [this]
-    (let [{:keys [course/title course/topics]} (om/props this)]
+    (let [{:keys [course/title course/topics course/description]} (om/props this)]
       (dom/div #js {}
-        (course-banner {:title title :intro "intro"})
+        (course-banner {:title title :intro description})
         (dom/div #js {:className "pad30"})
         (dom/div #js {:className "container wrapper"}
           (dom/div #js {:className "thumbnails tabbable"}
@@ -210,5 +199,5 @@

         (dom/div #js {:className "pad30"})))))

-(def course-with-topics (om/factory CourseWithTopics))
-
+(def course-with-topics (om/factory CourseWithTopics {:keyfn :db/id}))
+


fix tags style

fix tags style

--- src/cljs/re_form/inputs/tags_input_impl.cljs
+++ src/cljs/re_form/inputs/tags_input_impl.cljs
@@ -22,16 +22,14 @@
    [:.tag
     {:border border
      :position :relative
-     :display :inline-block
+     :display :inline-flex
+     :align-items :center
      :padding {:left (u/px-div w 2)
-               :right (u/px w)}
+               :right (u/px 2)}
      :margin-right (u/px w)}
     [:.cross
-     {:position :absolute
-      :cursor :pointer
-      :font-size (u/px w)
-      :top 0
-      :right 0}]]])
+     {:cursor :pointer
+      :font-size (u/px h)}]]])

 (defn tag [label on-delete]
   [:span.tag label