Patch an error where the sym could not be a symbol

--- src/oxcart/passes/lambda_lift.clj
+++ src/oxcart/passes/lambda_lift.clj
@@ -101,10 +101,11 @@
               depth        (b/depth bindings)
               used-locals  (collect-used-locals bindings depth ast)
               sym          (fn->name-or-gensym ast)
-              def-form     `(def ~sym ~(-> (:form ast)
-                                           (fn*->cannonical-fn*)
-                                           (rewrite-fn* used-locals)))
-              partial-form `(partial ~sym ~@used-locals)
+              def-form     `(def ~(symbol sym)
+                                 ~(-> (:form ast)
+                                      (fn*->cannonical-fn*)
+                                      (rewrite-fn* used-locals)))
+              partial-form `(partial ~(symbol sym) ~@used-locals)
               def-ast      (util/ast def-form)
               partial-ast  (util/ast partial-form)]


ignore defmacro in normal cljs compilation

--- src/main/shadow/build/compiler.clj
+++ src/main/shadow/build/compiler.clj
@@ -235,24 +235,32 @@
   (Math/max x (System/currentTimeMillis)))

 (defn default-compile-cljs
-  [{:keys [last-progress-ref] :as state} compile-state form]
-  (let [{:keys [op] :as ast}
-        (analyze state compile-state form)
-
-        js
-        (with-out-str
-          (shadow-emit state ast))]
-
-    ;; bump for every compiled form might be overkill
-    (swap! last-progress-ref progress-bump)
-
-    (-> compile-state
-        (update-in [:js] str js)
-        (cond->
-          (= op :ns)
-          (assoc
-            :ns (:name ast)
-            :ns-info (dissoc ast :env))))))
+  [{:keys [last-progress-ref] :as state} {:keys [ns macros-ns] :as compile-state} form]
+  ;; ignore (defmacro ...) in normal cljs compilation since they otherwise end
+  ;; up as normal vars and can be called as fns. compile as usual when compiling as macro ns
+  ;; FIXME: could use a better warning than "Use of undeclared Var demo.browser/dummy-macro"
+  (if (and (not macros-ns)
+           (list? form)
+           (= 'defmacro (first form)))
+    compile-state
+
+    (let [{:keys [op] :as ast}
+          (analyze state compile-state form)
+
+          js
+          (with-out-str
+            (shadow-emit state ast))]
+
+      ;; bump for every compiled form might be overkill
+      (swap! last-progress-ref progress-bump)
+
+      (-> compile-state
+          (update-in [:js] str js)
+          (cond->
+            (= op :ns)
+            (assoc
+              :ns (:name ast)
+              :ns-info (dissoc ast :env)))))))

 (defn warning-collector [build-env warnings warning-type env extra]
   ;; FIXME: currently there is no way to turn off :infer-externs


better error when package.json "main" entries are missing

--- src/main/shadow/build/npm.clj
+++ src/main/shadow/build/npm.clj
@@ -170,24 +170,35 @@
         (->> main-keys
              (map #(get package-json %))
              (remove nil?)
-             (into []))]
-
-    (reduce
-      (fn [_ entry]
-        ;; test file exts first, so we don't pick a directory over a file
-        ;; lib/jsdom
-        ;; lib/jsdom.js
-        (when-let [file (or (test-file-exts npm package-dir entry)
-                            (when-let [file-or-dir (test-file package-dir entry)]
-                              (if-not (.isDirectory file-or-dir)
-                                file-or-dir
-                                (let [index (io/file file-or-dir "index.js")]
-                                  (and (.exists index) index)))))]
-
-          ;; we only want the first one in case more exist
-          (reduced file)))
-      nil
-      entries)))
+             (into []))
+
+        entry-file
+        (reduce
+          (fn [_ entry]
+            ;; test file exts first, so we don't pick a directory over a file
+            ;; lib/jsdom
+            ;; lib/jsdom.js
+            (when-let [file (or (test-file-exts npm package-dir entry)
+                                (when-let [file-or-dir (test-file package-dir entry)]
+                                  (if-not (.isDirectory file-or-dir)
+                                    file-or-dir
+                                    (let [index (io/file file-or-dir "index.js")]
+                                      (and (.exists index) index)))))]
+
+              ;; we only want the first one in case more exist
+              (reduced file)))
+          nil
+          entries)]
+
+    (when (and (seq entries)
+               (not entry-file))
+      (throw (ex-info
+               (str "package in " package-dir "specified entries but they were all missing")
+               {:tag ::missing-entries
+                :entries entries
+                :package-dir package-dir})))
+
+    entry-file))

 (defn find-package-require [{:keys [node-modules-dir] :as npm} require]
   {:pre [(not (util/is-relative? require))
@@ -737,8 +748,8 @@
      ;; JVM working dir always
      :project-dir project-dir
      :node-modules-dir node-modules-dir
-     :extensions [#_ ".mjs" ".js" ".json"]
-     :main-keys [#_#_ "module" "jsnext:main" "browser" "main"]
+     :extensions [#_".mjs" ".js" ".json"]
+     :main-keys [#_#_"module" "jsnext:main" "browser" "main"]
      }))

 (defn stop [npm])


Fix phonebook tests

Fix phonebook tests

--- examples/phonebook/test/phonebook/resources_test.clj
+++ examples/phonebook/test/phonebook/resources_test.clj
@@ -9,7 +9,7 @@
    [juxt.iota :refer (given)]
    [clojure.edn :as edn]
    [ring.mock.request :refer [request]]
-   ;;[yada.util :refer [to-manifold-stream]]
+   [yada.util :refer [to-manifold-stream]]
    [phonebook.util :refer [to-string]]
    [phonebook.db :as db]
    [phonebook.api :refer [api]]))
@@ -47,7 +47,8 @@
 (deftest create-entry
   (let [db (db/create-db {})
         h (make-handler (create-api db))
-        req (request :post "/phonebook" {"surname" "Pither" "firstname" "Jon" "phone" "1235"})
+        req (-> (request :post "/phonebook" {"surname" "Pither" "firstname" "Jon" "phone" "1235"})
+                (update :body to-manifold-stream))
         response @(h req)]

     (given response
@@ -62,7 +63,7 @@
     (let [req (->
                (request :put "/phonebook/2" (slurp (io/resource "phonebook/update-data")))
                (assoc-in [:headers "content-type"] "multipart/form-data; boundary=ABCD")
-               ;;(update :body to-manifold-stream)
+               (update :body to-manifold-stream)
                )
           response @(h req)]


removed redundant 'task' suffix.

removed redundant 'task' suffix.

--- src/onyx/tasks/core_async.clj
+++ src/onyx/tasks/core_async.clj
@@ -6,7 +6,7 @@

 (def default-channel-size 1000)

-(s/defn input-task
+(s/defn input
   ([task-name :- s/Keyword opts]
    (input-task task-name opts default-channel-size))
   ([task-name :- s/Keyword opts chan-size]
@@ -26,7 +26,7 @@
     :schema {:task-map os/TaskMap
              :lifecycles [os/Lifecycle]}}))

-(s/defn output-task
+(s/defn output
   ([task-name :- s/Keyword opts]
    (output-task task-name opts default-channel-size))
   ([task-name :- s/Keyword opts chan-size]


format docstring

format docstring

--- src/overtone/sc/cgens/env.clj
+++ src/overtone/sc/cgens/env.clj
@@ -11,8 +11,9 @@
                  :default 0.01}
    done         {:doc "action to take after release"
                  :default nil}]
-  "Hold an input source for a set period of time and then stop by applying a
-   simple envelope. Takes a hold-time, a release-time, and a done action."
+  "Hold an input source for a set period of time and then stop by
+   applying a simple envelope. Takes a hold-time, a release-time, and a
+   done action."
   (:ar (let [gate (trig 1 hold-time)
              env  (linen gate 0 1 release-time done)]
          (* in env))))


docstring for line action args

docstring for line action args

--- src/overtone/sc/ugen/line.clj
+++ src/overtone/sc/ugen/line.clj
@@ -7,14 +7,14 @@
        :args [{:name "start", :default 0.0 :doc "Starting value"}
               {:name "end", :default 1.0 :doc "Ending value"}
               {:name "dur", :default 1.0 :doc "Duration in seconds"}
-              {:name "action", :default 0 :map DONE-ACTIONS}]
+              {:name "action", :default 0 :map DONE-ACTIONS :doc "A done action to be evaluated when the line is completed."}]
        :doc "Generates a line from the start value to the end value."}

       {:name "XLine",
        :args [{:name "start", :default 1.0 :doc "Starting value"}
               {:name "end", :default 2.0 :doc "Ending value"}
               {:name "dur", :default 1.0 :doc "Duration in seconds"}
-              {:name "action", :default 0 :map DONE-ACTIONS}]
+              {:name "action", :default 0 :map DONE-ACTIONS :doc "A done action to be evaluated when the line is completed."}]
        :doc "Generates an exponential curve from the start value to the end value. Both the start and end values
  must be non-zero and have the same sign."}


Recording the stop time before doing the accounting.

--- src/poky/benchmark/simple.clj
+++ src/poky/benchmark/simple.clj
@@ -62,10 +62,10 @@
   (. java.lang.System  (clojure.core/nanoTime)))

 (defn elapsed-time
-  [start]
-  (/ (double (- (current-time)
-                start))
-     1000000.0))
+  ([start] (elapsed-time start (current-time)))
+  ([start stop]
+   (/ (double (- stop start))
+      1000000.0)))

 (comment
   (bench/bench-jdbc-mget
@@ -88,9 +88,10 @@
                             (elapsed-time start)))
                         sets))
         total (count result)
-        mean (util/mean result total)]
+        mean (util/mean result total)
+        stop (current-time)]
     {:count total
      :mean mean
      :variance (double (util/variance result mean total))
      :95th (util/percentile result 0.95)
-     :elapsed (elapsed-time start)}))
+     :elapsed (elapsed-time start stop)}))


Tinker with examples.

Tinker with examples.

--- src/african_polyphony_and_polyrhythm/talk.clj
+++ src/african_polyphony_and_polyrhythm/talk.clj
@@ -126,6 +126,7 @@

 (comment
   (live/play (aga-terumo)))
+

@@ -163,6 +164,7 @@

+
 ;;;;;;;;;;;;;;;;;;
 ; Natural scales ;
 ;;;;;;;;;;;;;;;;;;
@@ -177,9 +179,14 @@

 ; Midi
 (comment
+
+  (midi->hz 69) ; 440.0
+  (midi->hz 71) ; 493.9
+
   (->> (phrase (repeat 1/4) [69 71 73 74 76 78 80 81])
        (where :pitch midi->hz)
        live/play))
+

 ; Keys
 (defn A [midi] (+ midi 69))
@@ -196,20 +203,29 @@
 (def minor (scale [2 1 2 2 1 2 2]))
 (def pentatonic (scale [2 3 2 2 3]))

