Removed unused lat/lon/bounds records.

Removed unused lat/lon/bounds records.

--- src/cmr/opendap/ous/core.clj
+++ src/cmr/opendap/ous/core.clj
@@ -51,16 +51,6 @@
 ;;; documented. Additionally, this will make converting between parameter
 ;;; schemes an explicit operation on explicit data.

-(defrecord Longitude [low high])
-(defrecord Latitude [low high])
-(defrecord Bounds [lat lon])
-
-(defn bounds->rec
-  [[lon-lo lat-lo lon-hi lat-hi]]
-  (map->Bounds
-    {:lat (map->Latitude {:low lat-lo :high lat-hi})
-     :lon (map->Longitude {:low lon-lo :high lon-hi})}))
-
 (defn ->pixels
   [{x-dim :x y-dim :y} bounds]
   (let [[lon-lo lat-lo lon-hi lat-hi] (map #(Integer/parseInt %) bounds)
@@ -74,6 +64,14 @@
 (defn bounding-info->pixels
   [bounding-info]
   (map #(->pixels (:dimensions %) (:bounds %)) bounding-info))
+
+(defn bounding-info->opendap-query
+  [bounding-info]
+  (when (seq bounding-info)
+    (->> bounding-info
+         (map identity)
+         (string/join ",")
+         (str "?"))))

 ;; XXX WARNING!!! The pattern matching code has been taken from the Node.js
 ;;                prototype ... and IT IS AWFUL. This is only temporary ...
@@ -100,10 +98,10 @@
                           (str "$1" fallback-replacement "$3")))))))

 (defn data-files->opendap-urls
-  [params pattern-info data-files]
+  [params pattern-info data-files query-string]
   (->> data-files
        (map (partial data-file->opendap-url pattern-info))
-       (map #(str % "." (:format params)))))
+       (map #(str % "." (:format params) query-string))))

 (defn get-opendap-urls
   [search-endpoint user-token raw-params]
@@ -119,12 +117,14 @@
         all-vars (collection/extract-variable-ids coll)
         vars (variable/get-metadata search-endpoint user-token params all-vars)
         bounding-info (map variable/extract-bounding-info vars)
-        pixels (bounding-info->pixels bounding-info)]
+        pixels (bounding-info->pixels bounding-info)
+        query (bounding-info->opendap-query bounding-info)]
     (log/debug "data-files:" (into [] data-files))
     (log/debug "pattern-info:" pattern-info)
     (log/debug "all variable ids:" all-vars)
     (log/debug "variable bounding-info:" (into [] bounding-info))
     (log/debug "pixels:" (into [] pixels))
+    (log/debug "query:" query)
     (results/create
-     (data-files->opendap-urls params pattern-info data-files)
+     (data-files->opendap-urls params pattern-info data-files query)
      :elapsed (util/timed start))))


Kibitzed.

Kibitzed.

--- src/com/lemonodor/gflags.clj
+++ src/com/lemonodor/gflags.clj
@@ -11,7 +11,7 @@
                               (:boolean flag))
                        "1"
                        value-string)]
-    (when (= (count value-string) 0)
+    (when (zero? (count value-string))
       (throw (Exception. (str "Must specify a value for flag " optname))))
     (let [value
           (try ((:parser flag) value-string)
@@ -159,7 +159,7 @@

 (defn integer-parser [argument]
   (try
-    (. Integer parseInt argument)
+    (Integer/parseInt ^String argument)
     (catch Exception e
       (throw (Exception.
               (str "Could not parse as integer: \"" argument "\""))))))


cli: refactor process-line

cli: refactor process-line

--- src/com/okl/tokenmgr/cli.clj
+++ src/com/okl/tokenmgr/cli.clj
@@ -6,22 +6,17 @@
             [clojure.tools.cli :refer [parse-opts]]
             [clojure-csv.core :as csv]))

+(defn- expand-line [line token]
+  "Returns expanded line with provided token."
+  (string/replace line (str "__" (key token) "__") (val token)))
+
 (defn process-line [line tokens]
-  (log/trace (str "Attempting to process line " line))
-  (let [replace-token
-        (fn [string token]
-          (let [pattern (java.util.regex.Pattern/quote (str "__"(name (key token)) "__"))
-                pattern (re-pattern pattern)
-                matcher (re-matcher pattern string)
-                replacement (java.util.regex.Matcher/quoteReplacement (str (val token)))]
-            (log/trace (str "pattern is " pattern))
-            (log/trace (str "Reduced is " reduced))
-            (log/trace (str "Replacement is " replacement))
-            (.replaceAll matcher replacement)))
-        reduced (reduce replace-token line (seq tokens))]
-    (if (= reduced line)
-      reduced
-      (process-line reduced tokens))))
+  "Returns expanded line with all provided tokens."
+  (log/trace (str "process-line: " line))
+  (let [expanded (reduce expand-line line (seq tokens))]
+    (if (= expanded line)
+      expanded
+      (process-line expanded tokens))))

 (defn- process-file! [file tokens]


Remove duplicate problem #56.

Remove duplicate problem #56.

--- src/foreclojure/data_set.clj
+++ src/foreclojure/data_set.clj
@@ -618,18 +618,6 @@
             :tests ["(= (__ [1 1 2 3 2 1 1]) {1 4, 2 2, 3 1})"
                     "(= (__ [:b :a :b :a :b]) {:a 2, :b 3})"
                     "(= (__ '([1 2] [1 3] [1 3])) {[1 2] 1, [1 3] 2})"]})
