GAWB-1790: tweek

GAWB-1790: tweek

--- src/cljs/main/broadfcui/page/workspace/monitor/submission_details.cljs
+++ src/cljs/main/broadfcui/page/workspace/monitor/submission_details.cljs
@@ -43,13 +43,13 @@
       {:empty-message "No Workflows"
        :columns [{:header "Data Entity" :starting-width 200
                   :as-text
-                  (fn [workflow] (get-in workflow ["workflowEntity" "entityName"]))
+                  (fn [workflow] (get-in workflow [:workflowEntity :entityName]))
                   :sort-by :text
                   :content-renderer
                   (fn [workflow]
-                    (let [entity (workflow "workflowEntity")
-                          id (workflow "workflowId")
-                          name (str (entity "entityName") " (" (entity "entityType") ")")]
+                    (let [entity (:workflowEntity workflow)
+                          id (:workflowId workflow)
+                          name (str (:entityName entity) " (" (:entityType entity) ")")]
                       (if-not id
                         name
                         (style/create-link {:text name :href (nav/create-href (:nav-context props) id)}))))}
@@ -67,15 +67,15 @@
                                             message-list)])}
                  {:header "Workflow ID" :starting-width 300
                   :as-text
-                  (fn [workflow] (workflow "workflowId"))
+                  (fn [workflow] (:workflowId workflow))
                   :sort-by :text
                   :content-renderer
                   (fn [workflow]
                     (let [{:keys [submission-id bucketName]} props
-                          inputs (second (second (first (workflow "inputResolutions"))))
+                          inputs (second (second (first (:inputResolutions workflow))))
                           input-names (string/split inputs ".")
                           workflow-name (first input-names)
-                          workflowId (workflow "workflowId")]
+                          workflowId (:workflowId workflow)]
                       (style/create-link {:text workflowId
                                           :target "_blank"
                                           :style {:color "-webkit-link" :textDecoration "underline"}
@@ -88,14 +88,15 @@
        :data (:workflows props)
        :->row (fn [row]
                 [row
-                 (row "statusLastChangedDate")
-                 (row "status")
-                 (row "messages")
+                 (:statusLastChangedDate row)
+                 (:status row)
+                 (:messages row)
                  row])}])
    :render-workflow-details
    (fn [{:keys [props]} workflowId]
      (let [workflows (:workflows props)
-           workflowName (get-in (filterv #(= (get-in % ["workflowId"]) workflowId) workflows) [0 "workflowEntity" "entityName"])]
+           workflowName (->> workflows (filterv #(= (:workflowId %) workflowId))
+                             first :workflowEntity :entityName)]
        [:div {}
         [:div {:style {:marginBottom "1rem" :fontSize "1.1rem"}}
          [comps/Breadcrumbs {:crumbs
@@ -146,16 +147,16 @@
          :else
          [:div {}
           [:div {:style {:float "left" :width 290 :marginRight 40}}
-           [comps/StatusLabel {:text (submission "status")
+           [comps/StatusLabel {:text (:status submission)
                                :color (color-for-submission submission)
                                :icon (icon-for-submission submission)}]
-           (when (contains? moncommon/sub-running-statuses (submission "status"))
+           (when (contains? moncommon/sub-running-statuses (:status submission))
              [AbortButton
               {:on-abort (fn []
                            (swap! state assoc :server-response nil)
                            (react/call :load-details this))
                :workspace-id (:workspace-id props)
-               :submission-id (submission "submissionId")}])]
+               :submission-id (:submissionId submission)}])]
           [:div {:style {:float "left"}}
            (style/create-section-header "Method Configuration")
            (style/create-paragraph
@@ -169,29 +170,29 @@
            (style/create-paragraph
             [:div {}
              [:div {:style {:fontWeight 200 :display "inline-block" :width 90}} "Type:"]
-             [:span {:style {:fontWeight 500}} (get-in submission ["submissionEntity" "entityType"])]]
+             [:span {:style {:fontWeight 500}} (get-in submission [:submissionEntity :entityType])]]
             [:div {}
              [:div {:style {:fontWeight 200 :display "inline-block" :width 90}} "Name:"]
-             [:span {:style {:fontWeight 500}} (get-in submission ["submissionEntity" "entityName"])]])]
+             [:span {:style {:fontWeight 500}} (get-in submission [:submissionEntity :entityName])]])]
           [:div {:style {:float "right"}}
            (style/create-section-header "Submitted by")
            (style/create-paragraph
-            [:div {} (submission "submitter")]
-            [:div {} (common/format-date (submission "submissionDate")) " ("
-             (duration/fuzzy-time-from-now-ms (.parse js/Date (submission "submissionDate")) true) ")"])
+            [:div {} (:submitter submission)]
+            [:div {} (common/format-date (:submissionDate submission)) " ("
+             (duration/fuzzy-time-from-now-ms (.parse js/Date (:submissionDate submission)) true) ")"])
            (style/create-section-header "Submission ID")
-           (style/create-link {:text (style/create-paragraph (submission "submissionId"))
+           (style/create-link {:text (style/create-paragraph (:submissionId submission))
                                :target "_blank"
                                :style {:color "-webkit-link" :textDecoration "underline"}
                                :href (str moncommon/google-cloud-context
-                                          (:bucketName props) "/" (submission "submissionId") "/")})]
+                                          (:bucketName props) "/" (:submissionId submission) "/")})]
           (common/clear-both)
           [:h2 {} "Workflows:"]
-          [WorkflowsTable {:workflows (submission "workflows")
+          [WorkflowsTable {:workflows (:workflows submission)
                            :workspace-id (:workspace-id props)
                            :submission submission
                            :bucketName (:bucketName props)
-                           :submission-id (submission "submissionId")
+                           :submission-id (:submissionId submission)
                            :nav-context nav-context}]])))
    :load-details
    (fn [{:keys [props state]}]
@@ -199,6 +200,6 @@
       {:endpoint (endpoints/get-submission (:workspace-id props) (:submission-id props))
        :on-done (fn [{:keys [success? status-text get-parsed-response]}]
                   (swap! state assoc :server-response (if success?
-                                                        {:submission (get-parsed-response false)}
+                                                        {:submission (get-parsed-response)}
                                                         {:error-message status-text})))}))
    :component-did-mount (fn [{:keys [this]}] (react/call :load-details this))})


disabled test due to many open-schema issues

--- test/src/dda/pallet/dda_serverspec_crate/infra/fact/file_test.clj
+++ test/src/dda/pallet/dda_serverspec_crate/infra/fact/file_test.clj
@@ -21,7 +21,7 @@
     [pallet.actions :as actions]
     [dda.pallet.dda-serverspec-crate.infra.fact.file :as sut]))

-(s/set-fn-validation! true)
+;(s/set-fn-validation! true)

 (def one-file
   "/file'17418'mje'mje'600'f''Sun Mar 12 13:16:42.0709127452 2017'Sun Mar 12 13:16:42.0709127452 2017'Sun Mar 12 13:16:51.0409287069 2017'")


(SERVER-1183) environment-class-info-tags test cleanup

This commit includes some cleanup to the environment-class-info-tags
test around the use of variable names and also adds some fuller
assertion messages for a few of the assertions that are less obvious.

--- test/unit/puppetlabs/services/jruby/jruby_puppet_service_test.clj
+++ test/unit/puppetlabs/services/jruby/jruby_puppet_service_test.clj
@@ -297,7 +297,7 @@
      default-services
      (jruby-service-test-config 1)
      (let [service (app/get-service app :JRubyPuppetService)
-           production-before-first-update
+           production-cache-id-before-first-update
            (jruby-protocol/get-environment-class-info-cache-generation-id!
             service
             "production")]
@@ -305,13 +305,13 @@
          (is (nil? (jruby-protocol/get-environment-class-info-tag
                     service
                     "production")))
-         (is (not (nil? production-before-first-update))))
+         (is (not (nil? production-cache-id-before-first-update))))
        (testing "when environment info first set to cache"
          (jruby-protocol/set-environment-class-info-tag!
           service
           "production"
           "1234prod"
-          production-before-first-update)
+          production-cache-id-before-first-update)
          (is (= "1234prod" (jruby-protocol/get-environment-class-info-tag
                             service
                             "production")))
@@ -331,74 +331,91 @@
          (is (= "1234test" (jruby-protocol/get-environment-class-info-tag
                             service
                             "test"))))
-       (let [production-first-update
+       (let [production-cache-id-after-first-update
              (jruby-protocol/get-environment-class-info-cache-generation-id!
               service
               "production")
-             test-first-update
+             test-cache-id-after-first-update
              (jruby-protocol/get-environment-class-info-cache-generation-id!
               service
               "test")]
          (testing "when environment info reset in the cache"
-           (is (not (nil? production-first-update)))
-           (is (not (nil? test-first-update)))
+           (is (not (nil? production-cache-id-after-first-update)))
+           (is (not (nil? test-cache-id-after-first-update)))
            (jruby-protocol/set-environment-class-info-tag!
             service
             "production"
             "5678prod"
-            production-first-update)
+            production-cache-id-after-first-update)
            (is (= "5678prod" (jruby-protocol/get-environment-class-info-tag
                               service
                               "production")))
            (is (= "1234test" (jruby-protocol/get-environment-class-info-tag
                               service
                               "test")))
-           (is (= test-first-update
+           (is (= test-cache-id-after-first-update
                   (jruby-protocol/get-environment-class-info-cache-generation-id!
                    service
                    "test")))
            (testing "and environment expired between get and corresponding set"
-             (let [production-second-update
+             (let [production-cache-id-after-second-update
                    (jruby-protocol/get-environment-class-info-cache-generation-id!
                     service
                     "production")
                    _ (jruby-protocol/mark-environment-expired! service
                                                                "production")
-                   production-third-update
+                   production-cache-id-after-third-update
                    (jruby-protocol/get-environment-class-info-cache-generation-id!
                     service
                     "production")]
-               (is (not= production-first-update production-second-update))
+               (is (not= production-cache-id-after-first-update
+                         production-cache-id-after-second-update))
+               (is (= nil (jruby-protocol/get-environment-class-info-tag
+                           service
+                           "production"))
+                   (str "Tag was unexpectedly non-nil, however, it should have "
+                        "been because of the prior call to "
+                        "`mark-environment-expired`"))
                (jruby-protocol/set-environment-class-info-tag!
                 service
                 "production"
                 "89abprod"
-                production-second-update)
+                production-cache-id-after-second-update)
                (is (= nil (jruby-protocol/get-environment-class-info-tag
                            service
-                           "production")))
-               (is (= production-third-update
+                           "production"))
+                   (str "Tag should not have been changed by the prior set "
+                        "since the environment was marked expired after the "
+                        "cache was read for `production-second-update`"))
+               (is (= production-cache-id-after-third-update
                       (jruby-protocol/get-environment-class-info-cache-generation-id!
                        service
-                       "production"))))))
+                       "production"))
+                   (str "Cache id should not have been changed by the prior "
+                        "set since the environment was marked expired after "
+                        "cache was read for `production-second-update`")))))
          (testing "when an individual environment is marked expired"
-           (jruby-protocol/mark-environment-expired! service "production")
-           (is (nil? (jruby-protocol/get-environment-class-info-tag
-                      service
-                      "production")))
-           (is (not= production-first-update
-                     (jruby-protocol/get-environment-class-info-cache-generation-id!
-                      service
-                      "production")))
+           (let [production-cache-id-before-marked-expired
+                 (jruby-protocol/get-environment-class-info-cache-generation-id!
+                  service
+                  "production")]
+             (jruby-protocol/mark-environment-expired! service "production")
+             (is (nil? (jruby-protocol/get-environment-class-info-tag
+                        service
+                        "production")))
+             (is (not= production-cache-id-before-marked-expired
+                       (jruby-protocol/get-environment-class-info-cache-generation-id!
+                        service
+                        "production"))))
            (is (= "1234test" (jruby-protocol/get-environment-class-info-tag
                               service
                               "test")))
-           (is (= test-first-update
+           (is (= test-cache-id-after-first-update
                   (jruby-protocol/get-environment-class-info-cache-generation-id!
                    service
                    "test"))))
          (testing "when all environments are marked expired"
-           (let [production-update
+           (let [production-cache-id-before-set-tag
                  (jruby-protocol/get-environment-class-info-cache-generation-id!
                   service
                   "production")]
@@ -406,11 +423,11 @@
               service
               "production"
               "8910prod"
-              production-update)
+              production-cache-id-before-set-tag)
              (is (= "8910prod" (jruby-protocol/get-environment-class-info-tag
                                 service
                                 "production"))))
-           (let [production-third-update
+           (let [production-cache-id-before-marked-expired
                  (jruby-protocol/get-environment-class-info-cache-generation-id!
                   service
                   "production")]
@@ -418,24 +435,24 @@
              (is (nil? (jruby-protocol/get-environment-class-info-tag
                         service
                         "production")))
-             (is (not= production-third-update
+             (is (not= production-cache-id-before-marked-expired
                        (jruby-protocol/get-environment-class-info-cache-generation-id!
                         service
                         "production")))
              (is (nil? (jruby-protocol/get-environment-class-info-tag service
                                                                       "test")))
-             (is (not= test-first-update
+             (is (not= test-cache-id-after-first-update
                        (jruby-protocol/get-environment-class-info-cache-generation-id!
                         service
                         "test")))))
          (testing (str "when all environments expired between get and set "
                        "for environment that did not previously exist")
-           (let [staging-before-marked-expired
+           (let [staging-cache-id-before-marked-expired
                  (jruby-protocol/get-environment-class-info-cache-generation-id!
                   service
                   "staging")
                  _ (jruby-protocol/mark-all-environments-expired! service)
-                 staging-after-marked-expired
+                 staging-cache-id-after-marked-expired
                  (jruby-protocol/get-environment-class-info-cache-generation-id!
                   service
                   "staging")]
@@ -443,11 +460,18 @@
               service
               "staging"
               "1234staging"
-              staging-before-marked-expired)
+              staging-cache-id-before-marked-expired)
              (is (= nil (jruby-protocol/get-environment-class-info-tag
                          service
-                         "staging")))
-             (is (= staging-after-marked-expired
+                         "staging"))
+                 (str "Tag should not have been changed by the prior set "
+                      "since the environment was marked expired after the "
+                      "`staging-cache-id-before-marked-expired` was read"))
+             (is (= staging-cache-id-after-marked-expired
                     (jruby-protocol/get-environment-class-info-cache-generation-id!
                      service
-                     "staging"))))))))))
+                     "staging"))
+                 (str "Cache id should not have been changed by the prior "
+                      "set since the environment was marked expired after the "
+                      "`staging-cache-id-before-marked-expired` was "
+                      "read")))))))))