-(def central-african-scale (comp pentatonic -))
-
 (comment
   (map (comp A major) (range 0 8))
   (map (comp A minor) (range 0 8))
-  (map (comp A central-african-scale) (range 0 6))
+  (map (comp A pentatonic) (range 0 6))

   (->> (phrase (repeat 1/4) (range 0 8))
        (where :pitch (comp midi->hz A major))
-       live/play)
+       live/play))
+
+
+; Little-endian scale
+(def little-endian-pentatonic
+  "In Central African music, we play scales from small sounds to big ones."
+  (comp pentatonic -))
+
+(comment
+  (map (comp A little-endian-pentatonic) (range 0 6))

   (->> (phrase (repeat 1/4) (range 0 6))
-       (where :pitch (comp midi->hz A central-african-scale))
-       live/play))
+       (where :pitch (comp midi->hz A little-endian-pentatonic))
+       live/play))
+
+

@@ -275,7 +291,7 @@
        (map rand-variations)
        (introduce-after 4)
        (map pan)
-       (where :pitch (comp midi->hz high A central-african-scale))
+       (where :pitch (comp midi->hz high A little-endian-pentatonic))
        (tempo (bpm 120))))

 (comment
@@ -322,7 +338,9 @@
       (* vol)))

 (defmethod live/play-note :horn [{:keys [pitch pan duration]}]
-  (whistle :freq pitch :pan (or pan 0) :dur (min duration 0.2)))
-
-(defmethod live/play-note :default [note]
-  (-> note (assoc :part :horn) live/play-note))
+  (whistle :freq pitch :pan (or pan 0) :dur (min duration 0.2))
+  ;(drum :freq pitch :pan (or pan 0) :dur (min duration 0.2))
+  )
+
+(defmethod live/play-note :default [{:keys [pitch duration]}]
+  (whistle :freq pitch :dur duration))


Cleaned up the canvas util class a bit.

Cleaned up the canvas util class a bit.