-
-      (insert! :problems
-           {:_id 56
-            :title "Find Distinct Items"
-            :times-solved 0
-            :restricted ["distinct"]
-            :description "Write a function which removes the duplicates from a sequence. Order of the items must be maintained."
-            :tags ["medium" "seqs" "core-functions"]
-            :approved true
-            :tests ["(= (__ [1 2 1 3 1 2 4]) [1 2 3 4])"
-                    "(= (__ [:a :a :b :b :c :c]) [:a :b :c])"
-                    "(= (__ '([2 4] [1 2] [1 3] [1 3])) '([2 4] [1 2] [1 3]))"]})

       (insert! :problems
            {:_id 56


Problem added - Sequence Reductions

Problem added - Sequence Reductions

--- src/foreclojure/data_set.clj
+++ src/foreclojure/data_set.clj
@@ -614,4 +614,15 @@
             :tags ["medium" "higher-order-functions" "core-functions"]
             :tests ["(= [21 6 1] ((__ + max min) 2 3 5 1 6 4))"
                     "(= [\"HELLO\" 5] ((__ #(.toUpperCase %) count) \"hello\"))"
-                    "(= [2 6 4] ((__ :a :c :b) {:a 2, :b 4, :c 6, :d 8 :e 10}))"]})))
+                    "(= [2 6 4] ((__ :a :c :b) {:a 2, :b 4, :c 6, :d 8 :e 10}))"]})
+
+      (insert! :problems
+           {:_id 60
+            :title "Sequence Reductions"
+            :times-solved 0
+            :restricted ["reductions"]
+            :description "Write a function which behaves like reduce, but returns each intermediate value of the reduction."
+            :tags ["medium" "seqs" "core-functions"]
+            :tests ["(= (take 5 (__ + (range))) [0 1 3 6 10])"
+                    "(= (__ conj [1] [2 3 4]) [[1] [1 2] [1 2 3] [1 2 3 4]])"
+                    "(= (last (__ * 2 [3 4 5])) (reduce * 2 [3 4 5]) 120)"]})))


Destructuring problems refactored

Destructuring problems refactored

--- src/foreclojure/data_set.clj
+++ src/foreclojure/data_set.clj
@@ -515,8 +515,16 @@

        (insert! :problems
            {:_id 51
+            :title "Advanced Destructuring"
+            :times-solved 0
+            :description "Here is an example of some more sophisticated destructuring."
+            :tags ["medium" "destructuring"]
+            :tests ["(= __ (let [[a b & c :as d] [1 2 3 4 5]] [a b c d]))"]})
+
+      (insert! :problems
+           {:_id 52
             :title "Intro to Destructuring"
             :times-solved 0
             :description "Let bindings and function parameter lists support destructuring."
-            :tags ["easy"]
-            :tests ["(= __ (let [[a b & c :as d] [1 2 3 4 5]] [a b c d]))"]})))+            :tags ["easy" "destructuring"]
+            :tests ["(= [2 4] (let [[a b c d e f g] (range)] __))"]})))


Re-enable storing submitted code in the stateful session, for cases where ajax is disabled, broken, whatever

--- src/foreclojure/problems.clj
+++ src/foreclojure/problems.clj
@@ -75,6 +75,9 @@
   "Turn an integer into a key suitable for fetching from mongodb."
   [id]
   keyword str int)
+
+(defn trim-code [code]
+  (when code (.trim code)))

 (defn code-length [code]
   (count (remove #(Character/isWhitespace %)
@@ -159,10 +162,9 @@
 specified id.

 Return a map, {:message, :url, :num-tests-passed}."
-  [id raw-code]
+  [id code]
   (try
-    (let [code (.trim raw-code)
-          {:keys [tests restricted] :as problem} (get-problem id)
+    (let [{:keys [tests restricted] :as problem} (get-problem id)
           sb-tester (get-tester restricted)
           user-forms (s/join " " (map pr-str (read-string-safely code)))
           results (if (empty? user-forms)
@@ -184,10 +186,11 @@
     (catch Throwable t {:message (.getMessage t), :url *url*
                         :num-tests-passed 0})))

-(defn static-run-code [id raw-code]
+(defn static-run-code [id code]
+  (session/flash-put! :code code)
   (let [{:keys [message url num-tests-passed]}
         (binding [*url* (str *url* "#prob-desc")]
-          (run-code id raw-code))]
+          (run-code id code))]
     (session/flash-put! :failing-test num-tests-passed)
     (flash-msg message url)))

@@ -453,10 +456,10 @@
   (POST "/problem/reject" [id]
     (reject-problem (Integer. id) "We didn't like your problem."))
   (POST "/problem/:id" [id code]
-    (static-run-code (Integer. id) code))
+    (static-run-code (Integer. id) (trim-code code)))
   (POST "/rest/problem/:id" [id code]
      {:headers {"Content-Type" "application/json"}}
-     (rest-run-code (Integer. id) code))
+     (rest-run-code (Integer. id) (trim-code code)))
   (GET "/problems/rss" [] (create-feed
                            "4Clojure: Recent Problems"
                            "http://4clojure.com/problems"


Store / get currently selected statement for reference

--- src/discuss/utils/common.cljs
+++ src/discuss/utils/common.cljs
@@ -34,6 +34,7 @@
                              :statement  ""
                              :selection  nil
                              :selected-reference nil
+                             :selected-statement nil
                              :logged-in? false}
                 :clipboard  {:selections nil
                              :current    nil}
@@ -155,6 +156,15 @@
   []
   (get-in @app-state [:user :selected-reference]))

+(defn save-selected-statement!
+  "Saves the currently clicked reference for further processing."
+  [statement]
+  (update-state-item! :user :selected-statement (fn [_] statement)))
+
+(defn selected-statement
+  "Returns the currently selected reference."
+  []
+  (get-in @app-state [:user :selected-statement]))

 ;;;; CSRF Token
 (defn get-csrf


Fixed indentation after let forms.

Fixed indentation after let forms.

--- src/clj_formal_specifications_app/core.clj
+++ src/clj_formal_specifications_app/core.clj
@@ -17,8 +17,8 @@
 (defn example
   [path]
   (let [filename (peek (str/split path #"/"))]
-  {:title (filename-as-text filename)
-   :filename filename}))
+    {:title (filename-as-text filename)
+     :filename filename}))

 (defn files-as-strings
   [dir]
@@ -74,7 +74,7 @@
 (defn compose
   [spec]
   (let [ns (get-ns-name spec)]
-  {:body (do (remove-ns (symbol ns)) (load-string spec) ns)}))
+    {:body (do (remove-ns (symbol ns)) (load-string spec) ns)}))

 (defn execute-with-ns
   [ns command]


allow returning nil from message emitter to indicate no change (cached previous value)

--- src/cljx/jamesmacaulay/zelkova/signal.cljx
+++ src/cljx/jamesmacaulay/zelkova/signal.cljx
@@ -56,9 +56,8 @@
     {:sources [:events]
      :relayed-event-topics topics
      :msg-fn (fn [prev [event]]
-               (if (contains? topics (:topic event))
-                 (->Fresh (:value event))
-                 (->Cached (:value prev))))}))
+               (when (contains? topics (:topic event))
+                 (->Fresh (:value event))))}))

 (defrecord Signal
   [init message-emitter deps event-sources]
@@ -118,9 +117,8 @@
                        (core/map ->Fresh))
                  conj)
         msg-fn (fn [prev [msg :as msg-in-seq]]
-                 (if (fresh? msg)
-                   (reduce reducer [] msg-in-seq)
-                   (->Cached (:value prev))))
+                 (when (fresh? msg)
+                   (reduce reducer [] msg-in-seq)))
         pipelined-init-msg (->> (:init sig) ->Fresh vector (msg-fn nil) last)
         init-val (if (nil? pipelined-init-msg)
                    base
@@ -135,9 +133,8 @@
     (constant (f))
     (let [sources (vec sources)
           emit-message (fn [prev messages]
-                         (if (some fresh? messages)
-                           (->Fresh (apply f (mapv :value messages)))
-                           (->Cached (:value prev))))]
+                         (when (some fresh? messages)
+                           (->Fresh (apply f (mapv :value messages)))))]
       (map->Signal {:init (->> sources
                                (mapv (comp ->Fresh :init))
                                (emit-message nil)
@@ -161,19 +158,18 @@
   (map->Signal {:init init
                 :message-emitter {:sources [source]
                                   :msg-fn (fn [acc [message]]
-                                            (if (fresh? message)
-                                              (->Fresh (f (:value message) (:value acc)))
-                                              (->Cached (:value acc))))}}))
+                                            (when (fresh? message)
+                                              (->Fresh (f (:value message)
+                                                          (:value acc)))))}}))

 (defn drop-repeats
   [sig]
   (map->Signal {:init (:init sig)
                 :message-emitter {:sources [sig]
                                   :msg-fn (fn [prev [msg]]
-                                            (if (and (fresh? msg)
-                                                     (not= (:value msg) (:value prev)))
-                                              msg
-                                              (->Cached (:value prev))))}}))
+                                            (when (and (fresh? msg)
+                                                       (not= (:value msg) (:value prev)))
+                                              msg))}}))

 (defn reducep
@@ -208,8 +204,7 @@
   (map->Signal {:init (:init (first sigs))
                 :message-emitter {:sources sigs
                                   :msg-fn (fn [prev messages]
-                                            (or (first (filter fresh? messages))
-                                                (->Cached (:value prev))))}}))
+                                            (first (filter fresh? messages)))}}))

 (defn merge
   [& sigs]
@@ -224,9 +219,8 @@
   (map->Signal {:init (:init value-sig)
                 :message-emitter {:sources [sampler-sig value-sig]
                                   :msg-fn (fn [prev [sampler-msg value-msg]]
-                                            (if (fresh? sampler-msg)
-                                              (->Fresh (:value value-msg))
-                                              (->Cached (:value prev))))}}))
+                                            (when (fresh? sampler-msg)
+                                              (->Fresh (:value value-msg))))}}))

 (defn count
   [sig]
@@ -246,10 +240,9 @@
                         base)
                 :message-emitter {:sources [sig]
                                   :msg-fn (fn [prev [msg]]
-                                            (if (and (fresh? msg)
-                                                     (pred (:value msg)))
-                                              (->Fresh (:value msg))
-                                              (->Cached (:value prev))))}}))
+                                            (when (and (fresh? msg)
+                                                       (pred (:value msg)))
+                                              (->Fresh (:value msg))))}}))

 (defn drop-if
   [pred base sig]
@@ -330,9 +323,12 @@

 (defn- ensure-sequential
   [x-or-xs]
-  (if (sequential? x-or-xs) x-or-xs [x-or-xs]))
-
-(defn pad
+  (cond
+    (sequential? x-or-xs) x-or-xs
+    (nil? x-or-xs) []
+    :else [x-or-xs]))
+
+(defn- pad
   [msg-lists]
   (if (>= 1 (core/count msg-lists))
     msg-lists
@@ -342,11 +338,11 @@
                      (into [] (comp cat (take max-count)))))]
       (core/map pad msg-lists))))

