Cleanup tests

Cleanup tests

--- test/cljc/reitit/impl_test.cljc
+++ test/cljc/reitit/impl_test.cljc
@@ -11,21 +11,15 @@
 (deftest strip-nils-test
   (is (= {:a 1, :c false} (impl/strip-nils {:a 1, :b nil, :c false}))))

-(deftest into-string-test
-  (is (= "1" (impl/into-string 1)))
-  (is (= "2.2" (impl/into-string 2.2)))
-  (is (= "kikka" (impl/into-string "kikka")))
-  (is (= "kikka" (impl/into-string :kikka)))
-  (is (= "reitit.impl-test/kikka" (impl/into-string ::kikka))))
-
 (deftest url-encode-and-decode-test
   (is (= "reitit.impl-test%2Fkikka" (-> ::kikka
                                         impl/into-string
                                         impl/url-encode)))
-  (is (= "reitit.impl-test/kikka" (-> ::kikka
-                                      impl/into-string
-                                      impl/url-encode
-                                      impl/url-decode))))
+  (is (= ::kikka (-> ::kikka
+                     impl/into-string
+                     impl/url-encode
+                     impl/url-decode
+                     keyword))))

 (deftest path-params-test
   (is (= {:n "1"


fixed unit tests

fixed unit tests

--- ssclj/jar/src/test/clojure/com/sixsq/slipstream/ssclj/usage/launcher_test.clj
+++ ssclj/jar/src/test/clojure/com/sixsq/slipstream/ssclj/usage/launcher_test.clj
@@ -13,7 +13,7 @@
 (defn error-matches?
   [[expected-code expected-msg] [actual-code actual-msg]]
   (is (= expected-code actual-code))
-  (is (.startsWith actual-msg expected-msg))) ;; TODO with a regexp would be better
+  (is (.contains actual-msg expected-msg)))

 (deftest test-launcher-checks-args
   (is (success-matches? ["2015-01-15T00:00:00.0Z" "2015-01-16T00:00:00.0Z"]


Now properly getting a collection of all factions on first page (200) and urls to their respective pages.

--- scraper/src/scraper/core.clj
+++ scraper/src/scraper/core.clj
@@ -33,10 +33,25 @@
 (defn by-tag [html-tree x]
       (by-fn html-tree #(= (tag %) x)))

+(defn get-content [html-tree x]
+      (let [[tag-element attributes-element content-element] x]
+           content-element))
+
+(defn get-attribute [html-tree x]
+      (let [[tag-element attributes-element content-element] html-tree]
+           (attributes-element x)))
+(def factions {})
 ;we'll have to create a method to walk through the vector tree to extract tags/attributes
 (defn -main
-  "Entry point to scraper methods. Pulls in data from project1999's wiki to insert into an SQLite DB."
-  [& args]
-  ;The main wiki page detailing the first 200 factions. This is where we will get a list of faction links to scrape
-  (dorun (map #(tag %) (next parse "http://wiki.project1999.com/index.php?title=Category:Factions")))
+      "Entry point to scraper methods. Pulls in data from project1999's wiki to insert into an SQLite DB."
+      [& args]
+      ;The main wiki page detailing the first 200 factions. This is where we will get a list of faction links to scrape
+      ;(dorun (map #(tag %) (next parse "http://wiki.project1999.com/index.php?title=Category:Factions")))
+      (map
+        #(assoc-in factions [(get-attribute % :title)] {:href (get-attribute % :href)})
+        (-> (parse "http://wiki.project1999.com/index.php?title=Category:Factions")
+            (by-attribute {:class "mw-content-ltr"})
+            (first)
+            (by-tag :a))
+        )
       )


Tests for preemptive authentication.

Tests for preemptive authentication.

--- test/http/async/client/test.clj
+++ test/http/async/client/test.clj
@@ -486,17 +486,29 @@
        200)))

 (deftest preemptive-authentication
-  (is (=
-       (:code (status (GET *client* "http://localhost:8123/preemptive-auth"
-                           :auth {:user "beastie"
-                                  :password "boys"})))
-       401))
-  (is (=
-       (:code (status (GET *client* "http://localhost:8123/preemptive-auth"
-                           :auth {:user "beastie"
-                                  :password "boys"
-				  :preemptive true})))
-       200)))
+  (let [url "http://localhost:8123/preemptive-auth"
+        cred {:user "beastie"
+              :password "boys"}]
+    (testing "Per request configuration"
+      (is (=
+           (:code (status (GET *client* url
+                               :auth cred)))
+           401))
+      (is (=
+           (:code (status (GET *client* url
+                               :auth (assoc cred :preemptive true))))
+           200)))
+    (testing "Global configuration"
+      (with-open [c (create-client :auth (assoc cred :preemptive true))]
+        (testing "Global preemptive, no per request"
+          (is (= 200
+                 (:code (status (GET c url))))))
+        (testing "Global preeptive, per request preemptive"
+          (is (= 200
+                 (:code (status (GET c url :auth (assoc cred :preemptive true)))))))
+        (testing "Global preemptive, per request no preemptive"
+          (is (= 401
+                 (:code (status (GET c url :auth (assoc cred :preemptive false)))))))))))

 (deftest canceling-request
   (let [resp (GET *client* "http://localhost:8123/")]


Make a note that a test is potentially flaky

--- test/lambdacd_git/core_test.clj
+++ test/lambdacd_git/core_test.clj
@@ -209,7 +209,7 @@
       (is (= (commit-hash-by-msg state "initial commit") (:old-revision (step-result state))))
       (is (= (commit-hash-by-msg state "other commit") (:revision (step-result state))))
       (is (str-containing (commit-hash-by-msg state "other commit") (:out (step-result state))))))
-  (testing "that we can pass a function that allows all refs"
+  (testing "that we can pass a function that allows all refs" ; flaky?
     (let [state (-> (init-state)
                     (git-init)
                     (git-commit "initial commit")


test fix

test fix

--- test/metabase/api/user_test.clj
+++ test/metabase/api/user_test.clj
@@ -149,7 +149,7 @@

 ;; Check that a non-superuser CANNOT update someone else's user details
 (expect "You don't have permissions to do that."
-  ((user->client :rasta) :put 403 (str "user/" (user->id :trashbird))))
+  ((user->client :rasta) :put 403 (str "user/" (user->id :trashbird)) {email "toucan@metabase.com"}))

 ;; ## PUT /api/user/:id/password


(maint) Alphabetize Puppet settings

(maint) Alphabetize Puppet settings

This list of settings was initially in alphabetical order, and it's a
little easier to maintain that way.

--- src/clj/puppetlabs/services/config/puppet_server_config_core.clj
+++ src/clj/puppetlabs/services/config/puppet_server_config_core.clj
@@ -25,20 +25,20 @@
     :capub
     :ca-ttl
     :certdir
+    :certname
     :cert-inventory
-    :certname
     :csrdir
-    :keylength
+    :csr-attributes
+    :dns-alt-names
     :hostcert
     :hostcrl
     :hostprivkey
     :hostpubkey
+    :keylength
     :localcacert
+    :requestdir
     :serial
     :signeddir
-    :requestdir
-    :dns-alt-names
-    :csr-attributes
     :ssl-client-header
     :ssl-client-verify-header})


Add regression test for swagger-spec 3arity handler

--- test/cljc/reitit/swagger_test.clj
+++ test/cljc/reitit/swagger_test.clj
@@ -68,66 +68,73 @@
   (testing "swagger-spec"
     (let [spec (:body (app
                         {:request-method :get
-                         :uri "/api/swagger.json"}))]
-      (is (= {:x-id #{::math}
-              :swagger "2.0"
-              :info {:title "my-api"}
-              :paths {"/api/schema/plus/{z}" {:get {:parameters [{:description ""
-                                                                  :format "int32"
-                                                                  :in "query"
-                                                                  :name "x"
-                                                                  :required true
-                                                                  :type "integer"}
-                                                                 {:description ""
-                                                                  :format "int32"
-                                                                  :in "query"
-                                                                  :name "y"
-                                                                  :required true
-                                                                  :type "integer"}
-                                                                 {:in "path"
-                                                                  :name "z"
-                                                                  :description ""
-                                                                  :type "integer"
-                                                                  :required true
-                                                                  :format "int32"}]
-                                                    :responses {200 {:description ""
-                                                                     :schema {:additionalProperties false
-                                                                              :properties {"total" {:format "int32"
-                                                                                :type "integer"}}
-                                                                              :required ["total"]
-                                                                              :type "object"}}
-                                                                400 {:schema {:type "string"}
-                                                                     :description "kosh"}
-                                                                500 {:description "fail"}}
-                                                    :summary "plus"}}
-                      "/api/spec/plus/{z}" {:get {:parameters [{:description ""
-                                                                :format "int64"
-                                                                :in "query"
-                                                                :name "x"
-                                                                :required true
-                                                                :type "integer"}
-                                                               {:description ""
-                                                                :format "int64"
-                                                                :in "query"
-                                                                :name "y"
-                                                                :required true
-                                                                :type "integer"}
-                                                               {:in "path"
-                                                                :name "z"
-                                                                :description ""
-                                                                :type "integer"
-                                                                :required true
-                                                                :format "int64"}]
-                                                  :responses {200 {:description ""
-                                                                   :schema {:properties {"total" {:format "int64"
-                                                                                :type "integer"}}
-                                                                            :required ["total"]
-                                                                            :type "object"}}
-                                                              400 {:schema {:type "string"}
-                                                                   :description "kosh"}
-                                                              500 {:description "fail"}}
-                                                  :summary "plus"}}}}
-             spec)))))
+                         :uri "/api/swagger.json"}))
+          expected {:x-id #{::math}
+                    :swagger "2.0"
+                    :info {:title "my-api"}
+                    :paths {"/api/schema/plus/{z}" {:get {:parameters [{:description ""
+                                                                        :format "int32"
+                                                                        :in "query"
+                                                                        :name "x"
+                                                                        :required true
+                                                                        :type "integer"}
+                                                                       {:description ""
+                                                                        :format "int32"
+                                                                        :in "query"
+                                                                        :name "y"
+                                                                        :required true
+                                                                        :type "integer"}
+                                                                       {:in "path"
+                                                                        :name "z"
+                                                                        :description ""
+                                                                        :type "integer"
+                                                                        :required true
+                                                                        :format "int32"}]
+                                                          :responses {200 {:description ""
+                                                                           :schema {:additionalProperties false
+                                                                                :properties {"total" {:format "int32"
+                                                                                :type "integer"}}
+                                                                                :required ["total"]
+                                                                                :type "object"}}
+                                                                      400 {:schema {:type "string"}
+                                                                           :description "kosh"}
+                                                                      500 {:description "fail"}}
+                                                          :summary "plus"}}
+                            "/api/spec/plus/{z}" {:get {:parameters [{:description ""
+                                                                      :format "int64"
+                                                                      :in "query"
+                                                                      :name "x"
+                                                                      :required true
+                                                                      :type "integer"}
+                                                                     {:description ""
+                                                                      :format "int64"
+                                                                      :in "query"
+                                                                      :name "y"
+                                                                      :required true
+                                                                      :type "integer"}
+                                                                     {:in "path"
+                                                                      :name "z"
+                                                                      :description ""
+                                                                      :type "integer"
+                                                                      :required true
+                                                                      :format "int64"}]
+                                                        :responses {200 {:description ""
+                                                                         :schema {:properties {"total" {:format "int64"
+                                                                                :type "integer"}}
+                                                                                :required ["total"]
+                                                                                :type "object"}}
+                                                                    400 {:schema {:type "string"}
+                                                                         :description "kosh"}
+                                                                    500 {:description "fail"}}
+                                                        :summary "plus"}}}}]
+      (is (= expected spec))
+
+      (testing "ring-async swagger-spec"
+        (let [response* (atom nil)
+              respond (partial reset! response*)]
+          (app {:request-method :get
+                :uri "/api/swagger.json"} respond (fn [_] (is false)))
+          (is (= expected (:body @response*))))))))

 (defn spec-paths [app uri]
   (-> {:request-method :get, :uri uri} app :body :paths keys))


Added tests for retrieving metadata in its native format.

--- test/cmr/system_int_test/search/collection_search_format_test.clj
+++ test/cmr/system_int_test/search/collection_search_format_test.clj
@@ -102,9 +102,13 @@
              "application/dif+xml" :dif true
              "application/echo10+xml" :echo10 false
              "application/echo10+xml" :echo10 true))