--- src/cljs/wombats_web_client/utils/canvas.cljs
+++ src/cljs/wombats_web_client/utils/canvas.cljs
@@ -15,50 +15,52 @@

 (defn draw-image
   "Draws an image at a certain coordinate
-  w/ source/destination attributes"
-  [canvas image sx sy swidth sheight dx dy dwidth dheight]
-    (.drawImage (context canvas)
-                image
-                sx sy swidth sheight
-                dx dy dwidth dheight))
+  w/ source and destination attributes"
+  ([canvas image sx sy swidth sheight dx dy dwidth dheight]
+   (.drawImage (context canvas)
+               image
+               sx sy swidth sheight
+               dx dy dwidth dheight))
+
+  ([canvas image sx sy swidth sheight dx dy dwidth dheight transforms]
+   (let [ctx (context canvas)]
+     (.save ctx)
+     (transforms ctx)
+
+     (.drawImage ctx
+                 image
+                 sx sy swidth sheight
+                 dx dy dwidth dheight)
+
+     (.restore ctx))))

 (defn draw-image-flipped-horizontally
   "Same as draw-image but you flip the image before drawing it"
   [canvas image sx sy swidth sheight dx dy dwidth dheight]
-    (let [ctx (context canvas)]
-      (.save ctx)
-
-      (.translate ctx dx dy)
-      (.translate ctx dwidth 0)
-      (.scale ctx -1 1)
-
-      (.drawImage ctx
-                  image
-                  sx sy swidth sheight
-                  0 0 dwidth dheight)
-
-      (.restore ctx)))
+  (draw-image canvas image
+              sx sy swidth sheight
+              0 0 dwidth dheight
+              (fn [ctx]
+                (.translate ctx dx dy)
+                (.translate ctx dwidth 0)
+                (.scale ctx -1 1))))

 (defn draw-image-rotated
-  "Same as draw-image but you can rotate the drawn image"
+  "Same as draw-image but you can rotate the image before drawing it"
   [canvas image sx sy swidth sheight dx dy dwidth dheight degreeRotation]
     (if (= degreeRotation 0)
-      (draw-image canvas image sx sy swidth sheight dx dy dwidth dheight)
+      (draw-image canvas image
+                  sx sy swidth sheight
+                  dx dy dwidth dheight)

-      (let [rotationRadians (/ (* js/Math.PI degreeRotation) 180)
-            ctx (context canvas)]
-
-        (.save ctx)
-        (.translate ctx dx dy)
-        (.translate ctx (/ dwidth 2) (/ dheight 2))
-        (.rotate ctx rotationRadians)
-
-        (.drawImage ctx
-                    image
+      (let [radians (/ (* js/Math.PI degreeRotation) 180)]
+        (draw-image canvas image
                     sx sy swidth sheight
-                    (/ dwidth -2) (/ dheight -2) dwidth dheight)
-
-        (.restore ctx))))
+                    (/ dwidth -2) (/ dheight -2) dwidth dheight
+                    (fn [ctx]
+                      (.translate ctx dx dy)
+                      (.translate ctx (/ dwidth 2) (/ dheight 2))
+                      (.rotate ctx radians))))))

 (defn width
   "Gets the width of a canvas element"


RS & GG | #5 | Test that storage throws psqlexceptions when insert fails

--- integration/objective8/db/storage_tests.clj
+++ integration/objective8/db/storage_tests.clj
@@ -18,6 +18,19 @@
   (against-background
    [(before :contents (db-connection)) (after :facts (truncate-tables))]
    (facts "About storage"
+
+          ;;GENERAL
+          (fact "pg-store! throws org.postgresql.util.PSQLException when insert fails"
+                (let [NOT-EXISTENT-USER-ID 1
+                      objective {:entity :objective
+                                 :created-by-id NOT-EXISTENT-USER-ID
+                                 :end-date "2015-01-01T00:00:00Z"
+                                 :description "description"
+                                 :goals "goals"
+                                 :title "title"}]
+                      (storage/pg-store! objective) => (throws org.postgresql.util.PSQLException)))
+
+
           ;;USERS
           (fact "a user entity can be stored in the database"
                 (let [user {:entity :user :twitter-id "the-twitter-id" :foo "bar"}


'append' param for file upload

'append' param for file upload

--- src/cavm/views/datasets.clj
+++ src/cavm/views/datasets.clj
@@ -111,21 +111,21 @@
     (last (map #(loader % {:always (boolean always) :delete (boolean delete)})
                 (if (coll? files) files [files])))))

-(defn upload-files [ip loader docroot file]
+(defn upload-files [ip loader docroot file append]
   (when (is-local? ip)
     (let [files (if (vector? file) file [file])]
       (doseq [{:keys [bytes filename]} files]
         ; XXX catch errors & return http code
         (let [dest (docroot-path docroot filename)]
-          (with-open [w (clojure.java.io/output-stream dest)]
+          (with-open [w (clojure.java.io/output-stream dest :append append)]
             (.write w ^bytes bytes)))))
     "ok"))

 ; XXX add the custom pattern #".+" to avoid nil, as above?
 (defroutes routes
-  (POST ["/upload/"] [file :as req]
+  (POST ["/upload/"] [file append :as req]
         (let [{loader :loader docroot :docroot ip :remote-addr} req]
-          (upload-files ip loader docroot file)))
+          (upload-files ip loader docroot file append)))
   (GET ["/download/:dataset" :dataset #".+"] [dataset :as {docroot :docroot}]
        (let [resp (response/file-response dataset {:root docroot :index-files? false})]
          (if (re-find #"\.gz$" dataset)


token mapping simplified

token mapping simplified

--- src/cerber/stores/token.clj
+++ src/cerber/stores/token.clj
@@ -14,30 +14,29 @@

 (defrecord Token [client-id user-id scope secret refreshing created-at expires-at])

-(defn sql->map [{:keys [client_id user_id secret scope login refreshing created_at expires_at]}]
-  {:client-id client_id
-   :user-id user_id
-   :secret secret
-   :login login
-   :scope scope
-   :refreshing refreshing
-   :expires-at expires_at
-   :created-at created_at})
+(defn sql->map [result]
+  (when-let [{:keys [client_id user_id secret scope login refreshing created_at expires_at]} result]
+    {:client-id client_id
+     :user-id user_id
+     :secret secret
+     :login login
+     :scope scope
+     :refreshing refreshing
+     :expires-at expires_at
+     :created-at created_at}))

 (defrecord SqlTokenStore []
   Store
   (fetch-one [this [client-id tag secret]]
-    (when (= tag "access")
-      (when-let [token (first (db/find-access-token {:client-id client-id :secret secret}))]
-        (sql->map token))))
+    (sql->map (first (and (= tag "access")
+                          (db/find-access-token {:client-id client-id :secret secret})))))
   (fetch-all [this [client-id tag secret login]]
-    (when (= tag "refresh")
-      (let [tokens (if secret
-                     (db/find-refresh-token-by-secret {:client-id client-id :secret secret})
-                     (if client-id
-                       (db/find-refresh-token-by-client {:client-id client-id :login login})
-                       (db/find-refresh-token-by-login  {:login login})))]
-        (map sql->map tokens))))
+    (map sql->map (and (= tag "refresh")
+                       (if secret
+                         (db/find-refresh-token-by-secret {:client-id client-id :secret secret})
+                         (if client-id
+                           (db/find-refresh-token-by-client {:client-id client-id :login login})
+                           (db/find-refresh-token-by-login  {:login login}))))))
   (revoke-one! [this [client-id tag arg]]
     (db/delete-token {:client-id client-id :secret arg}))
   (store! [this k token]


Add persistent flag functionality

Add persistent flag functionality

Persistent flags are similar to turn flags and run flags, but persist
until cleared, and can be cleared individually.

--- src/clj/game/core-flags.clj
+++ src/clj/game/core-flags.clj
@@ -53,6 +53,26 @@
 (defn clear-turn-register! [state]
   (swap! state assoc-in [:stack :current-turn] nil))

+(defn register-persistent-flag!
+  "A flag that persists until cleared."
+  [state side card flag condition]
+  (let [stack (get-in @state [:stack :persistent flag])]
+    (swap! state assoc-in [:stack :persistent flag] (conj stack {:card card :condition condition}))))
+
+(defn persistent-flag?
+  "Check if any conditions for the flag evaluate to true for the given card."
+  [state side card flag]
+  (some true?
+        (for [condition (get-in @state [:stack :persistent flag])
+              :let [result ((:condition condition) state side card)]]
+          result)))
+
+(defn clear-persistent-flag!
+  "Remove any entry associated with card for the given flag"
+  [state side card flag]
+  (swap! state update-in [:stack :persistent flag]
+         #(remove (fn [map] (= (:cid (map :card)) (:cid %2))) %1) card))
+
 ; Functions for preventing specific game actions.
 ; TODO: look into migrating these to turn-flags and run-flags.
 (defn prevent-run [state side]


Factorization

Factorization

--- src/cljs/triboard/core.cljs
+++ src/cljs/triboard/core.cljs
@@ -227,25 +227,18 @@
   [str-code]
   [:div {:dangerouslySetInnerHTML {:__html str-code}}])

-(defn restart-button
-  []
-  [:button.help-button
-   {:on-click #(swap! app-state update :help not)}
-   [special-char "↻"]])
-
-(defn help-button
-  []
-  [:button.help-button
-   {:on-click #(swap! app-state update :help not)} "?"])
+(defn top-panel-button
+  [on-click txt]
+  [:button.help-button {:on-click on-click} txt])

 (defn show-top-panel
   [scores player]
   (into
     [:div.scores]
     (concat
-      [[restart-button]]
+      [[top-panel-button #(swap! app-state update :help not) (special-char "↻")]]
       (show-scores scores player)
-      [[help-button]]
+      [[top-panel-button #(swap! app-state update :help not) "?"]]
       )))

 (defn run-game []


Added *load-fn* enabling cljs files to import other files

--- src/clojurescript/core.cljs
+++ src/clojurescript/core.cljs
@@ -1,7 +1,8 @@
 (ns clojurescript.core
   (:require [cljs.pprint :refer [pprint]]
             [cljs.js :as cljs]
-            [cljs.tools.reader :as r]))
+            [cljs.tools.reader :as r]
+            [clojure.string :as str]))

 (enable-console-print!)

@@ -9,24 +10,87 @@

 (def ^:export readString r/read-string)

-(defn ^:export eval [in-str]
+;;; node js imports
+(def node-fs (js/require "fs"))
+(def node-path (js/require "path"))
+
+;;; path relative to core.js containing standard library namespace
+(def standard-library-path "cljs")
+
+;;; the directory containing this script (core.js)
+(def __dirname (js* "__dirname"))
+
+;;; predicate returns true iff the file at "path" is readable
+(defn file-readable? [path]
+  (try
+    (do
+      (.accessSync node-fs path (aget node-fs "F_OK"))
+      true)
+    (catch js/Error err false)))
+
+;;; returns the first element of "coll" satisfying the predicate
+;;; "pred?" or nil if no such elements exist
+(defn first-satisfying [pred? coll]
+  (if-let [[x & xs] (seq coll)]
+    (if (pred? x)
+        x
+        (first-satisfying pred? xs))
+    nil))
+
+;;; converts from the extension of a file to the expected file type
+;;; (clj or js) for a given extension
+(defn require-extension [extension]
+  (str/replace
+    (case extension
+          ".cljs" ".clj"
+          ".cljc" ".clj"
+          extension)
+    #"\." ""))
+
+;;; takes a list of library paths and returns a function suitable
+;;; for use as a *load-fn* that searches for imported files in
+;;; the library paths and a global standard library path
+(defn mk-load-fn [library-paths]
+  (fn [name cb]
+    (let [
+          specified-path (.toLowerCase (name :path))
+          specified-dir (.dirname node-path specified-path)
+          specified-file (.basename node-path specified-path)
+          extensions '(".cljs" ".cljc" ".js")
+          absolute-standard-library-path (.join node-path __dirname standard-library-path)
+          require-paths (concat [absolute-standard-library-path] library-paths)
+          require-paths-with-directory (flatten (map (fn [path] [(.join node-path path specified-dir)
+                                                                 (.join node-path path specified-path)])
+                                                     require-paths))
+
+          require-candidates (flatten (map
+                                        (fn [path] (map #(.join node-path path (str specified-file %)) extensions))
+                                        require-paths-with-directory))
+          require-file (first-satisfying file-readable? require-candidates)]
+      (do
+        (cb {
+          :lang (keyword (require-extension (.extname node-path require-file)))
+          :source (.readFileSync node-fs require-file "utf8")
+        })))))
+
+(defn ^:export eval ([in-str library-paths]
   (cljs/eval-str (cljs/empty-state)
                  in-str 'bar
                  {:eval cljs/js-eval
-                  :context :expr
-                  :def-emits-var true}
+                  :def-emits-var true
+                  :load (mk-load-fn library-paths)}
                  (fn [{:keys [error value]}]
                    (if-not error
                      value
                      (do
-                       (.error js/console error))))))
+                       (.error js/console error)))))))

-(defn ^:export compile [in-str]
+(defn ^:export compile [in-str library-paths]
   (cljs/compile-str (cljs/empty-state)
                     in-str 'bar
                     {:eval cljs/js-eval
-                     :context :expr
-                     :def-emits-var true}
+                     :def-emits-var true
+                     :load (mk-load-fn library-paths)}
                     (fn [{:keys [error value]}]
                       (if-not error
                         value
@@ -34,4 +98,4 @@
                           (.error js/console error))))))

 (set! *main-cli-fn*
-      (fn []))+      (fn []))


Calculate amount paid

Calculate amount paid

--- src/invadm/core.clj
+++ src/invadm/core.clj
@@ -11,6 +11,9 @@
 (defn cwd []
   (System/getProperty "user.dir"))

+(defn sum [v]
+  (reduce + 0 v))
+
 (def date-formatter
   (f/formatter "yyyy-MM-dd"))

@@ -19,6 +22,9 @@

 (defn parse-date [date-string]
   (f/parse date-formatter date-string))
+
+(defn format-amount [amount currency]
+  (format "%d %s" amount currency))

 (defn read-json [file]
   (json/read-str (slurp file)))
@@ -47,7 +53,9 @@
    "Client" (get invoice "client")
    "Issue date" (get invoice "issue-date")
    "Due date" (get invoice "due-date")
-   "Amount" (format "%d %s" (get invoice "amount") (get invoice "currency"))})
+   "Amount" (format-amount (get invoice "amount") (get invoice "currency"))
+   "Paid" (format-amount (sum (map #(get % "amount") (get invoice "payments")))
+                         (get invoice "currency"))})

 (defn options-to-filter [options]
   (fn [invoice]
@@ -105,6 +113,7 @@
   (write-invoice (get arguments 1)
                  (assoc options
                         "id" (get arguments 1)
+                        "payments" []
                         "due-date" (unparse-date (t/plus (parse-date (:issue-date options))
                                                          (t/days (:net options)))))))


But definitely this time

But definitely this time

--- src/korhal/core.clj
+++ src/korhal/core.clj
@@ -17,11 +17,13 @@
   (merge curr-val {k v}))

 (defn korhal-main [& args]
-  (let [ai (korhal.core.)]
-    (.start (:api @(.state ai)))))
+  (let [ai (korhal.core.)
+        api (jnibwapi.JNIBWAPI. this)]
+    (swap! (.state ai) swap-key :api api)
+    (.start (:api @ai))))

-(defn korhal-init [this]
-  [[] (atom {:api (jnibwapi.JNIBWAPI. this)})])
+(defn korhal-init []
+  [[] (atom {})])

 (defn korhal-deref [this]
   @(.state this))


Maybe a case of dumb defaults

Maybe a case of dumb defaults

--- src/korhal/core.clj
+++ src/korhal/core.clj
@@ -8,6 +8,7 @@
  :name "korhal.core"
  :implements [jnibwapi.BWAPIEventListener]
  :state state
+ :init korhal-init
  :main true
  :constructors {[] []}
  :prefix "korhal-")


Added selectable env edn file to main.

Added selectable env edn file to main.

--- src/profanity_power_index/core.clj
+++ src/profanity_power_index/core.clj
@@ -47,13 +47,21 @@
    :id :output-directory
    :default "site"]])

+(def main-spec
+  [[:long-opt "--env"
+    :required "ENV_FILE_NAME"
+    :desc "The name of the environment file."
+    :default "env.edn"
+    :id :env]])
+
 (defn -main
   [& args]

-  (let [env
-          (-> "env.edn" io/resource io/file slurp edn/read-string)
+  (let [options (parse-opts args main-spec)
+        env-file (get-in options [:options :env])
+        env (-> env-file slurp edn/read-string)
         command (first args)]
-
+
     (case command
       "collect" (let [options (parse-opts (rest args) collect-spec)]
                   (collect env options))


Remove hard dependency on Datomic

Remove hard dependency on Datomic

--- src/provisdom/spectomic/specs.cljc
+++ src/provisdom/spectomic/specs.cljc
@@ -9,14 +9,10 @@
   #{:db.type/string :db.type/boolean :db.type/long :db.type/bigint :db.type/float :db.type/double :db.type/bigdec
     :db.type/instant :db.type/uuid :db.type/uri :db.type/keyword :db.type/bytes :db.type/ref})

-(def datomic-schema-keys
-  #{:db/id :db/ident :db/valueType :db/cardinality :db/doc :db/unique :db/index :db/isComponent :db/noHistory
-    :db/fulltext :db.install/_attribute :db.install/_partition})
-
 (s/def ::tempid
   (s/with-gen
     (s/or
-      #?@(:clj [:dbid #(instance? datomic.db.DbId %)])
+      #?@(:clj [:dbid #(instance? (Class/forName "datomic.db.DbId") %)])
       :string (s/and string? #(not (str/starts-with? % ":"))))
     (fn [] (gen/return ((resolve 'datomic.api/tempid) :db.part/db)))))


Shut down UDP worker pool at server stop.

--- src/riemann/transport/udp.clj
+++ src/riemann/transport/udp.clj
@@ -51,9 +51,9 @@
   (start! [this]
           (locking this
             (when-not @killer
-              (let [bootstrap (ConnectionlessBootstrap.
-                                (NioDatagramChannelFactory.
-                                  (Executors/newCachedThreadPool)))
+              (let [pool (Executors/newCachedThreadPool)
+                    bootstrap (ConnectionlessBootstrap.
+                                (NioDatagramChannelFactory. pool))
                     all-channels (DefaultChannelGroup.
                                    (str "udp-server " host port max-size))
                     cpf (channel-pipeline-factory
@@ -77,6 +77,7 @@
                         (fn []
                           (-> all-channels .close .awaitUninterruptibly)
                           (.releaseExternalResources bootstrap)
+                          (.shutdown pool)
                           (info "UDP server" host port max-size "shut down")
                           ))))))


Changing how exceptions are handled during database synchronization. If an individual item fails then the error will be logged at the error level and processing will continue.

--- bootstrap-app/src/cmr/bootstrap/data/db_synchronization.clj
+++ bootstrap-app/src/cmr/bootstrap/data/db_synchronization.clj
@@ -205,22 +205,22 @@
   ;; and was deleted in Catalog REST in the mean time Ingest would return a 404 from the delete
   ;; and Catalog REST would ignore it. This would end up saving the item in Metadata DB making them
   ;; out of sync. The delete processing should happen after this step and put it back in sync.
-  (if (:format concept)
-    (let [mdb-context {:system (:metadata-db system)}
-          indexer-context {:system (:indexer system)}
-          {:keys [concept-id revision-id]} concept]
-      (try
-        (concept-service/save-concept mdb-context concept)
-        (index-service/index-concept indexer-context concept-id revision-id true)
-        (catch clojure.lang.ExceptionInfo e
-          (let [data (ex-data e)]
-            (if (= (:type data) :conflict)
-              (warn (format "Ignoring conflict saving revision for %s %s: %s"
-                            concept-id revision-id (pr-str (:errors data))))
-              (throw e))))))
-    (warn (str "Skipping item "
-               (:concept-id concept)
-               " from Catalog REST. It did not have a supported mime type in Metadata DB."))))
+  (let [mdb-context {:system (:metadata-db system)}
+        indexer-context {:system (:indexer system)}
+        {:keys [concept-id revision-id]} concept]
+    (try
+      (concept-service/save-concept mdb-context concept)
+      (index-service/index-concept indexer-context concept-id revision-id true)
+      (catch clojure.lang.ExceptionInfo e
+        (let [data (ex-data e)]
+          (if (= (:type data) :conflict)
+            (warn (format "Ignoring conflict saving revision for %s %s: %s"
+                          concept-id revision-id (pr-str (:errors data))))
+            (error e (format "Error saving or indexing concept %s with revision %s. Message: %s"
+                             concept-id revision-id (.getMessage e))))))
+      (catch Exception e
+        (error e (format "Error saving or indexing concept %s with revision %s. Message: %s"
+                         concept-id revision-id (.getMessage e)))))))

 (defn process-missing-concepts
   "Starts a series of threads that read concepts one at a time off the channel, save, and index them.
@@ -353,7 +353,11 @@
         (if (= (:type data) :conflict)
           (warn (format "Ignoring conflict creating tombstone for %s %s: %s"
                         concept-id revision-id (pr-str (:errors data))))
-          (throw e))))))
+          (error e (format "Error deleting or unindexing concept %s with revision %s. Message: %s"
+                           concept-id revision-id (.getMessage e))))))
+    (catch Exception e
+      (error e (format "Error deleting or unindexing concept %s with revision %s. Message: %s"
+                       concept-id revision-id (.getMessage e))))))

 (defn process-deletes
   "Starts a series of threads that read items one at a time off the channel then creates a tombstone


Safe swap! in 'create-flusher'

Safe swap! in 'create-flusher'

--- src/cyanite_cache/cache.clj
+++ src/cyanite_cache/cache.clj
@@ -46,9 +46,11 @@
    (doseq [path @pkeys]
      (fn-store tenant period rollup time path (fn-agg (fn-get path)) ttl)
      (swap! tkeys (fn [tkeys] (dissoc tkeys time)))
-     (when (empty? tkeys)
-       (swap! mkeys (fn [mkeys mkey] (dissoc mkeys mkey))
-              (construct-mkey tenant period rollup))))))
+     (let [mkey (construct-mkey tenant period rollup)]
+       (swap! mkeys (fn [mkeys]
+                      (when (empty? tkeys)
+                        (dissoc mkeys mkey)
+                        mkeys)))))))

 (defn run-delayer!
   [rollup flusher]
@@ -119,6 +121,7 @@
     (reify
       StoreCache
       (push! [this tenant period rollup time path data ttl]
-        (set-keys! mkeys tenant period rollup time path ttl (get-get-fn rollup) fn-agg fn-store)
+        (set-keys! mkeys tenant period rollup time path ttl (get-get-fn rollup)
+                   fn-agg fn-store)
         )
       )))


convert bread to non-unify style

convert bread to non-unify style

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -327,15 +327,13 @@
             :english {:past "broke"}}
    "bread"
    ;; inherently singular.
-   (unify agreement-noun
-          common-noun
-          masculine-noun
-          {:synsem {:sem {:pred :pane
-                          :edible true
-                          :artifact true}
-                    :subcat {:1 {:cat :det
-                                 :number :sing
-                                 :def :def}}}})
+   {:synsem {:agr {:number :sing}
+             :cat :noun
+             :sem {:pred :pane
+                   :edible true
+                   :artifact true}
+             :subcat {:1 {:cat :det
+                          :def :def}}}}

    "bring" {:synsem {:cat :verb
                    :sem {:pred :bring


fix typo

fix typo

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -128,7 +128,7 @@
                                        :1plur "were"
                                        :2plur "were"
                                        :3plur "were"}
-                                :past-participle {been}}}]
+                                :past-participle "been"}}]
           [;; intransitive
            (unify common
                   {:sense 1
@@ -1755,7 +1755,7 @@
                          :sem {:pred :ricordare}}}

     "remove" {:synsem {:cat :verb
-                    :sem {:pred :remove}}}
+                       :sem {:pred :remove}}}

     "repeat"  {:synsem {:cat :verb
                         :sem {:pred :repeat}}}


+aspect:simple for 'present'

+aspect:simple for 'present'

--- src/babel/espanol/grammar.cljc
+++ src/babel/espanol/grammar.cljc
@@ -27,7 +27,8 @@
    [:synsem :sem :pred]])

 (def tenses
-  {"present" {:synsem {:sem {:tense :present}}}
+  {"present" {:synsem {:sem {:tense :present
+                             :aspect :simple}}}
    "conditional" {:synsem {:sem {:tense :conditional}}}
    "future" {:synsem {:sem {:tense :future}}}
    "imperfect" {:synsem {:sem {:aspect :progressive


moved diviser alphab

moved diviser alphab

--- src/babel/francais/lexicon.clj
+++ src/babel/francais/lexicon.clj
@@ -149,16 +149,16 @@
                                :2plur "devez"
                                :3plur "doivent"}}}]
      [(unify common {:synsem {:sem {:pred :have-to
-                                    :subj {:human true}}}})
-
+                                    :subj {:human true}}}})
+
+   "décider" {:synsem {:cat :verb
+                       :sem {:pred :decide}}}
+
+   "désirer" {:synsem {:cat :verb
+                       :sem {:pred :desire}}}
+
    "diviser" {:synsem {:cat :verb
                       :sem {:pred :divide}}}