-(defn transpose
+(defn- transpose
   [msg-lists]
   (apply core/map vector msg-lists))

-(defn wrap-msg-fn
+(defn- wrap-msg-fn
   [msg-fn]
   (let [msg-fn (comp ensure-sequential msg-fn)]
     (fn [prev msg-payloads]


changed get to nth in mixture

changed get to nth in mixture

--- src/distributions/mixture.clj
+++ src/distributions/mixture.clj
@@ -47,7 +47,7 @@
            components (:components d)
            n (count weights)
            i (sample (discrete-integer (range 0 n) weights))]
-       (sample (get components i))))
+       (sample (nth components i))))
     ([d n] (take n (repeatedly #(sample d))))))


Directly pull the melody together instead of cryptically using =>.

--- src/overtunes/songs/canone_alla_quarta.clj
+++ src/overtunes/songs/canone_alla_quarta.clj
@@ -42,7 +42,7 @@
            :pitch (runs [[4] [4] [2 -3] [-1 -2] [0] [3 5] [1] [1] [1 2] [-1 1 -1] [5 0]])}
         line
           (merge-with concat call response development)]
-    (=> line #(update-in % [:length] sums) #(map vector (:length %) (:pitch %)))))
+    (map vector (sums (:length line)) (:pitch line))))

 (def bassline
   (map vector


implementing find-attr-node-test

implementing find-attr-node-test

--- test/synthesis_crawlers/core_test.clj
+++ test/synthesis_crawlers/core_test.clj
@@ -107,3 +107,7 @@
                                #{}))
            '("http://www.economist.com")))))

+#_(deftest find-attr-nodes-test
+  (testing "finds nodes which contain the specified attributes"
+    )
+  )


use proper thread-bound? check for nrepl vars

fixes #520

--- src/main/shadow/cljs/devtools/api.clj
+++ src/main/shadow/cljs/devtools/api.clj
@@ -438,7 +438,7 @@
            ;; switch REPL type to cljs. can't get to the nrepl session from here.
            (try
              (let [^Var pvar (find-var 'cemerick.piggieback/*cljs-compiler-env*)]
-               (when (and pvar (.isBound pvar))
+               (when (and pvar (thread-bound? pvar))
                  (.set pvar
                    (reify
                      clojure.lang.IDeref
@@ -450,7 +450,7 @@

            (try
              (let [^Var pvar (find-var 'cider.piggieback/*cljs-compiler-env*)]
-               (when (and pvar (.isBound pvar))
+               (when (and pvar (thread-bound? pvar))
                  ;; for reasons I do not understand this set! fails with
                  ;; java.lang.IllegalStateException: Can't change/establish root binding of: *cljs-compiler-env* with set
                  ;; although I do check isBound above?


add missing CLI remote fn

add missing CLI remote fn

--- src/main/shadow/cljs/devtools/cli.clj
+++ src/main/shadow/cljs/devtools/cli.clj
@@ -73,3 +73,7 @@
                  (System/exit 1)))]

     (apply actual-main args)))
+
+(defn from-remote [complete-token error-token args]
+  (let [actual (requiring-resolve 'shadow.cljs.devtools.cli-actual/from-remote)]
+    (actual complete-token error-token args)))


use SNS unless an exception is thrown, then use kinesis

--- src/oc/storage/async/notification.clj
+++ src/oc/storage/async/notification.clj
@@ -76,11 +76,23 @@
   (timbre/trace "Notification request:" trigger)
   (schema/validate NotificationTrigger trigger)
   (timbre/info "Sending request to topic:" config/aws-sns-storage-topic-arn)
-  (fh/put-record config/aws-kinesis-stream-name
-                 {:subject (str (name (:notification-type trigger))
-                                 " on " (name (:resource-type trigger))
-                                 ": " (-> trigger :current :uuid))
-                  :Message (json/generate-string trigger {:pretty true})})
+  (let [subject (str (name (:notification-type trigger))
+                     " on " (name (:resource-type trigger))
+                     ": " (-> trigger :current :uuid))]
+    (try
+      (sns/publish
+       {:access-key config/aws-access-key-id
+        :secret-key config/aws-secret-access-key}
+       :topic-arn config/aws-sns-storage-topic-arn
+       :subject subject
+       :message (json/generate-string trigger {:pretty true}))
+      (catch Exception e
+        (timbre/info "SNS failed with: " e)
+        ;; If an exception occurred write to the kinesis firehouse.
+        (fh/put-record
+          config/aws-kinesis-stream-name
+          {:subject subject
+           :Message (json/generate-string trigger {:pretty true})}))))
   (timbre/info "Request sent to topic:" config/aws-sns-storage-topic-arn))

 ;; ----- Event loop -----


RR: pass session for user-routes

RR: pass session for user-routes

--- tests/clj/ona/viewer/routes_tests.clj
+++ tests/clj/ona/viewer/routes_tests.clj
@@ -19,11 +19,13 @@
 (facts "user-routes"
   (fact "GET /temp-token should calls get-token"
     (user-routes (route-params :get
-                               (str "/" username "/temp-token"))) => (contains result)
+                               (str "/" username "/temp-token")
+                               session)) => (contains result)
     (provided
       (accounts/get-token :fake-account username) => result))
   (fact "GET /validate-token calls validate-token"
      (user-routes (route-params :get
-                                (str "/" username "/validate-token"))) => (contains result)
+                                (str "/" username "/validate-token")
+                                session)) => (contains result)
      (provided
        (accounts/validate-token :fake-account username) => result)))


Fix bug

Fix bug

--- src/halake_api/routes/api.clj
+++ src/halake_api/routes/api.clj
@@ -41,8 +41,9 @@
         (update-status temperature humidity congestion)))

 (defn wrap-authorize [app]
-  (fn [{{:keys [halake-api-key]} :headers :as req}]
-    (if (= halake-api-key @#'halake-api-key)
+  (fn [{{:strs [x-halake-api-key]} :headers :as req}]
+    (if (and (not (nil? x-halake-api-key))
+             (= x-halake-api-key halake-api-key))
       (app req)
       (response/response {:status :error, :messsage "Authorization required"}))))


Clarify limit text

Clarify limit text

--- src/qu/views.clj
+++ src/qu/views.clj
@@ -204,7 +204,7 @@
      {:key "where"    :label "Where"            :bootstrap_span 12     :tooltip_title "Where Clause"     :tooltip_body "Filters the result set via a subset of SQL syntax. Supports standard comparison and boolean operators. See the API documentation for more details." }
      {:key "group"    :label "Group By"         :bootstrap_span 6      :tooltip_title "Group By Clause"  :tooltip_body "As in SQL, projects rows with common values into a smaller set. Supports the aggregation functions SUM, MIN, MAX, and COUNT. Requires a select clause."}
      {:key "orderBy"  :label "Order By"         :bootstrap_span 6      :tooltip_title "Order By Clause"  :tooltip_body "A comma-delimited list of fields used to sort the result set. As with SQL, use DESC for descending order. If blank, the order will be consistent but unspecified."}
-     {:key "limit"    :label "Limit"            :bootstrap_span 1      :tooltip_title "Limit Clause"     :tooltip_body "The maximum number of results to return. Defaults to 100. For HTML output format, the hard limit is 10,000 results."}
+     {:key "limit"    :label "Limit"            :bootstrap_span 1      :tooltip_title "Limit Clause"     :tooltip_body "The maximum number of results to return. Defaults to 100. HTML returns are limited to 10,000 results. Other formats are not limited."}
      {:key "offset"   :label "Offset"           :bootstrap_span 1      :tooltip_title "Offset Clause"    :tooltip_body "Zero-based offset to start the result set from. Defaults to 0."}
      ])


Revert 524bcab, remove flush after writing csv

--- src/qu/views.clj
+++ src/qu/views.clj
@@ -49,8 +49,7 @@
          (response/content-type "text/html"))))

 (defn- write-csv [data]
-  (with-out-str (csv/write-csv *out* data))
-  (flush))
+  (with-out-str (csv/write-csv *out* data)))

 (defn slice-html
   [view-map]


Refactor vary.

Refactor vary.

--- src/african_polyphony_and_polyrhythm/talk.clj
+++ src/african_polyphony_and_polyrhythm/talk.clj
@@ -12,7 +12,7 @@
 ; Ostinato with variations ;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-(defn vary
+(defn target
   "Apply f to the note at time t."
   [t f]
   (fn [notes]
@@ -27,18 +27,18 @@
   (letfn [(f [note]
             [(-> note (assoc :duration duration))
              (-> note (update :duration - duration) (update :time + duration))])]
-    (vary t f)))
+    (target t f)))

 (defn accent
   "Accent the pitch of the note at time t."
   [t]
   (letfn [(f [note] [(-> note (update :pitch dec))])]
-    (vary t f)))
+    (target t f)))

 (defn skip
   "Skip the note at time t."
   [t]
-  (vary t (constantly [])))
+  (target t (constantly [])))

 (defn rand-variations
   "Assemble an infinite random concatenation of variations."
@@ -53,10 +53,10 @@
 (defn part
   "Generate version of the model using the variations fns."
   [instrument model & variations]
-  (->>
-    model
-    ((apply juxt identity variations))
-    (map (partial all :part instrument))))
+  (let [vary (apply juxt identity variations)]
+    (->> model
+         vary
+         (map #(all :part instrument %)))))

 (defn introduce-after
   "Gradually introduce each part after t beats."
@@ -72,7 +72,7 @@
 ;;;;;;;;;;;;;;

 (def child
-  (let [model (->> (rhythm [2/5 3/5 1/5 1/5 3/5]) (all :part :child))
+  (let [model (rhythm [2/5 3/5 1/5 1/5 3/5])
         a (split 6/5 1/10)
         b (split 5/5 1/10)
         c (comp (split 17/15 2/15) (split 5/5 2/15) (skip 6/5))
@@ -80,7 +80,7 @@
     (part :child model a b c d)))

 (def mother
-  (let [model (->> (rhythm [2/5 2/5 4/5 1/5 1/5]))
+  (let [model (rhythm [2/5 2/5 4/5 1/5 1/5])
         a (skip 9/5)
         b (skip 0)
         c (comp a b)
@@ -88,7 +88,7 @@
     (part :mother model a b c d)))

 (def father
-  (let [model (->> (rhythm [2/5 1/5 2/5]))
+  (let [model (rhythm [2/5 1/5 2/5])
         a (skip 2/5)
         b (skip 3/5)
         c (comp (split 0 1/5) a)


more utilities to model

more utilities to model

--- src/be/ac/ua/aspchecker/model.clj
+++ src/be/ac/ua/aspchecker/model.clj
@@ -2,8 +2,24 @@
   (:require [damp.ekeko :as ek])
   (:require [damp.ekeko.aspectj.weaverworld :as eaj])
   (:require [damp.ekeko.jdt [astnode :as ast]])
-  (:require [damp.ekeko.jdt.convenience :as conv]))
+  (:require [damp.ekeko.jdt.convenience :as conv])
+  (:require [damp.ekeko.jdt.astbindings :as astb]))

+
+
+(defn shadows
+  []
+  (ek/ekeko [?advice ?shadow]
+            (eaj/advice-shadow
+              ?advice
+              ?shadow)))
+
+(defn annotations
+  []
+  (ek/ekeko [?annotation ?binding]
+            (astb/ast|annotation-binding|annotation
+              ?annotation
+              ?binding)))

 (defn annotations|requires
   []


Specify where NONE is in regex*.

Specify where NONE is in regex*.

--- src/clj/com/rpl/specter/navs.cljc
+++ src/clj/com/rpl/specter/navs.cljc
@@ -480,7 +480,7 @@

 (defnav regex* [re]
   (select* [this structure next-fn]
-           (doseqres NONE [s (re-seq re structure)]
+           (doseqres i/NONE [s (re-seq re structure)]
                      (next-fn s)))
   (transform* [this structure next-fn]
               (clojure.string/replace structure re next-fn)))


Product Recall has to account for trash cost modifiers

e.g. Industrial Genomics increased trash cost--per Business First UFAQ

--- src/clj/game/cards-operations.clj
+++ src/clj/game/cards-operations.clj
@@ -422,9 +422,14 @@
    {:prompt "Choose a rezzed asset or upgrade to trash"
     :choices {:req #(and (rezzed? %)
                          (or (is-type? % "Asset") (is-type? % "Upgrade")))}
-    :msg (msg "trash " (card-str state target) " and gain " (:trash target) " [Credits]")
-    :effect (effect (trash target)
-                    (gain :credit (:trash target)))}
+    :effect (req (let [c target]
+                   (trigger-event state side :pre-trash c)
+                   (let [tcost (trash-cost state side c)]
+                     (trash state side c)
+                     (gain state :corp :credit tcost)
+                     (resolve-ability state side
+                       {:msg (msg "trash " (card-str state c) " and gain " tcost " [Credits]")}
+                      card nil))))}

    "Psychographics"
    {:req (req tagged) :choices :credit :prompt "How many credits?"


Activity add datepicker kind of works.

Activity add datepicker kind of works.

--- src/cljs/elevent_client/core.cljs
+++ src/cljs/elevent_client/core.cljs
@@ -14,7 +14,8 @@
       [alandipert.storage-atom :refer [local-storage]]
       [ajax.core :refer [DELETE GET POST PUT]]
       [cljs-time.coerce :refer [from-string to-string from-long to-long from-date to-date]]
-      [cljs-time.core :refer [after? at-midnight now plus minus hours]]
+      [cljs-time.core :refer [after? at-midnight now plus minus hours days minutes date-midnight local-date
+                              local-date-time year month day hour minute]]
       [cljs-time.format :refer [formatter formatters unparse parse]]
       [datascript :as d]
       [garden.core :refer [css]]
@@ -386,7 +387,7 @@
   min-date-atom: atom representing the minimum date for the selector.
   pikaday-attrs: a map of options to be passed to the Pikaday constructor.
   input-attrs: a map of options to be used as <input> tag attributes."
-  [{:keys [date-atom max-date-atom min-date-atom pikaday-attrs input-attrs]}]
+  [{:keys [date-atom max-date-atom min-date-atom pikaday-attrs input-attrs static-attrs]}]
   (let [in #(if (from-string %)
               (unparse input-date-time-formatter (from-string %))
               %)
@@ -398,7 +399,18 @@
                                (unparse (:date-hour-minute formatters) (parse input-date-time-formatter %))
                                %))
         normalize ; because of GMT
-        #(to-date (plus (from-string %) (hours 6)))]
+        #(to-date (plus (from-string %) (hours 6)))
+        min-date (when (:min-date static-attrs) (:min-date static-attrs))
+        max-date (when (:max-date static-attrs) (:max-date static-attrs))
+        set-date! (fn [new-date]
+                    (when (and date-atom new-date)
+                      (if (and min-date max-date)
+                        (if (after? (from-date new-date) max-date)
+                          (reset! date-atom (out (to-string max-date)))
+                          (if (after? min-date (from-date new-date))
+                            (reset! date-atom (out (to-string min-date)))
+                            (reset! date-atom (out (to-string (minus (from-date new-date) (hours 6)))))))
+                        (reset! date-atom (out (to-string (minus (from-date new-date) (hours 6))))))))]
     (r/create-class
       {:component-did-mount
         (fn [this]
@@ -406,9 +418,16 @@
                 {:field (.getDOMNode this)
                  :defaultDate @date-atom
                  :setDefaultDate true
-                 :onSelect #(when date-atom (reset! date-atom (out (to-string (minus (from-date %) (hours 6))))))}
-                opts (clj->js (merge default-opts pikaday-attrs))
-                instance (js/Pikaday. opts)]
+                 :onSelect set-date!}
+                opts (merge default-opts pikaday-attrs)
+                instance (js/Pikaday. (clj->js opts))]
+            (when (and (:defaultDate opts)
+                       (:setDefaultDate opts))
+              (when (from-date (:defaultDate opts))
+                (-> this
+                    r/dom-node
+                    js/jQuery
+                    (.val (in (to-string (minus (from-date (:defaultDate opts)) (hours 6))))))))
             ; This code could probably be neater
             (when date-atom
               (add-watch date-atom :update-instance
@@ -1449,7 +1468,9 @@
                                   (presence-of :EndTime)
                                   (format-of :EnrollmentCap :format #"^\d*$"
                                              :allow-blank true
-                                             :allow-nil true))]
+                                             :allow-nil true)
+                                  (format-of   :StartTime :format #"\d\d\d\d-\d\d-\d\dT\d\d:\d\d")
+                                  (format-of   :EndTime   :format #"\d\d\d\d-\d\d-\d\dT\d\d:\d\d"))]
     (when activity-id
       (if-let [activity (seq (d/entity @activities-db activity-id))]
         (reset! form (let [activity (into {} activity)]
@@ -1529,21 +1550,41 @@
                                      "error")}
                 [:label "Enrollment Cap"]
                 [input-atom :text {} (r/wrap EnrollmentCap swap! form assoc :EnrollmentCap)]]]
-              [:div.two.fields =
-               [:div.required.field {:class (when (and StartTime (:StartTime errors))
-                                              "error")}
-                [:label "Start Time"]
-                [input-atom :datetime-local {}
-                 (r/wrap StartTime swap! form assoc :StartTime)
-                 #(or % (unparse (:date-hour-minute formatters) (now))) ; todo: date inputs clear on input
-                 #(unparse (:date-hour-minute formatters) (from-string %))]]
-               [:div.required.field {:class (when (and EndTime (:EndTime errors))
-                                              "error")}
-                [:label "End Time"]
-                [input-atom :datetime-local {}
-                 (r/wrap EndTime swap! form assoc :EndTime)
-                 #(or % (unparse (:date-hour-minute formatters) (now)))
-                 #(unparse (:date-hour-minute formatters) (from-string %))]]]
+              (let [start-time     (r/wrap StartTime swap! form assoc :StartTime)
+                    end-time       (r/wrap EndTime swap! form assoc :EndTime)
+                    event-start    (let [d (from-string (:StartDate event))]
+                                     (local-date-time (year d) (month d) (day d) (hour d) (minute d)))
+                    event-end      (let [d (from-string (:EndDate event))]
+                                     (local-date-time (year d) (month d) (day d) (hour d) (minute d)))
+                    event-start-js (let [d (from-string (:StartDate event))]
+                                     (to-date (date-midnight (local-date (year d) (month d) (day d)))))
+                    event-end-js   (let [d (from-string (:EndDate event))]
+                                     (to-date (date-midnight (local-date-time (year d) (month d) (day d) 23 59))))]
+                [:div.two.fields
+                 [:div.required.field {:class (when (and StartTime (:StartTime errors))
+                                                "error")}
+                  [:label "Start Time"]
+                  [date-selector {:date-atom start-time
+                                  :max-date-atom end-time
+                                  :pikaday-attrs {:minDate event-start-js
+                                                  :maxDate event-end-js
+                                                  :defaultDate event-start
+                                                  :setDefaultDate false
+                                                  }
+                                  :static-attrs  {:min-date event-start
+                                                  :max-date event-end}}]]
+                 [:div.required.field {:class (when (and EndTime (:EndTime errors))
+                                                "error")}
+                  [:label "End Time"]
+                  [date-selector {:date-atom end-time
+                                  :min-date-atom start-time
+                                  :pikaday-attrs {:minDate event-start-js
+                                                  :maxDate event-end-js
+                                                  :defaultDate event-start
+                                                  :setDefaultDate false
+                                                  }
+                                  :static-attrs  {:min-date event-start
+                                                  :max-date event-end}}]]])
               [:div.field
                [:label "Description"]
                [input-atom :textarea {}


refactor move (expriments

refactor move (expriments

--- src/cljs/triboard/logic/move.cljs
+++ src/cljs/triboard/logic/move.cljs
@@ -121,24 +121,28 @@
 ;; (require '[clojure.test.check.generators :as gen])
 ;; (def b (first (gen/sample (s/gen ::board/board) 1)))

+(defn map-values
+  "Apply a function to the values of a key-value collection"
+  [xf coll]
+  (into {}
+    (map (fn [[k v]] [k (xf v)]))
+    coll))
+
 (defn available-transitions
   [board]
-  (into {}
-    (map
+  (map-values
+    (partial map-values
+      (fn [moves]
+        {:transition moves                                  ;; TODO - Add empty move (or add one to score...)
+         :board (delay (apply-conversions board moves))}
+        ))

-      (fn [[winner moves-by-pos]]                           ;; TODO - This is double Map.fmap
-        [winner
-         (into {}
-           (map (fn [[pos moves]]
-                  [pos {:transition moves                   ;; TODO - Add empty move
-                        :board (delay (apply-conversions board moves))}]
-                  ))
-           moves-by-pos)
-         ])
+    (transduce
+      (mapcat #(available-conversions-at board %))
+      #(update-in %1 [(:winner %2) (:point %2)] conj %2)    ;; TODO - List of conversions
+      {}
+      (board/empty-cells board)))
+  )

-      (transduce
-        (mapcat #(available-conversions-at board %))
-        #(update-in %1 [(:winner %2) (:point %2)] conj %2)  ;; TODO - List of conversions
-        {}
-        (board/empty-cells board))))
-  )
+
+


Added support for starting point path

Added support for starting point path

--- src/clojure/staircase/handler.clj
+++ src/clojure/staircase/handler.clj
@@ -187,8 +187,9 @@
 (defn- build-app-routes [{conf :config :as router}]
   (routes
     (GET "/" [] (views/index))
+    (GET "/about" [] (views/index))
     (GET "/history/:id/:idx" [] (views/index))
-    (GET "/about" [] (views/index))
+    (GET "/starting-point/:tool" [] (views/index))
     (GET "/tools" [capabilities] (response (get-tools conf capabilities)))
     (GET "/tools/:id" [id] (if-let [tool (get-tool conf id)]
                              (response tool)


added intermine-tools.github.io to friendly-hosts list. This should fix the crazy font loading in iframe tools, as the iframes weren't trusted and were being told No by CORS headers.

--- src/clojure/staircase/handler.clj
+++ src/clojure/staircase/handler.clj
@@ -125,7 +125,7 @@
 (defn- build-app-routes [{conf :config :as app}]
   (let [serve-index #(views/index @conf)
         greedy #".+"]
-    (routes
+    (routes
       (GET "/" [] (serve-index))
       (GET "/about" [] (serve-index))
       (GET "/projects" [] (serve-index))
@@ -204,9 +204,12 @@
         (handler request)))))

 ;; Move to config! TODO
-(def friendly-hosts [ #"http://localhost:"
+(def friendly-hosts [ #"http://localhost:" ;; iframe tools will not be allowed to access fonts if the iframe source is not configure in this list
+                                           ;; the primary symptom of this is crazy icons which are defaulting to system wierdness, and cors font
+                                           ;; errors in the console.
                      #"http://[^/]*labs.intermine.org"
                      #"http://intermine.github.io"
+                     #"http://intermine-tools.github.io"
                      #"http://alexkalderimis.github.io"])

 (defn allowed-origins


Trace log config values for system properties and env.

--- src/cmr/metadata/proxy/config.clj
+++ src/cmr/metadata/proxy/config.clj
@@ -60,14 +60,16 @@
   (->> (#'environ/read-system-props)
        (map normalize-prop)
        (remove nil?)
-       (reduce nest-vars {})))
+       (reduce nest-vars {})
+       ((fn [x] (log/trace "props-data:" x) x))))

 (defn env-data
   []
   (->> (#'environ/read-system-env)
        (map normalize-env)
        (remove nil?)
-       (reduce nest-vars {})))
+       (reduce nest-vars {})
+       ((fn [x] (log/trace "env-data:" x) x))))

 (defn data
   []


Allow callers to run functions within the scope of a transaction.

This generalizes the transactor loop to allow callers to run
an arbitrary function within an `in-transaction!` body.

Combined with exposing `<report-transact-tx-data!`, this allows
an admittedly sophisticated consumer to conditionally query and
transact in a consistent way -- for example, cleaning up inconsistent
data then transacting a new schema version.

--- src/common/datomish/transact.cljc
+++ src/common/datomish/transact.cljc
@@ -791,14 +791,14 @@
       (-> report
           (assoc-in [:db-after] db-after)))))

-(defn- <with [db tx-data]
+(defn <transact-tx-data-in-transaction! [db tx-data]
   (let [fail-touch-attr  (fn [old new] (raise "Altering schema attributes is not yet supported, got " new " altering existing schema attribute " old
                                               {:error :schema/alter-schema :old old :new new}))]
     (<with-internal db tx-data fail-touch-attr)))

-(defn <db-with [db tx-data]
+(defn <db-transact-tx-data! [db tx-data]
   (go-pair
-    (:db-after (<? (<with db tx-data)))))
+    (:db-after (<? (<transact-tx-data-in-transaction! db tx-data)))))

 (defn <transact!
   "Submits a transaction to the database for writing.
@@ -806,11 +806,15 @@
   Returns a pair-chan resolving to `[result error]`."
   ([conn tx-data]
    (<transact! conn tx-data (a/chan 1) true))
-  ([conn tx-data result close?]
+  ([conn tx-data-or-fn result close?]
    {:pre [(conn? conn)]}
    ;; Any race to put! is a real race between callers of <transact!.  We can't just park on put!,
    ;; because the parked putter that is woken is non-deterministic.
-   (let [closed? (not (a/put! (:transact-chan conn) [:sentinel-transact tx-data result close?]))]
+   (let [op (if (fn? tx-data-or-fn)
+              :sentinel-fn
+              :sentinel-transact)
+         closed? (not (a/put! (:transact-chan conn)
+                              [op tx-data-or-fn result close?]))]
      (go-pair
        ;; We want to return a pair-chan, no matter what kind of channel result is.
        (if closed?
@@ -823,30 +827,50 @@
       (>! token-chan (gensym "transactor-token"))
       (loop []
         (when-let [token (<! token-chan)]
-          (when-let [[sentinel tx-data result close?] (<! (:transact-chan conn))]
-            (let [pair
-                  (<! (go-pair ;; Catch exceptions, return the pair.
-                        (case sentinel
-                          :sentinel-close
-                          ;; Time to close the underlying DB.
-                          (<? (db/close-db @(:current-db conn)))
-
-                          ;; Default: process the transaction.
-                          (do
-                            (when @(:closed? conn)
-                              ;; Drain enqueued transactions.
-                              (raise "Connection is closed" {:error :transact/connection-closed}))
-                            (let [db (db conn)
-                                  report (<? (db/in-transaction!
-                                               db
-                                               #(-> (<with db tx-data))))]
-                              (when report
-                                ;; <with returns non-nil or throws, but we still check report just in
-                                ;; case.  Here, in-transaction! function completed and returned non-nil,
-                                ;; so the transaction has committed.
-                                (reset! (:current-db conn) (:db-after report))
-                                (>! (:listener-source conn) report))
-                              report)))))]
+          (when-let [[sentinel tx-data-or-fn result close?] (<! (:transact-chan conn))]
+            (let
+              [pair
+               (<!
+                 (go-pair ;; Catch exceptions, return the pair.
+                   (case sentinel
+                     :sentinel-close
+                     ;; Time to close the underlying DB.
+                     (<? (db/close-db @(:current-db conn)))
+
+                     ;; Default: process the transaction.
+                     (do
+                       (when @(:closed? conn)
+                         ;; Drain enqueued transactions.
+                         (raise "Connection is closed" {:error :transact/connection-closed}))
+
+                       (let [db (db conn)
+                             in-transaction-fn
+                             (case sentinel
+                               :sentinel-fn
+                               ;; This is a function that we'd like to run
+                               ;; within a database transaction. See
+                               ;; db/in-transaction! for details.
+                               ;; The function is invoked with two arguments:
+                               ;; the db and a function that takes (db,
+                               ;; tx-data) and transacts it to return a
+                               ;; TxReport.
+                               ;; The function must return a TxReport.
+                               ;; The function must not itself call
+                               ;; `in-transaction!` or `<transact!`.
+                               (partial tx-data-or-fn db <transact-tx-data-in-transaction!)
+
+                               :sentinel-transact
+                               ;; This is data. Apply it with `<transact-tx-data-in-transaction!`.
+                               (partial <transact-tx-data-in-transaction! db tx-data-or-fn))
+
+                               report (<? (db/in-transaction! db in-transaction-fn))]
+                         (when report
+                           ;; <r-t-t-d! returns non-nil or throws, but we still check report just in
+                           ;; case.  Here, in-transaction! function completed and returned non-nil,
+                           ;; so the transaction has committed.
+                           (reset! (:current-db conn) (:db-after report))
+                           (>! (:listener-source conn) report))
+                         report)))))]
               ;; Even when report is nil (transaction not committed), pair is non-nil.
               (>! result pair))
             (>! token-chan token)


Add db/get-albums

Add db/get-albums

--- src/trak/db.cljs
+++ src/trak/db.cljs
@@ -22,3 +22,12 @@
   (->> collection-of-ids
        (map first)
        (map #(d/entity db %))))
+
+
+;; Data retrieval
+
+(defn get-albums [db]
+  (unpack-entities db (d/q '[:find ?album
+                             :where [?album :album/id _]]
+                           db)))
+


allow creating a task

allow creating a task

NOTE: I had to pass reconciler to transact! instead of the component
otherwise I would get an error similar to::

    Error: No queries exist for component path (tudu.ui/UI tudu.ui/NewTodoItemUI)

To have a form to edit the new task we add a new key to the initial
state called :tudu.item/editing which contains the state of the task we
are editing, for now it's only the title, but later it could include
something else.

we add an input to enter the title, on change it sets the title on
tudu.item/editing to the new value by calling the mutator tudu.item.editing/set-title

on click of the button we call tudu.item/create passing the content of
tudu.item/editing in the mutator we add a temp id (the current
timestamp) and set the status to open.

--- src/tudu/ui.cljs
+++ src/tudu/ui.cljs
@@ -4,14 +4,18 @@
             [om.dom :as dom]))

 (enable-console-print!)
+(declare reconciler)

-(def initial-state {:tudu/items
+(def clean-item-editing {:title ""})
+
+(def initial-state {:tudu.item/editing clean-item-editing
+                    :tudu/items
                     [{:id 1 :status :close :title "Implement this Step"}
                      {:id 2 :status :open :title "Buy Food"}
                      {:id 3 :status :open :title "Implement next Step"}]})

-(defn close-item [component id]
-  (om/transact! component `[(tudu.item/close {:id ~id}) :tudu/items]))
+(defn close-item [c-or-r id]
+  (om/transact! c-or-r `[(tudu.item/close {:id ~id}) :tudu/items]))

 (defui TodoItemUI
   static om/IQuery
@@ -28,7 +32,7 @@
             (dom/div #js {:className "todo-list-item" :key (str "todo-item-" id)}
                      (dom/input #js {:type "checkbox" :disabled closed?
                                      :checked closed?
-                                     :onClick #(close-item this id)})
+                                     :onClick #(close-item reconciler id)})

                      (dom/span #js {:className class-name} title)))))

@@ -46,16 +50,53 @@

 (def todo-list-ui (om/factory TodoListUI))

+(defn on-change-cb [c-or-r callback]
+  (fn [e]
+    (let [target (.-target e)
+          value (.-value target)]
+      (callback c-or-r value))))
+
+(defn task-title-change [c-or-r text]
+  (om/transact! c-or-r `[(tudu.item.editing/set-title {:value ~text})
+                            :tudu.item/editing]))
+
+(defn create-task [c-or-r task]
+  (om/transact! c-or-r `[(tudu.item/create {:task ~task})
+                            :tudu.item/editing :tudu/items]))
+
+(defui NewTodoItemUI
+  static om/IQuery
+  (query [this]
+         [:tudu.item/editing])
+  Object
+  (render [this]
+          (let [{:keys [tudu.item/editing]} (om/props this)
+                {:keys [title]} editing
+                on-change (on-change-cb reconciler task-title-change)]
+            (dom/div #js {:className "new-todo-item-form"}
+                      (dom/div #js {:className "form-group"}
+                               (dom/label nil "Task")
+                               (dom/input #js {:value title
+                                               :onChange on-change}))
+                      ; NOTE: I have to pass the reconciler here and not the
+                      ; component otherwise I get:
+                      ; Error: No queries exist for component path (tudu.ui/UI tudu.ui/NewTodoItemUI)
+                      (dom/button #js {:onClick #(create-task reconciler editing)}
+                                  "Create")))))
+
+(def new-todo-item-ui (om/factory NewTodoItemUI))
+
 (defui UI
   static om/IQuery
   (query [this]
-         ; if I just return (om/get-query TodoListUI) I get
-         ; Error: Assert failed: Query violation
-         (vec (concat (om/get-query TodoListUI))))
+         (vec (concat (om/get-query TodoListUI)
+                      (om/get-query NewTodoItemUI))))
   Object
   (render [this]
           (let [props (om/props this)]
-            (todo-list-ui props))))
+            (dom/div nil
+                     (todo-list-ui props)
+                     (new-todo-item-ui props)))))

 (defmulti read om/dispatch)
 (defmulti mutate om/dispatch)
@@ -77,6 +118,22 @@
              (swap! state
                     #(assoc-in % [:tudu.items/by-id id :status] :close)))})

+(defmethod mutate 'tudu.item.editing/set-title [{:keys [state]} _ {:keys [value]}]
+  {:action (fn []
+             (swap! state
+                    #(assoc-in % [:tudu.item/editing :title] value)))})
+
+(defmethod mutate 'tudu.item/create [{:keys [state]} _ {:keys [task]}]
+  {:action (fn []
+             (let [id (.getTime (js/Date.))
+                   full-task (assoc task :id id :status :open)]
+               (swap! state
+                      #(-> %
+                           (assoc :tudu.item/editing clean-item-editing)
+                           (assoc-in [:tudu.items/by-id id] full-task)
+                           (update :tudu/items
+                                   (fn [s] (conj s [:tudu.items/by-id id])))))))})
+
 (defonce reconciler (om/reconciler
                       {:state initial-state
                        :parser (om/parser {:read read :mutate mutate})}))