finished part 1

finished part 1


Fix build on 3.12.1 by upgrading ocp-build to OCamlPro/typerex@1fa4aeb21f7848891646e2107cd2c6991f4e85ed


fix typo

fix typo

--- dada-core/src/main/clojure/org/dada/core/RemoteView.clj
+++ dada-core/src/main/clojure/org/dada/core/RemoteView.clj
@@ -70,6 +70,6 @@
   (with-record (immutable this) [send-to]
 	       (.hashCode send-to)))

-(defn ^String -toString [^org.dada.core.SimpleModelView this]
+(defn ^String -toString [^org.dada.core.RemoteView this]
   (let [{send-to :send-to} (immutable this)]
     (print-object this send-to)))


Add root concept assignment rule name

Add root concept assignment rule name

--- kabob-build/src/main/resources/edu/ucdenver/ccp/kabob/build/rules/bio_to_ice/ontology_ice_gen_rules.clj
+++ kabob-build/src/main/resources/edu/ucdenver/ccp/kabob/build/rules/bio_to_ice/ontology_ice_gen_rules.clj
@@ -2,7 +2,7 @@
 ;; --------- Root Concept Assignment ---------
 ;; -------------------------------------------
 ;; create ICE URI's for each term in the ontology
-`{:name "ontology-concept-record-gen"
+`{:name "root-concept-identifier-gen"
   :head ((?/id rdf/type ccp/IAO_EXT_0000190) ; ontology root concept identifer
          (?/id obo/IAO_0000219 ?/root)) ; denotes
   :sparql-string "select ?root {


Target Java 6 in a sample project as well

--- sample/project.clj
+++ sample/project.clj
@@ -9,6 +9,8 @@

   :source-paths ["src/clojure" "src"]
   :java-source-paths ["src/java" "gen"]
+  :javac-options ["-target" "1.6" "-source" "1.6" "-Xlint:-options"]
+
   ;; The following two definitions are optional. The default
   ;; target-path is "target", but you can change it to whatever you like.
   ;; :target-path "bin"


Add 'try it' button to examples

Add 'try it' button to examples

--- dev/src/yada/dev/examples.clj
+++ dev/src/yada/dev/examples.clj
@@ -160,20 +160,24 @@
                  [:p (format "Click on the %s button to run this example, and check the response below"
                              (->meth method))]
                  [:pre
+                  (->meth method) (format " %s HTTP/1.1" url)
+                  (for [[k v] headers] (format "\n%s: \"%s\"" k v))]
+                 [:p
                   [:button.btn.btn-primary
                    {:type "button"
                     :onClick (format "tryIt('%s','%s','%s',%s)"
                                      (->meth method)
                                      url
                                      ix (json/encode headers))}
-                   (->meth method)] (format " %s HTTP/1.1" url)
-                  (for [[k v] headers] (format "\n%s: \"%s\"" k v))]])
+                   "Try it"]
+                  " "
+                  [:button.btn
+                   {:type "button"
+                    :onClick (format "clearIt('%s')" ix)}
+                   "Clear"]]])

               [:div {:id (str "response-" ix)}
-               [:h4 "Response " [:button.btn
-                                 {:type "button"
-                                  :onClick (format "clearIt('%s')" ix)}
-                                 "Clear"]]
+               [:h4 "Response"]

                [:table.table
                 [:tbody


Трансляторы для типа json

Трансляторы для типа json

--- radiolamp-6P3/src/ixinfestor/core.clj
+++ radiolamp-6P3/src/ixinfestor/core.clj
@@ -16,6 +16,7 @@
             [image-resizer.format :as format]
             [image-resizer.pad :as pad]

+             [cheshire.core :as cheshire-c]

             [cemerick.friend :as friend]
             (cemerick.friend [workflows :as workflows]
@@ -567,6 +568,21 @@
    field #(->> % .getTime (new java.util.Date)) row))

 ;; ---------------------------------------
+;; JSON transformations
+
+(defn prepare-as-json  [field row]
+  (if-empty?-row-or-nil?-val-then-row-else-do
+   field cheshire-c/generate-string row))
+
+(defn transform-as-clj [field keywordize? row]
+  (if-empty?-row-or-nil?-val-then-row-else-do
+   field
+   (fn [v]
+     (cheshire-c/parse-string (str v) keywordize?))
+   row))
+
+
+;; ---------------------------------------

 (defn check-row [is-error-fn? message row]
   (if (is-error-fn? row) (throw (Exception. (str "Error on row -> " message "\nrow: " row)))


improve output

improve output

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -325,7 +325,7 @@
       false)))

 (defn truncate [input truncate-paths language-model]
-  (log/info (str "truncating " (show-bolt input language-model) " with paths: " truncate-paths))
+  (log/debug (str "truncating@" truncate-paths ":" (show-bolt input language-model)))
   (let [serialized (if (:serialized input)
                      (:serialized input)
                      (serialize input))


more spec info

more spec info

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -118,7 +118,11 @@
             (if expression
               (log/info (str "generate: generated "
                              "'" (morph expression) "'"
-                             " for spec:" (strip-refs spec)))
+                             " for spec:" (strip-refs spec) ";"
+                             " expr spec: "
+                             (unifyc
+                              spec
+                              {:synsem {:sem (strip-refs (get-in expression [:synsem :sem]))}})))
               (log/info (str "generate: no expression could be generated for spec:" (strip-refs spec))))
             expression))))


fix custom encoding correctly calling * methods

--- src/cheshire/custom.clj
+++ src/cheshire/custom.clj
@@ -43,12 +43,9 @@
      (encode obj nil))
   ([obj opt-map]
      (try
-       (core/encode obj :date-format (:date-format opt-map)
-                    :pretty (:pretty opt-map)
-                    :ex core-failure)
+       (core/encode obj (merge opt-map {:ex core-failure}))
        (catch JsonGenerationException _
-         (encode* obj :date-format (:date-format opt-map)
-                  :pretty (:pretty opt-map))))))
+         (encode* obj opt-map)))))

 (defn ^String encode-stream*
   ([obj ^BufferedWriter w]
@@ -69,12 +66,9 @@
      (encode-stream obj w nil))
   ([obj ^BufferedWriter w opt-map]
      (try
-       (core/encode-stream obj w :date-format (:date-format opt-map)
-                           :pretty (:pretty opt-map)
-                           :ex core-failure)
+       (core/encode-stream obj w (merge opt-map {:ex core-failure}))
        (catch JsonGenerationException _
-         (encode-stream* obj :date-format (:date-format opt-map)
-                         :pretty (:pretty opt-map))))))
+         (encode-stream* obj opt-map)))))

 (defn encode-smile*
   ([obj]
@@ -94,9 +88,9 @@
      (encode-smile* obj nil))
   ([obj opt-map]
      (try
-       (core/encode-smile obj (:date-format opt-map) core-failure)
+       (core/encode-smile obj (merge opt-map {:ex core-failure}))
        (catch JsonGenerationException _
-         (encode-smile* obj (:date-format opt-map))))))
+         (encode-smile* obj opt-map)))))

 ;; there are no differences in parsing, but these are here to make
 ;; this a self-contained namespace if desired


Add java-home discovery

Add java-home discovery

--- src/clj/runbld/java.clj
+++ src/clj/runbld/java.clj
@@ -36,6 +36,17 @@
       (str/replace path #"^(.*)/jre$" "$1")
       path)))

+(defn java-home
+  ([]
+   (java-home "java"))
+  ([java-bin]
+   (-> (io/resolve-binary java-bin)
+       io/file
+       .getParent
+       io/file
+       .getParent
+       no-jre-path)))
+
 (defn java-home-java [java-home allow-jre]
   (when-let [jh (if allow-jre java-home (no-jre-path java-home))]
     (str (io/file jh "bin/java"))))


Remove all :refer from quil.core. Needed for cljs-in-cljs.

--- src/cljc/quil/core.cljc
+++ src/cljc/quil/core.cljc
@@ -7,16 +7,15 @@
      (:require quil.sketch
                [clojure.set]
                [quil.helpers.docs :as docs]
-               [quil.util :as u :refer [int-like? resolve-constant-key length-of-longest-key gen-padding print-definition-list
-                                        absolute-path clj-compilation?]]
-               [quil.applet :refer [current-applet applet-state applet defapplet resolve-renderer]]))
+               [quil.util :as u]
+               [quil.applet :as ap]))

    :cljs
    (ns quil.core
      (:require clojure.string
                org.processingjs.Processing
-               [quil.sketch :as applet :refer [current-applet resolve-renderer]]
-               [quil.util :as u :refer [resolve-constant-key] :include-macros true])))
+               [quil.sketch :as ap :include-macros true]
+               [quil.util :as u :include-macros true])))

 (def ^{:dynamic true
        :private true}
@@ -38,8 +37,8 @@
   (.beginDraw (current-graphics))."
   []
   (or *graphics*
-      #?(:clj (.-g (current-applet))
-         :cljs (current-applet))))
+      #?(:clj (.-g (ap/current-applet))
+         :cljs (ap/current-applet))))

 ;; -------------------- PConstants section -----------------------

@@ -160,7 +159,7 @@
   A new line is put between each element of the array. This function can only print 1D arrays,
   but can test to see if the content are null or not null for 2+ dimensional arrays."
      [msg]