-
-   "décider" {:synsem {:cat :verb
-                       :sem {:pred :decide}}}
-
-   "désirer" {:synsem {:cat :verb
-                       :sem {:pred :desire}}}

    "donner" {:synsem {:cat :verb
                       :sem {:pred :give}}}


added future indicative

added future indicative

--- src/babel/latin/morphology.clj
+++ src/babel/latin/morphology.clj
@@ -270,6 +270,138 @@

+FUTURE BEGINS HERE
+
+(def are-future-indicative
+  (conjugation
+   {:infinitive "āre"
+    :common {:synsem {:infl :present
+                      :sem {:tense :present}}}
+    :forms
+    [["abo"
+      {:synsem {:sem {:subj {:pred :I}}}}]
+
+     ["abis"
+      {:synsem {:sem {:subj {:pred :tu}}}}]
+
+     ["abit"
+      {:synsem {:sem {:subj {:pred :lui}}}}]
+
+     ["abimus"
+      {:synsem {:sem {:subj {:pred :noi}}}}]
+
+     ["abitis"
+      {:synsem {:sem {:subj {:pred :voi}}}}]
+
+     ["abunt"
+      {:synsem {:sem {:subj {:pred :loro}}}}]]}))
+
+(def ere-bar-imperfect-indicative
+  (conjugation
+   {:infinitive "ēre"
+    :common {:synsem {:infl :present
+                      :sem {:tense :present}}}
+    :forms
+    [["ebo"
+      {:synsem {:sem {:subj {:pred :I}}}}]
+
+     ["ebis"
+      {:synsem {:sem {:subj {:pred :tu}}}}]
+
+     ["ebit"
+      {:synsem {:sem {:subj {:pred :lui}}}}]
+
+     ["ebimus"
+      {:synsem {:sem {:subj {:pred :noi}}}}]
+
+     ["ebitis"
+      {:synsem {:sem {:subj {:pred :voi}}}}]
+
+     ["ebunt"
+      {:synsem {:sem {:subj {:pred :loro}}}}]]}))
+
+(def ere-future-indicative
+  (conjugation
+   {:infinitive "ere"
+    :common {:synsem {:infl :present
+                      :sem {:tense :present}}}
+    :forms
+    [["am"
+      {:synsem {:sem {:subj {:pred :I}}}}]
+
+     ["es"
+      {:synsem {:sem {:subj {:pred :tu}}}}]
+
+     ["et"
+      {:synsem {:sem {:subj {:pred :lui}}}}]
+
+     ["emus"
+      {:synsem {:sem {:subj {:pred :noi}}}}]
+
+     ["etis"
+      {:synsem {:sem {:subj {:pred :voi}}}}]
+
+     ["ent"
+      {:synsem {:sem {:subj {:pred :loro}}}}]]}))
+
+
+
+(def ere-future-indicative
+  (conjugation
+   {:infinitive "ere-i"
+    :common {:synsem {:infl :present
+                      :sem {:tense :present}}}
+    :forms
+    [["iam"
+      {:synsem {:sem {:subj {:pred :I}}}}]
+
+     ["ies"
+      {:synsem {:sem {:subj {:pred :tu}}}}]
+
+     ["iet"
+      {:synsem {:sem {:subj {:pred :lui}}}}]
+
+     ["iemus"
+      {:synsem {:sem {:subj {:pred :noi}}}}]
+
+     ["ietis"
+      {:synsem {:sem {:subj {:pred :voi}}}}]
+
+     ["ient"
+      {:synsem {:sem {:subj {:pred :loro}}}}]]}))
+
+
+
+
+
+(def ire-future-indicative
+  (conjugation
+   {:infinitive "īre"
+    :common {:synsem {:infl :present
+                      :sem {:tense :present}}}
+    :forms
+    [["iam"
+      {:synsem {:sem {:subj {:pred :I}}}}]
+
+     ["ies"
+      {:synsem {:sem {:subj {:pred :tu}}}}]
+
+     ["iet"
+      {:synsem {:sem {:subj {:pred :lui}}}}]
+
+     ["iemus"
+      {:synsem {:sem {:subj {:pred :noi}}}}]
+
+     ["ietis"
+      {:synsem {:sem {:subj {:pred :voi}}}}]
+
+     ["ient"
+      {:synsem {:sem {:subj {:pred :loro}}}}]]}))
+
+(def replace-patterns (concat are-future-indicative
+                              ere-bar-future-indicative
+                              ere-future-indicative
+                              ire-future-indicative))


Update work stuff

Update work stuff

--- src/benjaminwarfield/views.clj
+++ src/benjaminwarfield/views.clj
@@ -35,7 +35,7 @@
     [:ul
       [:li [:a {:href "http://twitter.com/benjaminws"} "Twitter"]]
       [:li [:a {:href "http://github.com/benjaminws"} "GitHub"]]
-      [:li [:a {:href "http://www.dreamhost.com"} "DreamHost"] " — Sr. Systems Engineer"]
+      [:li [:a {:href "http://thegroundwork.com/"} "The Groundwork"] " — Software Engineer"]
       [:li [:a {:href "http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x8EA10315498C1579"} "GPG Key"]]]])

 (def articles-root (str (System/getProperty "user.dir") "/articles/"))


Fix upsert of new quest record

Fix upsert of new quest record

Need to specify which user the quest record is being created for if
new -- otherwise the quest is lost on reload