-      (testing "default format"
+      (testing "native format"
+        ;; Native format can be specified using application/xml or not specifying any format
         (let [response (search/get-concept-by-concept-id (:concept-id c1-echo) {:accept nil})]
-          (is (= (umm/umm->xml c1-echo :echo10) (:body response)))))
+          (is (= (umm/umm->xml c1-echo :echo10) (:body response))))
+
+        (let [response (search/get-concept-by-concept-id (:concept-id c3-dif) {:accept nil})]
+          (is (= (umm/umm->xml c3-dif :dif) (:body response)))))
       (testing "unsupported formats"
         (are [mime-type]
              (let [response (search/get-concept-by-concept-id
@@ -115,8 +119,7 @@
                     (= {:errors [(str "The mime type [" mime-type "] is not supported.")]} parsed)))
              "application/atom+xml"
              "application/json"
-             "text/csv"
-             "application/xml")))
+             "text/csv")))

     (testing "Retrieving results as XML References"
       (let [refs (search/find-refs :collection {:short-name "S1"})


Added integration test for JSONP callback

--- test/integration/handler_test.clj
+++ test/integration/handler_test.clj
@@ -52,7 +52,14 @@

              (app (request :get "/data/county_taxes/incomes.xml"))
              => (contains {:status 200
-                           :headers {"Content-Type" "application/xml;charset=UTF-8"}})))
+                           :headers {"Content-Type" "application/xml;charset=UTF-8"}}))
+
+       (fact "JSONP uses the callback we supply"
+             (let [result (app (request :get "/data/county_taxes/incomes.jsonp?$callback=foo"))]
+               result => (contains {:status 200
+                                    :headers {"Content-Type" "text/javascript;charset=UTF-8"}})
+
+               (:body result) => #"^foo\(")))

   (facts "about /data/bad-dataset/bad-slice"
          (fact "it returns a 404"


Use render-to-static-markup instead of render-to-string for tests

--- test/reagenttest/testreagent.cljs
+++ test/reagenttest/testreagent.cljs
@@ -26,6 +26,9 @@
 (def isClient r/is-client)

 (def rflush r/flush)
+
+(defn rstr [react-elem]
+  (server/render-to-static-markup react-elem))

 (deftest really-simple-test
   (when (and isClient
@@ -347,15 +350,12 @@

 (deftest test-static-markup
   (is (= "
foo
"
-         (server/render-to-static-markup
-          [:div "foo"])))
+         (rstr [:div "foo"])))
   (is (= "

foo

"
-         (server/render-to-static-markup
-          [:div.bar [:p "foo"]])))
+         (rstr [:div.bar [:p "foo"]])))
   (is (= "

foobar

"
-         (server/render-to-static-markup
-          [:div.bar {:dangerously-set-inner-HTML
-                     {:__html "
foobar
"}} ]))))
+         (rstr [:div.bar {:dangerously-set-inner-HTML
+                          {:__html "
foobar
"}} ]))))

 (deftest test-return-class
   (when isClient
@@ -416,9 +416,6 @@
           (is (found-in #"hi me" div))
           (is (= 1 @top-ran))
           (is (= 4 @ran)))))))
-
-(defn rstr [react-elem]
-  (server/render-to-static-markup react-elem))

 (deftest test-create-element
   (let [ae r/as-element
@@ -1075,29 +1072,24 @@

 (deftest style-property-names-are-camel-cased
   (is (re-find #"
foo
"
-               (server/render-to-static-markup
-                 [:div {:style {:text-align "center"}} "foo"]))))
+               (rstr [:div {:style {:text-align "center"}} "foo"]))))

 (deftest custom-element-class-prop
   (is (re-find #"<custom-element class=\"foobar\">foo</custom-element>"
-               (server/render-to-static-markup
-                 [:custom-element {:class "foobar"} "foo"])))
+               (rstr [:custom-element {:class "foobar"} "foo"])))

   (is (re-find #"<custom-element class=\"foobar\">foo</custom-element>"
-               (server/render-to-static-markup
-                 [:custom-element.foobar "foo"]))))
+               (rstr [:custom-element.foobar "foo"]))))

 (deftest html-entities
   (testing "entity numbers can be unescaped always"
     (is (= " "
-           (server/render-to-static-markup
-             [:i (gstr/unescapeEntities " ")]))))
+           (rstr [:i (gstr/unescapeEntities " ")]))))

   (when r/is-client
     (testing "When DOM is available, all named entities can be unescaped"
       (is (= " "
-             (server/render-to-static-markup
-               [:i (gstr/unescapeEntities " ")]))))))
+             (rstr [:i (gstr/unescapeEntities " ")]))))))

 (defn context-wrapper []
   (r/create-class


Clarify 5-4 instructions.

Clarify 5-4 instructions.

--- test/workshop/jobs/test_5_4.clj
+++ test/workshop/jobs/test_5_4.clj
@@ -11,11 +11,11 @@
 ;; key exclusions. Sometimes, you'll want to convey some information
 ;; from a function to a flow condition predicate that doesn't
 ;; need to be sent downstream. In the example below, we're going
-;; to route users based on their age. Their age is only relevant
-;; to the routing, and isn't required after that.
+;; to route users to different tasks based on their age.
+;; Their age is only relevant to the routing, and isn't required after that.
 ;;
-;; Use :flow/exclude-keys and set its value to a vector of keywords
-;; to remove from each segment if present.
+;; Use :flow/exclude-keys to remove the :age key from all the segments
+;; after it passes through the :identity function.
 ;;
 ;; Try it with:
 ;;


Places import: LEFT JOIN correctly to pick up unvisited pages.

--- src/datomish/places/import.cljc
+++ src/datomish/places/import.cljc
@@ -75,8 +75,8 @@
               places-connection
               ["SELECT DISTINCT p.id AS id, p.url AS url, p.title AS title, p.visit_count, p.last_visit_date, p.guid,
                hv.visit_date
-               FROM moz_places AS p LEFT JOIN moz_historyvisits AS hv
-               WHERE p.hidden = 0 AND p.id = hv.place_id
+               FROM moz_places AS p LEFT JOIN moz_historyvisits AS hv ON p.id = hv.place_id
+               WHERE p.hidden = 0
                ORDER BY p.id, hv.visit_date"]))]
       (<?
         (transact/<transact!


more ideas for macros

more ideas for macros

--- src/clj/algorithms_clj/macro_initiation.clj
+++ src/clj/algorithms_clj/macro_initiation.clj
@@ -38,7 +38,7 @@
     ;; (println (add-m x y))
     ;; (println (add-m-2 x y))

-    ;; TODO - Does not do what I think it does
+    ;; TODO - Does not do what I think it does?
     ;; This however works, but only with add-m-2
     (defmacro x1 [] 1)
     (defmacro x2 [] 2)
@@ -93,13 +93,16 @@

 (defmacro freq-map-m
   [coll]
-  (freq-map coll))
+  `(freq-map ~coll))

 (defn test-freq-map
   []
   (let [inputs [1 2 1 4 1 3]]
     (println (freq-map inputs))
     (println (freq-map-m [1 2 1 4 1 3]))
+
+    (defmacro inputs-m [] [1 2 1 4 1 3])
+    (println (freq-map-m (inputs-m)))
     ))


complete topological sort

complete topological sort

--- src/clj/algorithms_clj/macro_initiation.clj
+++ src/clj/algorithms_clj/macro_initiation.clj
@@ -395,25 +395,28 @@
     modules))

 (defn visit
-  [{:keys [graph visited sorted] :as dfs} node]
-  (if-not (visited node)
-    (let [new-visited (conj visited node)
-          neighbors (get graph node [])]
-      (->
-        (reduce visit (assoc dfs :visited new-visited) neighbors)
-        (update :sorted conj node)))
+  [{:keys [graph not-visited sorted] :as dfs} node]
+  (if (not-visited node)
+    (->
+      (reduce visit
+        (update dfs :not-visited disj node)
+        (get graph node []))
+      (update :sorted conj node))
     dfs))

 (defn topological-sort
   [graph]
-  (let [start (-> graph first first)]
-    (:sorted
-      (visit {:graph graph :visited #{} :sorted []} start)
-      )))
+  (some
+    #(if (-> % :not-visited empty?) (:sorted %))
+    (iterate
+      #(visit % (-> % :not-visited first))
+      {:graph graph
+       :not-visited (set (keys graph))
+       :sorted []})))

 (defn test-topological-sort
   []
-  (println (topological-sort {:a [:b] :b [:c]}))
+  (println (topological-sort {:a [:b] :b [:c] :c []}))
   (println (topological-sort module-dependencies))
   )


good vibes

good vibes

--- src/cljs/reagent_demo/views/about_page.cljs
+++ src/cljs/reagent_demo/views/about_page.cljs
@@ -6,7 +6,7 @@

 (def ac (new window/AudioContext))

-(defn play-clip [url, position, duration]
+(defn play-clip [url, position, duration, rate, reverse]
   (let [xhr (new window/XMLHttpRequest)]
     (.open xhr "get" url true)
     (set! (.-responseType xhr) "arraybuffer")
@@ -14,6 +14,10 @@
       (.decodeAudioData ac (.-response xhr)
         (fn [buffer]
           (let [source (.createBufferSource ac)]
+            (when reverse
+              (js/Array.prototype.reverse.call (.getChannelData buffer 0))
+              (js/Array.prototype.reverse.call (.getChannelData buffer 1)))
+            (set! (.-value (.-playbackRate source)) rate)
             (set! (.-buffer source) buffer)
             (.connect source (aget ac "destination"))
             (.start source (.-currentTime ac) position)
@@ -23,11 +27,15 @@
     (.send xhr)))

 (def url "http://static.kevvv.in/sounds/callmemaybe.mp3")
-; (play-clip url 3 100)
+(play-clip url 2 100 0.5 true)
+(play-clip url 0 100 0.25 false)

 ; (js/setInterval #(play-clip url 7.1 30) 4000)

 ; (play-clip url 7.1 0.35)
-; (js/setInterval #(play-clip url 7.1 2) 2000)
+; (js/setInterval #(play-clip url 7.1 2 2 false) 2000)

 ; (js/setInterval #(play-clip url 17.1 2.5) 1350)
+
+; Array.prototype.reverse.call(buffer.getChannelData(0))
+;       Array.prototype.reverse.call(buffer.getChannelData(1))


Fix references in `invert-function` and `invert-relation`

--- test/com/nomistech/clojure_the_language/c_850_utils/s_100_utils.clj
+++ test/com/nomistech/clojure_the_language/c_850_utils/s_100_utils.clj
@@ -57,8 +57,7 @@
   `f` takes elements of `domain-subset` (and possibly other values, not
   relevant here) as argument, and returns a single value.
   For explanations of terminology, see:
-    https://www.mathsisfun.com/sets/domain-range-codomain.html
-    https://www.mathsisfun.com/sets/injective-surjective-bijective.html"
+    https://www.mathsisfun.com/sets/domain-range-codomain.html"
   (dissoc (group-by f domain-subset)
           nil))

@@ -67,8 +66,7 @@
   `rel` takes elements of `domain-subset` (and possibly other values, not
   relevant here) as argument, and returns a collection of values.
   For explanations of terminology, see:
-    https://www.mathsisfun.com/sets/domain-range-codomain.html
-    https://www.mathsisfun.com/sets/injective-surjective-bijective.html"
+    https://www.mathsisfun.com/sets/domain-range-codomain.html"
   (let [domain-range-pairs (for [d domain-subset
                                  r (rel d)]
                              [d r])]


Implemented day-ranges function

Implemented day-ranges function

--- src/mafia_votecount/scraper/team_liquid.clj
+++ src/mafia_votecount/scraper/team_liquid.clj
@@ -119,15 +119,22 @@
   (filter #(and (is-host? % host) (is-cycle-change? (:message (val %))))
           (rest indexed)))

-;; TODO: These are next on line
+(defn- dec-or-nil [num]
+  (if (nil? num)
+    nil
+    (dec num)))

-;; (defn day-ranges [cycle-changes]
-;;   (loop [pairs '()
-;;          left cycle-changes]
-;;     (if (empty? left) pairs
-;;         (recur ()))))
+(defn- day-ranges [cycle-changes]
+  (loop [pairs []
+         left cycle-changes]
+    (if (empty? left) pairs
+        (let [next (take 2 left)
+              start (inc (first next))
+              end (first (rest next))]
+          (recur (conj pairs (remove nil? [start (dec-or-nil end)]))
+                 (drop 2 left))))))

 ;; (defn get-votes [player-message-maps]
 ;;   (let [indexed (enumerate player-message-maps)
-;;         day-indices (day-ranges indexed)]
+;;         day-ranges (day-ranges indexed)]
 ;;     ))


Added basic characters and gamestate manipulation.

--- src-browser/simplestrat/core.cljs
+++ src-browser/simplestrat/core.cljs
@@ -6,19 +6,45 @@

 ;;(repl/connect "http://localhost:9000/repl")

-;; gameassets
-(def gameassets)
+(def spritescale 2)
+(def basetilesize 12)
+(def tilespacing (* spritescale basetilesize))

-;; game state as an atom
-(def gamestate (atom {:stage nil :map nil :characters nil }))
+;; gameassets: images, sounds, etc. use (get gameassets "image") to
+;; get images
+(def gameassets {})

-(defn clearscreen [gamescreen]
+;; the current game state as an atom
+(def gamestate (atom {:map [] :characters [] }))
+
+;; contains various rendering objects. These are easelJS containers
+(def renderer (atom {:stage nil :stage-map nil :stage-characters nil}))
+
+;;
+;; sprite sheet cache
+;;
+
+(def spritecache (atom {}))
+
+(defn getspritesheet [spritesheetname]
+  (if (contains? @spritecache spritesheetname)
+    ;; spritesheet is already in the cache, just return it
+    (get @spritecache spritesheetname)
+    (let [spritesheetimage (get-in gameassets ["image" spritesheetname])
+          spritesheet-config (clj->js {:images [spritesheetimage] :frames {:width 12 :height 12}})
+          spritesheet (createjs/SpriteSheet. spritesheet-config)]
+      ;; add the new spritesheet to the cache and return it
+      (swap! spritecache assoc spritesheetname spritesheet)
+      spritesheet)))
+
+
+#_(defn clearscreen [gamescreen]
   (let [width (-> gamescreen .-canvas .-width)
         height (-> gamescreen .-canvas .-width)]
     (aset gamescreen "fillStyle" "#000000")
     (.fillRect gamescreen 0 0 width height)))

-(defn simpletitle [gamescreen]
+#_(defn simpletitle [gamescreen]
   (let [canvas (.-canvas gamescreen)
         width (.-width canvas)
         height (.-height canvas)
@@ -27,73 +53,108 @@
     (aset gamescreen "fillStyle" "orange")
     (.fillText gamescreen "argh!" textx texty)))

-(defn addimage [stage img]
+#_(defn addimage [stage img]
   (let [bitmap (createjs/Bitmap. img)]
     (.addChild stage bitmap)
     (aset bitmap "x" 400)
     (aset bitmap "y" 200)
     (.update stage)))

-(defn putonstage [stage shape x y]
-  (.addChild stage shape)
-  (aset shape "x" x)
-  (aset shape "y" y)
-  stage)
+
+(defn updatecharactersprite [character]
+  ;; create sprite if needed
+  (let [charactersprite (:sprite character)
+        newx (* tilespacing (:x character))
+        newy (* tilespacing (:y character))]
+    (aset charactersprite "x" newx)
+    (aset charactersprite "y" newy)))
+
+(defn addcharactersprite [character]
+  (let [freshsprite (getspritesheet ["icons"])
+        characterstage (:stage-characters @renderer)]
+    (.addChild characterstage freshsprite)
+    (assoc character :sprite freshsprite)))
+
+(defn removecharactersprite [character]
+  (let [characterstage (:stage-characters @renderer)]
+    (.removeChild characterstage (:sprite character))
+    (dissoc character :sprite)))
+
+(defn action-addcharacter [gamestate freshcharacter]
+  (conj gamestate freshcharacter))
+
+(defn action-movecharacter [gamestate character newx newy]
+  (let [characters (:characters gamestate)
+        movedcharacter (-> character (assoc :x newx) (assoc :y newy))
+        modifiedcharacters (conj (disj characters character) movedcharacter)]
+    (assoc gamestate :characters modifiedcharacters)))
+
+(defn action-removecharacter [gamestate character]
+  (let [modifiedcharacters (disj (:characters gamestate) character)]
+    (assoc gamestate :characters modifiedcharacters)))
+
+(defn makecharacters []
+
+  )
+

 (defn chooseterrain [x y]
   (if (> x y)
-    0
-    3))
+    39
+    54))

 (defn generatemap [{:keys [width height]}]
   (for [x (range 0 width)
         y (range 0 height)]
     {:x x :y y :terrain (chooseterrain x y)}))

-(comment
-  (defn initeaselold [canvas]
-  (let [shape (createjs/Shape.)
-        shape-graphics (aget shape "graphics")
-        stage (createjs/Stage. canvas)
-        text (createjs/Text. "text on the canvas" "36px Arial" "#0FF")
-        checkX (js/Image.)
-        ]
-    (set! gamestage stage)
-    (-> shape-graphics
-        (.beginFill "blue")
-        (.drawRoundRect 0 0 120 120 10))
-    (-> stage
-        (putonstage shape 100 100)
-        (putonstage text 50 20))
-    (aset text "rotation" 20))))
+(defn rendermap [gamemap]
+  (let [gameboardcontainer (:stage-map @renderer)
+        spritesheet (getspritesheet "icons")]
+    (.removeAllChildren gameboardcontainer)
+    (doseq [tile gamemap
+            :let [{:keys [x y terrain]} tile
+                  freshtile (createjs/BitmapAnimation. spritesheet)]]
+      (aset freshtile "x" (* x tilespacing))
+      (aset freshtile "y" (* y tilespacing))
+      (aset freshtile "scaleX" spritescale)
+      (aset freshtile "scaleY" spritescale)
+      (.gotoAndStop freshtile terrain)
+      (.addChild gameboardcontainer freshtile))))

 (defn setupboard []
   ;; should have the gamestate setup by now
-  (let [scale 2
-        tilespacing (* scale 12)
-        stage (:stage @gamestate)
-        gamemap (generatemap {:width 10 :height 10})
-        mapicons (get-in gameassets ["image" "icons"])
-        spritesheet-config (clj->js {:images [mapicons] :frames {:width 12 :height 12}})
-        spritesheet (createjs/SpriteSheet. spritesheet-config)
-        bitmapbase (createjs/BitmapAnimation. spritesheet)]
+  (let [gamemap (generatemap {:width 10 :height 10})]
     ;; generate a bunch of icons based off of the map data
     #_(js/console.log mapicons)
-    (doseq [tile gamemap
-            :let [{:keys [x y terrain]} tile
-                  freshtile (.clone bitmapbase)]]
-      (aset freshtile "x" (* x tilespacing))
-      (aset freshtile "y" (* y tilespacing))
-      (aset freshtile "scaleX" scale)
-      (aset freshtile "scaleY" scale)
-      (.gotoAndStop freshtile terrain)
-      (.addChild stage freshtile)
-      )
-    (.update stage)))
+    (swap! gamestate assoc :map gamemap)
+    (rendermap gamemap)
+    (.update (:stage @renderer))))
+
+
+(defn createnamedcontainer [name]
+  (let [freshcontainer (createjs/Container.)]
+    (aset freshcontainer "id" name)
+    freshcontainer))

 (defn startgame [loadedassets]
   (set! gameassets loadedassets)
   #_(js/console.log loadedassets)
+  (let [stage (:stage @renderer)
+        tilemap (createnamedcontainer "tilemap")
+        characters (createnamedcontainer "characters")]
+    (.addChild stage tilemap)
+    (aset tilemap "id" "tilemap")
+    (aset tilemap "x" 100)
+    (aset tilemap "y" 100)
+    (.addChild stage characters)
+    (aset characters "id" "characters")
+    (aset characters "x" 100)
+    (aset characters "y" 100)
+    ;; embed direct references to the map and character containers for
+    ;; easy manipulation later
+    (swap! renderer assoc :stage-map tilemap)
+    (swap! renderer assoc :stage-characters characters))
   (setupboard))

 (def manifest [{:id "icons" :src "gfx/placeholders_tigsource.png"}])
@@ -105,7 +166,7 @@
 (defn createjsstartgame []
   (let [canvas (dom/get-element "target")
         stage (createjs/Stage. canvas)]
-    (swap! gamestate assoc :stage stage)
+    (swap! renderer assoc :stage stage)
     ;; the preloader loads all the assets and then calls startgame with the results
     (preloader/preloadgame stage manifest startgame)))


:lipstick: Cosmetic changes on initial align shape event.

--- frontend/src/uxbox/main/data/workspace.cljs
+++ frontend/src/uxbox/main/data/workspace.cljs
@@ -582,20 +582,19 @@

 ;; --- Shape Transformations

-(defrecord InitialShapeAlign [id]
-  ptk/WatchEvent
-  (watch [_ state s]
-    (let [{:keys [x1 y1] :as shape} (->> (get-in state [:shapes id])
-                                         (geom/shape->rect-shape state))
-          point (gpt/point x1 y1)]
-      (->> (uwrk/align-point point)
-           (rx/map (fn [{:keys [x y] :as pt}]
-                     (apply-temporal-displacement id (gpt/subtract pt point))))))))
-
 (defn initial-shape-align
   [id]
   {:pre [(uuid? id)]}
-  (InitialShapeAlign. id))
+  (reify
+    ptk/WatchEvent
+    (watch [_ state s]
+      (let [{:keys [x1 y1] :as shape} (->> (get-in state [:shapes id])
+                                           (geom/shape->rect-shape state))
+            point (gpt/point x1 y1)]
+        (->> (uwrk/align-point point)
+             (rx/map (fn [{:keys [x y] :as pt}]
+                       (apply-temporal-displacement id (gpt/subtract pt point)))))))))
+

 ;; --- Apply Temporal Displacement


:bug: Fix ordering on delete shape undo operation.

--- frontend/src/uxbox/main/data/workspace.cljs
+++ frontend/src/uxbox/main/data/workspace.cljs
@@ -692,6 +692,7 @@
                                        (let [item (get objects id)]
                                          {:type :add-obj
                                           :id (:id item)
+                                          :index (cph/position-on-parent id objects)
                                           :frame-id (:frame-id item)
                                           :parent-id (:parent-id item)
                                           :obj item}))]


shorten connect-loop-with-thread-pool and add docstring

--- src/brainbot/nozzle/mqhelper.clj
+++ src/brainbot/nozzle/mqhelper.clj
@@ -67,11 +67,14 @@

 (defn connect-loop-with-thread-pool
+  "connect to rabbitmq with settings rmq-settings and call
+  handle-connection with the connection object. if the connection
+  fails, wait for 5 seconds and try again. Use thread-pool for
+  handling messages"
   [rmq-settings handle-connection thread-pool]
-  (let [connect (partial connect-with-thread-pool rmq-settings thread-pool)]
-    (connect-loop
-     connect
-     handle-connection)))
+  (connect-loop
+   #(connect-with-thread-pool rmq-settings thread-pool)
+   handle-connection))

 (defn make-handler


first stage of transformation

first stage of transformation

--- src/ceres_collector/migrator.clj
+++ src/ceres_collector/migrator.clj
@@ -1,7 +1,7 @@
 (ns ceres-collector.migrator
   (:refer-clojure :exclude [sort find])
   (:require [clojure.java.shell :refer [sh]]
-            [ceres-collector.db :refer [db news-accounts custom-formatter time-interval]]
+            [ceres-collector.db :refer [db news-accounts custom-formatter time-interval set-db]]
             [monger.core :as mg]
             [monger.collection :as mc]
             [monger.operators :refer :all]
@@ -20,9 +20,9 @@

 (defn store-reference
   "Store reference between tweet and another entity"
-  [source target type]
+  [source target type db]
   (mc/insert-and-return
-   @db
+   db
    "references"
    {:source source
     :target target
@@ -30,18 +30,18 @@
     :ts (t/now)}))

-(defn store-hashtag [text]
+(defn store-hashtag [text db]
   (mc/insert-and-return
-   @db
+   db
    "hashtags-2"
    {:text text
     :ts (t/now)}))

-(defn store-author [{:keys [screen_name id created_at]}]
+(defn store-author [{:keys [screen_name id created_at]} db]
   (let [date (f/parse custom-formatter created_at)]
     (mc/insert-and-return
-     @db
+     db
      "authors"
      {:id id
       :name screen_name
@@ -49,9 +49,50 @@
       :ts (t/now)})))

-(defn store-url [url]
+(defn store-url [url db]
   (mc/insert-and-return
-   @db
+   db
    "urls-2"
    {:path url
     :ts (t/now)}))
+
+
+(defn store-message
+  [text source tid db]
+  (mc/insert-and-return
+   db
+   "messages"
+   {:text text
+    :source source
+    :ts (t/now) :tweet tid}))
+
+
+
+(comment
+
+  (set-db "athena")
+
+  ;; migration db
+  (def db2 (let [^MongoOptions opts (mg/mongo-options :threads-allowed-to-block-for-connection-multiplier 300)
+                 ^ServerAddress sa  (mg/server-address (or (System/getenv "DB_PORT_27017_TCP_ADDR") "127.0.0.1") 27017)]
+             (mg/get-db (mg/connect sa opts) "demeter")))
+
+
+  ;; migrate users
+  (->> (mc/find-maps @db "publications")
+       (pmap (fn [{:keys [url tweet user hashtags type]}]
+               (let [text (:text (mc/find-map-by-id @db "tweets" tweet))
+                     mid (-> (store-message text (= type "source") tweet db2)
+                             from-db-object
+                             :_id)]
+                 (map #(store-reference mid % "tag" db2) hashtags)
+                 (store-reference mid user "pub" db2)
+                 (when url
+                   (store-reference mid url "url" db2)))
+                 ))))
+
+  (->> (mc/find-maps @db "publications")
+       (take 100)
+       (map :type)
+       (into #{}))
+  )


Support objects (references) in arrays.

Support objects (references) in arrays.

--- src/isla/interpreter.clj
+++ src/isla/interpreter.clj
@@ -40,17 +40,26 @@
       (utils/thr (str "I do not know what a " type-identifier " is.")))))

 (defmethod interpret :list-assignment [node env]
-  (let [assignee-name (utils/extract node [:c 0 :c 0 :c 0 :c 0])
-        assignee (resolve- {:ref assignee-name} env)]
-    (if (nil? assignee)
-      (utils/thr (str "I do not know of a list called " assignee-name "."))
+  (let [assignee (utils/extract node [:c 0])
+        ;; little hack - dive into assignee, get object/scalar node and evaluate value
+        original-list (:val (evaluate-value (utils/extract assignee [:c 0]) env))]
+    (if (nil? original-list)
+      (let [ref (:ref (evaluate-value (utils/extract assignee [:c 0]) env))
+            variable-str (if (coll? ref)
+                           (str (first ref) " " (name (second ref)))
+                           ref)]
+        (utils/thr (str "I do not know of a list called " variable-str ".")))
       (let [operation (utils/extract node [:c 1 :c 0 :tag])
-            value (:val (interpret (utils/extract node [:c 2]) env))]
-        (let [new-list (cond
-                        (= :add operation) (conj assignee value)
-                        (= :remove operation) (disj assignee value)
-                        :else (utils/thr (str "You cannot " operation " on lists.")))]
-          (assoc-in env [:ctx assignee-name] new-list))))))
+            item-eval (interpret (utils/extract node [:c 2]) env)
+            item (if (contains? item-eval :ref)
+                   {:ref (:ref item-eval)}
+                   (:val item-eval))
+            new-list (cond
+                      (= :add operation) (conj original-list item)
+                      (= :remove operation) (disj original-list item)
+                      :else (utils/thr (str "You cannot " operation " on lists.")))
+            new-ctx (assign (:ctx env) assignee new-list)]
+        (nreturn new-ctx)))))

 (defmethod interpret :invocation [node env]
   (let [function (resolve- {:ref (interpret (utils/extract node [:c 0]) env)} env)


:sparkles: Do not show radius option for shapes that do not have it

--- frontend/src/uxbox/main/ui/workspace/sidebar/options/measures.cljs
+++ frontend/src/uxbox/main/ui/workspace/sidebar/options/measures.cljs
@@ -183,7 +183,7 @@
            :value (attr->string :rotation values)}]])

       ;; RADIUS
-      (when (options :radius)
+      (when (and (options :radius) (not (nil? (:rx values))))
         [:div.row-flex
          [:span.element-set-subtitle (t locale "workspace.options.radius")]
          [:div.input-element.pixels


Add humane-test-output

Add humane-test-output

--- roles/clojure/files/profiles.clj
+++ roles/clojure/files/profiles.clj
@@ -8,6 +8,7 @@
                        [criterium "0.4.2"]
                        [org.clojure/tools.namespace "0.2.5"]
                        [org.clojure/tools.nrepl "0.2.7"]
+                       [pjstadig/humane-test-output "0.7.0"]
                        [slamhound "1.5.3"]]

         :plugins [[cider/cider-nrepl "0.10.0-SNAPSHOT"]
@@ -28,6 +29,9 @@

         :global-vars {*print-length* 100
                       *warn-on-reflection* true}
+
+        :injections [(require 'pjstadig.humane-test-output)
+                     (pjstadig.humane-test-output/activate!)]

         :shorthand {. [^:lazy alembic.still/distill
                        ^:lazy alembic.still/load-project


Always warn on reflection

Always warn on reflection

--- roles/clojure/files/profiles.clj
+++ roles/clojure/files/profiles.clj
@@ -24,6 +24,8 @@
                   [lein-try "0.4.3"]
                   [lein-typed "0.3.5"]
                   [refactor-nrepl "1.1.0-SNAPSHOT"]]
+
+        :global-vars {*warn-on-reflection* true}

         :shorthand {. [^:lazy alembic.still/distill
                        ^:lazy alembic.still/load-project


Correcting skybox image location.

Correcting skybox image location.

--- src/brevis/graphics/basic_3D.clj
+++ src/brevis/graphics/basic_3D.clj
@@ -30,7 +30,7 @@
 (defn init-sky
   []
   (def #^:dynamic *sky*
-    (load-texture-from-file "img/sky.jpg")))
+    (load-texture-from-file "resources/img/sky.jpg")))
 ;    (load-texture-from-file "resources/img/sky.jpg")))

 (defn init-shader


Use the substring.pl file that is installed in the file system

and provided via a deb package. Don't know how we can easily invoke a
perl script which is in the resources inside a jar file.

--- src/clj/hyphen_keeper/export.clj
+++ src/clj/hyphen_keeper/export.clj
@@ -7,6 +7,11 @@
             [hyphen-keeper
              [db :as db]
              [hyphenate :as hyphenate]]))
+
+(def ^:private substrings-program
+  "Program to prepare the hyphenation dics. Expected to be installed
+  on the system."
+  "/usr/share/libhyphen/substrings.pl")

 (def dictionaries {0 ["/tmp/whitelist_de_DE_OLDSPELL.txt"
                       "/usr/share/hyphen/hyph_de_DE_OLDSPELL.dic"
@@ -52,17 +57,16 @@
   "Export all hyphenation patterns from the database and prepare for
   libhyphen consumption, i.e. run them through substrings.pl"
   []
-  (let [program (.getAbsolutePath (io/file (io/resource "perl/substrings.pl")))]
-    ;; I tried to run this in parallel (simply by using (dorun (pmap))
-    ;; instead of (doseq)) but as it turns out the jobs are so uneven,
-    ;; i.e. the first one is very small compared to the second one, we
-    ;; end up waiting the same time.
-    (doseq [[spelling [white-list dictionary original]] dictionaries]
-      (->
-       spelling
-       get-hyphenations
-       (write-file white-list original))
-      (sh program white-list dictionary))))
+  ;; I tried to run this in parallel (simply by using (dorun (pmap))
+  ;; instead of (doseq)) but as it turns out the jobs are so uneven,
+  ;; i.e. the first one is very small compared to the second one, we
+  ;; end up waiting the same time.
+  (doseq [[spelling [white-list dictionary original]] dictionaries]
+    (->
+     spelling
+     get-hyphenations
+     (write-file white-list original))
+    (sh substrings-program white-list dictionary)))

 (defn- exporter
   "Create a channel and attach a listener to it so that events can be


change naming so it is closer to cond-> et al

--- src/clj/shadow/devtools/test.clj
+++ src/clj/shadow/devtools/test.clj
@@ -31,12 +31,12 @@
 (defmacro log [& args]
   `(js/console.log ~@args))

-(defmacro ->log [obj & args]
+(defmacro log-> [obj & args]
   `(do (let [obj# ~obj]
          (js/console.log ~@args obj#)
          obj#)))

-(defmacro ->>log [& args]
+(defmacro log->> [& args]
   `(do (let [obj# ~(last args)]
          (js/console.log ~@(butlast args) obj#)
          obj#)))


Add adhoc validation for empty tags

Add adhoc validation for empty tags

--- src/clojournal/routes/author.clj
+++ src/clojournal/routes/author.clj
@@ -17,6 +17,7 @@

 (defn post-article [author-id title content tags]
   (let [tags' (clojure.string/split tags #"\s*,\s*")]
+    (assert (some empty? tags'))
     (article/add-article! :title title :content content :author author-id :tags tags')
     (response/redirect "/author")))


Updates for data sets that validly expect XDim and YDim.

--- src/cmr/opendap/ous/variable.clj
+++ src/cmr/opendap/ous/variable.clj
@@ -314,7 +314,7 @@
              "lat"
              ;; XXX See CMR-4985
              (get-in bounding-info [:original-dimensions :YDim])
-             "Latitude")
+             "YDim")
        "%s,"
        (cond (get-in bounding-info [:original-dimensions :Longitude])
              "Longitude"
@@ -322,7 +322,7 @@
              "lon"
              ;; XXX See CMR-4985
              (get-in bounding-info [:original-dimensions :XDim])
-             "Longitude")
+             "XDim")
        "%s"))

 (defn format-opendap-lat-lon


audit-traces

audit-traces

--- src/com/billpiel/sayid/trace.clj
+++ src/com/billpiel/sayid/trace.clj
@@ -185,6 +185,56 @@
       (doseq [f ns-fns]
         (untrace-var* f)))))

+(defn apply->vec
+  [f]
+  (fn [v] [v (f v)]))
+
+(defn audit-fn
+  [fn-var trace-selection]
+  (let [fn-meta (meta fn-var)]
+    (-> fn-meta
+        (update-in [:ns] str)
+        (assoc :trace-type (::trace-type fn-meta)
+               :trace-selection trace-selection)
+        (dissoc ::trace-type
+                ::traced))))
+
+(defn audit-fn-sym
+  [fn-sym trace-selection]
+  (-> fn-sym
+      resolve
+      (audit-fn trace-selection)))
+
+(defn audit-ns
+  [ns-sym]
+  (let [mk-vec-fn (fn [fn-var]
+                    [(-> fn-var meta :name)
+                     (audit-fn fn-var :ns)])]
+    (->> ns-sym
+         ns-interns
+         vals
+         (filter (comp fn? var-get))
+         (map mk-vec-fn)
+         (into {}))))
+
+(defn audit-traces
+  [traced]
+  (let [{outer :fn inner :deep-fn ns' :ns} traced
+        f (fn [trace-type]
+            (fn [fn-sym]
+              (let [fn-var (resolve fn-sym)]
+                [(-> fn-var meta :name)
+                 (audit-fn fn-var trace-type)])))
+        fn-audits (->> (concat (map (f :fn) outer)
+                               (map (f :deep-fn) inner))
+                       (group-by #(-> % second :ns))
+                       (map (fn [[k v]] [(symbol k) (into {} v)]))
+                       (into {}))]
+    {:ns (into {}
+               (map (apply->vec audit-ns)
+                    ns'))
+     :fn fn-audits}))
+
 (defmulti trace* (fn [type sym workspace] type))

 (defmethod trace* :ns


Fix wildcard sub processing on bounded recursive queries

--- src/com/wsscode/pathom/core.cljc
+++ src/com/wsscode/pathom/core.cljc
@@ -206,6 +206,9 @@
                         ffirst)]
     (apply update-in ast [:children idx] args)
     ast))
+
+(defn remove-query-wildcard [query]
+  (into [] (remove #{'*}) query))

 (defn join
   "Runs a parser with current sub-query."
@@ -232,10 +235,10 @@
          (let [parent-query' (-> (fp/query->ast parent-query)
                                  (update-child (:key ast) update :query dec)
                                  (fp/ast->query))]
-           (parser (assoc env' ::parent-query parent-query') parent-query')))
+           (parser (assoc env' ::parent-query parent-query') (remove-query-wildcard parent-query'))))

        (some #{'*} query)
-       (let [computed-e (parser env' (filterv (complement #{'*}) query))]
+       (let [computed-e (parser env' (remove-query-wildcard query))]
          (merge (entity env') computed-e))

        :else


Move all deprecates to the end of file

Move all deprecates to the end of file

--- src/com/wsscode/pathom/core.cljc
+++ src/com/wsscode/pathom/core.cljc
@@ -182,10 +182,6 @@
                    (assoc entity-key %)
                    (update ::path conj %2))) coll (range)))

-;; old names for join and join-seq
-(def continue join)
-(def continue-seq join-seq)
-
 (defn ident-key [{:keys [ast]}]
   (let [key (some-> ast :key)]
     (if (vector? key) (first key))))
@@ -224,9 +220,6 @@
     (if (= ns (namespace (:dispatch-key ast)))
       (join env)
       ::continue)))
-
-; keep old name for compatibility
-(def placeholder-node placeholder-reader)

 ;; BUILT-IN READERS

@@ -378,6 +371,13 @@

 ;;;; DEPRECATED

+;; old names for join and join-seq
+(def continue join)
+(def continue-seq join-seq)
+
+; keep old name for compatibility
+(def placeholder-node placeholder-reader)
+
 (defn pathom-read
   "DEPRECATED: use p/parser to create your parser"
   [{::keys [reader process-reader] :as env} _ _]


Fixed bug in clj->vim of Named things

Fixed bug in clj->vim of Named things

--- src/de/kotka/vimclojure/util.clj
+++ src/de/kotka/vimclojure/util.clj
@@ -226,7 +226,9 @@

 (defmethod clj->vim clojure.lang.Named
   [thing]
-  (str-wrap (name thing) \"))
+  (if-let [prefix (namespace thing)]
+    (str-wrap (str prefix "/" (name thing)) \")
+    (str-wrap (name thing) \")))

 (defmethod clj->vim Number
   [thing]


Print body for non-200 responses

Print body for non-200 responses

--- web/dev-resources/testing/web.clj
+++ web/dev-resources/testing/web.clj
@@ -50,8 +50,10 @@
   (with-open [client (http/create-client)]
     (let [response (get-response url :headers headers :cookies cookies)]
       (if (= 200 (:status response))
-          (:body response)
-          (:status response)))))
+        (:body response)
+        (do
+          (if-let [b (:body response)] (println b))
+          (:status response))))))

 (defn event-source
   "Returns an SSE EventSource client"


1. indention 정리 2. check-validation 추가 3. 에러 등의 응답도 다 json 처리

--- src/clj/cauca/component/rest.clj
+++ src/clj/cauca/component/rest.clj
@@ -14,18 +14,8 @@
  (:gen-class)
  )

- (defn error-page [e]
-   (concat
-     [[:h2 "Internal Server Error"]]
-     [[:pre (let [sw (java.io.StringWriter.)]
-       (.printStackTrace e (java.io.PrintWriter. sw))
-       (.toString sw))]]
-     )
-   )
-
-
- (defn main-page []
-   (html5
+(defn main-page []
+  (html5
     [:head
      [:title "CAUCA"]
      (include-css "/css/bootstrap-1.1.0.css")
@@ -53,99 +43,85 @@
       ]
      ]
     )
-   )
+  )

- (defn cauca-writer [key value]
+(defn cauca-writer [key value]
   (if (or (= key :auctionDate) (= key :regDate) (= key :updDate))
     (str (java.sql.Date. (.getTime value)))
     value
     )
   )

- (defn response [json]
-   (log/log-message json)
-   (-> (resp/response json)
-     (resp/content-type "application/json; charset=utf-8"))
-   )
+(defn response [json status]
+  (log/log-message json)
+  (-> (resp/response json)
+    (resp/status status)
+    (resp/content-type "application/json; charset=utf-8")
+    )
+  )
+
+(defn check-validation [value min max regex isMatch error-msg]
+  (if-not (nil? value)
+    (if (false? (util/validation value min max regex isMatch))
+      (throw (Exception. error-msg))
+      )
+    )
+  )

- (defn check-params [params]
-   (if-not (nil? (params "page"))
-     (if (false? (util/validation (params "page") 1 3 #"[0-9]+" true))
-       (throw (Exception. "invalid.param.page"))
-       )
-     )
-   (if-not (nil? (params "pageSize"))
-     (if (false? (util/validation (params "pageSize") 1 3 #"[0-9]+" true))
-       (throw (Exception. "invalid.param.pageSize"))
-       )
-     )
-   (if-not (nil? (params "itemType"))
-     (if (false? (util/validation (params "itemType") nil nil #".*[\s~!@#$%^&*()_+`\\=\-{}|\\[\\]:\\\\\";'<>?,./].*" false))
-       (throw (Exception. "invalid.param.itemType"))
-       )
-     )
-   (if-not (nil? (params "addr0"))
-     (if (false? (util/validation (params "addr0") nil nil #".*[\s~!@#$%^&*()_+`\\=\-{}|\\[\\]:\\\\\";'<>?,./].*" false))
-       (throw (Exception. "invalid.param.addr0"))
-       )
-     )
-   (if-not (nil? (params "addr1"))
-     (if (false? (util/validation (params "addr1") nil nil #".*[\s~!@#$%^&*()_+`\\=\-{}|\\[\\]:\\\\\";'<>?,./].*" false))
-       (throw (Exception. "invalid.param.addr1"))
-       )
-     )
-   (if-not (nil? (params "auctionStartDate"))
-     (if (false? (util/validation (params "auctionStartDate") 9 11 #"20[0-9][0-9]-[0-1][0-9]-[0-3][0-9]" true))
-       (throw (Exception. "invalid.param.auctionStartDate"))
-       )
-     )
-   (if-not (nil? (params "auctionEndDate"))
-     (if (false? (util/validation (params "auctionEndDate") 9 11 #"20[0-9][0-9]-[0-1][0-9]-[0-3][0-9]" true))
-       (throw (Exception. "invalid.param.auctionEndDate"))
-       )
-     )
-   )
+(defn check-params [params]
+  (check-validation (params "page") 1 3 #"[0-9]+" true "invalid.param.page")
+  (check-validation (params "pageSize") 1 3 #"[0-9]+" true "invalid.param.pageSize")
+  (check-validation (params "itemType") nil nil #".*[\s~!@#$%^&*()_+`\\=\-{}|\\[\\]:\\\\\";'<>?,./].*" false "invalid.param.itemType")
+  (check-validation (params "addr0") nil nil #".*[\s~!@#$%^&*()_+`\\=\-{}|\\[\\]:\\\\\";'<>?,./].*" false "invalid.param.addr0")
+  (check-validation (params "addr1") nil nil #".*[\s~!@#$%^&*()_+`\\=\-{}|\\[\\]:\\\\\";'<>?,./].*" false "invalid.param.addr1")
+  (check-validation (params "auctionStartDate") 9 11 #"20[0-9][0-9]-[0-1][0-9]-[0-3][0-9]" true "invalid.param.auctionStartDate")
+  (check-validation (params "auctionEndDate") 9 11 #"20[0-9][0-9]-[0-1][0-9]-[0-3][0-9]" true "invalid.param.auctionEndDate")
+  )

- (defroutes main-routes
-   (GET "/" [] (main-page))
-   (GET ["/api/courtauction/:id", :id #"[0-9]+"] [id]
-        (let [dao-impl# (f/get-obj :courtauction-dao)
-              ret-courtauction (first (.get-courtauction dao-impl# id))
-              json (json/write-str ret-courtauction :value-fn cauca-writer :escape-unicode false)]
-          (response json)))
-   (GET "/api/courtauction" {params :query-params}
-        (check-params params)
-        (let [dao-impl# (f/get-obj :courtauction-dao)
-              ret-courtauction-list (.get-courtauction-list dao-impl# params)
-              json (json/write-str ret-courtauction-list :value-fn cauca-writer :escape-unicode false)]
-          (response json)))
-   (route/not-found "Page not found")
-   )
+(defroutes main-routes
+  (GET "/" [] (main-page))
+  (GET ["/api/courtauction/:id", :id #"[0-9]+"] [id]
+       (let [dao-impl# (f/get-obj :courtauction-dao)
+             ret-courtauction (first (.get-courtauction dao-impl# id))
+             json (json/write-str {:msg "ok" :result ret-courtauction}
+                                  :value-fn cauca-writer :escape-unicode false)]
+         (response json 200)))
+  (GET "/api/courtauction" {params :query-params}
+       (check-params params)
+       (let [dao-impl# (f/get-obj :courtauction-dao)
+             ret-courtauction-list (.get-courtauction-list dao-impl# params)
+             json (json/write-str {:msg "ok" :result ret-courtauction-list}
+                                  :value-fn cauca-writer :escape-unicode false)]
+         (response json 200)))
+  (route/not-found
+    (let [json (json/write-str {:msg "page.not.found"})]
+      (response json 404)))
+  )

- (def main-handler
-   (-> main-routes handler/api))
+(def main-handler
+  (-> main-routes handler/api))

- (defn catch-errors [handler]
-   (fn [request]
-     (try
-       (handler request)
-       (catch Exception e
-         (-> (resp/response (error-page e))
-           (resp/status 500)
-           (resp/content-type "text/html"))
-         ))
-     )
-   )
+(defn catch-errors [handler]
+  (fn [request]
+    (try
+      (handler request)
+      (catch Exception e
+        (let [json (json/write-str {:msg (.getMessage e)})]
+          (response json 400))
+        )
+      )
+    )
+  )

- (def app
-   (-> #'main-handler
-       (wrap-reload '[cauca.component.rest])
-       catch-errors))
+(def app
+  (-> #'main-handler
+    (wrap-reload '[cauca.component.rest])
+    catch-errors))

- (defn start-server! []
-   (run-jetty app {:port 8080 :join? false})
-   )
+(defn start-server! []
+  (run-jetty app {:port 8080 :join? false})
+  )

- (defn -main []
-   (start-server!)
-   )+(defn -main []
+  (start-server!)
+  )


json encode

json encode

--- src/clj/dokkaa_builder/route.clj
+++ src/clj/dokkaa_builder/route.clj
@@ -71,7 +71,7 @@
 (defn get-access-tokens [req]
   (let [user (auth/current-user req)]
     {:status 200
-     :body (auth/get-access-tokens user)}))
+     :body (j/encode (auth/get-access-tokens user))}))

 (defn add-access-token [req]
   (let [user (auth/current-user req)


Do not use session for state management

Do not use session for state management

--- src/cljs/caves_of_cljs/core.cljs
+++ src/cljs/caves_of_cljs/core.cljs
@@ -1,34 +1,49 @@
 (ns caves-of-cljs.core
     (:require [reagent.core :as reagent :refer [atom]]
-              [reagent.session :as session]
               [secretary.core :as secretary :include-macros true]
               [goog.events :as events]
               [goog.history.EventType :as EventType])
     (:import goog.History))

 ;; -------------------------
+;; State
+
+(def app-state (atom {}))
+
+;; -------------------------
 ;; Views

 (defn home-page []
-  [:div [:h2 "Welcome to caves-of-cljs"]
-   [:div [:a {:href "#/about"} "go to about page"]]])
+  [:div [:h2 "Caves of Clojurescript"]
+   [:div [:a {:href "#/about"} "go to the about page"]]])

 (defn about-page []
   [:div [:h2 "About caves-of-cljs"]
    [:div [:a {:href "#/"} "go to the home page"]]])

-(defn current-page []
-  [:div [(session/get :current-page)]])
+(defmulti page #(:current-page (deref %)))
+
+(defmethod page nil [state]
+  [home-page])
+
+(defmethod page :home [state]
+  [home-page])
+
+(defmethod page :about [state]
+  [about-page])
+
+(defn current-page [app-state]
+  [:div [page app-state]])

 ;; -------------------------
 ;; Routes
 (secretary/set-config! :prefix "#")

 (secretary/defroute "/" []
-  (session/put! :current-page #'home-page))
+  (swap! app-state assoc :current-page :home))

 (secretary/defroute "/about" []
-  (session/put! :current-page #'about-page))
+  (swap! app-state assoc :current-page :about))

 ;; -------------------------
 ;; History
@@ -45,4 +60,4 @@
 ;; Initialize app
 (defn init! []
   (hook-browser-navigation!)
-  (reagent/render-component [current-page] (.getElementById js/document "app")))
+  (reagent/render-component [current-page app-state] (.getElementById js/document "app")))


Reset select dropdowns when select-text is changed.

--- src/cljs/movement/generator.cljs
+++ src/cljs/movement/generator.cljs
@@ -1,5 +1,6 @@
 (ns movement.generator
-  (:require-macros [cljs.core.async.macros :refer (go)])
+  (:require-macros [cljs.core.async.macros :refer (go)]
+                   [cljs.core :refer [this-as]])
   (:import [goog.events EventType])
   (:require
     [reagent.session :as session]
@@ -14,6 +15,9 @@
     [movement.state :refer [movement-session handler-fn log-session]]))

 (defonce m-counter (atom 0))
+(defonce getting-templates
+         (GET "templates" {:handler       #(session/put! :templates %)
+                           :error-handler #(print "error retrieving templates.")}))

 (defn equipment-symbol [equipment-name]
   (first (shuffle ["images/squat.png"
@@ -74,12 +78,19 @@
         movements (dissoc movements (:id m))]
     (session/assoc-in! [:movement-session :parts position-in-parts :movements] movements)))

+(defonce rep-atom (atom "-"))
+
 (defn set-element-values!
-
   [class value]
   (let [elements (array-seq (.getElementsByClassName js/document class))]
     (doseq [e elements]
-      (set! (.-value e) value))))
+      (do (set! (.-value e) value)
+          #_(.onchange e)))))
+
+(defn set-movement-rep-text! [])
+(defn set-movement-set-text! [])
+(defn set-movement-rep! [])
+(defn set-movement-set! [])

 (defn movement-component []
   (let [rep-text (atom "Rep")
@@ -108,36 +119,48 @@
           [:div.pure-u-1-3.sw
            [:div.pure-g
             [:label.pure-u.rep-text {:on-click #(if (= @rep-text "Rep")
-                                                (reset! rep-text "Distance")
-                                                (reset! rep-text "Rep"))
-                                     :title "Change between rep and distance"}
+                                                 (let [elements (array-seq (.getElementById js/document (str "rep-" id)))]
+                                                   (doseq [e elements]
+                                                     (set! (.-selected e) false))
+                                                   (reset! rep-text "Distance"))
+                                                 (let [elements (array-seq (.getElementById js/document (str "distance-" id)))]
+                                                   (doseq [e elements]
+                                                     (set! (.-selected e) false))
+                                                   (reset! rep-text "Rep")))
+                                     :title    "Change between rep and distance"}
              @rep-text]
             (let [txt @rep-text]
               (case txt
                 "Rep" [:div.pure-u.rep {:className " custom-select"}
-                       [:select.rep-select
+                       [:select {:className "rep-select"
+                                 :id (str "rep-" id)
+                                 :on-change #(let [x (.-value (.getElementById js/document (str "rep-" id)))]
+                                                         (print x))}
                         [:option "-"]
-                        [:option "1"]
-                        [:option "2"]
-                        [:option "3"]
-                        [:option "4"]
-                        [:option "5"]
-                        [:option "6"]
-                        [:option "7"]
-                        [:option "8"]
-                        [:option "9"]
-                        [:option "10"]
-                        [:option "15"]
-                        [:option "20"]
-                        [:option "25"]
-                        [:option "30"]
-                        [:option "40"]
-                        [:option "50"]
-                        [:option "60"]
-                        [:option "80"]
-                        [:option "100"]]]
+                        [:option 1]
+                        [:option 2]
+                        [:option 3]
+                        [:option 4]
+                        [:option 5]
+                        [:option 6]
+                        [:option 7]
+                        [:option 8]
+                        [:option 9]
+                        [:option 10]
+                        [:option 15]
+                        [:option 20]
+                        [:option 25]
+                        [:option 30]
+                        [:option 40]
+                        [:option 50]
+                        [:option 60]
+                        [:option 80]
+                        [:option 100]]]
                 "Distance" [:div.pure-u.rep {:className " custom-select"}
-                             [:select.distance-select
+                             [:select {:className "distance-select"
+                                       :id (str "distance-" id)
+                                       :on-change #(let [x (.-value (.getElementById js/document (str "distance-" id)))]
+                                                    (print x))}
                               [:option "-"]
                               [:option "10 m"]
                               [:option "20 m"]
@@ -166,27 +189,39 @@
           [:div.pure-u-1-3.se
            [:div.pure-g
             [:label.pure-u.set-text {:on-click #(if (= @set-text "Set")
-                                                 (reset! set-text "Duration")
-                                                 (reset! set-text "Set"))
+                                                 (let [elements (array-seq (.getElementById js/document (str "set-" id)))]
+                                                   (doseq [e elements]
+                                                     (set! (.-selected e) false))
+                                                   (reset! set-text "Duration"))
+                                                 (let [elements (array-seq (.getElementById js/document (str "duration-" id)))]
+                                                   (doseq [e elements]
+                                                     (set! (.-selected e) false))
+                                                   (reset! set-text "Set")))
                                      :title "Change between set and duration"}
              @set-text]
             (let [txt @set-text]
               (case txt
                 "Set" [:div.pure-u.set {:className " custom-select"}
-                                     [:select.set-select
+                                     [:select {:className "set-select"
+                                               :id (str "set-" id)
+                                               :on-change #(let [x (.-value (.getElementById js/document (str "set-" id)))]
+                                                            (print x))}
                                       [:option "-"]
-                                      [:option "1"]
-                                      [:option "2"]
-                                      [:option "3"]
-                                      [:option "4"]
-                                      [:option "5"]
-                                      [:option "6"]
-                                      [:option "7"]
-                                      [:option "8"]
-                                      [:option "9"]
-                                      [:option "10"]]]
+                                      [:option 1]
+                                      [:option 2]
+                                      [:option 3]
+                                      [:option 4]
+                                      [:option 5]
+                                      [:option 6]
+                                      [:option 7]
+                                      [:option 8]
+                                      [:option 9]
+                                      [:option 10]]]
                 "Duration" [:div.pure-u.duration {:className " custom-select"}
-                            [:select.duration-select
+                            [:select {:className "duration-select"
+                                      :id (str "duration-" id)
+                                      :on-change #(let [x (.-value (.getElementById js/document (str "duration-" id)))]
+                                                   (print x))}
                              [:option "-"]
                              [:option "5 s"]
                              [:option "10 s"]
@@ -234,7 +269,7 @@
        [:div.pure-g
         [:label.pure-u.pure-u-md-1-5]
         [:h1.pure-u.pure-u-md-3-5 title]
-        [:button.pure-u.pure-u-md-1-5 {:on-click #(set-element-values! "rep" 5)} "Fill in 5 reps"]]
+        [:button.pure-u.pure-u-md-1-5 {:on-click #(set-element-values! "rep-select" 5)} "Fill in 5 reps"]]
        [:div {:on-click #(handler-fn (reset! adding-description true))} description]
        (when @adding-description
          [text-edit-component {:class   "edit" :title description
@@ -271,10 +306,6 @@
                             {:handler       add-session-handler
                              :error-handler (fn [] (print "error getting session data from server."))})}
        template-name])))
-
-(defonce getting-templates
-         (GET "templates" {:handler       #(session/put! :templates %)
-                           :error-handler #(print "error retrieving templates.")}))

 (defn generator-component []
   (let []


removed pprinting

removed pprinting

--- src/leiningen/new/onyx_app/src/onyx_app/launcher/launch_prod_peers.clj
+++ src/leiningen/new/onyx_app/src/onyx_app/launcher/launch_prod_peers.clj
@@ -2,8 +2,7 @@
   (:require [clojure.core.async :refer [<!! chan]]
             [environ.core :refer [env]]
             [onyx.test-helper :refer [load-config]]
-            {{#docker?}}[taoensso.timbre :as t]
-            [clojure.pprint :refer [pprint]]{{/docker?}}
+            {{#docker?}}[taoensso.timbre :as t]{{/docker?}}
             [onyx.plugin.kafka]
             [onyx.plugin.sql]
             [onyx.plugin.core-async]
@@ -19,7 +18,7 @@
   "Logger to output on std-out, for use with docker-compose"
   [data]
   (let [{:keys [output-fn]} data]
-    (pprint (output-fn data))))
+    (println (output-fn data))))
 {{/docker?}}
 (defn -main [onyx-id n & args]
   (let [n-peers (Integer/parseInt n)


Fx editor view (no edit).

Fx editor view (no edit).

--- sonic-jam/src/sonic_jam/core.cljs
+++ sonic-jam/src/sonic_jam/core.cljs
@@ -272,6 +272,41 @@
 (def grid-sample-editor
   (select-editor-builder "grid-sample" samples))

+(defn fx-editor [{:keys [cursor id set-state-ch]} owner]
+  (reify
+    om/IInitState
+    (init-state [_]
+      {:state :init})
+    om/IRenderState
+    (render-state [_ state]
+      (let [transition #(om/update-state! owner (fn [s] (merge {:state %})))]
+        (condp = (:state state)
+          :init (dom/span #js {:onClick #(transition :open)}
+                          "{..}")
+          :open (dom/table nil
+                           (apply dom/tbody nil
+                                  (concat
+                                   [(dom/tr nil
+                                            (dom/td #js {:onClick #(transition :init)} "{")
+                                            (dom/td nil nil)
+                                            (dom/td nil nil))]
+                                   (map #(dom/tr nil
+                                                 (dom/td nil nil)
+                                                 (dom/td nil (get % "fx"))
+                                                 (dom/td nil (om/build param-editor
+                                                                       {:cursor %
+                                                                        :id id
+                                                                        :set-state-ch set-state-ch})))
+                                        cursor)
+                                   [(dom/tr nil
+                                            (dom/td nil nil)
+                                            (dom/td #js {:onClick #(transition :open)} "[+]") ; TODO(:adding)
+                                            (dom/td nil nil))
+                                    (dom/tr nil
+                                            (dom/td #js {:onClick #(transition :init)} "}")
+                                            (dom/td nil nil)
+                                            (dom/td nil nil))]))))))))
+
 (defn track-editor [{:keys [cursor id delete-ch set-state-ch] :as input} owner]
   (reify
     om/IInitState
@@ -283,76 +318,86 @@
         (condp = (:state state)
           :init (dom/p style-grey
                        (dom/span #js {:onClick #(om/update-state! owner (fn [s] (merge s {:state :open})))} "{..}"))
-          :open (dom/p style-grey
-                       (dom/table nil
-                                  (apply dom/tbody nil
-                                         (concat
-                                          [(dom/tr nil
-                                                   (dom/td nil nil)
-                                                   (dom/td nil nil)
-                                                   (dom/td nil (dom/span #js {:onClick #(go (>! delete-ch cursor))
-                                                                              :style #js {:float "right"}} "X")))
-                                           (dom/tr nil
-                                                   (dom/td closer "{")
-                                                   (dom/td nil nil)
-                                                   (dom/td nil nil))
-                                           (dom/tr nil
-                                                   (dom/td nil nil)
-                                                   (dom/td nil "type:")
-                                                   (dom/td nil (om/build type-editor input)))]
-                                          (condp = (get cursor "type")
-                                            "synth" [(dom/tr nil
-                                                             (dom/td nil nil)
-                                                             (dom/td nil "synth:")
-                                                             (dom/td nil (om/build synth-editor input)))]
-                                            "sample" [(dom/tr nil
-                                                              (dom/td nil nil)
-                                                              (dom/td nil "sample:")
-                                                              (dom/td nil (om/build sample-editor input)))]
-                                            "play" [(dom/tr nil
-                                                            (dom/td nil nil)
-                                                            (dom/td nil "note:")
-                                                            (dom/td nil (get cursor "note")))]
-                                            [])
-                                          (condp = (get cursor "type")
-                                            "none" []
-                                            "grid" (condp = (get cursor "grid-type")
-                                                     "synth" [(dom/tr nil
-                                                                      (dom/td nil nil)
-                                                                      (dom/td nil "grid-type:")
-                                                                      (dom/td nil (om/build grid-type-editor input)))
-                                                              (dom/tr nil
-                                                                      (dom/td nil nil)
-                                                                      (dom/td nil "synth:")
-                                                                      (dom/td nil (om/build grid-synth-editor input)))
-                                                              (dom/tr nil
-                                                                      (dom/td nil nil)
-                                                                      (dom/td nil "params:")
-                                                                      (dom/td nil (om/build synth-param-editor input)))]
-                                                     "sample" [(dom/tr nil
-                                                                       (dom/td nil nil)
-                                                                       (dom/td nil "grid-type:")
-                                                                       (dom/td nil (om/build grid-type-editor input)))
-                                                               (dom/tr nil
-                                                                       (dom/td nil nil)
-                                                                       (dom/td nil "sample:")
-                                                                       (dom/td nil (om/build grid-sample-editor input)))
-                                                               (dom/tr nil
-                                                                       (dom/td nil nil)
-                                                                       (dom/td nil "params:")
-                                                                       (dom/td nil (om/build sample-param-editor input)))]
-                                                     [(dom/tr nil
-                                                              (dom/td nil nil)
-                                                              (dom/td nil "grid-type:")
-                                                              (dom/td nil (om/build grid-type-editor input)))])
+          :open (let [fx-row (dom/tr nil
+                                     (dom/td nil nil)
+                                     (dom/td nil "fx:")
+                                     (dom/td nil (om/build fx-editor {:cursor (get cursor "fx")
+                                                                      :id id
+                                                                      :set-state-ch set-state-ch})))]
+                  (dom/p style-grey
+                         (dom/table nil
+                                    (apply dom/tbody nil
+                                           (concat
                                             [(dom/tr nil
                                                      (dom/td nil nil)
-                                                     (dom/td nil "params:")
-                                                     (dom/td nil (om/build param-editor input)))])
-                                          [(dom/tr nil
-                                                   (dom/td closer "}")
-                                                   (dom/td nil nil)
-                                                   (dom/td nil))])))))))))
+                                                     (dom/td nil nil)
+                                                     (dom/td nil (dom/span #js {:onClick #(go (>! delete-ch cursor))
+                                                                                :style #js {:float "right"}} "X")))
+                                             (dom/tr nil
+                                                     (dom/td closer "{")
+                                                     (dom/td nil nil)
+                                                     (dom/td nil nil))
+                                             (dom/tr nil
+                                                     (dom/td nil nil)
+                                                     (dom/td nil "type:")
+                                                     (dom/td nil (om/build type-editor input)))]
+                                            (condp = (get cursor "type")
+                                              "synth" [(dom/tr nil
+                                                               (dom/td nil nil)
+                                                               (dom/td nil "synth:")
+                                                               (dom/td nil (om/build synth-editor input)))]
+                                              "sample" [(dom/tr nil
+                                                                (dom/td nil nil)
+                                                                (dom/td nil "sample:")
+                                                                (dom/td nil (om/build sample-editor input)))]
+                                              "play" [(dom/tr nil
+                                                              (dom/td nil nil)
+                                                              (dom/td nil "note:")
+                                                              (dom/td nil (get cursor "note")))]
+                                              [])
+                                            (condp = (get cursor "type")
+                                              "none" []
+                                              "grid" (condp = (get cursor "grid-type")
+                                                       "synth" [(dom/tr nil
+                                                                        (dom/td nil nil)
+                                                                        (dom/td nil "grid-type:")
+                                                                        (dom/td nil (om/build grid-type-editor input)))
+                                                                (dom/tr nil
+                                                                        (dom/td nil nil)
+                                                                        (dom/td nil "synth:")
+                                                                        (dom/td nil (om/build grid-synth-editor input)))
+                                                                (dom/tr nil
+                                                                        (dom/td nil nil)
+                                                                        (dom/td nil "params:")
+                                                                        (dom/td nil (om/build synth-param-editor input)))
+                                                                fx-row]
+                                                       "sample" [(dom/tr nil
+                                                                         (dom/td nil nil)
+                                                                         (dom/td nil "grid-type:")
+                                                                         (dom/td nil (om/build grid-type-editor input)))
+                                                                 (dom/tr nil
+                                                                         (dom/td nil nil)
+                                                                         (dom/td nil "sample:")
+                                                                         (dom/td nil (om/build grid-sample-editor input)))
+                                                                 (dom/tr nil
+                                                                         (dom/td nil nil)
+                                                                         (dom/td nil "params:")
+                                                                         (dom/td nil (om/build sample-param-editor input)))
+                                                                 fx-row]
+                                                       [(dom/tr nil
+                                                                (dom/td nil nil)
+                                                                (dom/td nil "grid-type:")
+                                                                (dom/td nil (om/build grid-type-editor input)))
+                                                        fx-row])
+                                              [(dom/tr nil
+                                                       (dom/td nil nil)
+                                                       (dom/td nil "params:")
+                                                       (dom/td nil (om/build param-editor input)))
+                                               fx-row])
+                                            [(dom/tr nil
+                                                     (dom/td closer "}")
+                                                     (dom/td nil nil)
+                                                     (dom/td nil))]))))))))))

 (defn track-builder [{:keys [cursor id set-state-ch]} owner]
   (reify