-     (.println (current-applet) msg)))
+     (.println (ap/current-applet) msg)))

 #?(:cljs
    (defn
@@ -174,7 +173,7 @@
   The companion function println() works like print(), but creates a new line of text for each call to the function.
    Individual elements can be separated with quotes (\"\") and joined with the addition operator (+). "
      [msg]
-     (.print (current-applet) msg)))
+     (.print (ap/current-applet) msg)))

 #?(:cljs
    (defn
@@ -190,7 +189,7 @@

 #?(:clj
    (defmacro with-sketch [applet & body]
-     (when-not (clj-compilation?)
+     (when-not (u/clj-compilation?)
        `(quil.sketch/with-sketch ~applet ~@body))))

 (defn
@@ -206,8 +205,8 @@
   (state :foo) ;=> 1
   (swap! (state-atom) update-in [:foo] inc)
   (state :foo) ;=> 2"
-  #?(:clj ([] (-> (current-applet) meta :state))
-     :cljs ([] (. (current-applet) -quil))))
+  #?(:clj ([] (-> (ap/current-applet) meta :state))
+     :cljs ([] (. (ap/current-applet) -quil))))

 (defn
   ^{:requires-bindings true
@@ -286,11 +285,11 @@
   an int or float appropriately"
   [n]
   #?(:clj
-     (if (int-like? n)
+     (if (u/int-like? n)
        (abs-int n)
        (abs-float n))
      :cljs
-     (.abs (current-applet) n)))
+     (.abs (ap/current-applet) n)))

 (defn
   ^{:requires-bindings false
@@ -304,7 +303,7 @@
   returned in the range 0 to Math/PI (3.1415927)."
   [n]
   #?(:clj (PApplet/acos (float n))
-     :cljs (.acos (current-applet) n)))
+     :cljs (.acos (ap/current-applet) n)))

 (defn
   ^{:requires-bindings true
@@ -364,7 +363,7 @@
   green light to reflect. Used in combination with emissive, specular,
   and shininess in setting the material properties of shapes."
   ([rgb]
-   #?(:clj (if (int-like? rgb) (ambient-int rgb) (ambient-float rgb))
+   #?(:clj (if (u/int-like? rgb) (ambient-int rgb) (ambient-float rgb))
       :cljs (ambient-float rgb)))
   ([x y z] (ambient-float x y z)))

@@ -428,13 +427,13 @@
   ellipse-mode function. The start and stop parameters specify the
   angles at which to draw the arc. The mode is either :open, :chord or :pie."
   ([x y width height start stop]
-    (.arc (current-applet) (float x) (float y) (float width) (float height)
+    (.arc (ap/current-applet) (float x) (float y) (float width) (float height)
         (float start) (float stop)))

   #?(:clj
      ([x y width height start stop mode]
-      (let [arc-mode (resolve-constant-key mode arc-modes)]
-        (.arc (current-applet) (float x) (float y) (float width) (float height)
+      (let [arc-mode (u/resolve-constant-key mode arc-modes)]
+        (.arc (ap/current-applet) (float x) (float y) (float width) (float height)
               (float start) (float stop) (int arc-mode))))))

 (defn
@@ -449,7 +448,7 @@
   in the range -PI/2 to PI/2."
   [n]
   #?(:clj (PApplet/asin (float n))
-     :cljs (.asin (current-applet) n)))
+     :cljs (.asin (ap/current-applet) n)))

 (defn
   ^{:requires-bindings false
@@ -464,7 +463,7 @@
   PI/2 ."
   [n]
   #?(:clj (PApplet/atan (float n))
-     :cljs (.atan (current-applet) n)))
+     :cljs (.atan (ap/current-applet) n)))

 (defn
   ^{:requires-bindings false
@@ -482,7 +481,7 @@
   calculating the tangent."
   [y x]
   #?(:clj (PApplet/atan2 (float y) (float x))
-     :cljs (.atan2 (current-applet) y x)))
+     :cljs (.atan2 (ap/current-applet) y x)))

 (defn
   ^{:requires-bindings false
@@ -558,9 +557,9 @@
   It is not possible to use transparency (alpha) in background colors
   with the main drawing surface, however they will work properly with
   create-graphics. Converts args to floats."
-  #?(:clj ([rgb] (if (int-like? rgb) (background-int rgb) (background-float rgb)))
+  #?(:clj ([rgb] (if (u/int-like? rgb) (background-int rgb) (background-float rgb)))
      :cljs ([rgb] (.background (current-graphics) rgb)))
-  #?(:clj ([rgb alpha] (if (int-like? rgb) (background-int rgb alpha) (background-float rgb alpha)))
+  #?(:clj ([rgb alpha] (if (u/int-like? rgb) (background-int rgb alpha) (background-float rgb alpha)))
      :cljs ([rgb alpha] (.background (current-graphics) rgb alpha)))
   ([r g b] (background-float r g b))
   ([r g b a] (background-float r g b a)))
@@ -626,7 +625,7 @@
   that a multi-segment line shape (such as a curve) will be rendered
   as individual segments."
      ([renderer filename]
-      (.beginRaw (current-applet) (resolve-renderer renderer) (absolute-path filename)))))
+      (.beginRaw (ap/current-applet) (ap/resolve-renderer renderer) (u/absolute-path filename)))))

 (defn
   ^{:requires-bindings true
@@ -657,7 +656,7 @@
   such as ellipse or rect within begin-shape."
   ([] (.beginShape (current-graphics)))
   ([mode]
-     (let [mode (resolve-constant-key mode shape-modes)]
+     (let [mode (u/resolve-constant-key mode shape-modes)]
        (.beginShape (current-graphics) (int mode)))))

 (defn
@@ -766,10 +765,10 @@
   the number of digits used."
   ([val]
    #?(:clj (PApplet/binary (int val))
-      :cljs (.binary (current-applet) val)))
+      :cljs (.binary (ap/current-applet) val)))
   ([val num-digits]
    #?(:clj (PApplet/binary (int val) (int num-digits))
-      :cljs (.binary (current-applet) val num-digits))))
+      :cljs (.binary (ap/current-applet) val num-digits))))

 (defn
   ^{:requires-bindings true
@@ -816,7 +815,7 @@
   ([^PImage src-img x y width height dx dy dwidth dheight mode]
    (blend src-img (current-graphics) x y width height dx dy dwidth dheight mode))
   ([^PImage src-img ^PImage dest-img x y width height dx dy dwidth dheight mode]
-     (let [mode (resolve-constant-key mode blend-modes)]
+     (let [mode (u/resolve-constant-key mode blend-modes)]
        (.blend dest-img src-img (int x) (int y) (int width) (int height)
                (int dx) (int dy) (int dwidth) (int dheight) (int mode)))))

@@ -859,7 +858,7 @@
                 lights. Called \"Color Burn\" in Illustrator and
                 Photoshop."
   [c1 c2 mode]
-  (let [mode (resolve-constant-key mode blend-modes)]
+  (let [mode (u/resolve-constant-key mode blend-modes)]
     #?(:clj (PApplet/blendColor (unchecked-int c1) (unchecked-int c2) (int mode))
        :cljs (.blendColor (current-graphics) c1 c2 mode))))

@@ -895,7 +894,7 @@

   factor is alpha value of pixel being drawed"
      ([mode]
-      (let [mode (resolve-constant-key mode blend-modes)]
+      (let [mode (u/resolve-constant-key mode blend-modes)]
         (.blendMode (current-graphics) mode)))))

 (defn
@@ -977,7 +976,7 @@
   value 10."
   [n]
   #?(:clj (PApplet/ceil (float n))
-     :cljs (.ceil (current-applet) n)))
+     :cljs (.ceil (ap/current-applet) n)))

 #?(:clj
    (defn
@@ -1051,16 +1050,16 @@
   0 and 1. The limits for defining colors are altered by setting the
   parameters range1, range2, range3, and range 4."
   ([mode]
-     (let [mode (resolve-constant-key mode color-modes)]
+     (let [mode (u/resolve-constant-key mode color-modes)]
        (.colorMode (current-graphics) (int mode))))
   ([mode max]
-     (let [mode (resolve-constant-key mode color-modes)]
+     (let [mode (u/resolve-constant-key mode color-modes)]
        (.colorMode (current-graphics) (int mode) (float max))))
   ([mode max-x max-y max-z]
-     (let [mode (resolve-constant-key mode color-modes)]
+     (let [mode (u/resolve-constant-key mode color-modes)]
        (.colorMode (current-graphics) (int mode) (float max-x) (float max-y) (float max-z))))
   ([mode max-x max-y max-z max-a]
-     (let [mode (resolve-constant-key mode color-modes)]
+     (let [mode (u/resolve-constant-key mode color-modes)]
        (.colorMode (current-graphics) (int mode) (float max-x) (float max-y) (float max-z) (float max-a)))))

 #?(:clj
@@ -1100,10 +1099,10 @@
   "Constrains a value to not exceed a maximum and minimum value."
   [amt low high]
   #?(:clj
-     (if (int-like? amt)
+     (if (u/int-like? amt)
        (constrain-int amt low high)
        (constrain-float amt low high))
-     :cljs (.constrain (current-applet) amt low high)))
+     :cljs (.constrain (ap/current-applet) amt low high)))

 (defn
   ^{:requires-bindings true
@@ -1143,7 +1142,7 @@
   Math/PI*2). Values are returned in the range -1 to 1."
   [angle]
   #?(:clj (PApplet/cos (float angle))
-     :cljs (.cos (current-applet) angle)))
+     :cljs (.cos (ap/current-applet) angle)))

 #?(:clj
    (defn
@@ -1192,10 +1191,10 @@
   speed and appearance, results are poor when exporting if the sketch
   does not include the .otf or .ttf file, and the requested font is
   not available on the machine running the sketch."
-  ([name size] (.createFont (current-applet) (str name) (float size)))
-  ([name size smooth] (.createFont (current-applet) (str name) (float size) smooth))
+  ([name size] (.createFont (ap/current-applet) (str name) (float size)))
+  ([name size smooth] (.createFont (ap/current-applet) (str name) (float size) smooth))
   ([name size smooth ^chars charset]
-     (.createFont (current-applet) (str name) (float size) smooth charset)))
+     (.createFont (ap/current-applet) (str name) (float size) smooth charset)))

 (defn
   ^{:requires-bindings true
@@ -1228,12 +1227,12 @@
   using save to write a PNG or TGA file, the transparency of the
   graphics object will be honored."
   ([w h]
-   (.createGraphics (current-applet) (int w) (int h) #?(:cljs :p2d)))
+   (.createGraphics (ap/current-applet) (int w) (int h) #?(:cljs :p2d)))
   ([w h renderer]
-   (.createGraphics (current-applet) (int w) (int h) (resolve-renderer renderer)))
+   (.createGraphics (ap/current-applet) (int w) (int h) (ap/resolve-renderer renderer)))
   ([w h renderer path]
-   (.createGraphics (current-applet) (int w) (int h) (resolve-renderer renderer)
-                    #?(:clj (absolute-path path)
+   (.createGraphics (ap/current-applet) (int w) (int h) (ap/resolve-renderer renderer)
+                    #?(:clj (u/absolute-path path)
                        :cljs path))))

 (defn
@@ -1254,8 +1253,8 @@
   Prefer using create-image over initialising new PImage instances
   directly."
   [w h format]
-  (let [format (resolve-constant-key format image-formats)]
-    (.createImage (current-applet) (int w) (int h) (int format))))
+  (let [format (u/resolve-constant-key format image-formats)]
+    (.createImage (ap/current-applet) (int w) (int h) (int format))))

 (defn
   ^{:requires-bindings true
@@ -1293,10 +1292,10 @@

   See cursor-image for specifying a generic image as the cursor
   symbol."
-  ([] (.cursor (current-applet)))
+  ([] (.cursor (ap/current-applet)))
   ([cursor-mode]
-   (let [cursor-mode (resolve-constant-key cursor-mode cursor-modes)]
-     (.cursor (current-applet)
+   (let [cursor-mode (u/resolve-constant-key cursor-mode cursor-modes)]
+     (.cursor (ap/current-applet)
               #?(:clj (int cursor-mode)
                  :cljs (str cursor-mode))))))

@@ -1310,8 +1309,8 @@
   "Set the cursor to a predefined image. The horizontal and vertical
   active spots of the cursor may be specified with hx and hy.
   It is recommended to make the size 16x16 or 32x32 pixels."
-  ([^PImage img] (.cursor (current-applet) img))
-  ([^PImage img hx hy] (.cursor (current-applet) img (int hx) (int hy))))
+  ([^PImage img] (.cursor (ap/current-applet) img))
+  ([^PImage img hx hy] (.cursor (ap/current-applet) img (int hx) (int hy))))

 (defn
   ^{:requires-bindings true
@@ -1429,7 +1428,7 @@
   "Get the current day of the month (1 through 31)."
   []
   #?(:clj (PApplet/day)
-     :cljs (.day (current-applet))))
+     :cljs (.day (ap/current-applet))))

 (defn
   ^{:requires-bindings false
@@ -1446,7 +1445,7 @@
   specified in radians."
   [radians]
   #?(:clj (PApplet/degrees (float radians))
-     :cljs (.degrees (current-applet) radians)))
+     :cljs (.degrees (ap/current-applet) radians)))

 (defn
   ^{:requires-bindings true
@@ -1464,7 +1463,7 @@
   update when the delay fn is used. This function has no affect
   inside setup."
   [freeze-ms]
-  (.delay (current-applet) (int freeze-ms)))
+  (.delay (ap/current-applet) (int freeze-ms)))

 (defn
   ^{:requires-bindings true
@@ -1498,10 +1497,10 @@
   "Calculates the distance between two points"
   ([x1 y1 x2 y2]
    #?(:clj (PApplet/dist (float x1) (float y1) (float x2) (float y2))
-      :cljs (.dist (current-applet) x1 y1 x2 y2)))
+      :cljs (.dist (ap/current-applet) x1 y1 x2 y2)))
   ([x1 y1 z1 x2 y2 z2]
    #?(:clj (PApplet/dist (float x1) (float y1) (float z1) (float x2) (float y2) (float z2))
-      :cljs (.dist (current-applet) x1 y1 z1 x2 y2 z2))))
+      :cljs (.dist (ap/current-applet) x1 y1 z1 x2 y2 z2))))

 (defn
   ^{:requires-bindings true
@@ -1535,7 +1534,7 @@
   :corners - uses the four parameters to ellipse to set two opposing
              corners of the ellipse's bounding box."
   [mode]
-  (let [mode (resolve-constant-key mode ellipse-modes)]
+  (let [mode (u/resolve-constant-key mode ellipse-modes)]
     (.ellipseMode (current-graphics) (int mode))))

 (defn
@@ -1580,7 +1579,7 @@
   If passed one arg - it is assumed to be an int (i.e. a color),
   multiple args are converted to floats."
   ([c]
-   #?(:clj (if (int-like? c) (emissive-int c) (emissive-float c))
+   #?(:clj (if (u/int-like? c) (emissive-int c) (emissive-float c))
       :cljs (emissive-float c)))
   ([r g b] (emissive-float r g b)))

@@ -1655,7 +1654,7 @@
   completed (or after setup completes if called during the setup
   method). "
   []
-  (.exit (current-applet)))
+  (.exit (ap/current-applet)))

 (defn
   ^{:requires-bindings false
@@ -1668,7 +1667,7 @@
   value parameter."
   [val]
   #?(:clj (PApplet/exp (float val))
-     :cljs (.exp (current-applet) val)))
+     :cljs (.exp (ap/current-applet) val)))

 (defn- clear-no-fill-cljs
   "Sets custom property on graphcis object indicating that it has
@@ -1722,11 +1721,11 @@
   fill
   "Sets the color used to fill shapes."
   ([rgb]
-   #?(:clj (if (int-like? rgb) (fill-int rgb) (fill-float rgb))
+   #?(:clj (if (u/int-like? rgb) (fill-int rgb) (fill-float rgb))
       :cljs (fill-float rgb)))

   ([rgb alpha]
-   #?(:clj (if (int-like? rgb) (fill-int rgb alpha) (fill-float rgb alpha))
+   #?(:clj (if (u/int-like? rgb) (fill-int rgb alpha) (fill-float rgb alpha))
       :cljs (fill-float rgb alpha)))

   ([r g b] (fill-float r g b))
@@ -1745,8 +1744,8 @@
   Linux) and a 1 if not. This information is useful for a program to
   adapt to run at double the pixel density on a screen that supports
   it. Can be used in conjunction with (pixel-density)"
-     ([] (.displayDensity (current-applet)))
-     ([display] (.displayDensity (current-applet) display))))
+     ([] (.displayDensity (ap/current-applet)))
+     ([display] (.displayDensity (ap/current-applet) display))))

 (defn
   ^{:requires-bindings true
@@ -1783,10 +1782,10 @@
   :dilate    - increases the light areas.  Doesn't work with level."
   ([mode]
    (.filter (current-graphics)
-            (int (resolve-constant-key mode filter-modes))))
+            (int (u/resolve-constant-key mode filter-modes))))

   ([mode level]
-     (let [mode (resolve-constant-key mode filter-modes)]
+     (let [mode (u/resolve-constant-key mode filter-modes)]
        (.filter (current-graphics) (int mode) (float level)))))

 #?(:clj
@@ -1812,7 +1811,7 @@
   value of the parameter. For example, (floor 9.03) returns the value 9."
   [n]
   #?(:clj (PApplet/floor (float n))
-     :cljs (.floor (current-applet) n)))
+     :cljs (.floor (ap/current-applet) n)))

 (defn
   ^{:requires-bindings true
@@ -1822,7 +1821,7 @@
     :added "1.0"}
   focused
   "Returns a boolean value representing whether the applet has focus."
-  []  (.-focused (current-applet)))
+  []  (.-focused (ap/current-applet)))

 (defn
   ^{:requires-bindings true
@@ -1835,8 +1834,8 @@
   displayed since the program started. Inside setup() the value is 0
   and after the first iteration of draw it is 1, etc."
   []
-  #?(:clj (.frameCount (current-applet))
-     :cljs (.-frameCount (current-applet))))
+  #?(:clj (.frameCount (ap/current-applet))
+     :cljs (.-frameCount (ap/current-applet))))

 (defn
   ^{:requires-bindings true
@@ -1847,8 +1846,8 @@
   current-frame-rate
   "Returns the current framerate"
   []
-  #?(:clj (.frameRate (current-applet))
-     :cljs (.-__frameRate (current-applet))))
+  #?(:clj (.frameRate (ap/current-applet))
+     :cljs (.-__frameRate (ap/current-applet))))

 (defn
   ^{:requires-bindings true
@@ -1865,8 +1864,8 @@
   is 60 frames per second."
   [new-rate]
   (do
-    #?(:cljs (reset! (.-target-frame-rate (current-applet)) new-rate))
-    (.frameRate (current-applet) (float new-rate))))
+    #?(:cljs (reset! (.-target-frame-rate (ap/current-applet)) new-rate))
+    (.frameRate (ap/current-applet) (float new-rate))))

 (defn
   ^{:requires-bindings true
@@ -1935,10 +1934,10 @@
   geeky debugging sessions much happier. "
   ([val]
    #?(:clj (PApplet/hex (int val))
-      :cljs (.hex (current-applet) val)))
+      :cljs (.hex (ap/current-applet) val)))
   ([val num-digits]
    #?(:clj (PApplet/hex (int val) (int num-digits))
-      :cljs (.hex (current-applet) val num-digits))))
+      :cljs (.hex (ap/current-applet) val num-digits))))

 (defn
   ^{:requires-bindings true
@@ -1951,7 +1950,7 @@
   "Height of the display window. The value of height is zero until
   size is called."
   []
-  (.-height (current-applet)))
+  (.-height (ap/current-applet)))

 (defn
   ^{:requires-bindings true
@@ -2033,7 +2032,7 @@
   "Returns the current hour as a value from 0 - 23."
   []
   #?(:clj (PApplet/hour)
-     :cljs (.hour (current-applet))))
+     :cljs (.hour (ap/current-applet))))

 (defn
   ^{:requires-bindings true
@@ -2110,10 +2109,10 @@
   :erode     - reduces the light areas. Doesn't work with level.
   :dilate    - increases the light areas.  Doesn't work with level."
   ([^PImage img mode]
-    (let [mode (resolve-constant-key mode filter-modes)]
+    (let [mode (u/resolve-constant-key mode filter-modes)]
       (.filter img (int mode))))
   ([^PImage img mode level]
-     (let [mode (resolve-constant-key mode filter-modes)]
+     (let [mode (u/resolve-constant-key mode filter-modes)]
        (.filter img (int mode) (float level)))))

 (defn
@@ -2136,7 +2135,7 @@

   :center  - draw images centered at the given x and y position."
   [mode]
-  (let [mode (resolve-constant-key mode image-modes)]
+  (let [mode (u/resolve-constant-key mode image-modes)]
     (.imageMode (current-graphics) (int mode))))

 (defn
@@ -2164,7 +2163,7 @@
   KeyEvent.VK_DOWN. Other keyCode values can be found in the Java
   KeyEvent reference."
   []
-  (.-keyCode (current-applet)))
+  (.-keyCode (ap/current-applet)))

 (defn
   ^{:requires-bindings true
@@ -2175,7 +2174,7 @@
   key-pressed?
   "true if any key is currently pressed, false otherwise."
   []
-  (.-keyPressed (current-applet)))
+  (.-keyPressed (ap/current-applet)))

 (defn
   ^{:requires-bindings true
@@ -2231,7 +2230,7 @@
   drawing dotted lines."
   [start stop amt]
   #?(:clj (PApplet/lerp (float start) (float stop) (float amt))
-     :cljs (.lerp (current-applet) start stop amt)))
+     :cljs (.lerp (ap/current-applet) start stop amt)))

 (defn
   ^{:requires-bindings true
@@ -2319,7 +2318,7 @@
   when many font sizes are needed, or when using any renderer based on
   JAVA2D, such as the PDF library."
   [filename]
-  (.loadFont (current-applet)  (str filename)))
+  (.loadFont (ap/current-applet)  (str filename)))

 (defn
   ^{:requires-bindings true
@@ -2350,7 +2349,7 @@
   error or that redirect to a password prompt, because load-image
   will attempt to interpret the HTML as image data."
   [filename]
-  (.loadImage (current-applet) (str filename)))
+  (.loadImage (ap/current-applet) (str filename)))

 (defn
   ^{:requires-bindings true
@@ -2375,7 +2374,7 @@
   load-shape
   "Load a geometry from a file as a PShape."
   [filename]
-  (.loadShape (current-applet) filename))
+  (.loadShape (ap/current-applet) filename))

 (defn
   ^{:requires-bindings false
@@ -2388,7 +2387,7 @@
   number. This function expects the values greater than 0.0."
   [val]
   #?(:clj (PApplet/log (float val))
-     :cljs (.log (current-applet) val)))
+     :cljs (.log (ap/current-applet) val)))

 (defn
   ^{:requires-bindings false
@@ -2404,10 +2403,10 @@
   value. Therefore, mag is a shortcut for writing (dist 0 0 x y)."
   ([a b]
    #?(:clj (PApplet/mag (float a) (float b))
-      :cljs (.mag (current-applet) a b)))
+      :cljs (.mag (ap/current-applet) a b)))
   ([a b c]
    #?(:clj (PApplet/mag (float a) (float b) (float c))
-      :cljs (.mag (current-applet) a b c))))
+      :cljs (.mag (ap/current-applet) a b c))))

 (defn
   ^{:requires-bindings false
@@ -2422,7 +2421,7 @@
   out-of-range values are often intentional and useful."
   [val low1 high1 low2 high2]
   #?(:clj (PApplet/map (float val) (float low1) (float high1) (float low2) (float high2))
-     :cljs (.map (current-applet) val low1 high1 low2 high2)))
+     :cljs (.map (ap/current-applet) val low1 high1 low2 high2)))

 #?(:clj
    (defn
@@ -2458,7 +2457,7 @@
   starting the sketch. This information is often used for timing
   animation sequences."
   []
-  (.millis (current-applet)))
+  (.millis (ap/current-applet)))

 (defn
   ^{:requires-bindings false
@@ -2470,7 +2469,7 @@
   "Returns the current minute as a value from 0 - 59"
   []
   #?(:clj (PApplet/minute)
-     :cljs (.minute (current-applet))))
+     :cljs (.minute (ap/current-applet))))

 (defn
   ^{:requires-bindings true
@@ -2527,7 +2526,7 @@
   "Returns the current month as a value from 1 - 12."
   []
   #?(:clj (PApplet/month)
-     :cljs (.month (current-applet))))
+     :cljs (.month (ap/current-applet))))

 (defn
   ^{:requires-bindings true
@@ -2539,7 +2538,7 @@
   "The value of the system variable mouseButton is either :left, :right,
   or :center depending on which button is pressed. nil if no button pressed"
   []
-  (let [button-code   (.-mouseButton (current-applet))]
+  (let [button-code   (.-mouseButton (ap/current-applet))]
     #?(:clj
        (condp = button-code
          PConstants/LEFT :left
@@ -2565,7 +2564,7 @@
   system variable mousePressed is true if a mouse button is pressed
   and false if a button is not pressed."
   []
-  (.-mousePressed (current-applet)))
+  (.-mousePressed (ap/current-applet)))

 (defn
   ^{:requires-bindings true
@@ -2576,7 +2575,7 @@
   mouse-x
   "Current horizontal coordinate of the mouse."
   []
-  (.-mouseX (current-applet)))
+  (.-mouseX (ap/current-applet)))

 (defn
   ^{:requires-bindings true
@@ -2587,7 +2586,7 @@
   mouse-y
   "Current vertical coordinate of the mouse."
   []
-  (.-mouseY (current-applet)))
+  (.-mouseY (ap/current-applet)))

 #?(:clj
    (defn
@@ -2611,7 +2610,7 @@
   "Hides the cursor from view. Will not work when running the in full
   screen (Present) mode."
   []
-  (.noCursor (current-applet)))
+  (.noCursor (ap/current-applet)))

 (defn
   ^{:requires-bindings true
@@ -2661,9 +2660,9 @@
   difference between coordinates, the smoother the resulting noise
   sequence will be. Steps of 0.005-0.03 work best for most
   applications, but this will differ depending on use."
-  ([x] (.noise (current-applet) (float x)))
-  ([x y] (.noise (current-applet) (float x) (float y)))
-  ([x y z] (.noise (current-applet) (float x) (float y) (float z))))
+  ([x] (.noise (ap/current-applet) (float x)))
+  ([x y] (.noise (ap/current-applet) (float x) (float y)))
+  ([x y z] (.noise (ap/current-applet) (float x) (float y) (float z))))

 (defn
   ^{:requires-bindings true
@@ -2689,8 +2688,8 @@
   By changing these parameters, the signal created by the noise
   function can be adapted to fit very specific needs and
   characteristics."
-  ([octaves] (.noiseDetail (current-applet) (int octaves)))
-  ([octaves falloff] (.noiseDetail (current-applet) (int octaves) (float falloff))))
+  ([octaves] (.noiseDetail (ap/current-applet) (int octaves)))
+  ([octaves falloff] (.noiseDetail (ap/current-applet) (int octaves) (float falloff))))

 (defn
   ^{:requires-bindings true
@@ -2704,7 +2703,7 @@
   constant to return the same pseudo-random numbers each time the
   software is run."
   [val]
-  (.noiseSeed (current-applet) (int val)))
+  (.noiseSeed (ap/current-applet) (int val)))

 (defn
   ^{:requires-bindings true
@@ -2744,7 +2743,7 @@
   specified. Otherwise, the sketch would enter an odd state until
   loop was called."
   []
-  (.noLoop (current-applet)))
+  (.noLoop (ap/current-applet)))

 (defn
   ^{:requires-bindings true
@@ -2756,7 +2755,7 @@
   "Normalize a value to exist between 0 and 1 (inclusive)."
   [val start stop]
   #?(:clj (PApplet/norm (float val) (float start) (float stop))
-     :cljs (.norm (current-applet) val start stop)))
+     :cljs (.norm (ap/current-applet) val start stop)))

 (defn
   ^{:requires-bindings true
@@ -2867,7 +2866,7 @@
   :settings handler. To get density of the current screen you can use
   (display-density) function."
      [density]
-     (.pixelDensity (current-applet) density)))
+     (.pixelDensity (ap/current-applet) density)))

 (defn
   ^{:requires-bindings true
@@ -2903,7 +2902,7 @@
   pmouse-x
   "Horizontal coordinate of the mouse in the previous frame"
   []
-  (.-pmouseX (current-applet)))
+  (.-pmouseX (ap/current-applet)))

 (defn
   ^{:requires-bindings true
@@ -2914,7 +2913,7 @@
   pmouse-y
   "Vertical coordinate of the mouse in the previous frame"
   []
-  (.-pmouseY (current-applet)))
+  (.-pmouseY (ap/current-applet)))

 (defn
   ^{:requires-bindings true
@@ -2995,7 +2994,7 @@
   equivalent to (/ 1 (* 3 3 3 3 3))."
   [num exponent]
   #?(:clj (PApplet/pow (float num) (float exponent))
-     :cljs (.pow (current-applet) num exponent)))
+     :cljs (.pow (ap/current-applet) num exponent)))

 (defn
   ^{:requires-bindings true
@@ -3126,7 +3125,7 @@
   radians."
   [degrees]
   #?(:clj (PApplet/radians (float degrees))
-     :cljs (.radians (current-applet) degrees)))
+     :cljs (.radians (ap/current-applet) degrees)))

 (defn
   ^{:requires-bindings true
@@ -3144,8 +3143,8 @@
   with a value between the parameters. The function call
   (random -5 10.2) returns values starting at -5 up to (but not
   including) 10.2."
-  ([max] (.random (current-applet) (float max)))
-  ([min max] (.random (current-applet) (float min) (float max))))
+  ([max] (.random (ap/current-applet) (float max)))
+  ([min max] (.random (ap/current-applet) (float min) (float max))))

 (defn
   ^{:requires-bindings true
@@ -3162,7 +3161,7 @@
   from the mean will be returned; and a higher probability that numbers near
   the mean will be returned. ."
   []
-  (.randomGaussian (current-applet)))
+  (.randomGaussian (ap/current-applet)))

 (defn
   ^{:requires-bindings true
@@ -3176,7 +3175,7 @@
   parameter to a constant to return the same pseudo-random numbers
   each time the software is run."
   [w]
-  (.randomSeed (current-applet) (float w)))
+  (.randomSeed (ap/current-applet) (float w)))

 (defn
   ^{:requires-bindings true
@@ -3197,7 +3196,7 @@
   Macintosh. Check for both ENTER and RETURN to make sure your program
   will work for all platforms."
   []
-  (.-key (current-applet)))
+  (.-key (ap/current-applet)))

 (defn
   ^{:requires-bindings true
@@ -3251,7 +3250,7 @@
              image's width and height."

   [mode]
-  (let [mode (resolve-constant-key mode rect-modes)]
+  (let [mode (u/resolve-constant-key mode rect-modes)]
     (.rectMode (current-graphics) (int mode))))

 (defn
@@ -3285,7 +3284,7 @@
   Calling redraw within draw has no effect because draw is
   continuously called anyway."
   []
-  (.redraw (current-applet)))
+  (.redraw (ap/current-applet)))

 (defn
   ^{:requires-bindings true
@@ -3302,7 +3301,7 @@
   will be greater than 0. Asynchronous image loading (particularly
   when downloading from a server) can dramatically improve
   performance."
-  [filename] (.requestImage (current-applet) (str filename)))
+  [filename] (.requestImage (ap/current-applet) (str filename)))

 (defn
   ^{:requires-bindings true
@@ -3335,7 +3334,7 @@
   type of shader, either :points, :lines, or :triangles"
      ([] (.resetShader (current-graphics)))
      ([kind]
-      (let [mode (resolve-constant-key kind shader-modes)]
+      (let [mode (u/resolve-constant-key kind shader-modes)]
         (.resetShader (current-graphics) mode)))))

 (defn
@@ -3459,7 +3458,7 @@
   (round 9.2) returns the value 9."
   [val]
   #?(:clj (PApplet/round (float val))
-     :cljs (.round (current-applet) val)))
+     :cljs (.round (ap/current-applet) val)))

 (defn
   ^{:requires-bindings true
@@ -3507,8 +3506,8 @@
   Examples:
   (save-frame)
   (save-frame \"pretty-pic-####.jpg\")"
-  ([] (.saveFrame (current-applet)))
-  ([name] (.saveFrame (current-applet) (str name))))
+  ([] (.saveFrame (ap/current-applet)))
+  ([name] (.saveFrame (ap/current-applet) (str name))))

 (defn
   ^{:requires-bindings true
@@ -3615,7 +3614,7 @@
   "Returns the current second as a value from 0 - 59."
   []
   #?(:clj (PApplet/second)
-     :cljs (.second (current-applet))))
+     :cljs (.second (ap/current-applet))))

 (defn
   ^{:requires-bindings true
@@ -3669,7 +3668,7 @@
   parameter - type of shader, either :points, :lines, or :triangles"
      ([shader] (.shader (current-graphics) shader))
      ([shader kind]
-      (let [mode (resolve-constant-key kind shader-modes)]
+      (let [mode (u/resolve-constant-key kind shader-modes)]
         (.shader (current-graphics) shader mode)))))

 (defn
@@ -3768,7 +3767,7 @@
              and forth parameters of shape to specify the width and
              height. "
   [mode]
-  (let [mode (resolve-constant-key mode p-shape-modes)]
+  (let [mode (u/resolve-constant-key mode p-shape-modes)]
     (.shapeMode (current-graphics) (int mode))))

 (defn
@@ -3796,7 +3795,7 @@
   6.28). A float within the range -1 to 1 is returned."
   [angle]
   #?(:clj (PApplet/sin (float angle))
-     :cljs (.sin (current-applet) angle)))
+     :cljs (.sin (ap/current-applet) angle)))

 (defn
   ^{:requires-bindings true
@@ -3822,9 +3821,9 @@
   machine that is running the software.

   Note that smooth will also improve image quality of resized images."
-  ([] (.smooth #?(:clj (current-applet)
+  ([] (.smooth #?(:clj (ap/current-applet)
                   :cljs (current-graphics))))
-  ([level] (.smooth #?(:clj (current-applet)
+  ([level] (.smooth #?(:clj (ap/current-applet)
                        :cljs (current-graphics))
                      (int level))))

@@ -3908,7 +3907,7 @@
   yields a positive result. For example, -1 * -1 = 1."
   [a]
   #?(:clj (PApplet/sq (float a))
-     :cljs (.sq (current-applet) a)))
+     :cljs (.sq (ap/current-applet) a)))

 (defn
   ^{:requires-bindings false
@@ -3923,7 +3922,7 @@
   is the opposite of squaring."
   [a]
   #?(:clj (PApplet/sqrt (float a))
-     :cljs (.sqrt (current-applet) a)))
+     :cljs (.sqrt (ap/current-applet) a)))

 (defn
   ^{:requires-bindings true
@@ -3935,7 +3934,7 @@
   "Causes Processing to continuously execute the code within
   draw. If no-loop is called, the code in draw stops executing."
   []
-  (.loop (current-applet)))
+  (.loop (ap/current-applet)))

 (defn
   ^{:requires-bindings true
@@ -3975,11 +3974,11 @@
   on the current color-mode (the default color space is RGB, with
   each value in the range from 0 to 255)."
   ([rgb]
-   #?(:clj (if (int-like? rgb) (stroke-int rgb) (stroke-float rgb))
+   #?(:clj (if (u/int-like? rgb) (stroke-int rgb) (stroke-float rgb))
       :cljs (stroke-float rgb)))

   ([rgb alpha]
-   #?(:clj (if (int-like? rgb) (stroke-int rgb alpha) (stroke-float rgb alpha))
+   #?(:clj (if (u/int-like? rgb) (stroke-int rgb alpha) (stroke-float rgb alpha))
       :cljs (stroke-float rgb alpha)))

   ([x y z] (stroke-float x y z))
@@ -3996,7 +3995,7 @@
   squared, extended, or rounded and specified with the corresponding
   parameters :square, :project, and :round. The default cap is :round."
   [cap-mode]
-  (let [cap-mode (resolve-constant-key cap-mode stroke-cap-modes)]
+  (let [cap-mode (u/resolve-constant-key cap-mode stroke-cap-modes)]
     (.strokeCap (current-graphics)
                 #?(:clj (int cap-mode)
                    :cljs (str cap-mode)))))
@@ -4016,7 +4015,7 @@
   This function is not available with the :p2d, :p3d, or :opengl
   renderers."
   [join-mode]
-  (let [join-mode (resolve-constant-key join-mode stroke-join-modes)]
+  (let [join-mode (u/resolve-constant-key join-mode stroke-join-modes)]
     (.strokeJoin (current-graphics)
                  #?(:clj (int join-mode)
                     :cljs (str join-mode)))))
@@ -4046,7 +4045,7 @@
   infinity to -infinity."
   [angle]
   #?(:clj (PApplet/tan (float angle))
-     :cljs (.tan (current-applet) angle)))
+     :cljs (.tan (ap/current-applet) angle)))

 (defn
   ^{:requires-bindings true
@@ -4056,8 +4055,8 @@
   target-frame-rate
   "Returns the target framerate specified with the fn frame-rate"
   []
-  #?(:clj @(quil.applet/target-frame-rate)
-     :cljs @(.-target-frame-rate (current-applet))))
+  #?(:clj @(ap/target-frame-rate)
+     :cljs @(.-target-frame-rate (ap/current-applet))))

 (defn- no-fill?
   "Returns whether fill is disabled for current graphics."
@@ -4155,11 +4154,11 @@
   text-ascent or text-descent so that the hack works even if you
   change the size of the font."
   ([align]
-     (let [align (resolve-constant-key align horizontal-alignment-modes)]
+     (let [align (u/resolve-constant-key align horizontal-alignment-modes)]
        (.textAlign (current-graphics) (int align))))
   ([align-x align-y]
-     (let [align-x (resolve-constant-key align-x horizontal-alignment-modes)
-           align-y (resolve-constant-key align-y vertical-alignment-modes)]
+     (let [align-x (u/resolve-constant-key align-x horizontal-alignment-modes)
+           align-y (u/resolve-constant-key align-y vertical-alignment-modes)]
        (.textAlign (current-graphics) (int align-x) (int align-y)))))

 (defn
@@ -4254,7 +4253,7 @@
   recording shape data, use :model until you're ready to capture the
   geometry with begin-raw."
   [mode]
-  (let [mode (resolve-constant-key mode text-modes)]
+  (let [mode (u/resolve-constant-key mode text-modes)]
     (.textMode (current-graphics) (int mode))))

 (defn
@@ -4305,7 +4304,7 @@
   points (0,0) (0,100) (100,200) (0,200). The same mapping in
   NORMAL_SPACE is (0,0) (0,1) (1,1) (0,1)."
   [mode]
-  (let [mode (resolve-constant-key mode texture-modes)]
+  (let [mode (u/resolve-constant-key mode texture-modes)]
     (.textureMode (current-graphics) (int mode))))

 #?(:clj
@@ -4320,7 +4319,7 @@
   parameters are :clamp (the default behavior) and :repeat. This function
   only works with the :p2d and :p3d renderers."
      [mode]
-     (let [mode (resolve-constant-key mode texture-wrap-modes)]
+     (let [mode (u/resolve-constant-key mode texture-wrap-modes)]
        (.textureWrap (current-graphics) mode))))

 (defn
@@ -4402,9 +4401,9 @@
   maximum value is 255.

   Also used to control the coloring of textures in 3D."
-  #?(:clj ([rgb] (if (int-like? rgb) (tint-int rgb) (tint-float rgb)))
+  #?(:clj ([rgb] (if (u/int-like? rgb) (tint-int rgb) (tint-float rgb)))
      :cljs ([rgb] (.tint (current-graphics) rgb)))
-  #?(:clj ([rgb alpha] (if (int-like? rgb) (tint-int rgb alpha) (tint-float rgb alpha)))
+  #?(:clj ([rgb alpha] (if (u/int-like? rgb) (tint-int rgb alpha) (tint-float rgb alpha)))
      :cljs ([rgb alpha] (.tint (current-graphics) rgb alpha)))
   ([r g b] (tint-float r g b))
   ([r g b a] (tint-float r g b a)))
@@ -4458,7 +4457,7 @@
   integers to strings."
   [str-val]
   #?(:clj (PApplet/unbinary (str str-val))
-     :cljs (.unbinary (current-applet) (str str-val))))
+     :cljs (.unbinary (ap/current-applet) (str str-val))))

 (defn
   ^{:require-binding false
@@ -4470,7 +4469,7 @@
   equivalent integer value."
   [hex-str]
   #?(:clj (PApplet/unhex (str hex-str))
-     :cljs (.unhex (current-applet) (str hex-str))))
+     :cljs (.unhex (ap/current-applet) (str hex-str))))

 (defn
   ^{:requires-bindings true
@@ -4538,7 +4537,7 @@
   "Returns the current year as an integer (2003, 2004, 2005, etc)."
   []
   #?(:clj (PApplet/year)
-     :cljs (.year (current-applet))))
+     :cljs (.year (ap/current-applet))))

 (defn
   ^{:requires-bindings true
@@ -4551,7 +4550,7 @@
   "Width of the display window. The value of width is zero until size is
   called."
   []
-  (.-width (current-applet)))
+  (.-width (ap/current-applet)))

 #?(:clj
    (defmacro
@@ -4659,8 +4658,8 @@
   new sketches programmatically. See documentation for 'defsketch' for
   list of available options."
   [& opts]
-  #?(:clj (apply applet opts)
-     :cljs (apply applet/sketch opts)))
+  #?(:clj (apply ap/applet opts)
+     :cljs (apply ap/sketch opts)))

 #?(:clj
   (defmacro ^{:requires-bindings false
@@ -4806,8 +4805,8 @@
                      (no-smooth). Due to Processing limitations these functions
                      cannot be used neither in :setup nor in :draw."
     [app-name & options]
-    (if (clj-compilation?)
-      `(defapplet ~app-name ~@options)
+    (if (u/clj-compilation?)
+      `(ap/defapplet ~app-name ~@options)
       `(quil.sketch/defsketch ~app-name ~@options))))

 (defn ^{:requires-bindings false
@@ -4917,4 +4916,4 @@
   Processing-core equivalent."
      [orig-name]
      (let [res (docs/matching-processing-methods fn-metas orig-name)]
-       (print-definition-list res))))
+       (u/print-definition-list res))))