--- src/braid/quests/server/db.clj
+++ src/braid/quests/server/db.clj
@@ -30,10 +30,12 @@

 (defn upsert-quest-record-txn
   [user-id quest-record]
-  (let [db-id (if (d/entity (db/db) [:quest-record/id (quest-record :id)])
+  (let [db-id (if (d/entity (db/db) [:quest-record/id (quest-record :quest-record/id)])
                 [:quest-record/id (quest-record :quest-record/id)]
                 (d/tempid :entities))]
-    [(assoc quest-record :db/id db-id)]))
+    [(assoc quest-record
+            :db/id db-id
+            :quest-record/user [:user/id user-id])]))

 (defn activate-first-quests-txn
   [user-id]


fix missing user avatar

fix missing user avatar

--- src/braid/ui/views/header.cljs
+++ src/braid/ui/views/header.cljs
@@ -88,7 +88,7 @@

 (defn current-user-button-view [{:keys [subscribe]}]
   (let [user-id (subscribe [:user-id])
-        user-avatar-url (subscribe [:user-avatar-url])
+        user-avatar-url (subscribe [:user-avatar-url @user-id])
         open-group-id (subscribe [:open-group-id])]
     (fn []
       (let [path (routes/page-path {:group-id @open-group-id


remove debugging info

remove debugging info

--- src/braid/ui/views/thread.cljs
+++ src/braid/ui/views/thread.cljs
@@ -178,7 +178,6 @@

          [:div.card
           [:div.head
-           [:code (pr-str (thread :group-id))]
            (when (and (not new?) @open?)
              [:div.close
               {:on-click (fn [_]


require run to exist when using Nisei counter

--- src/clj/game/cards-agendas.clj
+++ src/clj/game/cards-agendas.clj
@@ -282,7 +282,9 @@
     :advancement-cost-bonus (req (:bad-publicity corp))}

    "Nisei MK II"
-   {:data {:counter 1} :abilities [{:counter-cost 1 :msg "end the run" :effect (effect (end-run))}]}
+   {:data {:counter 1}
+    :abilities [{:req (req (:run @state)) :counter-cost 1 :msg "end the run"
+                 :effect (effect (end-run))}]}

    "Oaktown Renovation"
    {:install-state :face-up


Ensure that preview canvas stays in sync with canvas dimensions

--- src/cljs/goya/timemachine.cljs
+++ src/cljs/goya/timemachine.cljs
@@ -16,12 +16,26 @@
 (defn update-preview []
   (reset! previewstate/preview-state
           (assoc-in @previewstate/preview-state [:main-app :image-data]
-                    (get-in @app/app-state [:main-app :image-data]))))
+                    (get-in @app/app-state [:main-app :image-data])))
+  (reset! previewstate/preview-state
+          (assoc-in @previewstate/preview-state [:main-app :canvas-width]
+                    (get-in @app/app-state [:main-app :canvas-width])))
+  (reset! previewstate/preview-state
+          (assoc-in @previewstate/preview-state [:main-app :canvas-height]
+                    (get-in @app/app-state [:main-app :canvas-height]))))
+

 (defn show-history-preview [idx]
   (reset! previewstate/preview-state
           (assoc-in @previewstate/preview-state [:main-app :image-data]
-                    (get-in (nth @app-history idx) [:image-data]))))
+                    (get-in (nth @app-history idx) [:image-data])))
+  (reset! previewstate/preview-state
+          (assoc-in @previewstate/preview-state [:main-app :canvas-width]
+                    (get-in (nth @app-history idx) [:canvas-width])))
+  (reset! previewstate/preview-state
+          (assoc-in @previewstate/preview-state [:main-app :canvas-height]
+                    (get-in (nth @app-history idx) [:canvas-height]))))
+

 (add-watch app/app-state :preview-watcher
   (fn [_ _ _ _] (update-preview)))


Improve performance on rules rendering.

Improve performance on rules rendering.

--- src/uxbox/ui/workspace/rules.cljs
+++ src/uxbox/ui/workspace/rules.cljs
@@ -82,6 +82,20 @@
     :name "vertical-tick-render"
     :mixins [mx/static]}))

+(defn vertical-ticks-render
+  [own]
+  (html
+   [:g
+    (for [value +ticks+]
+      (-> (vertical-tick value)
+          (rum/with-key value)))]))
+
+(def ^:const vertical-ticks
+  (mx/component
+   {:render vertical-ticks-render
+    :name "vertical-ticks-render"
+    :mixins [mx/static]}))
+
 (defn horizontal-rule-render
   [own sidebar?]
   (let [scroll (rum/react wb/scroll-a)
@@ -92,9 +106,7 @@
       {:width wb/viewport-width
        :height 20}
       [:g {:transform (str "translate(" translate-x ", 0)")}
-       (for [value +ticks+]
-         (-> (vertical-tick value)
-             (rum/with-key value)))]])))
+       (vertical-ticks)]])))

 (def horizontal-rule
   (mx/component
@@ -157,6 +169,20 @@
     :name "horizontal-tick-render"
     :mixins [mx/static]}))

+(defn- horizontal-ticks-render
+  [own]
+  (html
+   [:g
+    (for [value +ticks+]
+      (-> (horizontal-tick value)
+          (rum/with-key value)))]))
+
+(def ^:const horizontal-ticks
+  (mx/component
+   {:render horizontal-ticks-render
+    :name "horizontal-ticks-render"
+    :mixins [mx/static]}))
+
 (defn vertical-rule-render
   [own sidebar?]
   (let [scroll (rum/react wb/scroll-a)
@@ -168,9 +194,7 @@
        :height wb/viewport-height}

       [:g {:transform (str  "translate(0, " translate-y ")")}
-       (for [value +ticks+]
-         (-> (horizontal-tick value)
-             (rum/with-key value)))]
+       (horizontal-ticks)]
       [:rect {:x 0
               :y 0
               :height 20


poll more often to make ui more responsive

--- src/cljs/lambdacd/ui_core.cljs
+++ src/cljs/lambdacd/ui_core.cljs
@@ -13,13 +13,13 @@

 (enable-console-print!)

-(def history-poll-frequency 5000)
+(def poll-frequency 1000)

 (defn poll [atom fn]
   (go-loop []
     (let [history (async/<! (fn))]
       (reset! atom history))
-    (async/<! (utils/timeout history-poll-frequency))
+    (async/<! (utils/timeout poll-frequency))
     (recur)))

 (defn poll-history [history-atom]


Add response function to http ns.

Add response function to http ns.

--- src/clojure/catacumba/http.clj
+++ src/clojure/catacumba/http.clj
@@ -23,11 +23,17 @@
 ;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 (ns catacumba.http
-  (:require [catacumba.impl.http :refer [response]]))
+  (:require [catacumba.impl.http :as http]))
+
+(defn response
+  "Create a response instance."
+  ([body] (http/response body 200 {}))
+  ([body status] (http/response body status {}))
+  ([body status headers] (http/response body status headers)))

 (defn continue
-  ([body] (response body 100))
-  ([body headers] (response body 100 headers)))
+  ([body] (http/response body 100))
+  ([body headers] (http/response body 100 headers)))

 (defn ok
   "HTTP 200 OK
@@ -38,8 +44,8 @@
   the REST API successfully carried out whatever action the client requested,
   and that no more specific code in the 2xx series is appropriate. Unlike
   the 204 status code, a 200 response should include a response body."
-  ([body] (response body 200))
-  ([body headers] (response body 200 headers)))
+  ([body] (http/response body 200))
+  ([body headers] (http/response body 200 headers)))

 (defn created
   "HTTP 201 Created
@@ -49,9 +55,9 @@
   or a store adds, a new resource at the client's request. There may also be
   times when a new resource is created as a result of some controller action,
   in which case 201 would also be an appropriate response."
-  ([location] (response "" 201 {:location location}))
-  ([location body] (response body 201 {:location location}))
-  ([location body headers] (response body 201 (merge headers {:location location}))))
+  ([location] (http/response "" 201 {:location location}))
+  ([location body] (http/response body 201 {:location location}))
+  ([location body headers] (http/response body 201 (merge headers {:location location}))))

 (defn accepted
   "HTTP 202 Accepted
@@ -62,8 +68,8 @@
   appears valid, but it still may have problems once it's finally processed.
   A 202 response is typically used for actions that take a long while to
   process."
-  ([body] (response body 202))
-  ([body headers] (response body 202 headers)))
+  ([body] (http/response body 202))
+  ([body headers] (http/response body 202 headers)))

 (defn no-content
   "HTTP 204 No Content
@@ -74,8 +80,8 @@
   or representation in the response message's body. An API may also send 204
   in conjunction with a GET request to indicate that the requested resource
   exists, but has no state representation to include in the body."
-  ([] (response "" 204))
-  ([headers] (response "" 204 headers)))
+  ([] (http/response "" 204))
+  ([headers] (http/response "" 204 headers)))

 (defn moved-permanently
   "301 Moved Permanently
@@ -85,9 +91,9 @@
   significantly redesigned and a new permanent URI has been assigned to the
   client's requested resource. The REST API should specify the new URI in
   the response's Location header."
-  ([location] (response "" 301 {:location location}))
-  ([location body] (response body 301 {:location location}))
-  ([location body headers] (response body 301 (merge headers {:location location}))))
+  ([location] (http/response "" 301 {:location location}))
+  ([location body] (http/response body 301 {:location location}))
+  ([location body headers] (http/response body 301 (merge headers {:location location}))))

 (defn found
   "HTTP 302 Found
@@ -106,9 +112,9 @@
   To clear things up, HTTP 1.1 introduced status codes 303 (\"See Other\")
   and 307 (\"Temporary Redirect\"), either of which should be used
   instead of 302."
-  ([location] (response "" 302 {:location location}))
-  ([location body] (response body 302 {:location location}))
-  ([location body headers] (response body 302 (merge headers {:location location}))))
+  ([location] (http/response "" 302 {:location location}))
+  ([location body] (http/response body 302 {:location location}))
+  ([location body headers] (http/response body 302 (merge headers {:location location}))))

 (defn see-other
   "HTTP 303 See Other
@@ -123,9 +129,9 @@
   reference to a resource without forcing the client to download its state.
   Instead, the client may send a GET request to the value of the Location
   header."
-  ([location] (response "" 303 {:location location}))
-  ([location body] (response body 303 {:location location}))
-  ([location body headers] (response body 303 (merge headers {:location location}))))
+  ([location] (http/response "" 303 {:location location}))
+  ([location body] (http/response body 303 {:location location}))
+  ([location body headers] (http/response body 303 (merge headers {:location location}))))

 (defn temporary-redirect
   "HTTP 307 Temporary Redirect
@@ -140,9 +146,9 @@
   A REST API can use this status code to assign a temporary URI to the
   client's requested resource. For example, a 307 response can be used to
   shift a client request over to another host."
-  ([location] (response "" 307 {:location location}))
-  ([location body] (response body 307 {:location location}))
-  ([location body headers] (response body 307 (merge headers {:location location}))))
+  ([location] (http/response "" 307 {:location location}))
+  ([location body] (http/response body 307 {:location location}))
+  ([location body headers] (http/response body 307 (merge headers {:location location}))))

 (defn bad-request
   "HTTP 400 Bad Request
@@ -150,8 +156,8 @@

   400 is the generic client-side error status, used when no other 4xx error
   code is appropriate."
-  ([body] (response body 400))
-  ([body headers] (response body 400 headers)))
+  ([body] (http/response body 400))
+  ([body headers] (http/response body 400 headers)))

 (defn unauthorized
   "HTTP 401 Unauthorized
@@ -160,8 +166,8 @@
   A 401 error response indicates that the client tried to operate on a
   protected resource without providing the proper authorization. It may have
   provided the wrong credentials or none at all."
-  ([body] (response body 401))
-  ([body headers] (response body 401 headers)))
+  ([body] (http/response body 401))
+  ([body headers] (http/response body 401 headers)))

 (defn forbidden
   "HTTP 403 Forbidden
@@ -174,8 +180,8 @@
   client may be authorized to interact with some, but not all of a REST API's
   resources. If the client attempts a resource interaction that is outside of
   its permitted scope, the REST API should respond with 403."
-  ([body] (response body 403))
-  ([body headers] (response body 403 headers)))
+  ([body] (http/response body 403))
+  ([body headers] (http/response body 403 headers)))

 (defn not-found
   "HTTP 404 Not Found
@@ -183,41 +189,41 @@

   The 404 error status code indicates that the REST API can't map the
   client's URI to a resource."
-  ([body] (response body 404))
-  ([body headers] (response body 404 headers)))
+  ([body] (http/response body 404))
+  ([body headers] (http/response body 404 headers)))

 (defn method-not-allowed
-  ([body] (response body 405))
-  ([body headers] (response body 405 headers)))
+  ([body] (http/response body 405))
+  ([body headers] (http/response body 405 headers)))

 (defn not-acceptable
-  ([body] (response body 406))
-  ([body headers] (response body 406 headers)))
+  ([body] (http/response body 406))
+  ([body headers] (http/response body 406 headers)))

 (defn conflict
-  ([body] (response body 409))
-  ([body headers] (response body 409 headers)))
+  ([body] (http/response body 409))
+  ([body headers] (http/response body 409 headers)))

 (defn gone
-  ([body] (response body 410))
-  ([body headers] (response body 410 headers)))
+  ([body] (http/response body 410))
+  ([body headers] (http/response body 410 headers)))

 (defn precondition-failed
-  ([body] (response body 412))
-  ([body headers] (response body 412 headers)))
+  ([body] (http/response body 412))
+  ([body headers] (http/response body 412 headers)))

 (defn unsupported-mediatype
-  ([body] (response body 415))
-  ([body headers] (response body 415 headers)))
+  ([body] (http/response body 415))
+  ([body headers] (http/response body 415 headers)))

 (defn too-many-requests
-  ([body] (response body 429))
-  ([body headers] (response body 429 headers)))
+  ([body] (http/response body 429))
+  ([body headers] (http/response body 429 headers)))

 (defn internal-server-error
-  ([body] (response body 500))
-  ([body headers] (response body 500 headers)))
+  ([body] (http/response body 500))
+  ([body headers] (http/response body 500 headers)))

 (defn not-implemented
-  ([body] (response body 501))
-  ([body headers] (response body 501 headers)))
+  ([body] (http/response body 501))
+  ([body headers] (http/response body 501 headers)))


