More cleanup

More cleanup

--- src/angelic/search/implicit/dash_astar.clj
+++ src/angelic/search/implicit/dash_astar.clj
@@ -30,6 +30,8 @@
 ;;;;; Pessimistic
 ;; TODO: add pessimistic variants (shared primitives)
 ;; TODO: bounding pressimistic descritpions (assume consistency for now)
+;; TODO: hook up pess/opt with same input set?
+;; TODO: pruning.

 ;;;;; Tree construction
 ;; TODO: smarter output-collector (semantic) -- problems here though.
@@ -128,6 +130,8 @@

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Protocol  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+;; Here, inputs and outputs are [:opt/:pess actual-set] pairs.
+
 (defprotocol Subproblem
   (sp-name             [s])
   (input-set           [s])
@@ -171,18 +175,18 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Generic Trait  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 ;; Canonical SPs are Atomic and Pair; wrappers use TS of inner SP.
-(defn canonicalize [sp] (ts-sp (sp-ts sp)))
-(defn canonical? [sp] (identical? sp (ts-sp (sp-ts sp))))
-
-(traits/deftrait simple-subproblem
-  [nm inp-set wrapped-ts eval!-fn ri-fn]
-  [                 ts-atom          (atom wrapped-ts)
-   ^PubSubHub       output-ps        (make-pubsubhub)
-   ^PubSubHub       child-ps         (make-pubsubhub)
-   ^PubSubHub       all-child-ps     (make-pubsubhub) ;; For sub-following -- remove if no help.
-   ^IdentityHashMap subsuming-sp-set (IdentityHashMap.)]
-  [summaries/simple-cached-node]
-  Subproblem
+(defn- canonicalize [sp] (ts-sp (sp-ts sp)))
+(defn- canonical? [sp] (identical? sp (ts-sp (sp-ts sp))))
+
+(defn- make-subproblem [nm inp-set wrapped-ts eval!-fn ri-fn summary-fn]
+ (let [                 ts-atom          (atom wrapped-ts)
+       ^PubSubHub       output-ps        (make-pubsubhub)
+       ^PubSubHub       child-ps         (make-pubsubhub)
+       ^PubSubHub       all-child-ps     (make-pubsubhub) ;; For sub-following -- remove if no help.
+       ^IdentityHashMap subsuming-sp-set (IdentityHashMap.)]
+  (traits/reify-traits [summaries/simple-cached-node]
+   summaries/Summarizable (summarize [s] (summary-fn s))
+   Subproblem
   (sp-name             [s] nm)
   (input-set           [s] inp-set)
   (sp-ts               [s] (or @ts-atom (reset! ts-atom (make-tree-summarizer s))))
@@ -215,16 +219,14 @@
       (schedule-increase! (sp-ts s)))
     (publish! child-ps c))

-  (add-all-child-watcher! [s w] (subscribe! all-child-ps w))
-
-
+  (add-all-child-watcher! [s w] (subscribe! all-child-ps w))
   (subsuming-sps [s] (keys subsuming-sp-set))
   (add-subsuming-sp! [s subsuming-sp]
     (util/assert-is (canonical? s))
     (util/assert-is (canonical? subsuming-sp))
     (util/assert-is (= nm (sp-name subsuming-sp)))
-    (util/assert-is (not (identical? s subsuming-sp)))
-    (when-not (.containsKey subsuming-sp-set subsuming-sp)
+    (when-not (or (identical? s subsuming-sp)
+                  (.containsKey subsuming-sp-set subsuming-sp))
       (.put subsuming-sp-set subsuming-sp true)
       (schedule-subsumption! (sp-ts subsuming-sp) (sp-ts s))
       (when *propagate-subsumption*
@@ -235,16 +237,17 @@
               (add-all-child-watcher! subsuming-sp
                 (fn [subsuming-child]
                   (let [can-subsuming-child (canonicalize subsuming-child)]
-                    (when (and (not (identical? can-child can-subsuming-child))
-                               (= (sp-name can-child) (sp-name can-subsuming-child)))
-                      #_(print ".")
-                      #_ (println [s subsuming-sp] "==>" [child subsuming-child])
+                    (when (= (sp-name can-child) (sp-name can-subsuming-child))
                       (when (add-subsuming-sp! can-child can-subsuming-child)
                         #_ (println [s subsuming-sp] "==>" [child subsuming-child])
                         )))))))))
       true))

-  (refine-input    [s ni] (let [ret (ri-fn s ni)] (util/assert-is (= nm (sp-name ret))) ret)))
+  (refine-input    [s ni]
+    (let [ret (ri-fn s ni)]
+      (util/assert-is (= nm (sp-name ret)))
+      (when (canonical? s) (add-subsuming-sp! ret s))
+      ret)))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Utils  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -266,26 +269,15 @@

 (defn make-wrapped-subproblem [nm inp-set prefix-set inner-sp output-wrap child-watch ri-fn]
   (util/assert-is (contains? prefix-set (first (sp-name inner-sp))))
-  (let [ret (traits/reify-traits
-             [summaries/or-summarizable
-              (simple-subproblem nm inp-set (sp-ts inner-sp) noeval ri-fn)])]
+  (let [ret (make-subproblem nm inp-set (sp-ts inner-sp) noeval ri-fn summaries/or-summary)]
     (connect-and-watch! ret inner-sp
       (fn [o] (set-output-set! ret (output-wrap o)))
       (fn [inner-child] (child-watch ret inner-child)))
     ret))

-
 ;; Note: summary-fn should take subsuming-bound into account.
 (defn- make-simple-subproblem [nm inp-set ri-fn eval-fn summary-fn]
-  (traits/reify-traits
-   [(simple-subproblem
-     nm inp-set nil eval-fn
-     (fn [s ni] ;; Note ni may have different context.
-       (if (= ni inp-set) s
-         (let [subsumed-sp (ri-fn s ni)]
-           (add-subsuming-sp! subsumed-sp s)
-           subsumed-sp))))]
-   summaries/Summarizable (summarize [s] (summary-fn s))))
+  (make-subproblem nm inp-set nil eval-fn (fn [s ni] (if (= ni inp-set) s (ri-fn s ni))) summary-fn))

 ;; Get a fresh subproblem with the given name and input.
 (defmulti get-subproblem (fn get-subproblem-dispatch [nm inp] (first nm)))


Implemented the ^:clj tag for entity properties.

--- src/appengine_magic/services/datastore.clj
+++ src/appengine_magic/services/datastore.clj
@@ -109,7 +109,15 @@
    field becomes the key. If a record has no :key metadata tags, then a key is
    automatically generated for it. In either case, the key becomes part of the
    entity's metadata. Entity retrieval operations must set the :key metadata on
-   returned entity records."
+   returned entity records.
+
+   In addition, any field may be marked with a ^:clj metadata tag. This tag
+   means that the field's value goes through prn-str on its way out and through
+   read-string on its way in. It allows automatic serialization for some types
+   not directly supported by the datastore."
+  (get-clj-properties [this]
+    "Returns a set of all properties which pass through the Clojure reader on
+     their way in and out of the datastore.")
   (get-key-object [this] [this parent]
     "Returns nil if no tag is specified in the record definition, and no :key
      metadata exists. Otherwise returns a Key object. Specify optional entity
@@ -189,12 +197,15 @@

 (defn get-entity-object-helper [entity-record kind]
   (let [key-object (get-key-object entity-record)
+        clj-properties (get-clj-properties entity-record)
         entity (if key-object
                    (Entity. key-object)
                    (Entity. kind))]
     (doseq [[property-kw value] entity-record]
       (let [property-name (.substring (str property-kw) 1)]
-        (.setProperty entity property-name (coerce-clojure-type value))))
+        (.setProperty entity property-name (if (contains? clj-properties property-kw)
+                                               (Text. (prn-str value))
+                                               (coerce-clojure-type value)))))
     entity))

@@ -282,11 +293,13 @@
     fetch-options-object))

-(defn- entity->properties [raw-properties]
+(defn- entity->properties [raw-properties clj-properties]
   (reduce (fn [m [k v]]
-            (assoc m
-              (keyword k)
-              (coerce-java-type v)))
+            (let [k (keyword k)]
+             (assoc m k (if (contains? clj-properties k)
+                            (binding [*read-eval* false]
+                              (read-string (.getValue v)))
+                            (coerce-java-type v)))))
           {}
           raw-properties))

@@ -322,7 +335,9 @@
               model-record (record entity-record-type)]
           (map #(let [v (.getValue %)]
                   (with-meta
-                    (merge model-record (entity->properties (.getProperties v)))
+                    (merge model-record
+                           (entity->properties (.getProperties v)
+                                               (get-clj-properties model-record)))
                     {:key (.getKey v)}))
                entities))
         ;; handles singleton values
@@ -331,7 +346,8 @@
               raw-properties (into {} (.getProperties entity))
               entity-record (record entity-record-type)]
           (with-meta
-            (merge entity-record (entity->properties raw-properties))
+            (merge entity-record (entity->properties raw-properties
+                                                     (get-clj-properties entity-record)))
             {:key (.getKey entity)})))))