* src/cljs/cljs/core.cljs: use zero? & == for numeric tests

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -378,7 +378,7 @@
   "Accepts any collection which satisfies the ICount and IIndexed protocols and
 reduces them without incurring seq initialization"
   ([cicoll f]
-     (if (= 0 (-count cicoll))
+     (if (zero? (-count cicoll))
        (f)
        (loop [val (-nth cicoll 0), n 1]
          (if (< n (-count cicoll))
@@ -450,7 +450,7 @@
   (-hash [coll] (hash-coll coll)))

 (defn prim-seq [prim i]
-  (when-not (= 0 (.-length prim))
+  (when-not (zero? (.-length prim))
     (IndexedSeq. prim i)))

 (defn array-seq [array i]
@@ -2205,13 +2205,13 @@
      (lazy-seq
        (when-let [s (seq coll)]
          (let [p (take n s)]
-           (when (= n (count p))
+           (when (== n (count p))
              (cons p (partition n step (drop step s))))))))
   ([n step pad coll]
      (lazy-seq
        (when-let [s (seq coll)]
          (let [p (take n s)]
-           (if (= n (count p))
+           (if (== n (count p))
              (cons p (partition n step pad (drop step s)))
              (list (take n (concat p pad)))))))))

@@ -2601,7 +2601,7 @@
   (-peek [coll]
     (-nth v (dec end)))
   (-pop [coll]
-    (if (= start end)
+    (if (== start end)
       (throw (js/Error. "Can't pop empty vector"))
       (Subvec. meta v start (dec end) nil)))

@@ -2622,7 +2622,7 @@
   ISeqable
   (-seq [coll]
     (let [subvec-seq (fn subvec-seq [i]
-                       (when-not (= i end)
+                       (when-not (== i end)
                          (cons (-nth v i)
                                (lazy-seq
                                 (subvec-seq (inc i))))))]
@@ -2960,7 +2960,7 @@
   (boolean
     (when (map? y)
       ; assume all maps are counted
-      (when (= (count x) (count y))
+      (when (== (count x) (count y))
         (every? identity
                 (map (fn [xkv] (= (get y (first xkv) never-equiv)
                                   (second xkv)))
@@ -5010,7 +5010,7 @@
   (-equiv [coll other]
     (and
      (set? other)
-     (= (count coll) (count other))
+     (== (count coll) (count other))
      (every? #(contains? coll %)
              other)))

@@ -5105,7 +5105,7 @@
   (-equiv [coll other]
     (and
      (set? other)
-     (= (count coll) (count other))
+     (== (count coll) (count other))
      (every? #(contains? coll %)
              other)))

@@ -5351,13 +5351,13 @@
   (-nth [rng n]
     (if (< n (-count rng))
       (+ start (* n step))
-      (if (and (> start end) (= step 0))
+      (if (and (> start end) (zero? step))
         start
         (throw (js/Error. "Index out of bounds")))))
   (-nth [rng n not-found]
     (if (< n (-count rng))
       (+ start (* n step))
-      (if (and (> start end) (= step 0))
+      (if (and (> start end) (zero? step))
         start
         not-found)))

@@ -5496,7 +5496,7 @@
   [re s]
   (let [matches (.exec re s)]
     (when (= (first matches) s)
-      (if (= (count matches) 1)
+      (if (== (count matches) 1)
         (first matches)
         (vec matches)))))

@@ -5508,7 +5508,7 @@
   [re s]
   (let [matches (.exec re s)]
     (when-not (nil? matches)
-      (if (= (count matches) 1)
+      (if (== (count matches) 1)
         (first matches)
         (vec matches)))))

@@ -6055,9 +6055,9 @@
          (contains? ((:ancestors h) child) parent)
          ;;(and (class? child) (some #(contains? ((:ancestors h) %) parent) (supers child)))
          (and (vector? parent) (vector? child)
-              (= (count parent) (count child))
+              (== (count parent) (count child))
               (loop [ret true i 0]
-                (if (or (not ret) (= i (count parent)))
+                (if (or (not ret) (== i (count parent)))
                   ret
                   (recur (isa? h (child i) (parent i)) (inc i))))))))


#2 Math functions +, -, *, /, <, > - need reduce/first/rest

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -105,3 +105,82 @@
   ([f val coll]
      (let [s (seq coll)]
        (ireduce s f val))))
+
+;;; Math - variadic forms will not work until the following implemented:
+;;; first, next, reduce
+
+(defn +
+  "Returns the sum of nums. (+) returns 0."
+  ([] 0)
+  ([x] x)
+  ([x y] (js* "(~{x}+~{y})"))
+  ([x y & more] (reduce + (+ x y) more)))
+
+(defn -
+  "If no ys are supplied, returns the negation of x, else subtracts
+  the ys from x and returns the result."
+  ([x] (js* "(-~{x})"))
+  ([x y] (js* "(~{x}-~{y})"))
+  ([x y & more] (reduce - (- x y) more)))
+
+(defn *
+  "Returns the product of nums. (*) returns 1."
+  ([] 1)
+  ([x] x)
+  ([x y] (js* "(~{x}*~{y})"))
+  ([x y & more] (reduce * (* x y) more)))
+
+(defn /
+  "If no denominators are supplied, returns 1/numerator,
+  else returns numerator divided by all of the denominators."
+  ([x] (js* "(1/~{x})"))
+  ([x y] (js* "(~{x}/~{y})"))
+  ([x y & more] (reduce / (/ x y) more)))
+
+(defn <
+  "Returns non-nil if nums are in monotonically increasing order,
+  otherwise false."
+  ([x] true)
+  ([x y] (js* "(~{x}<~{y})"))
+  ([x y & more]
+     (if (< x y)
+       (if (next more)
+         (recur y (first more) (next more))
+         (< y (first more)))
+       false)))
+
+(defn <=
+  "Returns non-nil if nums are in monotonically non-decreasing order,
+  otherwise false."
+  ([x] true)
+  ([x y] (js* "(~{x}<=~{y})"))
+  ([x y & more]
+   (if (<= x y)
+     (if (next more)
+       (recur y (first more) (next more))
+       (<= y (first more)))
+     false)))
+
+(defn >
+  "Returns non-nil if nums are in monotonically decreasing order,
+  otherwise false."
+  ([x] true)
+  ([x y] (js* "(~{x}>~{y})"))
+  ([x y & more]
+   (if (> x y)
+     (if (next more)
+       (recur y (first more) (next more))
+       (> y (first more)))
+     false)))
+
+(defn >=
+  "Returns non-nil if nums are in monotonically non-increasing order,
+  otherwise false."
+  ([x] true)
+  ([x y] (js* "(~{x}>=~{y})"))
+  ([x y & more]
+   (if (>= x y)
+     (if (next more)
+       (recur y (first more) (next more))
+       (>= y (first more)))
+     false)))


Can't repeat arg name. Fixed.

Can't repeat arg name. Fixed.

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -99,7 +99,7 @@

 (defn js-keys [obj]
   (let [keys (array)]
-    (goog.object/forEach obj (fn [_ key _] (.push keys key)))
+    (goog.object/forEach obj (fn [val key obj] (.push keys key)))
     keys))

 (defn js-delete [obj key]


Fixed style and make dynamic a hash map that contains the factories of supported sockets.

--- src/clojure/nanomsg.clj
+++ src/clojure/nanomsg.clj
@@ -29,11 +29,17 @@
            clojure.lang.IFn)
   (:require [clojure.core.async :refer [chan put!]]))

-(def ^:static ^:private supported-sockets
-  {:pub PubSocket   :sub SubSocket
-   :req ReqSocket   :rep RepSocket
-   :bus BusSocket   :pair PairSocket
-   :push PushSocket :pull PullSocket})
+(def ^{:dynamic true
+       :private true}
+  *supported-sockets*
+  {:pub #(PubSocket.)
+   :sub #(SubSocket.)
+   :req #(ReqSocket.)
+   :rep #(RepSocket.)
+   :bus #(BusSocket.)
+   :pair #(PairSocket.)
+   :push #(PushSocket.)
+   :pull #(PullSocket.)})

 (defn- make-iasynccallback
   "Private function that create a new


Moved printing of instructions to pushgp.

--- src/clojush/clojush.clj
+++ src/clojush/clojush.clj
@@ -40,17 +40,14 @@

 (import java.lang.Math)

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; small things during initialization
+
 ;; backtrace abbreviation, to ease debugging
 (defn bt []
   (.printStackTrace *e))

-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; print all registered instructions on loading
-
-(printf "\nRegistered instructions: %s\n\n" @registered-instructions)
-(flush)
-
-;; also set default value for atom-generators
+;; set default value for atom-generators
 (reset! global-atom-generators
         (concat @registered-instructions
                 (list
@@ -578,6 +575,7 @@
     (reset! global-reuse-errors reuse-errors)
     (reset! global-use-historically-assessed-hardness use-historically-assessed-hardness)
     (reset! global-use-lexicase-selection use-lexicase-selection)
+    (printf "\nRegistered instructions: %s\n\n" @registered-instructions) (flush)
     (printf "\nStarting PushGP run.\n\n") (flush)
     (printf "Clojush version = ")
     (try


date-timestamp support; support for job database; new status msg support using job database

--- src/aerobio/server.clj
+++ src/aerobio/server.clj
@@ -35,6 +35,7 @@

   (:require
    [clojure.string :as str]
+   [clojure.pprint :refer [pprint]]
    [clojure.set :as set]
    [clojure.data.json :as json]
    [clojure.java.io :as io]
@@ -100,6 +101,11 @@
         dt (assoc dt :time-bits time)]
     dt))

+(defn date-time-stg []
+  (let [dt (date-time-map)]
+    (str (dt :date) "-"
+         (str/join ":" [(-> dt :time-bits :hour) (-> dt :time-bits :min)]))))
+
 ;;; ------------------------------------------------------------------------;;;
 ;;;                    Tool Config and  Watcher                             ;;;
 ;;; ------------------------------------------------------------------------;;;
@@ -311,6 +317,7 @@
    sp/ALL
    (fn[v]
      (cond
+       (isa? (type v) clojure.lang.Atom) (recur (deref v))
        (coll? v) (valuefy v)
        (not (future? v)) v
        (future-done? v) (deref v)
@@ -335,6 +342,9 @@
   ([key-path] (hc/get-db job-db key-path)))

+(defn get-job-status [user ])
+
+

 ;;; ------------------------------------------------------------------------;;;
@@ -355,6 +365,40 @@
   (infof "ERROR: unknown user message %s" msg)
   #_(srv/send-msg
      (msg :ws) {:op "error" :payload "ERROR: unknown user message"}))
+
+
+(defmethod user-msg :status [msg]
+  (let [params (msg :params)
+        {:keys [ws user eid action]} params]
+    (let [jinfo (hc/get-db (atom (valuefy @job-db)) [user eid action])
+          result (if (seq jinfo)
+                   (->> jinfo (sort-by #(-> % :request :timestamp))
+                        (mapv #(vector (-> % :request :timestamp)
+                                       (% :status)
+                                       (% :result))))
+                   (format "No job information for [%s %s %s]"
+                           user eid action))
+          retmsg (if (string? result)
+                   result
+                   (str/join
+                    "\n"
+                    (mapv #(let [timestamp (first %)
+                                 status (second %)
+                                 res (last %)
+                                 rstg (if (= res :future-not-yet-finished)
+                                        (format
+                                         "Currently still running:\n%s"
+                                         (with-out-str (pprint status)))
+                                        (format
+                                         "Finished:\n%s\nFinal result:\n%s"
+                                         (with-out-str (pprint status))
+                                         (with-out-str (pprint res))))]
+                             (with-out-str
+                               (print (format "%s : %s started @ %s\n%s"
+                                              eid action timestamp rstg))))
+                          result)))]
+      (send-end-msg ws {:op :status :payload retmsg}))))
+

 (defmethod user-msg :run [msg]
   (let [params (msg :params)
@@ -364,35 +408,45 @@
       (if (not-empty vmsg)
         (send-end-msg ws {:op :validate :payload vmsg})
         (let [{:keys [cmd eid template]} params
-              dt (date-time-map)
-              resfut (actions/action cmd eid params get-toolinfo template)]
+              dt (date-time-stg)
+              resmap (actions/action cmd eid params get-toolinfo template)
+              resfut (resmap :fut)
+              jobdb-info (or (get-jdb [user eid phase]) [])]
           (aerial.utils.misc/sleep 250)
-          (swap! dbg (fn[M] (assoc M eid resfut)))
-          (infof "%s : %s" cmd resfut)
-          (update-jdb [user (dt :date) (dt :time)]
-                      {:action {:params params :template template}
-                       :result resfut})
-          (if (future-done? resfut)
-            (let [cause (->> @resfut (austr/split #">>") second
-                             (str "Launch Failed: "))]
+          (swap! dbg (fn[M] (assoc M eid resmap)))
+          (infof "%s : %s" cmd (prn-str resfut))
+          (update-jdb [user eid phase]
+                      (conj jobdb-info
+                            {:request {:timestamp dt
+                                       :params (dissoc params :ws)}
+                             :status (resmap :status)
+                             :result resfut}))
+          (if (and (future-done? resfut) (map? @resfut) (@resfut :error))
+            (let [cause (->> (or (@resfut :msg) (prn-str (@resfut :error)))
+                             (str "Job Launch : "))]
               (srv/send-msg ws {:op :error :payload cause}))
             (srv/send-msg ws {:op :launch :payload "Successful"}))
           (srv/send-msg ws {:op :stop :payload {}} :noenvelope true))))))

+
 (defn msg-handler [msg]
   (let [{:keys [ws data]} msg
         {:keys [op data]} data
-        {:keys [user cmd phase modifier compfile eid]} data
+        {:keys [user cmd phase modifier compfile eid action]} data
         eid (if (str/ends-with? eid "/") (austr/butlast 1 eid) eid)
         eid (if (str/starts-with? eid "/") (austr/drop 1 eid) eid)
         params {:user user, :cmd op, :modifier modifier
-                :phase phase, :eid eid :ws ws}]
+                :phase phase, :action action :eid eid :ws ws}]
     (infof "MSG-HANDLER: MSG %s" (msg :data))
     (try
       (case op
         (:done "done")
         (do (infof "WS: %s, sending stop msg" ws)
             (srv/send-msg ws {:op :stop :payload {}} :noenvelope true))
+
+        (:status "status")
+        (user-msg {:op op :params params})
+
         ;;null for now
         (let [vmsg (va/validate-sheets-exist eid)]
           (if (not-empty vmsg)
@@ -408,10 +462,10 @@
                       params (assoc params :template template)]
                   (user-msg {:op op :params params})))))))
       (catch Error e
-        (infof "ERROR %s" (or (.getMessage e) e))
+        (errorf "ERROR %s: %s, %s" eid op (or (.getMessage e) e))
         (send-end-msg ws {:op :validate :payload (.getMessage e)}))
       (catch Exception e
-        (infof "EXCEPTION %s" (or (.getMessage e) e))
+        (errorf "EXCEPTION %s: %s, %s" eid op (or (.getMessage e) e))
         (send-end-msg ws {:op :validate :payload (.getMessage e)})))))

@@ -547,61 +601,28 @@

-
-
-
-
-(defn htseq-file-get [args reqmap]
-  (infof "Args %s\nParams %s" args (reqmap :params))
-  #_(infof "ReqMap %s" reqmap)
-  (binding [*ns* (find-ns 'aerobio.server)]
-    (let [params (reqmap :params)
-          {:keys [user cmd action rep compfile eid]} params
-          eid (if (str/ends-with? eid "/") (austr/butlast 1 eid) eid)
-          eid (if (str/starts-with? eid "/") (austr/drop 1 eid) eid)
-          user-agent (get-in reqmap [:headers "user-agent"])
-          reqtype (get-in reqmap [:headers "reqtype"])]
-      (if (= reqtype "cmdline")
-        (try
-          (let [_ (cmn/set-exp eid)
-                exp (cmn/get-exp-info eid :exp)
-                work-item (if action action cmd)
-                tempnm (str (name exp) "-" work-item "-job-template")
-                template (get-jobinfo tempnm)
-                result (actions/action cmd eid params get-toolinfo template)]
-            (aerial.utils.misc/sleep 250)
-            (swap! dbg (fn[M] (assoc M eid result)))
-            (infof "%s : %s" cmd result)
-            (json/json-str
-             {:params params
-              :result (str result)
-              :template tempnm
-              :recipient user}))
-          (catch Error e
-            (let [estg (format "Error %s" (or (.getMessage e) e))]
-              (errorf "%s: %s - Assert: %s" eid cmd estg)
-              (json/json-str
-             {:args args
-              :params params
-              :result estg
-              :recipient user
-              :user-agent user-agent
-              :reqtype reqtype})))
-          (catch Exception e
-            (let [emsg (or (.getMessage e) e)]
-              (errorf "%s: %s, Exception on Job launch: %s" eid cmd emsg)
-              (json/json-str
-               {:args args
-                :params params
-                :result (format "Exception: %s" emsg)
-                :recipient user
-                :user-agent user-agent
-                :reqtype reqtype}))))
-        (hiccup/html
-         [:h1 "HI from HTSeq command route"]
-         [:hr]
-         [:p (str "command and args: " args)]
-         [:hr]
-         [:p (str "Params" params)]
-         [:hr]
-         [:p (str "User Agent: " user-agent)])))))
+(comment
+
+  (let [eid "Ngon_cipro"
+        repk :rep
+        exp (cmn/get-exp-info eid :exp)
+        sample-names (cmn/get-exp-info eid :sample-names)
+        sample-names (if repk
+                       (mapcat #((cmn/get-exp-info eid :replicate-names) %)
+                               (cmn/get-exp-info eid :sample-names))
+                       sample-names)]
+    (partition-all 2 sample-names))
+
+
+  (let [eid "Ngon_cipro"
+        recipient "jsa"
+        template {:nodes
+                  {:ph0 {:name "rnaseq-phase0", :type "tool", :args []},
+                   :prn1 {:type "func", :name "prn"}},
+                  :edges {:ph0 [:prn1]}}
+        ph0 template
+        cfg (-> (assoc-in ph0 [:nodes :ph0 :args] [eid recipient])
+                (pg/config-pgm-graph-nodes get-toolinfo nil nil)
+                pg/config-pgm-graph)]
+    cfg)
+  )


Kill containium on hanging threads at shutdown.

--- src/containium/core.clj
+++ src/containium/core.clj
@@ -165,7 +165,9 @@
                (run []
                  (let [threads (keys (Thread/getAllStackTraces))]
                    (println (apply str "Threads still running (" (count threads) "):\n  "
-                                   (interpose "\n  " threads))))))]
+                                   (interpose "\n  " threads))))
+                 (println "Killing containium.")
+                 (System/exit 1)))]
     (.schedule timer task (int (* wait 1000)))))

 ;;; Daemon control


Add documentation, and rename functions more clearly.

--- src/defragment/core.clj
+++ src/defragment/core.clj
@@ -102,7 +102,6 @@
         (assoc :full-path filepath))))

-(def date-key-fn (juxt :year :month :day :time))

 (defn sort-and-partition
   "Takes a key and a seq of filename maps.
@@ -118,9 +117,6 @@

-
-
-
 (defn date-time-sort-partition
   "Takes a seq of filemaps.
    Sorts and groups them by DATE, not datetime,
@@ -156,12 +152,18 @@

 (defn format-show-save
+  "Takes file path, show name, and date.
+   Returns a string with the outgoing show filename and path, with ogg extension"
   [path name date]
   (format "%s/%s-%s.ogg"  path date name))

 (defn gen-command-line
-  "Takes a file glob, returns the string command to process it"
+  "Takes a concatenating file command full path (cmd-path),
+  the path to where the output file is to be saved,
+  and a file glob (name, date, filenames)
+  Returns the string shell command to concatenate all the filenames,
+  to the output dir, named properly with name and date."
   [cmd-path path {:keys [name date filenames]}]
   (let [cmd (format "cat %s | %s > %s"
                     (umisc/inter-str " " filenames)
@@ -170,15 +172,12 @@
     (format "echo \"%s\"\n%s\n" cmd cmd)))

-(defn gen-filenames
-  [cmd-path path files]
-  (umisc/inter-str "\n" (map (partial gen-command-line cmd-path path)  files)))
-
-
-

 (defn without-shows
+  "Takes a list of raw ogg files.
+   Filters only those without valid shows (in filename).
+   Returns a seq of file globs (name, date, filenames) for them"
   [files]
   (for [[show-name show-files] (->> files
                                     (remove :show)
@@ -187,14 +186,24 @@

 ;; TODO: protocol maybe?
-(defn header->vec
-  "Takes array of CommentFields and translates to a proper Clojure vector"
-  [hs]
-  (for [^CommentField h hs]
-    [(-> h .name s/lower-case keyword) (.value h)]))
+;; unused, but might be needed later
+#_(defn header->vec
+    "Takes array of CommentFields and translates to a proper Clojure vector"
+    [hs]
+    (for [^CommentField h hs]
+      [(-> h .name s/lower-case keyword) (.value h)]))

 (defn album-mover
+  "Returns a CommentUpdater for use with JVorbisComment,
+   for updating comments in place,
+   which moves any ALBUM tags to ARTIST, removing any
+   ARTIST tags which might have been there.
+   Necessary because liquidsoap is broken and won't save
+   anything but artist in filename, and we've cleaned the artist
+   to make it a legal unix filename, so the real show name with
+   unescaped characters is stashed in ALBUM instead, and must be
+   recovered here."
   []
   (reify CommentUpdater
     (updateComments [this comments]
@@ -214,7 +223,8 @@

-(defn bad-title
+(defn bad-title?
+  "Predicate for determining if a title needs to be replaced."
   [f]
   (let [n (.name f)
         v (.value f)]
@@ -223,14 +233,18 @@
              (= "%Y-%m-%d" (s/trim v))
              (empty? v)))))

-;; XXX this function ought to be taken out and shot
+
 (defn title-fixer
+  "Returns a CommentUpdater for use with JVorbisComment,
+   for updating comments in place,
+   which removes any bad TITLE tags and replaces
+   them with the show date"
   [^String date]
   (reify CommentUpdater
     (updateComments [this comments]
       (boolean
        (let [fields (.fields comments)
-             unknowns (doall (filter bad-title fields))]
+             unknowns (doall (filter bad-title? fields))]
          (log/debug "fixing titles" fields)
          (when (not (empty? unknowns))
            (log/debug "got unknowns" unknowns)
@@ -242,9 +256,10 @@
            true))))))

-
-(defn fix-in-place
-  [fpath fixer]
+(defn fix-in-place!
+  "Utility function to do in-place comment updating,
+   using the supplied CommentUpdater"
+  [fpath ^CommentUpdater fixer]
   (log/debug "fixing files" fpath)
   (try
     (-> fpath
@@ -254,49 +269,71 @@
       (log/error e))))

-(defn fix-comments
+(defn fix-comments!
+  "Takes a path to output files,
+   and a fileglob (name, date, filenames),
+   and executes album and title fixes for that output file.
+   The output file had better be there already."
   [path {:keys [name date]}]
   (let [out-path (format-show-save path name date)]
     (log/debug "fixing comments" out-path)
     (doseq [f [(title-fixer date) (album-mover)]]
-      (fix-in-place out-path f))))
+      (fix-in-place! out-path f))))

 (defn move-originals!
+  "Takes a fileglob (name, date filenames) and the directory for backup files.
+   Moves all the original filenames in the fileglob to the backup location."
   [{:keys [filenames]} backup-dir]
   (let [backup-dir (if (.endsWith backup-dir "/") backup-dir (str backup-dir "/"))]
     (doseq [f filenames]
       (log/debug "moving" f "to" backup-dir)
       (mv f backup-dir))))
-
-
-(defn execute!
-  [cmd-path path out-commands-file backup-dir fileglob]
+
+
+(defn concatenate!
+  "Takes a cmd-path (usually thrashcat) to a command which takes many streams on stdin and returns a concatenated single ogg/vorbis stream on stdout,
+  a path to deposit the concatenated file, an out-commands-file to dump a temporary shell script,
+  and a fileglob (name, date, filenames) with the info about a series of files to be concatenated.
+  Executes the cmd-path, feeding the filenames into it. Dumps the output to a specially-named
+  file in path."
+  [cmd-path path out-commands-file fileglob]
   (spit out-commands-file (gen-command-line cmd-path path fileglob))
   (let [{:keys [stdout stderr exit-code]} (bash out-commands-file {:verbose true})]
     (log/debug {:doing stdout, :result stderr, :status @exit-code})
     (when (not= 0 @exit-code)
       ;; TODO: throw exception too?
       (log/error {:doing stdout, :result stderr, :status @exit-code}))
-    (fix-comments path fileglob)
-    (move-originals! fileglob backup-dir)
+    ;; TODO: rm the old out-commands-file
     ))

 (defn execute-all!
+  "Takes a cmd-path to the external concatenating command,
+  a path to dump concatenated files,
+  an out-commands-file for temp scripts,
+  a backup-dir for moving the original filenames to,
+ and a fileglob (name, date, filenames) with the files to be concatenated.
+  Concatenates the files, fixes comments, and moves the originals to the backup-dir.
+  This is the core of the program."
   [cmd-path path out-commands-file backup-dir files]
   (doseq [f files]
     (log/info f)
-    (execute! cmd-path path out-commands-file backup-dir f)))
+    (concatenate! cmd-path path out-commands-file f)
+    (fix-comments! path f)
+    (move-originals! f backup-dir)))

 (defn prepare-all
+  "Takes list of files, and returns fileglobs (name, date, filenames) for them.
+   Processes files both with and without valid shows in their names."
   [files]
   (concat (prepare-shows files) (without-shows files)))

 (defn run-all
+  "Takes a config map, and runs the program, concatenating the oggs."
   [{:keys [in-oggs-path cmd-path out-oggs-path out-commands-file backup-dir]}]
   [{:pre [(assert (every? (comp not empty?) [in-oggs-path cmd-path backup-dir
                                              out-commands-file out-oggs-path]))]}]
@@ -311,6 +348,7 @@

 (defn process-config
+  "Read and deserialize the config"
   [config-path]
   (->> config-path
        slurp
@@ -319,6 +357,7 @@

 (defn revision-info
+  "Utility for determing the program's revision."
   []
   (let [{:keys [version revision]} (ujava/get-project-properties "defragment" "defragment")]
     (format "Version: %s, Revision %s" version revision)))


Make load/unload order problems easier to read

and add link to where to report such problems, if found.

--- src/dolly/namespace.clj
+++ src/dolly/namespace.clj
@@ -302,7 +302,7 @@
   "Returns nil if the tracker has load and unload orders that are
 consistent with its :dependencies and :dependents graphs.  If there
 are inconsistencies, returns a map containing either or both of the
-keys :load or :unload, where the values are a sequence of 2-element
+keys :load or :unload, where the values are a collection of 2-element
 vectors [a b] where a and b are symbols representing namespace names,
 and a requires or uses b, and that dependency order is violated by the
 load or unload order in the tracker."
@@ -313,16 +313,18 @@
         unload-set (set unload-order)
         dependency-pairs (tracker-dependency-pairs tracker)
         dependent-pairs (tracker-dependent-pairs tracker)
-        load-order-violations (filter
-                               (fn [[a b]]
-                                 (and (load-set a) (load-set b)
-                                      (before? load-order a b)))
-                               (concat dependency-pairs dependent-pairs))
-        unload-order-violations (filter
-                                 (fn [[a b]]
-                                   (and (unload-set a) (unload-set b)
-                                        (before? unload-order b a)))
-                                 (concat dependency-pairs dependent-pairs))]
+        load-order-violations (set
+                               (filter
+                                (fn [[a b]]
+                                  (and (load-set a) (load-set b)
+                                       (before? load-order a b)))
+                                (concat dependency-pairs dependent-pairs)))
+        unload-order-violations (set
+                                 (filter
+                                  (fn [[a b]]
+                                    (and (unload-set a) (unload-set b)
+                                         (before? unload-order b a)))
+                                  (concat dependency-pairs dependent-pairs)))]
     (if (or (seq load-order-violations)
             (seq unload-order-violations))
       {:load (seq load-order-violations)
@@ -337,14 +339,19 @@
    (with-out-str
      (when (:load bad-order)
        (println "Namespace tracker load order is:")
-       (println (:clojure.tools.namespace.track/load tracker))
-       (println "It violates the following [a b] dependencies, where a requires or uses b:")
-       (println (:load bad-order)))
+       (pp/pprint (:clojure.tools.namespace.track/load tracker))
+       (println "\nIt violates the following [a b] dependencies, where a requires or uses b:")
+       (pp/pprint (:load bad-order)))
      (when (:unload bad-order)
        (println "Namespace tracker unload order is:")
-       (println (:clojure.tools.namespace.track/unload tracker))
-       (println "It violates the following [a b] dependencies, where a requires or uses b:")
-       (println (:unload bad-order))))})
+       (pp/pprint (:clojure.tools.namespace.track/unload tracker))
+       (println "\nIt violates the following [a b] dependencies, where a requires or uses b:")
+       (pp/pprint (:unload bad-order)))
+     (println "
+This is most likely a bug in tools.namespace, or in the way that Dolly
+uses tools.namespace.  Please report this as an issue for Dolly at:
+
+    https://github.com/jafingerhut/dolly/issues"))})

 (defn namespaces-in-dirs [opts]


Minor change on cipher resolution impl on mac.

--- src/buddy/core/mac.clj
+++ src/buddy/core/mac.clj
@@ -144,17 +144,17 @@

 (defmethod -engine :poly1305+aes
   [options]
-  (let [cipher ((:aes +cipher-engines+))]
+  (let [cipher (resolve-cipher-engine :aes)]
     (Poly1305. cipher)))

 (defmethod -engine :poly1305+twofish
   [options]
-  (let [cipher ((:twofish +cipher-engines+))]
+  (let [cipher (resolve-cipher-engine :twofish)]
     (Poly1305. cipher)))

 (defmethod -engine :poly1305+serpent
   [options]
-  (let [cipher ((:serpent +cipher-engines+))]
+  (let [cipher (resolve-cipher-engine :serpent)]
     (Poly1305. cipher)))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Adds comments to cadence.config.

Adds comments to cadence.config.

--- src/cadence/config.clj
+++ src/cadence/config.clj
@@ -3,21 +3,30 @@
             [clojure.java.io :as io])
   (:import [java.net URL]))

+;; Define a map read from config.clj on the resource path.
 (def config-from-file
   (if-let [cres (io/resource "config.clj")]
     (-> cres (.getPath) (load-file)) {}))

-(defn read-config [config-var]
+(defn read-config
+  "Reads config by first accessing the map from the config file and falling back
+  on environment variables. This is heroku \"friendly\"."
+  [config-var]
   (get config-from-file
        (keyword (string/replace
                   (string/lower-case config-var)
                   "_" "-")) (System/getenv config-var)))

+;; Below we define some standard configuration values using read-config.
+
+;; These values are meant for setting up mongo.
 (def storage {:uri (read-config "MONGOHQ_URL")
               :db-name (read-config "MONGO_DB_NAME")
               :username (read-config "MONGO_USERNAME")
               :password (read-config "MONGO_PASSWORD")})

+;; Various tokens used by the application. At the moment Twitter is not being
+;; used, but hopefully it will be in the future.
 (def tokens
   {:recaptcha
    {:public-key (read-config "RECAPTCHA_PUBLIC_KEY")


Always generate correct code!

Always generate correct code!

I've tested this on jquery, react and few more libs. Also, source and
resulting ASTs are identical.

Woo-hoo!

--- src/harnocode/core.cljs
+++ src/harnocode/core.cljs
@@ -122,9 +122,11 @@
                     same-line? #(= (tok-line %1) (tok-line %2))

                     need-space (and (not-punct? t1) (not-punct? t2))
-                    glue-toks  (and (= (:value t2) "++") (same-line? t1 t2))]
+                    glue-toks  (and (same-line? t1 t2)
+                                    (or (contains? #{"++" "--"} (:value t2))
+                                        (contains? #{"continue" "break" "return" "throw"} (:value t1))))]
               (cond
-                glue-toks  (recur tokens           (conj result (str (:value t1) (:value t2))))
+                glue-toks  (recur tokens           (conj result (str (:value t1) " " (:value t2) " ")))
                 need-space (recur (conj tokens t2) (conj result (str (:value t1) " ")))
                 :else      (recur (conj tokens t2) (conj result (str (:value t1))))))))


fix Manhunt

fix Manhunt

Was triggering on every successful run

--- src/clj/game/cards.clj
+++ src/clj/game/cards.clj
@@ -1039,8 +1039,8 @@
    {:effect (effect (gain :click 1 :click-per-turn 1))}

    "Manhunt"
-   {:events {:successful-run {:trace {:base 3 :msg "give the Runner 1 tag"
-                                      :effect (effect (gain :runner :tag 1))}}}}
+   {:events {:successful-run {:once :per-turn :trace {:base 3 :msg "give the Runner 1 tag"
+                                                      :effect (effect (gain :runner :tag 1))}}}}

    "Marked Accounts"
    {:abilities [{:cost [:click 1] :msg "store 3 [Credits]"