Work on IReactive.

Work on IReactive.

--- src/clojure/freactive/core.clj
+++ src/clojure/freactive/core.clj
@@ -59,13 +59,18 @@
 (defrecord ReactiveState [dirty value f deps sully-fn])

 (defprotocol IReactive
-  (recompute! [this])
-  (rebind! [this f]))
+  (force-recompute! [this])
+  (rebind! [this f])
+  (deactivate! [this]))

 (defrecord Reactive [data]
   IReactive
-  (recompute! [this] (swap! data assoc :dirty true))
-  (rebind! [this f] (swap! data merge {:dirty true :f f :deps nil}))
+  (force-recompute! [this] (clojure.core/swap! data merge {:dirty true :deps nil}))
+  (rebind! [this f] (clojure.core/swap! data merge {:dirty true :f f :deps nil}))
+  (deactivate! [this]
+    (clojure.core/swap! data (fn [{:keys [deps sully-fn] :as state}]
+                  (doseq [d deps] (remove-watch d sully-fn))
+		  (merge state {:deps nil :dirty false}))))
   clojure.lang.IDeref
   (deref [this]
     (*register-dep* this)


Allow in-memory dseqs to specify default source shape.

--- src/clojure/parkour/io/mem.clj
+++ src/clojure/parkour/io/mem.clj
@@ -38,13 +38,16 @@

 (defn dseq
   "Distributed sequence producing key-value tuples from `data`, which should be
-either a map or a sequence of two-item vectors.  Stores input data in local
-process memory, and thus only works for jobs run in local mode."
-  [data]
-  (dseq/dseq
-   (fn [^Job job]
-     (let [iname (-> "input__" gensym keyword)]
-       (input-add iname data)
-       (doto job
-         (conf/assoc! iname-key (name iname))
-         (.setInputFormatClass Mem$InputFormat))))))
+either a map or a sequence of two-item vectors, and will have the default source
+shape `shape` if provided.  Stores input data in local process memory, and thus
+only works for jobs run in local mode."
+  ([data] (dseq :keyvals data))
+  ([shape data]
+     (dseq/dseq
+      (fn [^Job job]
+        (let [iname (-> "input__" gensym keyword)]
+          (input-add iname data)
+          (doto job
+            (conf/assoc! iname-key (name iname))
+            (.setInputFormatClass Mem$InputFormat)
+            (dseq/set-default-shape! shape)))))))


Fix an unbalanced paren

Fix an unbalanced paren

--- src/mdr2/abacus.clj
+++ src/mdr2/abacus.clj
@@ -52,7 +52,7 @@
   (doseq [f (filter #(and (.isFile %) (valid? %))
                     (file-seq (file import-dir)))]
     (msg/publish "queue.create" (read-file f))
-    (delete-file f))))
+    (delete-file f)))

 (defn status-sync
   "Import status updates from ABACUS and put them on the archive queue"
@@ -67,5 +67,4 @@
 (defn notify
   "Create an XML file to be read by ABACUS. This is used to send
   status notifications to ABACUS."
-  [production]
-  )
+  [production])


update make-cpu method

update make-cpu method

Signed-off-by: Yen-Chin Lee <082d453d72dce940e12089a4ad48b97cfe1f3ec4@gmail.com>

--- src/emulator_chip8/cpu.cljc
+++ src/emulator_chip8/cpu.cljc
@@ -1,55 +1,56 @@
 (ns emulator-chip8.cpu)

 (defn make-cpu
+  "Create a new chip8 cpu state."
   ([& {:keys [memory stack SP PC V I DT ST]
-       :or {SP 0
-            PC 0x200
-            I  0
-            DT 0
-            ST 0}}]
-   {;; CHIP-8 only has 4096 bytes (4KB) memory (0x0 ~ 0xFFF).
-    ;;
-    ;; The first 512 bytes, from 0x000 to 0x1FF, are where the
-    ;; original interpreter was located, and should not used by programs.
-    :memory (vec (take 4096 (concat memory (repeat 4096 0))))
+       :or
+       {
+        ;; CHIP-8 only has 4096 bytes (4KB) memory (0x0 ~ 0xFFF).
+        ;;
+        ;; The first 512 bytes, from 0x000 to 0x1FF, are where the
+        ;; original interpreter was located, and should not used by programs.
+        memory (vec (take 4096 (concat memory (repeat 4096 0))))

-    ;; The stack is used to remember the current location
-    ;; before a jump is performed. The system has 16 levels
-    ;; of stack and in order to remember which level of the
-    ;; stack is used.
-    :stack (vec (take 16 (concat stack (repeat 16 0))))
+        ;; The stack is used to remember the current location
+        ;; before a jump is performed. The system has 16 levels
+        ;; of stack and in order to remember which level of the
+        ;; stack is used.
+        stack (vec (take 16 (concat stack (repeat 16 0))))

-    ;; The stack pointer (SP) can be 8-bit, it is used to point
-    ;; to the topmost level of the stack.
-    :SP SP
+        ;; The stack pointer (SP) can be 8-bit, it is used to point
+        ;; to the topmost level of the stack.
+        SP 0

-    ;; Most CHIP-8 programs start at locastion 0x200 (512),
-    ;; but some begin at 0x600 (1536).
-    ;; The program counter (PC) should be 16-bit, and is used
-    ;; to store the currently executing address.
-    :PC PC
+        ;; Most CHIP-8 programs start at locastion 0x200 (512),
+        ;; but some begin at 0x600 (1536).
+        ;; The program counter (PC) should be 16-bit, and is used
+        ;; to store the currently executing address.
+        PC 0x200

-    ;; V-registers, CHIP-8 has 15 8-bit general purpose registers
-    ;; named V0, V1 ~ VE. The 16th register is used for
-    ;; the `carry flag`.
-    :V (vec (take 16  (concat V (repeat 16 0))))
+        ;; V-registers, CHIP-8 has 15 8-bit general purpose registers
+        ;; named V0, V1 ~ VE. The 16th register is used for
+        ;; the `carry flag`.
+        V (vec (take 16  (concat V (repeat 16 0))))

-    ;; I-register is used to store memory address
-    :I I
+        ;; I-register is used to store memory address
+        I 0

-    ;; The delay timer is active whenever the delay timer
-    ;; register (DT) is non-zero.
-    ;; This timer does nothing more than subtract 1 from the
-    ;; value of DT at a rate of 60Hz. When DT reaches 0, it deactivates.
-    :DT DT
+        ;; The delay timer is active whenever the delay timer
+        ;; register (DT) is non-zero.
+        ;; This timer does nothing more than subtract 1 from the
+        ;; value of DT at a rate of 60Hz. When DT reaches 0, it deactivates.
+        DT 0

-    ;; The sound timer is active whenever the sound timer
-    ;; register (ST) is non-zero. This timer also decrements
-    ;; at a rate of 60Hz, however, as long as ST's value is
-    ;; greater than zero, the Chip-8 buzzer will sound. When ST
-    ;; reaches zero, the sound timer deactivates.
-    :ST ST}))
+        ;; The sound timer is active whenever the sound timer
+        ;; register (ST) is non-zero. This timer also decrements
+        ;; at a rate of 60Hz, however, as long as ST's value is
+        ;; greater than zero, the Chip-8 buzzer will sound. When ST
+        ;; reaches zero, the sound timer deactivates.
+        ST 0
+        }}]))
+

 (defn reset-cpu
+  "Reset the full cpu state."
   []
   (make-cpu))


support additional where clauses

support additional where clauses

and use limit to restrict the select-one queries on the
server-side