@@ -359,9 +375,16 @@
                      {:keys [kind]
                       :or {kind (unqualified-name name)}}]
   (let [key-property-name (first (filter #(= (:tag (meta %)) :key) properties))
-        key-property (if key-property-name (keyword (str key-property-name)) nil)]
+        key-property (if key-property-name (keyword (str key-property-name)) nil)
+        ;; XXX: The keyword and str composition below works
+        ;; around a weird Clojure bug (see
+        ;; http://groups.google.com/group/clojure-dev/browse_thread/thread/655f6e7d1b312f17).
+        clj-properties (set (map (comp keyword str)
+                                 (filter #(= (:tag (meta %)) :clj) properties)))]
     `(defrecord ~name ~properties
        EntityProtocol
+       (get-clj-properties [this#]
+         ~clj-properties)
        (get-key-object [this#]
          (get-key-object-helper this# ~key-property ~kind nil))
        (get-key-object [this# parent#]
@@ -426,7 +449,9 @@
                                        ;; unknown type; just use a basic EntityProtocol
                                        (EntityBase.))]
                   (map #(with-meta
-                          (merge model-record (entity->properties (.getProperties %)))
+                          (merge model-record
+                                 (entity->properties (.getProperties %)
+                                                     (get-clj-properties model-record)))
                           {:key (.getKey %)})
                        results)))))


better resource handling

better resource handling

--- src/clj/work_sessions/core.clj
+++ src/clj/work_sessions/core.clj
@@ -118,13 +118,14 @@
   ;;      request
   ;;      (what-is-my-ip request))

-  (GET "/js/*" _
-       {:status 404})
+  ;; (GET "/js/*" _
+  ;;      {:status 404})

   (resources "/css/*")
+  (resources "/js/*")

-  #_(GET "/*" _
+  (GET "/*" _
     {:status 200
      :headers {"Content-Type" "text/html; charset=utf-8"}
      :body (io/input-stream (io/resource "public/index.html"))})


Use gzip compression

Use gzip compression

--- src/clj_crud/system/server.clj
+++ src/clj_crud/system/server.clj
@@ -1,15 +1,23 @@
 (ns clj-crud.system.server
   (:require [clojure.tools.logging :refer [info]]
             [com.stuartsierra.component :as component]
-            [ring.adapter.jetty :as jetty]))
+            [ring.adapter.jetty :as jetty])
+  (:import [org.eclipse.jetty.server.handler GzipHandler]))

+;; h/t http://cemerick.com/2011/04/22/adding-gzip-compression-to-a-clojure-webapp-in-30-seconds/#comment-2307
+(defn- configurator [server]
+  (.setHandler server
+               (doto (new GzipHandler)
+                 (.setMimeTypes "text/html,text/plain,text/xml,application/xhtml+xml,text/css,application/javascript,text/javascript,image/svg+xml,application/json,application/clojure")
+                 (.setHandler (.getHandler server)))))

 (defrecord Jetty [port handler]
   component/Lifecycle
   (start [component]
          (info "Starting jetty on port: " port)
          (assoc component :jetty (jetty/run-jetty (:app handler) {:port port
-                                                                  :join? false})))
+                                                                  :join? false
+                                                                  :configurator configurator})))
   (stop [component]
         (info "Stopping jetty")
         (when-let [jetty (:jetty component)]


sort bookmarks by date

sort bookmarks by date

--- src/cljs/lesezeichen/core.cljs
+++ src/cljs/lesezeichen/core.cljs
@@ -118,7 +118,7 @@
                        (listen :on-change #(do
                                              (println (:url-input-text state))
                                              (handle-text-change % owner :url-input-text))))
-   [:#url-list] (content (map #(url %) (get-bookmarks app)))
+   [:#url-list] (content (map #(url %) (sort-by :ts > (get-bookmarks app))))
    [:#bookmark-btn] (listen :on-click (fn [e]
                                         (do
                                           (if (clojure.string/blank? (:url-input-text state))
@@ -173,25 +173,7 @@

-
 (comment
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

   (-> @stage :volatile :peer deref :volatile :store :state deref)


Fix remaining server initiate pk-triad check

This problem was a mis-namespaced keyword.

Deleted the debug println calls I used to nail down the problems.

--- src/clojure/frereth_cp/server/initiate.clj
+++ src/clojure/frereth_cp/server/initiate.clj
@@ -299,7 +299,6 @@
          ^ByteBuf inner-vouch-buffer ::crypto/unboxed} (decrypt-cookie log-state
                                                                        cookie-cutter
                                                                        hello-cookie)]
-    (println "decrypt-cookie returned:" inner-vouch-buffer)
     (if inner-vouch-buffer
       ;; Yet again: Converting this to a ByteBuf was a mistake
       (let [inner-vouch-bytes (byte-array (.readableBytes inner-vouch-buffer))]
@@ -514,14 +513,12 @@
          inner-pk ::specs/public-short} (unbox-innermost-key log-state
                                                              my-keys
                                                              client-message-box)]
-    (println "Mark J. inner-pk:"
-             inner-pk
-             "log-state:"
-             (dissoc log-state ::log/entries))
     (if inner-pk
       (let [matched? (b-t/bytes= client-short-pk inner-pk)]
         {::log/state (if matched?
-                       log-state
+                       (log/debug log-state
+                                  ::client-public-key-triad-matches?
+                                  "Matched.")
                        (log/warn log-state
                                  ::client-public-key-triad-matches?
                                  "Inner pk doesn't match outer"
@@ -676,7 +673,6 @@
          :as cookie-extraction} (extract-cookie log-state
                                                 cookie-cutter
                                                 initiate)]
-    (println "Mark C. cookie:" cookie)
     (if cookie
       ;; It included a secret cookie that we generated sometime within the
       ;; past couple of minutes.
@@ -689,10 +685,6 @@
                                                                                packet
                                                                                cookie
                                                                                initiate)]
-        (println "Mark D. client-short-pk:"
-                 client-short-pk
-                 "\nclient-short<->server-short:"
-                 client-short<->server-short)
         (if client-short-pk
           (if client-short<->server-short
             (try
@@ -701,7 +693,6 @@
                       :as client-message-box} ::K/initiate-client-vouch-wrapper} (open-client-crypto-box log-state
                                                                                initiate
                                                                                client-short<->server-short)]
-                (println "Mark E. client-message-box:" client-message-box)
                 (if client-message-box
                   (let [client-long-pk (bytes client-long-pk)
                         active-client (assoc-in active-client
@@ -713,21 +704,18 @@
                                             ;; try to extract the inner hidden key
                                             {::message-box-keys (keys client-message-box)
                                              ::client-public-long-key (b-t/->string client-long-pk)})]
-                    (println "Mark F. client-long-pk" client-long-pk)
                     (try
                       (let [{:keys [::specs/matched?]
                              log-state ::log/state} (validate-server-name log-state
                                                                           my-keys
                                                                           client-message-box)]
-                        (println "Mark I. log-state:" (dissoc log-state ::log/entries))
                         (if matched?
                           ;; This takes us down to line 381
                           (let [{log-state ::log/state
-                                 :keys [::matched?]} (client-public-key-triad-matches? log-state
-                                                                                my-keys
-                                                                                client-short-pk
-                                                                                client-message-box)]
-                            (println "Mark G. matched?" matched?)
+                                 :keys [::specs/matched?]} (client-public-key-triad-matches? log-state
+                                                                                my-keys
+                                                                                client-short-pk
+                                                                                client-message-box)]
                             {::log/state log-state
                              ::state/current-client (when matched?
                                                       active-client)})
@@ -774,7 +762,6 @@
     :as state}
    packet
    initiate]
-  (println "Mark A")
   (let [{log-state-2 ::log/state
          active-client ::state/current-client
          :as built} (build-new-client {::state/cookie-cutter cookie-cutter
@@ -789,7 +776,6 @@
                               (str "Log state disappeared"
                                    "  trying to build-new-client")
                               {::built built}))]
-    (println "Mark B. active-client: " active-client)
     (if active-client
       (do-fork-child! (-> state
                           (select-keys [::state/child-spawner!])


Message queue: bring dry-run logic into `dequeue` fn (perf+simplicity)

--- src/taoensso/carmine/message_queue.clj
+++ src/taoensso/carmine/message_queue.clj
@@ -127,6 +127,7 @@
       if (not mid) or (mid == 'end-of-circle') then
         -- Set queue-wide polling backoff flag
         redis.call('psetex', _:qk-eoq-backoff, _:eoq-backoff-ms, 'true')
+        redis.call('incr', _:qk-ndry-runs)
         return 'eoq-backoff'
       elseif redis.call('sismember', _:qk-recently-done, mid) == 1 then -- GC
         redis.call('lrem', _:qk-mid-circle, 1, mid) -- Efficient here
@@ -135,6 +136,8 @@
         redis.call('hdel', _:qk-locks,         mid)
         return nil
       end
+
+      redis.call('set', _:qk-ndry-runs, 0)

       local now         = tonumber(_:now)
       local lock_exp    = tonumber(redis.call('hget', _:qk-locks,    mid) or 0)
@@ -164,7 +167,8 @@
     :qk-retry-counts  (qkey qname "retry-counts")
     :qk-mid-circle    (qkey qname "mid-circle")
     :qk-recently-done (qkey qname "recently-done")
-    :qk-eoq-backoff   (qkey qname "eoq-backoff?")}
+    :qk-eoq-backoff   (qkey qname "eoq-backoff?")
+    :qk-ndry-runs     (qkey qname "ndry-runs")}
    {:now              (System/currentTimeMillis)
     :lock-ms          lock-ms
     :eoq-backoff-ms   eoq-backoff-ms}))
@@ -199,18 +203,22 @@
                       (done mid)
                       (timbre/error
                        (if throwable throwable (Exception. ":error handler response"))
-                       (str "Error handling queue message: " qname "\n" poll-reply)))
-              ndruns #(wcar conn (case % :reset (car/set  (qk "ndry-runs") 0)
-                                         :inc   (car/incr (qk "ndry-runs"))))]
-
-          (ndruns :reset)
+                       (str "Error handling queue message: " qname "\n" poll-reply)))]
+
           (while @running?
             (try
-              (let [ndruns* (ndruns :inc) ; Speculative
+              (let [[ndruns mid-circle-len] (wcar conn (car/get  (qk "ndry-runs"))
+                                                       (car/llen (qk "mid-circle")))
+                    ndruns (or ndruns 0)
                     eoq-backoff-ms* (if (fn? eoq-backoff-ms)
-                                      (eoq-backoff-ms ndruns*)
+                                      (eoq-backoff-ms (inc ndruns))
                                       eoq-backoff-ms)
                     opts* (assoc opts :eoq-backoff-ms eoq-backoff-ms*)]
+
+                ;; TODO For optional logging fn
+                ;; {:ndry-runs      ndruns
+                ;;  :mid-circle-len mid-circle-len}
+
                 (when-let [[mid mcontent attempt :as poll-reply]
                            (wcar conn (dequeue qname opts*))]
                   (if (= poll-reply "eoq-backoff")
@@ -221,7 +229,6 @@
                                             (catch Throwable t {:status :error
                                                                 :throwable t}))]
                             (when (map? result) result))]
-                      (ndruns :reset)
                       (case status
                         :success (done mid)
                         :retry   (retry mid backoff-ms)


Update documentation for the resource query API

--- src/com/puppetlabs/cmdb/query/resource.clj
+++ src/com/puppetlabs/cmdb/query/resource.clj
@@ -1,3 +1,64 @@
+;; ## Request Format
+;;
+;; The single available route is `/resources?query=<query>`. The `query`
+;; parameter is a JSON array of query predicates in prefix form.
+;;
+;; ### Predicates
+;;
+;; #### =
+;;
+;; Resources tagged with "foo" (irrespective of other tags):
+;;
+;;     ["=" "tag" "foo"]
+;;
+;; Resources for the node "foo.example.com":
+;;
+;;     ["=" ["node" "<this value is ignored>"] "foo.example.com"]
+;;
+;; Resources whose owner parameter is "joe":
+;;
+;;     ["=" ["parameter" "owner"] "joe"]
+;;
+;; Resources whose title is "/etc/hosts"; "title" may be replaced with any legal column of the `resources` table, to query against that column:
+;;
+;;     ["=" "title" "/etc/hosts"]
+;;
+;; #### and
+;;
+;; Resources whose owner is "joe" and group is "people":
+;;
+;;     ["and" ["=" ["parameter" "owner"] "joe"]
+;;            ["=" ["parameter" "group"] "people"]]
+;;
+;; #### or
+;;
+;; Resources whose owner is "joe" or "jim":
+;;
+;;     ["or" ["=" ["parameter" "owner"] "joe"]
+;;           ["=" ["parameter" "owner"] "jim"]]
+;;
+;; #### not
+;;
+;; Resources whose owner is not "joe" AND is not "jim":
+;;
+;;     ["not" ["=" ["parameter" "owner"] "joe"]
+;;            ["=" ["parameter" "owner"] "jim"]]
+;;
+;; ## Response Format
+;;
+;; The response is a list of resource objects, returned in JSON form. Each
+;; resource object is a map of the following form:
+;;
+;;     {:hash       "the resource's unique hash"
+;;      :type       "File"
+;;      :title      "/etc/hosts"
+;;      :exported   "true"
+;;      :sourcefile "/etc/puppet/manifests/site.pp"
+;;      :sourceline "1"
+;;      :parameters {<parameter> <value>
+;;                   <parameter> <value>
+;;                   ...}}
+
 (ns com.puppetlabs.cmdb.query.resource
   (:require [com.puppetlabs.utils :as utils]
             [clojure.contrib.logging :as log]
@@ -21,7 +82,7 @@

 (defmulti compile-query->sql
-  "Recursively compile a query into a collection of SQL operations"
+  "Recursively compile a query into a collection of SQL operations."
   (fn [db query]
     (string/lower-case (first query))))

@@ -64,7 +125,7 @@
   (let [hashes (sql/with-connection db
                    (->> (query-to-vec query)
                         (map :hash)))]
-    ; We have to special-case this or we get invalid queries generated later :(
+    ;; We have to special-case this or we get invalid queries generated later
     (if (empty? hashes)
       []
       (let [resources (future
@@ -90,12 +151,11 @@

 (defn resource-list-as-json
   "Fetch a list of resources from the database, formatting them as a
-JSON array, and returning them as the body of the request."
+JSON array, and returning them as the body of the response."
   [request graphdata]
   (let [db (get-in request [:globals :scf-db])]
     (json/generate-string (or (vec (query-resources db (:query graphdata)))
                               []))))
-

 (defhandler resource-list-handler
   :allowed-methods        (constantly #{:get})
@@ -103,14 +163,11 @@
   :resource-exists?       (constantly true)
   :content-types-provided (constantly {resource-list-c-t resource-list-as-json}))

-
-
-
-
-
-
-;;;; The SQL query compiler implementation.
+;; ## SQL query compiler
 (defmethod compile-query->sql "="
+  "Compile an '=' predicate, the basic atom of a resource query. This will
+produce a query that selects a set of hashes matching the predicate, which
+can then be combined with connectives to build complex queries."
   [db [op path value :as term]]
   (let [count (count term)]
     (if (not (= 3 count))
@@ -166,11 +223,15 @@
       (apply vector (format "(%s)" sql) params)))

 (defn- alias-subqueries
+  "Produce distinct aliases for a list of queries, suitable for a join
+operation."
   [queries]
   (let [ids (range (count queries))]
     (map #(format "%s resources_%d" %1 %2) queries ids)))

 (defmethod compile-query->sql "and"
+  "Join a set of predicates together with an 'and' relationship, performing an
+intersection (via natural join)."
   [db [op & terms]]
   {:pre [(every? vector? terms)]
    :post [(string? (first %))
@@ -187,6 +248,8 @@
     (apply vector query params)))

 (defmethod compile-query->sql "or"
+  "Join a set of predicates together with an 'or' relationship, performing a
+union operation."
   [db [op & terms]]
   {:pre [(every? vector? terms)]
    :post [(string? (first %))
@@ -201,6 +264,8 @@
     (apply vector query params)))

 (defmethod compile-query->sql "not"
+  "Join a set of predicates together with a 'not' relationship, performing a
+set difference. This will reject resources matching _any_ child predicate."
   [db [op & terms]]
   {:pre [(every? vector? terms)]
    :post [(string? (first %))


make a map spanning line length with index->stuff to play

--- ohack/src/ohack/core.clj
+++ ohack/src/ohack/core.clj
@@ -225,7 +225,12 @@
     ;; now we will have a seq of [index value] pairs
     (map
      (fn [m] [(:start m) (Integer/parseInt (:group m))])
-     (re-seq-pos #"\d+" tab-string))))
+     (re-seq-pos #"\d+" tab-string))
+    ;; construct a hashmap of index -> stuff to play
+    ;; spanning the length of the line
+    (zipmap (range (count tab-string)) (cycle [nil]))
+
+    ))

 ;; first, filter out all lines that don't look like guitar lines
 ;; use map-index because we need to keep ordering information


update imports

update imports

--- ohack/src/ohack/core.clj
+++ ohack/src/ohack/core.clj
@@ -1,8 +1,10 @@
 (ns ohack.core
   (:use [overtone.live]
         [overtone.inst.piano]
-        [overtone.inst.sampled-piano])
-  (:require [overtone.inst.synth :as synth]))
+        [overtone.inst.sampled-piano]
+        [overtone.synth.stringed])
+  (:require [overtone.inst.synth :as synth]
+            [clojure.string :as s]))

 ;; run M-x cider-jack-in to get started
 ;;


CMR-2412 Refactors deleting access groups

--- metadata-db-app/src/cmr/metadata_db/data/oracle/providers.clj
+++ metadata-db-app/src/cmr/metadata_db/data/oracle/providers.clj
@@ -41,13 +41,7 @@
     ;; Access Group deletion is the same between all provider types. This does not remove the record
     ;; from search. access-control-app listens for :provider-delete messages and handles deleting the
     ;; relevant records from Elastic.
-    (sh/force-delete-concept-by-params db
-                                       ;; We need to pretend that the provider is small for
-                                       ;; force-delete-concept-by-params to include provider-id
-                                       ;; in the query.
-                                       (assoc provider :small true)
-                                       {:concept-type :access-group
-                                        :provider-id provider-id})
+    (j/delete! db (ct/get-table-name provider :access-group) ["provider_id = ?" provider-id])
     (if small
       (delete-small-provider-concepts db provider)
       (ct/delete-provider-concept-tables db provider))


reduce logging output

reduce logging output

--- dada-core/src/main/clojure/org/dada/core/jms/POJOInvoker.clj
+++ dada-core/src/main/clojure/org/dada/core/jms/POJOInvoker.clj
@@ -28,7 +28,7 @@
 	;; TODO - handle Exceptions later
 	#^Method method (.getMethod mapper (.getMethodIndex invocation))
 	args (.getArgs invocation)
-	dummy (println "POJO INCOMING:" (str "sessionManager." (.getName method) "(" (apply str (interpose ", " args)) ")"))
+	;;dummy (println "POJO INCOMING:" (str "sessionManager." (.getName method) "(" (apply str (interpose ", " args)) ")"))
 	results (.invoke method target args) ;TODO: introspection - slow
 	reply-to (.getJMSReplyTo request)
 	correlation-id (.getJMSCorrelationID request)]
@@ -36,7 +36,7 @@
       (let [#^ObjectMessage response (.createObjectMessage session)]
 	(.setJMSCorrelationID response correlation-id)
 	(.setObject response (Results. false results))
-	(println "POJO OUTGOING:" results)
+	;;(println "POJO OUTGOING:" results)
 	(.send producer reply-to response)
 	))
     ))


Make subheader a bit DRYer

Make subheader a bit DRYer

--- src-cljs/frontend/components/header.cljs
+++ src-cljs/frontend/components/header.cljs
@@ -106,6 +106,20 @@
 (defn maybe-active [current goal]
   {:class (when (= current goal)
             "active")})
+
+(defn outer-subheader [nav-maps nav-point]
+  (map
+   #(when (-> %
+              keys
+              set
+              (contains? nav-point))
+      [:div.navbar.navbar-default.navbar-static-top.subnav
+       [:div.container-fluid
+        [:ul.nav.navbar-nav
+         (for [[point {:keys [path title]}] %]
+           [:li (maybe-active nav-point point)
+            [:a {:href path} title]])]]])
+   nav-maps))

 (defn outer-header [app owner]
   (reify
@@ -173,7 +187,9 @@
               [:a {:href "/docs"} "Documentation"]]
              [:li {:class (when (contains? #{:about
                                              :contact
-                                             :team}
+                                             :team
+                                             :jobs
+                                             :press}
                                            nav-point)
                             "active")}
               [:a {:href "/about"} "About Us"]]
@@ -194,30 +210,24 @@
                                        :on-click #(raise! owner [:track-external-link-clicked {:path (auth-url) :event "login_click" :properties {:source "header sign-in" :url js/window.location.pathname}}])
                                        :title "Sign in with Github"}
                   "Sign in"]]]))]]
-          (when (contains? #{:mobile :ios :android} nav-point)
-            [:div.navbar.navbar-default.navbar-static-top.subnav
-             [:div.container-fluid
-              [:ul.nav.navbar-nav
-               [:li (maybe-active nav-point :mobile)
-                [:a {:href "/mobile"} "Mobile"]]
-               [:li (maybe-active nav-point :ios)
-                [:a {:href "/mobile/ios"} "iOS"]]
-               [:li (maybe-active nav-point :android)
-                [:a {:href "/mobile/android"} "Android"]]]]])
-          (when (contains? #{:about :team :contact :jobs :press} nav-point)
-            [:div.navbar.navbar-default.navbar-static-top.subnav
-             [:div.container-fluid
-              [:ul.nav.navbar-nav
-               [:li (maybe-active nav-point :about)
-                [:a {:href "/about"} "Overview"]]
-               [:li (maybe-active nav-point :team)
-                [:a {:href "/about/team"} "Team"]]
-               [:li (maybe-active nav-point :contact)
-                [:a {:href "/contact"} "Contact Us"]]
-               [:li (maybe-active nav-point :jobs)
-                [:a {:href "/jobs"} "Jobs"]]
-               [:li (maybe-active nav-point :press)
-                [:a {:href "/press"} "Press"]]]]])])))))
+          (outer-subheader
+           [{:mobile {:path "/mobile"
+                       :title "Mobile"}
+              :ios {:path "/mobile/ios"
+                    :title "iOS"}
+              :android {:path "/mobile/android"
+                        :title "Android"}}
+            {:about {:path "/about"
+                     :title "Overview"}
+             :team {:path "/about/team"
+                    :title "Team"}
+             :contact {:path "/contact"
+                       :title "Contact Us"}
+             :jobs {:path "/jobs"
+                    :title "Jobs"}
+             :press {:path "/press"
+                     :title "Press"}}]
+           nav-point)])))))

 (defn inner-header [app owner]
   (reify


escape to stop editing description

escape to stop editing description

--- src-cljs/frontend/components/issues.cljs
+++ src-cljs/frontend/components/issues.cljs
@@ -151,12 +151,12 @@
       (let [{:keys [issue-db cust cast!]} (om/get-shared owner)
             editable? (= (:cust/email cust) (:issue/author issue))
             editing? (and editable? (om/get-state owner :editing?))
+            clear-form #(om/update-state! owner (fn [s] (assoc s :issue-description nil :editing? false)))
             submit #(do (utils/stop-event %)
                         (when issue-description
                           (d/transact! issue-db [{:db/id (:db/id issue)
                                                   :issue/description issue-description}]))
-                        (om/set-state! owner :issue-description nil)
-                        (om/set-state! owner :editing? false))]
+                        (clear-form))]
         (html
          (if editing?
            [:form.issue-description-form {:on-submit submit}
@@ -165,6 +165,9 @@
                          :ref "description-input"
                          :value (or issue-description (:issue/description issue ""))
                          :required "true"
+                         :on-key-down #(if (= "Escape" (.-key %))
+                                         (clear-form)
+                                         true)
                          :on-change #(om/set-state! owner :issue-description (.. % -target -value))
                          :on-blur submit}]
              [:label {:data-label "Description"


+(defonce regular-future-generate-patterns)

--- src/babel/italiano/morphology/verbs.cljc
+++ src/babel/italiano/morphology/verbs.cljc
@@ -100,6 +100,55 @@
      }

     ]))
+
+(defn do-replace-on [infinitive patterns]
+  (if (not (empty? patterns))
+    (let [[from to] patterns]
+      (if (re-find from infinitive)
+        (cons (string/replace infinitive from to)
+              (do-replace-on infinitive (rest (rest patterns))))
+        (do-replace-on infinitive (rest (rest patterns)))))))
+
+;; TODO: unify with regular-patterns-future-tense (below).
+(defonce regular-future-generate-patterns
+  [
+   {:u {:agr {:person :1st
+              :number :sing}
+        :infl :future}
+    :g [#"^(.*)[ae]re$" "$1erò" ;; parlare,ricevere
+        #"^(.*)ire$"    "$1irò" ;; dormire
+        ]}
+   {:u {:agr {:person :2nd
+              :number :sing}
+        :infl :future}
+    :g [#"^(.*)[ae]re$" "$1erai" ;; parlare,ricevere
+        #"^(.*)ire$"    "$1irai" ;; dormire
+        ]}
+   {:u {:agr {:person :3rd
+              :number :sing}
+        :infl :future}
+    :g [#"^(.*)[ae]re$" "$1erà" ;; parlare,ricevere
+        #"^(.*)ire$"    "$1irà" ;; dormire
+        ]}
+
+   {:u {:agr {:person :1st
+              :number :plur}
+        :infl :future}
+    :g [#"^(.*)[ae]re$" "$1eremo" ;; parlare => parleremo
+        #"^(.*)ire$"    "$1iremo" ;; finire => finiremo
+        ]}
+   {:u {:agr {:person :2nd
+              :number :plur}
+        :infl :future}
+    :g [#"^(.*)[ae]re$" "$1erete" ;; parlare => parlerete
+        #"^(.*)ire$"    "$1irete" ;; finire => finiremo
+        ]}
+   {:u {:agr {:person :3rd
+              :number :plur}
+        :infl :future}
+    :g [#"^(.*)[ae]re$" "$1eranno" ;; parlare => parleranno
+        #"^(.*)ire$"    "$1iranno" ;; finire => finiranno
+        ]}])

 (defonce replace-patterns-future-tense
   (expand-replace-patterns
@@ -1148,39 +1197,13 @@
   (and (= (get-in word [:infl]) :future)
        (get-in word [:italiano])))

-(defn regular-future
-  "regular future"
-  [word]
-  (let [infinitive (get-in word [:italiano])
-        ;; e.g.: lavarsi => lavare
-        infinitive (if (re-find #"[aei]rsi$" infinitive)
-                     (string/replace infinitive #"si$" "e")
-                     infinitive)
-        person (get-in word [:agr :person])
-        number (get-in word [:agr :number])
-        drop-e (get-in word [:italiano :drop-e] false)
-        stem (stem-for-future infinitive drop-e)]
-    (cond
-      (and (= person :1st) (= number :sing))
-      (str stem "ò")
-
-      (and (= person :2nd) (= number :sing))
-      (str stem "ai")
-
-      (and (= person :3rd) (= number :sing))
-      (str stem "à")
-
-      (and (= person :1st) (= number :plur))
-      (str stem "emo")
-
-      (and (= person :2nd) (= number :plur))
-      (str stem "ete")
-
-      (and (= person :3rd) (= number :plur))
-      (str stem "anno")
-
-      :else
-      (get-in word [:italiano]))))
+(defn regular-future [word]
+  (let [unifying-patterns
+        (remove nil? (mapcat #(if (not (= :fail (unify (:u %) word)))
+                                (:g %))
+                             regular-future-generate-patterns))
+        infinitive (get-in word [:italiano])]
+    (first (remove nil? (do-replace-on infinitive unifying-patterns)))))

 (defn regular-conditional-with-future-stem? [word]
   ;; regular inflection of conditional with :future-stem


more dead code removal

more dead code removal

--- src/babel/italiano/morphology/verbs.cljc
+++ src/babel/italiano/morphology/verbs.cljc
@@ -536,12 +536,7 @@
    (map? (get-in word '(:future)))))

 (defn irregular-future [word]
-  (let [infinitive (get-in word '(:italiano)) ;; future irregular
-        ;; e.g.: lavarsi => lavare
-        infinitive (if (re-find #"[aei]rsi$" infinitive)
-                     (string/replace infinitive #"si$" "e")
-                     infinitive)
-        person (get-in word '(:agr :person))
+  (let [person (get-in word '(:agr :person))
         number (get-in word '(:agr :number))]
     (cond
       (and (= person :1st) (= number :sing))


fix typo

fix typo

--- src/babel/italiano/morphology/verbs.cljc
+++ src/babel/italiano/morphology/verbs.cljc
@@ -1274,7 +1274,7 @@
   (and
    (= (get-in word '(:infl)) :imperfect)
    (= :sing (get-in word '(:agr :number)))
-   (= :2nd (get-in word '(:agr :person)))
+   (= :3rd (get-in word '(:agr :person)))
    (string? (get-in word '(:imperfect :3sing)))))

 (defn irregular-imperfect-3sing [word]


make past-tense rewrite rules more concise

--- src/babel/italiano/morphology/verbs.cljc
+++ src/babel/italiano/morphology/verbs.cljc
@@ -261,199 +261,80 @@
          ]}]))

 (def replace-patterns-past-tense
-  [
-   {:p [#"^([^ ]+)esa" "$1eso"]
-    :u {:synsem {:subcat {:1 {:agr {:number :sing
-                                    :gender :fem}}}
-                 :infl :past}}}
-   {:p [#"^([^ ]+)ese" "$1eso"]
-    :u {:synsem {:subcat {:1 {:agr {:number :sing
-                                    :gender :fem}}}
-                 :infl :past}}}
-   {:p [#"^([^ ]+)esi" "$1eso"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur
-                                    :gender :masc}}}
-                 :infl :past}}}
-   {:p [#"^([^ ]+)([aiu])ta" "$1$2to"]
-    :u {:synsem {:subcat {:1 {:agr {:number :sing
-                                    :gender :fem}}}
-                 :infl :past}}}
-   {:p [#"^([^ ]+)([aiu])te" "$1$2to"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur
-                                    :gender :fem}}}
-                 :infl :past}}}
-   {:p [#"^([^ ]+)([aiu])ti" "$1$2to"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur
-                                    :gender :masc}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)tita" "$1tito"]
-    :u {:synsem {:subcat {:1 {:agr {:number :sing
-                                    :gender :fem}}}
-                 :infl :past}}}
-   {:p [#"^([^ ]+)tite" "$1tito"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur
-                                    :gender :fem}}}
-                 :infl :past}}}
-   {:p [#"^([^ ]+)titi" "$1tito"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur
-                                    :gender :masc}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)asta" "$1asto"]
-    :u {:synsem {:subcat {:1 {:agr {:number :sing
-                                    :gender :fem}}}
-                 :infl :past}}}
-   {:p [#"^([^ ]+)aste" "$1asto"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur
-                                    :gender :fem}}}
-                 :infl :past}}}
-   {:p [#"^([^ ]+)asti" "$1asto"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur
-                                    :gender :masc}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ata" "$1are"]
-    :u {:synsem {:subcat {:1 {:agr {:number :sing
-                                    :gender :fem}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ata" "$1arsi"]
-    :u {:synsem {:subcat {:1 {:agr {:number :sing
-                                    :gender :fem}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ate" "$1are"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur
-                                    :gender :fem}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ate" "$1arsi"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur
-                                    :gender :fem}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ati" "$1are"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur
-                                    :gender :masc}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ati" "$1arsi"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur
-                                    :gender :masc}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ato" "$1are"]
-    :u {:synsem {:infl :past}}}
-
-   {:p [#"^([^ ]+)ato" "$1arsi"]
-    :u {:synsem {:infl :past}}}
-
-   ;; scese -> sceso -> scendere
-   {:p [#"^([^ ]+)ese" "$1eso"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur
-                                    :gender :fem}}}
-                 :infl :past}}}
-
-   ;; scesi -> sceso -> scendere
-   {:p [#"^([^ ]+)esi" "$1eso"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur
-                                    :gender :masc}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ita" "$1ire"]
-    :u {:synsem {:subcat {:1 {:agr {:number :sing
-                                    :gender :fem}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ita" "$1irsi"]
-    :u {:synsem {:subcat {:1 {:agr {:number :sing
-                                    :gender :fem}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ite" "$1ire"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur
-                                    :gender :fem}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ite" "$1irsi"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur
-                                    :gender :fem}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)iti" "$1ire"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)iti" "$1irsi"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ito" "$1ire"]
-    :u {:synsem {:infl :past}}}
-
-   {:p [#"^([^ ]+)ito" "$1irsi"]
-    :u {:synsem {:infl :past}}}
-
-   {:p [#"^([^ ]+)uta" "$1ere"]
-    :u {:synsem {:subcat {:1 {:agr {:gender :fem
-                                    :number :sing}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)uta" "$1ersi"]
-    :u {:synsem {:subcat {:1 {:agr {:gender :fem
-                                    :number :sing}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)uta" "$1uto"]
-    :u {:synsem {:subcat {:1 {:agr {:gender :fem
-                                    :number :sing}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ute" "$1ere"]
-    :u {:synsem {:subcat {:1 {:agr {:gender :fem
-                                    :number :plur}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ute" "$1ersi"]
-    :u {:synsem {:subcat {:1 {:agr {:gender :fem
-                                    :number :plur}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ute" "$1irsi"]
-    :u {:synsem {:subcat {:1 {:agr {:gender :fem
-                                    :number :plur}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ute" "$1ire"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur
-                                    :gender :fem}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)ute" "$1uto"]
-    :u {:synsem {:subcat {:1 {:agr {:gender :fem
-                                    :number :plur}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)uti" "$1ere"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)uti" "$1ersi"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)uti" "$1ire"]
-    :u {:synsem {:subcat {:1 {:agr {:number :plur}}}
-                 :infl :past}}}
-
-   {:p [#"^([^ ]+)uto" "$1ere"]
-    :u {:synsem {:infl :past}}}
-
-   {:p [#"^([^ ]+)uto" "$1ersi"]
-    :u {:synsem {:infl :past}}}
-
-   ])
+  (concat
+   (expand-replace-patterns
+    {:synsem {:infl :past}}
+    [
+     {:agr {:synsem {:subcat {:1 {:agr {:number :sing
+                                        :gender :fem}}}}}
+      :p [
+          #"^([^ ]+)esa"       "$1eso"
+          #"^([^ ]+)([aiu])ta" "$1$2to"
+          #"^([^ ]+)tita"      "$1tito"
+          #"^([^ ]+)asta"      "$1asto"
+          #"^([^ ]+)ata"       "$1are"
+          #"^([^ ]+)ata"       "$1arsi"
+          #"^([^ ]+)ita"       "$1ire"
+          #"^([^ ]+)ita"       "$1irsi"
+          #"^([^ ]+)uta"       "$1ere"
+          #"^([^ ]+)uta"       "$1ersi"
+          #"^([^ ]+)uta"       "$1uto"
+          ]
+      }
+
+     {:agr {:synsem {:subcat {:1 {:agr {:number :plur
+                                        :gender :fem}}}}}
+      :p [
+          #"^([^ ]+)ese" "$1eso"
+          #"^([^ ]+)([aiu])te" "$1$2to"
+          #"^([^ ]+)tite" "$1tito"
+          #"^([^ ]+)aste" "$1asto"
+          #"^([^ ]+)ese" "$1eso"           ;; scese -> sceso -> scendere
+          #"^([^ ]+)ate" "$1are"
+          #"^([^ ]+)ate" "$1arsi"
+          #"^([^ ]+)ite" "$1ire"
+          #"^([^ ]+)ite" "$1irsi"
+          #"^([^ ]+)ute" "$1ere"
+          #"^([^ ]+)ute" "$1ersi"
+          #"^([^ ]+)ute" "$1irsi"
+          #"^([^ ]+)ute" "$1ire"
+          #"^([^ ]+)ute" "$1uto"
+
+          ]
+      }
+
+     {:agr {:synsem {:subcat {:1 {:agr {:number :plur
+                                        :gender :masc}}}}}
+      :p [
+          #"^([^ ]+)esi"       "$1eso"
+          #"^([^ ]+)([aiu])ti" "$1$2to"
+          #"^([^ ]+)titi"      "$1tito"
+          #"^([^ ]+)asti"      "$1asto"
+          #"^([^ ]+)ati"       "$1are"
+          #"^([^ ]+)ati"       "$1arsi"
+          #"^([^ ]+)esi"       "$1eso"    ;; scesi -> sceso -> scendere
+          ]
+      }
+
+     {:agr {:synsem {:subcat {:1 {:agr {:number :plur}}}}}
+      :p [
+          #"^([^ ]+)iti" "$1ire"
+          #"^([^ ]+)iti" "$1irsi"
+          #"^([^ ]+)uti" "$1ere"
+          #"^([^ ]+)uti" "$1ersi"
+          #"^([^ ]+)uti" "$1ire"
+          ]}
+
+     {:agr :top
+      :p [
+          #"^([^ ]+)ato" "$1are"
+          #"^([^ ]+)ato" "$1arsi"
+          #"^([^ ]+)ito" "$1ire"
+          #"^([^ ]+)ito" "$1irsi"
+          #"^([^ ]+)uto" "$1ere"
+          #"^([^ ]+)uto" "$1ersi"
+          ]}
+     ])))

 (def replace-patterns-present-tense
   (expand-replace-patterns


formatting

formatting

--- src/clj/backtype/storm/daemon/nimbus.clj
+++ src/clj/backtype/storm/daemon/nimbus.clj
@@ -425,9 +425,6 @@
         storm-conf (read-storm-conf conf storm-id)
         all-task-ids (set (.task-ids storm-cluster-state storm-id))

-
-        ;; if scratch?, slots = existing slots + available-slots, reassign-ids = all-ids
-        ;; otherwise, do timeout stuff
         existing-assigned (reverse-map (:task->node+port existing-assignment))
         alive-ids (if scratch?
                     all-task-ids


tweak the logic a bit, no need for polling

--- src/cljs/clojure_front_end_app/core.cljs
+++ src/cljs/clojure_front_end_app/core.cljs
@@ -44,16 +44,15 @@
   (om/component
     (apply dom/ul nil (om/build-all gas-station gas-stations))))

-(defn gas-stations-box [app _ {:keys [url params poll-interval]}]
+(defn gas-stations-box [app _ {:keys [url params]}]
   (reify
     om/IWillMount
     (will-mount [_]
       (om/transact! app [:gas-stations] (fn [] []))
-      (go (while true
-            (let [pos-params (<! (get-position))
-                  gas-stations (<! (fetch-gas-stations url (merge params pos-params)))]
-              (om/update! app (assoc app :gas-stations gas-stations)))
-            (<! (timeout poll-interval)))))
+      (go
+        (let [pos-params (<! (get-position))
+              gas-stations (<! (fetch-gas-stations url (merge params pos-params)))]
+          (om/update! app (assoc app :gas-stations gas-stations)))))
     om/IRender
     (render [_]
       (dom/h1 nil "Бензиностанции")
@@ -63,13 +62,12 @@
   (om/component
     (dom/div nil
              (om/build gas-stations-box app
-                       {:opts {:url           "/rest/fuel-near-me"
-                               :poll-interval 1000000
-                               :params        {:lon      25.55
-                                               :lat      43.45
-                                               :limit    50
-                                               :distance 50
-                                               :fuel     "lpg"}}}))))
+                       {:opts {:url    "/rest/fuel-near-me"
+                               :params {:lon      25.55
+                                        :lat      43.45
+                                        :limit    50
+                                        :distance 50
+                                        :fuel     "lpg"}}}))))

 (def app-state
   (atom {}))


Added :proportionate option for :age-combining-function; lein release :minor

--- src/clojush/pushgp/genetic_operators.clj
+++ src/clojush/pushgp/genetic_operators.clj
@@ -31,7 +31,24 @@
                 (inc (:age p2))))
     :average (fn [p1 p2 g]
                (average (inc (:age p1))
-                        (inc (:age p2))))))
+                        (inc (:age p2))))
+    :proportionate (fn [p1 p2 g]
+                     (if (= (:age p1) (:age p2))
+                       (inc (:age p1))
+                       (if (= (:genome p1) (:genome p2))
+                         (/ (+ (inc (:age p1)) (inc (:age p2))) 2)
+                         (let [p1-dist (levenshtein-distance g (:genome p1))
+                               p2-dist (levenshtein-distance g (:genome p2))]
+                           (+ (inc (:age p1))
+                              (* (/ p1-dist (+ p1-dist p2-dist))
+                                 (- (inc (:age p2))
+                                    (inc (:age p1)))))))))))
+
+;; test effects of :proportionate with expressions like this:
+;(float ((age-combining-function {:age-combining-function :proportionate})
+;        {:genome [1 2 3 4 5 6 7] :age 100}
+;        {:genome [1 2 3 4] :age 200}
+;        [1 2 3]))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; reproduction
@@ -945,3 +962,4 @@
         :is-random-replacement
         (if use-child false true)))))

+


Restricted setting of grain size to 1 for dummies to non-zero criterion.

--- src/clojush/pushgp/genetic_operators.clj
+++ src/clojush/pushgp/genetic_operators.clj
@@ -102,7 +102,10 @@
            (empty? genome))
      1
      (if (some :dummy [parent1 parent2])
-       1
+       (if (some #{(:criterion random-screen)}
+                 #{:non-zero-genetic-similarity-to-parent})
+         1
+         0)
        (case (:criterion random-screen)
          ;
          :genetic-similarity-to-parent


Allow produce-child-genome-by-autoconstruction to run pgm not from parent1.

--- src/clojush/pushgp/genetic_operators.clj
+++ src/clojush/pushgp/genetic_operators.clj
@@ -16,6 +16,8 @@
   (if (number? number-or-numbers)
     number-or-numbers
     (lrand-nth number-or-numbers)))
+
+(declare produce-child-genome-by-autoconstruction) ;; forward declaration for :consistency

 (defn age-combining-function
   "Returns the actual age combining function specified by the :age-combining-function
@@ -46,7 +48,12 @@
     :first (fn [p1 p2 g]
              (inc (:age p1)))
     :fidelity (fn [p1 p2 g]
-                (sequence-similarity g (:genome p1)))))
+                (sequence-similarity g (:genome p1)))
+    :consistency (fn [p1 p2 g]
+                   (let [child (produce-child-genome-by-autoconstruction g g false argmap)
+
+                         ]))
+    ))

 ;; test effects of :proportionate with expressions like this:
 ;(float ((age-combining-function {:age-combining-function :proportionate})
@@ -677,23 +684,26 @@
   "Runs the program expressed by parent1-genome with both parent genomes
 on the genome stack and also available via input instructions, and returns
 the resulting top genome."
-  [parent1-genome parent2-genome deterministic? argmap]
-  (let [run-result (top-item :genome
-                             (run-push
-                               (translate-plush-genome-to-push-program
-                                 {:genome (process-genome-for-autoconstruction
-                                            parent1-genome
-                                            deterministic?)}
-                                 argmap)
-                               (-> (->> (make-push-state)
-                                        (push-item parent2-genome :genome)
-                                        (push-item parent1-genome :genome))
-                                   (assoc :parent1-genome parent1-genome)
-                                   (assoc :parent2-genome parent2-genome)
-                                   (assoc :autoconstructing true))))]
-    (if (or (seq? run-result) (vector? run-result))
-      (vec run-result)
-      [])))
+  ([parent1-genome parent2-genome deterministic? argmap]
+   (produce-child-genome-by-autoconstruction
+     parent1-genome parent1-genome parent2-genome deterministic? argmap))
+  ([genome-to-run parent1-genome parent2-genome deterministic? argmap]
+   (let [run-result (top-item :genome
+                              (run-push
+                                (translate-plush-genome-to-push-program
+                                  {:genome (process-genome-for-autoconstruction
+                                             genome-to-run
+                                             deterministic?)}
+                                  argmap)
+                                (-> (->> (make-push-state)
+                                         (push-item parent2-genome :genome)
+                                         (push-item parent1-genome :genome))
+                                    (assoc :parent1-genome parent1-genome)
+                                    (assoc :parent2-genome parent2-genome)
+                                    (assoc :autoconstructing true))))]
+     (if (or (seq? run-result) (vector? run-result))
+       (vec run-result)
+       []))))

 (defn expressed-program-sequence-from-genome
   "Returns an open-close sequenc for the program produced by expressing
@@ -965,3 +975,4 @@
                                            (:ancestors parent1)))
         :is-random-replacement
         (if use-child false true)))))
+


Mark body-string as returning String

Mark body-string as returning String

Prevent reflection in callers.

--- ring-core/src/ring/util/request.clj
+++ ring-core/src/ring/util/request.clj
@@ -44,7 +44,7 @@
   (if-let [^String type (content-type request)]
     (.startsWith type "application/x-www-form-urlencoded")))

-(defmulti body-string
+(defmulti ^String body-string
   "Return the request body as a string."
   {:arglists '([request]), :added "1.2"}
   (comp class :body))


Fix for #59

Fix for #59

--- src/untangled/client/impl/network.cljc
+++ src/untangled/client/impl/network.cljc
@@ -60,9 +60,9 @@
                                         ;; note that impl.application/initialize will partially apply the
                                         ;; app-state as the first arg to global-error-callback
                                         (log/error str)
+                                        (error-callback error)
                                         (when @global-error-callback
-                                          (@global-error-callback status error))
-                                        (error-callback error))]
+                                          (@global-error-callback status error)))]
            (if (zero? status)
              (log-and-dispatch-error
                (str "UNTANGLED NETWORK ERROR: No connection established.")


updated api call

updated api call

--- src/flappy_bird_demo/core.cljs
+++ src/flappy_bird_demo/core.cljs
@@ -36,7 +36,7 @@
                          :pos-x 900
                          :cur-x 900
                          :gap-top 200 }]})
-(This)
+
 (defn reset-state [_ cur-time]
   (-> starting-state
       (update-in [:pillar-list] (fn [pls] (map #(assoc % :start-time cur-time) pls)))
@@ -54,12 +54,12 @@
   (and (>= (+ flappy-x flappy-width)
            cur-x)
        (< flappy-x (+ cur-x pillar-width))))
-(is)
+
 (defn in-pillar-gap? [{:keys [flappy-y]} {:keys [gap-top]}]
   (and (< gap-top flappy-y)
        (> (+ gap-top pillar-gap)
           (+ flappy-y flappy-height))))
-(cool)
+
 (defn bottom-collision? [{:keys [flappy-y]}]
   (>= flappy-y (- bottom-y flappy-height)))

@@ -199,9 +199,9 @@

 (reset! flap-state @flap-state)

-(fw/watch-and-reload  :jsload-callback (fn []
-                                         ;; you would add this if you
-                                         ;; have more than one file
-                                         #_(reset! flap-state @flap-state)
-                                         ))
-
+(fw/start { :on-jsload (fn []
+                         ;; you would add this if you
+                         ;; have more than one file
+                         #_(reset! flap-state @flap-state)
+                         )})
+


Moved "Who are we" button

Moved "Who are we" button

--- src/webapp/client/views/main_view.cljs
+++ src/webapp/client/views/main_view.cljs
@@ -37,18 +37,18 @@

         (el :button
+                      {:id    "who-button"
+                       :style "margin: 20px;"
+                       :class "btn btn-large"
+                       :text "Who are we"
+                       :onclick #(do-action "show who page")})
+
+        (el :button
                       {:id    "help-button"
                        :style "margin: 20px;"
                        :class "btn btn-large"
                        :text "Help"
                        :onclick #(help)})
-
-        (el :button
-                      {:id    "who-button"
-                       :style "margin: 20px;"
-                       :class "btn btn-large"
-                       :text "Who are we"
-                       :onclick #(do-action "show who page")})

         (el :button
                       {:id    "help-button"


Ignore post key in Parse->path.

Ignore post key in Parse->path.

--- src/incise/parsers/helpers.clj
+++ src/incise/parsers/helpers.clj
@@ -22,9 +22,9 @@
 (def date-str->path (comp date-time->path tc/from-string))

 (defn Parse->path
-  [^Parse {:keys [path layout date title extension]}]
+  [^Parse {:keys [path date title extension]}]
   (or path
-      (str (when (= layout :post) (date-str->path date))
+      (str (date-str->path date)
            (dashify title)
            extension)))


#23 fix misaki.compiler.default.core/-compile to only compile prev/next post when single compiling mode

--- src/misaki/compiler/default/core.clj
+++ src/misaki/compiler/default/core.clj
@@ -76,10 +76,12 @@
               (log tag-name (compile-tag tag-name) true)))
           ; compile prev/next posts
           (let [posts       ((sort-type->sort-fn) (get-posts))
-                [prev next] (get-prev-next #(= file (:file %)) posts)]
-            (if-let [prev-file (:file prev)]
+                [prev next] (get-prev-next #(= file (:file %)) posts)
+                prev-file   (:file prev)
+                next-file   (:file next)]
+            (if (and prev-file (= :single (:-compiling config)))
               (log (.getName prev-file) (compile-template prev-file) true))
-            (if-let [next-file (:file next)]
+            (if (and next-file (= :single (:-compiling config)))
               (log (.getName next-file) (compile-template next-file) true))))
         res))))


Fix or expression

Fix or expression

--- src/net/sekao/nightcode/projects.clj
+++ src/net/sekao/nightcode/projects.clj
@@ -125,7 +125,7 @@
         (if (.isDirectory file)
           (dir-pane)
           (let [state @state-atom
-                pane (or (get-in state [:panes path] (file-pane state file)))]
+                pane (or (get-in state [:panes path]) (file-pane state file))]
             (swap! state-atom update :panes assoc path pane)
             pane))))))


Fix textarea not shrinking after sending message

Also, only resize once per character typed

Fixes #156

--- src/braid/core/client/ui/views/new_message.cljs
+++ src/braid/core/client/ui/views/new_message.cljs
@@ -13,7 +13,7 @@
   (:import
    (goog.events KeyCodes)))

-(defn- resize-textbox [el]
+(defn- resize-textbox! [el]
   (set! (.. el -style -height) "auto")
   (let [new-height (str (min 300 (.-scrollHeight el)) "px")]
     (set! (.. el -style -height) new-height)
@@ -37,31 +37,38 @@
         _ (run! (do
                   (when (and @focused? @this-elt)
                     (.focus @this-elt))))]
-    (fn [{:keys [text set-text! config on-key-down on-change]}]
-      ;; wrap with a div that has a fixed height and overflow: hidden
-      ;; so that the auto-resize behaviour of the textarea does not cause
-      ;; double scroll events
-      [:div.textarea {:style {:overflow "hidden"
-                              ;; height gets overriden by JS
-                              :height "0px"}}
-       [:textarea {:placeholder (config :placeholder)
-                   :value text
-                   :ref (fn [x]
-                          (when (and x (nil? @this-elt))
-                            (reset! this-elt x)
-                            (resize-textbox @this-elt)))
-                   :disabled (not @connected?)
-                   :on-focus (fn [e]
-                               (dispatch [:focus-thread (config :thread-id)]))
-                   :on-change (on-change
-                                {:on-change
-                                 (fn [e]
-                                   (set-text! (.. e -target -value))
-                                   (resize-textbox (.. e -target)))})
-                   :on-key-down (on-key-down
-                                  {:on-submit (fn [e]
-                                                (send-message! config text)
-                                                (set-text! ""))})}]])))
+    (r/create-class
+      {:component-did-update
+       (fn [this [_ new-props]]
+         (when (not= (:text (r/props this))
+                     (:text new-props))
+           (resize-textbox! @this-elt)))
+
+       :reagent-render
+       (fn [{:keys [text set-text! config on-key-down on-change]}]
+         ;; wrap with a div that has a fixed height and overflow: hidden
+         ;; so that the auto-resize behaviour of the textarea does not cause
+         ;; double scroll events
+         [:div.textarea {:style {:overflow "hidden"
+                                 ;; height gets overriden by JS
+                                 :height "0px"}}
+          [:textarea {:placeholder (config :placeholder)
+                      :value text
+                      :ref (fn [x]
+                             (when (and x (nil? @this-elt))
+                               (reset! this-elt x)
+                               (resize-textbox! @this-elt)))
+                      :disabled (not @connected?)
+                      :on-focus (fn [e]
+                                  (dispatch [:focus-thread (config :thread-id)]))
+                      :on-change (on-change
+                                   {:on-change
+                                    (fn [e]
+                                      (set-text! (.. e -target -value)))})
+                      :on-key-down (on-key-down
+                                     {:on-submit (fn [e]
+                                                   (send-message! config text)
+                                                   (set-text! ""))})}]])})))

 (defn autocomplete-results-view [{:keys [results highlighted-result-index on-click]}]
   [:div.autocomplete


Set up autocomplete in didMount instead of willMount

--- src/braid/core/client/ui/views/new_message.cljs
+++ src/braid/core/client/ui/views/new_message.cljs
@@ -226,7 +226,7 @@

     (r/create-class
       {:display-name "autocomplete"
-       :component-will-mount
+       :component-did-mount
        (fn [c]
          (let [config (r/props c)]
            (go (loop []


(PDB-2487) Add log gc-resource-events! message for translation

Add the message we know we're going to want later so that it can be
translated in time for the rlease.  The remaining code will follow.

--- src/puppetlabs/puppetdb/cli/services.clj
+++ src/puppetlabs/puppetdb/cli/services.clj
@@ -176,6 +176,10 @@
     (catch Exception e
       (log/error e (trs "Error while running package gc")))))

+(defn gc-resource-events!
+  []
+  (trs "Error while sweeping resource events"))
+
 (defn garbage-collect!
   "Perform garbage collection on `db`, which means deleting any orphaned data.
   This basically just wraps the corresponding scf.storage function with some


Updated url to point to QA

Updated url to point to QA

--- src/cljs/wombats_web_client/constants/urls.cljs
+++ src/cljs/wombats_web_client/constants/urls.cljs
@@ -6,7 +6,7 @@
                            :config-panel "config"})

 ;; Remote Dev
-(def base-api-url "//dev.api.wombats.io")
+(def base-api-url "//qa.api.wombats.io")

 ;; Local Dev
 #_(def base-api-url "//localhost:8888")


Fixed regex

Fixed regex

--- src/clojurescript_css_modules_demo/js/core.cljs
+++ src/clojurescript_css_modules_demo/js/core.cljs
@@ -15,11 +15,10 @@
   (let [stringified (str i)
         class-lookup (re-find #"(?:CSS>)[^\s][a-zA-Z>-]+" stringified)
         tree (rest (string/split class-lookup #">"))
-        class-names (apply aget (js* "cssModules") tree)
+        class-names (or (apply aget (js* "cssModules") tree) ".")
         joined-class-names (string/replace-all class-names #" " ".")
         output (reader/read-string (string/replace-first stringified #"(?:CSS>)[^\s][a-zA-Z>-]+" joined-class-names))
         finished? (nil? (re-find #"(?:CSS>)[^\s][a-zA-Z>-]+" (str output)))]
-
     (if finished?
       output
       (recur output))))


refine budget report test

refine budget report test

--- test/clj_money/models/reports_test.clj
+++ test/clj_money/models/reports_test.clj
@@ -503,7 +503,7 @@
                            :budget 900M
                            :actual 904M
                            :difference -4M
-                           :percent-difference 0.00444444444M
+                           :percent-difference -0.004444444444M
                            :actual-per-period 452M}
                           {:caption "Rent"
                            :style :data
@@ -511,7 +511,7 @@
                            :actual 1400M
                            :difference 0M
                            :percent-difference 0M
-                           :actual-per-period 1400M}
+                           :actual-per-period 700M}
                           {:caption "Medicare"
                            :style :data
                            :budget 60M
@@ -524,7 +524,7 @@
                            :budget 268M
                            :actual 186M
                            :difference 82M
-                           :percent-difference 0.30M
+                           :percent-difference 0.3059701493M
                            :actual-per-period 93M}
                           {:caption "FIT"
                            :style :data
@@ -539,13 +539,19 @@
                            :actual 0M
                            :difference 400M
                            :percent-difference 1M
-                           :actual-per-period 0M}]}]
-
-    (pprint {:expected expected
-             :actual actual
-             :diff (diff expected actual)})
+                           :actual-per-period 0M}
+                          {:caption "Net"
+                           :style :summary
+                           :budget 178M
+                           :actual 875M
+                           :difference 697M
+                           :percent-difference 3.91573033M
+                           :actual-per-period 437.50M}]}]
+
+    (when (not= expected actual)
+      (pprint {:diff (diff expected actual)}))

-    #_(is (= expected actual) "The function products the correct data")))
+    (is (= expected actual) "The function products the correct data")))

 ; TODO
 ; create a budget report with nesting levels rolled up


sketched a needs-counter that takes a transaction and tallies all the items & stacks it mentions

--- test/push/design_spikes/dsl_macros.clj
+++ test/push/design_spikes/dsl_macros.clj
@@ -349,12 +349,16 @@

 ;; first let's take a transaction and make it into a real function

+
+
 (defmacro
   def-pushdsl
   [& transactions]
-  (let [interpreter (gensym 'interpreter)]
+  (let [interpreter (gensym 'interpreter)
+       words &form]
+    (do
     `(fn [~interpreter]
-      (first (-> [~interpreter {}] ~@transactions)))))
+      (first (-> [~interpreter {}] ~@transactions))))))

 (fact "that works maybe"
   (fn?
@@ -484,3 +488,67 @@
   (get-stack (code-do*range not-iterating) :code) => '(:nope)
   (get-stack (code-do*range not-iterating) :exec) =>
     '(() :qux))
+
+;; collect the needs while we have the transaction
+
+(defn needs-of
+  [step]
+  (let [cmd (first step)]
+    (condp = cmd
+      'consume-nth {(second step) 1}
+      'consume-stack {(second step) 0}
+      'consume-top-of {(second step) 1}
+      'count-of {(second step) 0}
+      'place {(second step) 0}
+      'remember-nth {(second step) 1}
+      'remember-stack {(second step) 0}
+      'remember-top {(second step) 1}
+      'replace-stack {(second step) 0}
+      nil
+      )))
+
+
+(defn count-needs
+  [transaction]
+  (apply (partial merge-with +)
+    (remove nil? (map needs-of transaction)))
+  )
+
+; : foo, bar, baz, qux, quux, corge, grault, garply, waldo, fred, plugh, xyzzy, thud
+(fact "returns a combined of all the needs of all the DSL steps it sees"
+  (count-needs
+    '(
+      (consume-nth :foo :at 5 :as :ugh)
+      (consume-stack :bar )
+      (consume-top-of :baz)
+      (consume-top-of :qux :as :int1)
+      (count-of :quux)
+      (place :corge :ugh)
+      (remember-calc [] #(8) :as :ugh)
+      (remember-nth :grault :as ugh :at 6)
+      (remember-stack :garply :as :ugh)
+      (remember-top :waldo :as :ugh)
+      (replace-stack :fred :ugh)
+      )
+    ) => {:bar 0, :baz 1, :corge 0, :foo 1, :fred 0, :garply 0, :grault 1, :quux 0, :qux 1, :waldo 1}
+
+  (count-needs
+    '(
+      (consume-nth :foo)     ; +1
+      (consume-stack :foo )  ; +0
+      (consume-top-of :foo)  ; +1
+      (consume-nth :foo)     ; +1
+      (remember-nth :foo :as ugh :at 6) ; +1
+
+      (consume-top-of :bar)  ; +1
+      (count-of :bar)        ; +0
+      (consume-nth :bar)     ; +1
+      (remember-stack :bar :as :ugh)    ; +0
+
+      (place :baz :ugh)      ; +0
+      (remember-top :baz :as :ugh)      ; +1
+
+      (replace-stack :fred :ugh)        ; +0
+      )
+    ) => {:foo 4, :bar 2, :baz 1,  :fred 0}
+  )


selectize working

selectize working

--- src/frontend/cljs/alibi/post_new_entry_bar.cljs
+++ src/frontend/cljs/alibi/post_new_entry_bar.cljs
@@ -44,6 +44,35 @@
 (defn entry-bar-form' [for-state owner]
   (log "data %o" for-state)
   (reify
+    om/IDidMount
+    (did-mount [_]
+      (let [$form (js/$ (om/get-node owner "the-form"))
+            $select (.find $form "select")]
+        (.selectize
+          $select #js
+          {:highlight false
+           :selectOnTab true
+           :score (partial selectize-score-fn for-state)
+           :render #js {:option (partial selectize-render-option
+                                         (:options-by-id for-state))
+                        :item (fn [i e] (selectize-render-option
+                                          (:options-by-id for-state)
+                                          i e "option-selected"))}})
+        (let [selectize (aget $select 0 "selectize")]
+          (.on selectize "dropdown_close"
+               (fn []
+                 (let [value (.getValue selectize)]
+                   (.setTimeout ; updating the state will trigger a destroy
+                                ; of selectize, which in turn will prevent
+                                ; the dropdown_close event handlers from
+                                ; complete correctly, so we schedule
+                                ; updating the state for a later moment
+                                js/window
+                                (fn [] (if (seq value)
+                                         ((:on-select-task for-state)
+                                          (parse-selected-item value))
+                                         ((:on-cancel for-state))))
+                                0)))))))
     om/IRender
     (render [_]
       (let [options (:options for-state)
@@ -52,7 +81,8 @@
                            (str projectId "," taskId) "")]
         (dom/form
           #js {:id "post-new-entry-bar"
-               :className "navbar-form navbar-form-post-new-entry-bar"}
+               :className "navbar-form navbar-form-post-new-entry-bar"
+               :ref "the-form"}
           (dom/select
             #js {:name "post-new-entry-bar"
                  :placeholder "Post new entry..."
@@ -66,23 +96,6 @@
                            :data-billing-method (:billing-method %)
                            :value value}
                       (:text %))) options)))))))
-        ;[:form#post-new-entry-bar.navbar-form.navbar-form-post-new-entry-bar
-         ;{:ref (fn [form] (aset this "form" form))}
-         ;[:select
-          ;{:name "post-new-entry-bar"
-           ;:placeholder "Post new entry..."
-           ;:defaultValue select-value}
-          ;[:option
-           ;{:value ""}
-           ;""]
-          ;(map #(let [value (str (:project-id %) "," (:task-id %))]
-                  ;[:option
-                   ;{:key value
-                    ;:data-project-id (:project-id %)
-                    ;:data-task-id (:task-id %)
-                    ;:data-billing-method (:billing-method %)
-                    ;:value value}
-                   ;(:text %)]) options)]]))))
   ;(letfn [(get-selectize [this] (.. (js/$ (aget this "form"))
                                      ;(find "select")
                                      ;(get 0)


fix comparison semantics test after introducing == to the basis