--- src/er_cassandra/record.clj
+++ src/er_cassandra/record.clj
@@ -22,10 +22,14 @@
   ([table
     key
     record-or-key-value
-    {:keys [columns only-if order-by limit] :as opts}]
-   (let [key-clause (extract-key-equality-clause key record-or-key-value opts)]
+    {:keys [columns where only-if order-by limit] :as opts}]
+   (let [key-clause (extract-key-equality-clause key record-or-key-value opts)
+         where-clause (if (sequential? (first where))
+                        where ;; it's already a seq of conditions
+                        (when (not-empty where) [where]))
+         where-clause (into key-clause where-clause)]
      (h/select table
-               (h/where key-clause)
+               (h/where where-clause)
                (when columns (apply h/columns columns))
                (when only-if (h/only-if only-if))
                (when order-by (h/order-by order-by))
@@ -49,7 +53,7 @@
    (select-one session table key record-or-key-value {}))

   ([session table key record-or-key-value opts]
-   (d/chain (select session table key record-or-key-value opts)
+   (d/chain (select session table key record-or-key-value (merge opts {:limit 1}))
             first)))

 (defn insert-statement


only #foo is only a hashtag at the start of the input or when preceeded by whitespace

--- src/statuses/views/common.clj
+++ src/statuses/views/common.clj
@@ -54,4 +54,4 @@
         escape-html
         (clojure.string/replace #"@(\w+)" handle)
         (clojure.string/replace uri anchor)
-        (clojure.string/replace #"#(\w+)" hashtag))))
+        (clojure.string/replace #"(?:^|(?<=\s))#(\w+)" hashtag))))


use global location not document.location

document.location isn't available in webworkers but location is

--- src/main/shadow/cljs/devtools/client/env.cljs
+++ src/main/shadow/cljs/devtools/client/env.cljs
@@ -65,10 +65,9 @@
 (defn get-server-host []
   (cond
     (and use-document-host
-         js/goog.global.document
-         js/goog.global.document.location
-         (seq js/goog.global.document.location.hostname))
-    js/document.location.hostname
+         js/goog.global.location
+         (seq js/goog.global.location.hostname))
+    js/goog.global.location.hostname

     (seq server-host)
     server-host


Resolvers can return non-channels

Resolvers can return non-channels

--- test-cljs/frontend/test_send.cljs
+++ test-cljs/frontend/test_send.cljs
@@ -4,7 +4,8 @@

             [cljs.core.async :as async :refer [<! chan close! put!]]
-            [om.next :as om])
+            [om.next :as om]
+            [cljs.core.async.impl.protocols :as async-impl])
   (:require-macros [devcards.core :as dc :refer [deftest]]
                    [cljs.core.async.macros :refer [go]]))

@@ -298,14 +299,20 @@

+(defn- read-port? [x]
+  (implements? async-impl/ReadPort x))
+
 (defn resolve* [context mapping key children]
   (async/map (fn [& vals]
                {key (into {}
                           (map #(vector (:key %1) %2)
                                children vals))})
              (map (fn [ast]
-                    (let [result ((get mapping (:key ast)) context ast)]
-                      (async/map (:key ast) [result])))
+                    (let [result ((get mapping (:key ast)) context ast)
+                          promise (if (read-port? result)
+                                    result
+                                    (doto (async/promise-chan) (put! result)))]
+                      (async/map (:key ast) [promise])))
                   children)))

@@ -316,8 +323,7 @@
 (def User
   {:user/name
    (fn [context ast]
-     (doto (async/promise-chan)
-       (put! {:user/name (:user/name context)})))
+     {:user/name (:user/name context)})

    :user/favorite-color
    (fn [context ast]


♻ Extract clarifying variables

♻ Extract clarifying variables

Why:
- Command handler tests do not need a specific time,
  but only process manager tests need it (so that they
  can assert the generated commands)

--- src/territory_bro/congregation.clj
+++ src/territory_bro/congregation.clj
@@ -119,11 +119,12 @@
   [command congregation {:keys [user-exists? check-permit]}]
   (let [cong-id (:congregation/id congregation)
         user-id (:user/id command)
-        user-permissions (set (get-in congregation [:congregation/user-permissions user-id]))]
+        user-permissions (set (get-in congregation [:congregation/user-permissions user-id]))
+        already-user? (contains? user-permissions :view-congregation)]
     (check-permit [:configure-congregation cong-id])
     (when-not (user-exists? user-id)
       (throw (ValidationException. [[:no-such-user user-id]])))
-    (when-not (contains? user-permissions :view-congregation)
+    (when-not already-user?
       [{:event/type :congregation.event/permission-granted
         :event/version 1
         :congregation/id cong-id
@@ -157,13 +158,15 @@

 (defmethod command-handler :congregation.command/rename-congregation
   [command congregation {:keys [check-permit]}]
-  (check-permit [:configure-congregation (:congregation/id congregation)])
-  (when-not (= (:congregation/name congregation)
-               (:congregation/name command))
-    [{:event/type :congregation.event/congregation-renamed
-      :event/version 1
-      :congregation/id (:congregation/id congregation)
-      :congregation/name (:congregation/name command)}]))
+  (let [cong-id (:congregation/id congregation)
+        old-name (:congregation/name congregation)
+        new-name (:congregation/name command)]
+    (check-permit [:configure-congregation cong-id])
+    (when-not (= old-name new-name)
+      [{:event/type :congregation.event/congregation-renamed
+        :event/version 1
+        :congregation/id cong-id
+        :congregation/name new-name}])))

 (defn handle-command [command events injections]
   (let [congregation (reduce write-model nil events)]


Remove IPrintWritter impl from dashboard events.

--- src/uxbox/data/dashboard.cljs
+++ src/uxbox/data/dashboard.cljs
@@ -63,44 +63,28 @@
         (assoc-in $ [:dashboard :section] section)
         (update $ :dashboard merge-if-not-exists
                 {:collection-type :builtin
-                 :collection-id 1})))
-
-    IPrintWithWriter
-    (-pr-writer [mv writer _]
-      (-write writer "#<event:u.d.d/initialize>"))))
+                 :collection-id 1})))))

 (defn set-project-ordering
   [order]
   (reify
     rs/UpdateEvent
     (-apply-update [_ state]
-      (assoc-in state [:dashboard :project-order] order))
-
-    IPrintWithWriter
-    (-pr-writer [mv writer _]
-      (-write writer "#<event:u.d.d/set-project-ordering>"))))
+      (assoc-in state [:dashboard :project-order] order))))

 (defn set-project-filtering
   [term]
   (reify
     rs/UpdateEvent
     (-apply-update [_ state]
-      (assoc-in state [:dashboard :project-filter] term))
-
-    IPrintWithWriter
-    (-pr-writer [mv writer _]
-      (-write writer "#<event:u.d.d/set-project-filtering>"))))
+      (assoc-in state [:dashboard :project-filter] term))))

 (defn clear-project-filtering
   []
   (reify
     rs/UpdateEvent
     (-apply-update [_ state]
-      (assoc-in state [:dashboard :project-filter] ""))
-
-    IPrintWithWriter
-    (-pr-writer [mv writer _]
-      (-write writer "#<event:u.d.d/clear-project-filtering>"))))
+      (assoc-in state [:dashboard :project-filter] ""))))

 (defn set-collection-type
   [type]
@@ -115,22 +99,14 @@
       (-apply-update [_ state]
         (as-> state $
           (assoc-in $ [:dashboard :collection-type] type)
-          (select-first $)))
-
-      IPrintWithWriter
-      (-pr-writer [mv writer _]
-        (-write writer "#<event:u.d.d/set-collection-type>")))))
+          (select-first $))))))

 (defn set-collection
   [id]
   (reify
     rs/UpdateEvent
     (-apply-update [_ state]
-      (assoc-in state [:dashboard :collection-id] id))
-
-    IPrintWithWriter
-    (-pr-writer [mv writer _]
-      (-write writer "#<event:u.d.d/set-collection>"))))
+      (assoc-in state [:dashboard :collection-id] id))))

 (defn mk-color-collection
   []
@@ -143,22 +119,14 @@
         (-> state
             (assoc-in [:colors-by-id id] coll)
             (assoc-in [:dashboard :collection-id] id)
-            (assoc-in [:dashboard :collection-type] :own))))
-
-    IPrintWithWriter
-    (-pr-writer [mv writer _]
-      (-write writer "#<event:u.d.d/mk-color-collection>"))))
+            (assoc-in [:dashboard :collection-type] :own))))))

 (defn rename-color-collection
   [id name]
   (reify
     rs/UpdateEvent
     (-apply-update [_ state]
-      (assoc-in state [:colors-by-id id :name] name))
-
-    IPrintWithWriter
-    (-pr-writer [mv writer _]
-      (-write writer "#<event:u.d.d/rename-color-collection>"))))
+      (assoc-in state [:colors-by-id id :name] name))))

 (defn delete-color-collection
   [id]
@@ -167,11 +135,7 @@
     (-apply-update [_ state]
       (let [state (update state :colors-by-id dissoc id)
             colls (sort-by :id (vals (:colors-by-id state)))]
-        (assoc-in state [:dashboard :collection-id] (:id (first colls)))))
-
-    IPrintWithWriter
-    (-pr-writer [mv writer _]
-      (-write writer "#<event:u.d.d/rename-color-collection>"))))
+        (assoc-in state [:dashboard :collection-id] (:id (first colls)))))))

 (defn replace-color
   "Add or replace color in a collection."
@@ -185,11 +149,7 @@
           (disj $ from)
           (conj $ to)
           (assoc-in state [:colors-by-id id :colors] $))
-        state))
-
-    IPrintWithWriter
-    (-pr-writer [mv writer _]
-      (-write writer "#<event:u.d.d/replace-color>"))))
+        state))))

 (defn remove-color
   "Remove color in a collection."
@@ -202,9 +162,5 @@
         (as-> colors $
           (disj $ color)
           (assoc-in state [:colors-by-id id :colors] $))
-        state))
+        state))))

-    IPrintWithWriter
-    (-pr-writer [mv writer _]
-      (-write writer "#<event:u.d.d/remove-color>"))))
-


Made test more repeatable on different JVMs

--- test/rpi_challenger/http_test.clj
+++ test/rpi_challenger/http_test.clj
@@ -5,7 +5,7 @@
 (deftest post-request-test

   (testing "Returns an error message on internal network library error"
-    (is (= {:body nil
-            :status nil
-            :error "java.lang.IllegalArgumentException"}
-          (http/post-request "<malformed url>" "")))))
+    (let [response (http/post-request "<malformed url>" "")]
+      (is (nil? (:body response)))
+      (is (nil? (:status response)))
+      (is (re-matches #".*IllegalArgumentException.*" (:error response))))))


Added tests for dataset handlers

Added tests for dataset handlers

--- test/cfpb/qu/handler_test.clj
+++ test/cfpb/qu/handler_test.clj
@@ -10,7 +10,7 @@

 (facts "about /data"
        (prerequisite (#'cfpb.qu.data/get-datasets) => [])
-
+
        (fact "it returns successfully"
              (app (request :get "/data"))
              => (contains {:status 200
@@ -20,3 +20,20 @@
              => (contains {:status 200
                            :headers {"Content-Type" "application/xml;charset=UTF-8"}})))

+(facts "about /data/dataset"
+       (fact "it returns successfully when the dataset exists"
+             (prerequisite (#'cfpb.qu.data/get-metadata "good-dataset") => {})
+
+             (app (request :get "/data/good-dataset"))
+             => (contains {:status 200
+                           :headers {"Content-Type" "text/html;charset=UTF-8"}})
+
+             (app (request :get "/data/good-dataset.xml"))
+             => (contains {:status 200
+                           :headers {"Content-Type" "application/xml;charset=UTF-8"}}))
+
+       (fact "it returns a 404 when the dataset does not exist"
+             (prerequisite (#'cfpb.qu.data/get-metadata "bad-dataset") => nil)
+
+             (app (request :get "/data/bad-dataset"))
+             => (contains {:status 404})))


Add a test showing a customized id-query-for.

--- test/clj_record/util_test.clj
+++ test/clj_record/util_test.clj
@@ -38,3 +38,12 @@
 (deftest throws-if-asked-for-id-query-of-unrecognized-db-spec
   (is (thrown? Exception
     (util/id-query-for {:classname "com.example.MadeUpDriver" :subprotocol "madeup"}))))
+
+(defmethod util/id-query-for "fake subprotocol" [db-spec table-name]
+  (str "made up query"))
+
+(deftest provides-id-query-for-whatever-dbms-you-like-if-you-defmethod-for-it
+  (are (= _1 (util/id-query-for _2 "table_name"))
+    "made up query" {:subprotocol "fake subprotocol"}))
+
+


Add unit test for derive-column

Add unit test for derive-column

--- test/grafter/tabular_test.clj
+++ test/grafter/tabular_test.clj
@@ -273,6 +273,15 @@
       (is (thrown? java.lang.Exception
              (swap ordered-ds "a" "b" "c"))))))

+(deftest derive-column-test
+  (let [subject (make-dataset [[1 2] [3 4]])
+        expected (make-dataset [[1 2 3] [3 4 7]])]
+
+    (is (= (derive-column subject "c" ["a" "b"] +)
+           expected))
+
+    (is (= (derive-column subject "c" [:a :b] +)
+           expected))))

 (deftest build-lookup-table-test
   (let [debts (make-dataset [["rick"  30     30]


add more text

add more text

--- src/mermaid_ldjam/core.cljs
+++ src/mermaid_ldjam/core.cljs
@@ -33,6 +33,10 @@
   (q/background 90 200 21)
   state)

+(defn lose-game [state]
+  (q/background 90 200 21)
+  state)
+
 (def actions-map
   {[:look :window] {:text "You look outside the window and see your home, the mighty ocean." :action []}
    [:look :bucket] {:text "You see a bucket. Maybe there is something inside." :action []}
@@ -41,17 +45,27 @@
    [:look :seagull] {:text "It's a seagull looking for company!"}
    [:look :broom] {:text "There is a broom. You wonder if it was there this whole time."}
    [:look :window-open] {:text "The window is open. You can see the sea. You can feel the breeze."}
+   [:look :starfish] {:text "There is a starfish. It looks kinda grumpy."}
    [:flap :window] {:text "You're too far away. You can't reach the window."}
    [:flap :bucket] {:text "You flap against the bucket. BÄM. The bucket falls over and stones spill on the floor." :action [unhide :stone]}
    [:flap :stone] {:text "You flap frustratedly against the stones. That's no use."}
+   [:flap :window-open] {:text "The window is open but it is still to far to reach."}
    [:flap :starfish] {:text "You flap against the starfish. 'Ouch!' - it cries."}
+   [:flap :bottle] {:text "You attempt flapping the bottle of wine but halt at the last moment. It's too previous to spill."}
+   [:flap :broom] {:text "You flap against the broom. It almost falls over. Maybe you can use it differently?"}
+   [:flap :seagull] {:text "You flap in the direction of the seagull. It seems intrigued."}
+   [:bottle :bucket] {:text "You put the bottle in the bucket. Then put it back. That makes no sense."}
+   [:stone :starfish] {:text "You throw stones at the starfish. You will probably never be friends."}
+   [:stone :bucket] {:text "You put a stone back in the bucket. Back to the beggining."}
    [:stone :window] {:text "You throw a stone against the window. Crash! The window shatters in tiny pieces." :action [unhide :window-open]}
-   [:starfish :window] {:text "You throw the starfish against the window. It bounces back and gives you a disappointed look."}
+   [:starfish :window] {:text "You throw the starfish against the window. It bounces back and gives you an angry look."}
    [:starfish :window-open] {:text "You throw the starfish out the window." :action [unhide :seagull]}
    [:bottle :seagull] {:text "You start drinking with the seagull. The seagull drunkenly points in the corner." :action [unhide :broom]}
    [:bottle :starfish] {:text "You hand the bottle to the starfish. It takes a sip of wine, but it's more of a whiskey person."}
    [:broom :window-open] {:text "You catapult yourself out of the room with the broom. FREEDOM! You won." :action [win-game]}
    [:broom :bucket] {:text "You try to put the broom in the bucket. That's where the broom belongs, but you're not here to clean up."}
+   [:bucket :seagull] {:text "You show the bucket to the seagull. It expected more of you."}
+   [:stone :seagull] {:text "You throw stones at the seagull. The seagull is disappointed and leaves. You guesss that's your life now." :action [lose-game]}
    })

 (defn point-in-rect? [entity mx my]


Fix board lookup when retrieving read data.

--- src/oc/storage/api/orgs.clj
+++ src/oc/storage/api/orgs.clj
@@ -171,7 +171,7 @@
         users-data-map (zipmap (map :user-id active-users) active-users)
         with-users-data (map #(assoc % :user (get users-data-map (:user-id %))) filtered-read-data)
         grouped-entries (group-by :item-id with-users-data)
-        allowed-boards-map (zipmap (:board-uuid allowed-boards) allowed-boards)
+        allowed-boards-map (zipmap (:uuid allowed-boards) allowed-boards)
         enrties-with-board (map #(let [board (get allowed-boards-map (:board-uuid %))]
                                    (assoc % :board-slug (:slug board)
                                             :board-name (:name board)


Remove accidental import.

Remove accidental import.

--- src/onyx/plugin/hornetq.clj
+++ src/onyx/plugin/hornetq.clj
@@ -3,7 +3,6 @@
             [onyx.coordinator.planning :as planning]
             [onyx.peer.task-lifecycle-extensions :as l-ext]
             [onyx.peer.pipeline-extensions :as p-ext]
-            [onyx.peer.task-lifecycle]
             [onyx.peer.operation :as operation]
             [onyx.queue.hornetq :refer [take-segments]]
             [onyx.extensions :as extensions]


Reuse react from util in server

Reuse react from util in server

--- src/reagent/dom/server.cljs
+++ src/reagent/dom/server.cljs
@@ -9,7 +9,7 @@
                                    js/ReactDOMServer)
                               (and (exists? js/require)
                                    (js/require "react-dom/server"))
-                              js/React))
+                              util/react))
 (assert react-dom-server)

 (defn render-to-string


Alias

Alias

--- test/ai_zootson/questions_test.clj
+++ test/ai_zootson/questions_test.clj
@@ -34,36 +34,79 @@

 (pldb/db-rel animal fact)
 (pldb/db-rel continent fact)
+(pldb/db-rel rank fact)
+
+(pldb/db-rel classify animal rank)
 (pldb/db-rel lives-in animal continent)
+(pldb/db-rel has-prop animal property)
+(pldb/db-rel eats animal food)
+(pldb/db-rel is-able-to thing)

+(pldb/db-rel is-alias a1 a2)
 (pldb/db-rel is-faster a1 a2)

 (defn is-slower [a1 a2]
   (is-faster a2 a1))

-(defn is-alias [x y]
-  [x y])
+(defn some-animal [q y]
+  (conde
+    [(animal y) (== q y)]
+    [(is-alias q y)]
+    ;; [(fresh [singular]
+    ;;         (== singular (subs 0 (- (count y))))
+    ;;         (some-animal q singular))]
+    ))
+
+(defn check-fact [animal fact]
+  (conde
+    [(has-prop animal fact)]
+    [(classify animal fact)]
+    [(eats animal fact)]
+    [(is-able-to animal fact)]))

 (def test-facts (pldb/db
                   [animal "Lion"]
-                  [animal "Pidgeon"]
+                  [animal "Pigeon"]
+
+                  [animal "Snake"]
+                  [rank "Reptile"]
+                  [classify "Snake" "Reptile"]
+                  [has-prop "Snake" "Hair"]
+
+                  [animal "Fish"]
+                  [is-able-to "Fish" "Swim"]
+                  [eats "Fish" "Plankton"]
+
+                  [not [is-able-to "Lion" "Swim"]]

                   [continent "Africa"]
                   [continent "Europe"]

+                  [is-faster "Pigeon" "Lion"]
+
                   [is-alias "Lion" "Leijona"]

-                  [is-faster "Pidgeon" "Lion"]
-
                   [lives-in "Lion" "Africa"]
-                  [lives-in "Pidgeon" "Europe"]))
+                  [lives-in "Pigeon" "Europe"]))

 (fact core.logic
   (pldb/with-db test-facts
+    (run* [q] (lives-in q "Africa")) => (just "Lion")
+    (run* [q] (is-faster q "Lion")) => (just "Pigeon")
+    (run* [q] (is-alias q "Leijona")) => (just "Lion")
+    (run* [q] (is-alias q "Lion")) => empty?
+    (run* [q] (is-slower q "Pigeon")) => (just "Lion")
+    (run* [q] (== q "Lion")) => (just "Lion")
+    (run* [q] (some-animal q "Lion")) => (just "Lion")
+    (run* [q] (some-animal q "Leijona")) => (just "Lion")
+    ;; (run* [q] (some-animal q "Lions")) => (just "Lion")
     (run* [q]
+          (some-animal q "Leijona")
           (lives-in q "Africa")) => (just "Lion")
     (run* [q]
-          (is-faster q "Lion")) => (just "Pidgeon")
-    (not (empty? (run* [q]
-                       (animal "Leijona")
-                       (lives-in q "Africa")))) => true))
+          (check-fact q "Reptile")
+          (check-fact q "Hair")) => (just "Snake")
+    (run* [q]
+          (check-fact q "Plankton")
+          (check-fact q "Swim")) => (just "Fish")
+    ))


Added four tests into core_test.clj module

--- test/emender_jenkins/core_test.clj
+++ test/emender_jenkins/core_test.clj
@@ -23,3 +23,30 @@
     [function-name]
     (clojure.test/function? function-name))

+;
+; Tests for various function definitions
+;
+
+(deftest test-start-server-existence
+    "Check that the emender-jenkins.core/start-server definition exists."
+    (testing "if the emender-jenkins.core/start-server definition exists."
+        (is (callable? 'emender-jenkins.core/start-server))))
+
+
+(deftest test-get-and-check-port-existence
+    "Check that the emender-jenkins.core/get-and-check-port definition exists."
+    (testing "if the emender-jenkins.core/get-and-check-port definition exists."
+        (is (callable? 'emender-jenkins.core/get-and-check-port))))
+
+
+(deftest test-get-port-existence
+    "Check that the emender-jenkins.core/get-port definition exists."
+    (testing "if the emender-jenkins.core/get-port definition exists."
+        (is (callable? 'emender-jenkins.core/get-port))))
+
+
+(deftest test--main-existence
+    "Check that the emender-jenkins.core/-main definition exists."
+    (testing "if the emender-jenkins.core/-main definition exists."
+        (is (callable? 'emender-jenkins.core/-main))))
+


Add test for simultaneous tackle case

Add test for simultaneous tackle case

--- test/monkey_music/tackle_test.cljs
+++ test/monkey_music/tackle_test.cljs
@@ -60,4 +60,35 @@
          [1 1] (get-in curr-state [:teams "2" :position])
          [1 2] (get-in curr-state [:teams "3" :position])))))

-;(test-ns 'monkey-music.tackle-test)
+(deftest test-tackle-without-move-without-steal
+  (with-redefs [c/check-steal-success! (constantly false)]
+    (let [curr-state
+        (-> state
+            ; team 2 tackles team 3
+            (c/run-commands [{:team-name "1" :command ::c/idle}
+                             {:team-name "2" :command ::c/move :direction ::c/right}
+                             {:team-name "3" :command ::c/idle}]))]
+    (are [x y] (= x y)
+         [1 1] (get-in curr-state [:teams "2" :position])
+         [1 2] (get-in curr-state [:teams "3" :position])))))
+
+(def tackle-state
+  (c/create-game-state
+    ["1" "2"]
+    {:layout [[::c/empty ::c/monkey ::c/monkey ::c/empty ::c/song]]
+     :turns 10
+     :inventory-size 3}))
+
+(deftest test-simulaneous-tackle
+  (with-redefs [c/weighted-shuffle!
+                (constantly [{:team-name "1" :command ::c/move :direction ::c/right}
+                             {:team-name "2" :command ::c/move :direction ::c/left}])]
+    (let [curr-state
+          (-> tackle-state
+              (c/run-commands [{:team-name "1" :command ::c/move :direction ::c/right}
+                               {:team-name "2" :command ::c/move :direction ::c/left}]))]
+      (are [x y] (= x y)
+           [0 2] (get-in curr-state [:teams "1" :position])
+           [0 3] (get-in curr-state [:teams "2" :position])))))
+
+(test-ns 'monkey-music.tackle-test)