Add some more beats

Add some more beats

--- src/overtone_workspace/grunbles.clj
+++ src/overtone_workspace/grunbles.clj
@@ -8,16 +8,15 @@
 ;; (def kick (sample "resources/kick.wav"))
 ;; (kick)

-(stop)
-
-(odoc line)
-(odoc asr)
-(odoc buf-rd)
-(odoc phasor)
-(odoc bpz2)
-(odoc latch)
-(odoc buf-rate-scale)
-(odoc buf-dur)
+(comment
+  (odoc line)
+  (odoc asr)
+  (odoc buf-rd)
+  (odoc phasor)
+  (odoc bpz2)
+  (odoc latch)
+  (odoc buf-rate-scale)
+  (odoc buf-dur))

 (definst grumble [freq 440 freq-mul 1 speed 10 attack 10 release 50]
   (let [snd (mix (map #(* (lf-cub (* % freq-mul freq))
@@ -163,11 +162,11 @@
 (defn normalise-beat-info
   [beat]
   (cond
-   (= 0 beat)         nil
-   (= 1 beat)         {}
-   (map? beat)        beat
-   (sequential? beat) beat
-   :else              {}))
+    (= 0 beat)         nil
+    (= 1 beat)         {}
+    (map? beat)        beat
+    (sequential? beat) beat
+    :else              {}))

 (defn schedule-pattern
   [curr-t pat-dur sound pattern]
@@ -187,19 +186,19 @@
   (let [new-t (+ curr-t pat-dur)]
     (apply-by new-t #'live-sequencer [new-t pat-dur live-patterns])))

+(def a {:rate 2 :amp 0.1 :time-scale-max 5})
 (def a {:rate 100 :amp 0.4 :time-scale-max 5})
-(def a {:rate 2 :amp 0.1 :time-scale-max 5})
 (def b {:pan -1 :freq 1000})
 (def c {:freq 25000 :amp 0.2})
 (def d {:amp 5.0 :dur 0.25})
 (def g {:freq-mul 1})

-(metro :bpm 110)
+(metro :bpm 128)
 (volume 0.5)
 (metro :bpm)

 ;;(def metro (metronome 128))
-(def one-beat-dur (/ 60.0 110))
+(def one-beat-dur (/ 60.0 128))
 (def one-bar-dur (* one-beat-dur 4))
 (def beat-per-pattern 4)
 (def dur-per-pattern (* beat-per-pattern one-beat-dur))
@@ -235,25 +234,62 @@
     ;;(live-sequencer (now) ms-per-pattern *beats)
     ;; (live-sequencer (metro (inc (metro))) ms-per-pattern *beats))
     (live-sequencer (metro (next-beat (metro) 0 beat-per-pattern)) ms-per-pattern *beats))
-  (laserplayer (next-beat (metro) 0 beat-per-pattern))
   (init-latchbell-mod (:rate @latchbell-arg))
-  (apply-by (metro (next-beat (metro) (+ 4 (* 7 beat-per-pattern)) (* 8 beat-per-pattern)))
-            #'swap! [*beats assoc laserbeam [d _ _ [d d] (vec (repeat 64 0.8)) _ _ d _ _ d _ b _ _ [d d d]]])
-  (apply-by (metro (next-beat (metro) 0 (* 8 beat-per-pattern)))
-    #'swap! [*beats assoc laserbeam [d _ _ [d d] (vec (repeat 64 0.8)) _ _ d _ _ d _ b _ _ [d d d]]])
+  (apply-by (metro (- (next-beat (metro) 0 (* 8 beat-per-pattern)) 1/16))
+            #'swap! [*beats assoc laserbeam [d _ _ [_ d d] (vec (repeat 64 0.5)) _ _ d _ _ d _ b _ _ [d d d]]])
+
+  (apply-by (metro (- (next-beat (metro) 0 (* 4 beat-per-pattern)) 1/16))
+            #'init-latchbell-mod [(:rate @latchbell-arg)])
+  (apply-by (metro (- (next-beat (metro) 0 (* 4 beat-per-pattern)) 1/16))
+            #'swap! [*beats assoc latchbell (vec (repeat 24 a))])

   (swap! *beats assoc laserbeam [d _ _ [d d] (vec (repeat 64 0.8)) _ _ d _ _ d _ b _ _ [d d d]])
   (swap! *beats assoc laserbeam [_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _])
   (swap! *beats assoc latchbell [a _ a _ a _ a _ a _ a _ a _ a _])
-  (swap! *beats assoc latchbell (vec (repeat 1 _)))
   (swap! *beats assoc laserbeam [d c c c b c c d c c d c b c c d])
   (swap! *beats assoc grumble [g _ _ _ _ _ _ _ _  _ _ _ _ _ _ _])

   (reset! *beats beats)
   (stop))

+(def beats16 {laserbeam [
+                         [[d _ d _] [b _ _ _] [_ d 1 _] [[b _] [1 1 1]]]
+                         [[d 1 _ d] [b 1 _ d] [d _ d _] [[b 0.5 0.5] (vec (repeat 3 0.5))]]
+                         [[d 1 _ d] [b 1 _ _] [d 1 _ d] [b 1 _ _]]
+                         [[d _ d _] [b _ _ _] [_ _ d _] [[b _] [1 1 1]]]
+                         [[d _ d _] [b _ _ _] [_ d 1 _] [[b _] [1 1 1]]]
+                         [[d 1 _ d] [b 1 _ [1 1 1]] [d _ d _] [[b 0.5 0.5] (vec (repeat 3 0.5))]]
+                         [[d 1 _ d] [b 1 _ _] [d 1 _ d] [b 1 _ _]]
+                         [[d _ d _] [b _ _ _] [_ _ d _] [[b _] [1 1 1]]]
+                         [[d _ d _] [b _ _ _] [_ d 1 _] [[b _] [1 1 1]]]
+                         [[d 1 _ d] [b 1 _ [1 1 1]] [d _ d _] [[b 0.5 0.5] (vec (repeat 3 0.5))]]
+                         [[d 1 _ d] [b 1 _ _] [d 1 _ d] [b 1 _ _]]
+                         [[d _ d _] [b _ _ _] [_ _ d _] [[b _] [1 1 1]]]
+                         [[d _ d _] [b _ _ _] [_ d 1 _] [[b _] [1 1 1]]]
+                         [[d 1 _ d] [b 1 _ [1 1 1]] [d _ d _] [[b 0.5 0.5] (vec (repeat 3 0.5))]]
+                         [[d 1 _ d] [b 1 _ _] [d 1 _ d] [b 1 _ _]]
+                         [[d _ d _] [b _ _ _] [_ _ d _] [[b _] [1 1 1]]]
+                         ]})
+(def *beats16 (atom beats16))
+(reset! *beats16 beats16)
+(metro :bpm 128)
+
+(comment
+  ;;(live-sequencer (now) 2000 *beats)
+  (let [ms-per-pattern (* 1000 dur-per-pattern)]
+    ;;(live-sequencer (now) ms-per-pattern *beats)
+    ;; (live-sequencer (metro (inc (metro))) ms-per-pattern *beats))
+    (live-sequencer (metro (next-beat (metro) 0 beat-per-pattern)) (* 16 ms-per-pattern) *beats16))
+  (reset! *beats16 beats16))
+
+
 (comment
   (live-sequencer metro (metro) *beats 1/4 0)
   (stop))

-(odoc metronome)
+(comment
+  (odoc metronome)
+  (odoc apply-by)
+  (odoc apply-at)
+  (odoc at-at)
+  )


adjust indentation on named matrix types for parinfer consistency

--- src/polismath/math/named_matrix.clj
+++ src/polismath/math/named_matrix.clj
@@ -20,32 +20,32 @@
 (deftype IndexHash
   [^java.util.Vector names ^clojure.lang.PersistentArrayMap index-hash]
   AutoIncIndex
-    (get-names [this] (.names this))
-    (next-index [this] (count (.names this)))
-    (index [this keyname] (index-hash keyname))
-    (append [this keyname]
-      (if ((.index-hash this) keyname)
-        this
-        (IndexHash.
-          (conj (get-names this) keyname)
-          (assoc (.index-hash this) keyname (next-index this)))))
-    (append-many [this keynames]
-      ; potentially faster
-      ;(let [uniq-kns (distinct keynames)
-            ;new-kns (remove (.index-hash this) uniq-kns)]
-        ;(IndexHash.
-          ;(into (.names this) new-kns)
-          ;(into (.index-hash)
-            ;(map
-              ;#(vector %1 (+ (count (.names this)) %2))
-              ;new-kns
-              ;(range)))))
-      ; much simpler
-      (reduce append this keynames))
-    (subset [this keynames]
-      (let [kn-set (set keynames)
-            new-kns (filter kn-set (.names this))]
-        (IndexHash. new-kns (into {} (map vector new-kns (range)))))))
+  (get-names [this] (.names this))
+  (next-index [this] (count (.names this)))
+  (index [this keyname] (index-hash keyname))
+  (append [this keyname]
+    (if ((.index-hash this) keyname)
+      this
+      (IndexHash.
+        (conj (get-names this) keyname)
+        (assoc (.index-hash this) keyname (next-index this)))))
+  (append-many [this keynames]
+    ; potentially faster
+    ;(let [uniq-kns (distinct keynames)
+          ;new-kns (remove (.index-hash this) uniq-kns)]
+      ;(IndexHash.
+        ;(into (.names this) new-kns)
+        ;(into (.index-hash)
+          ;(map
+            ;#(vector %1 (+ (count (.names this)) %2))
+            ;new-kns
+            ;(range)))))
+    ; much simpler
+    (reduce append this keynames))
+  (subset [this keynames]
+    (let [kn-set (set keynames)
+          new-kns (filter kn-set (.names this))]
+      (IndexHash. new-kns (into {} (map vector new-kns (range)))))))

 (defn index-hash
   "Construct a new IndexHash with the given keynames"
@@ -82,67 +82,67 @@

 (deftype NamedMatrix
-  [row-index col-index ^java.util.Vector matrix]
+  [row-index col-index matrix]
   PNamedMatrix
-    (update-nmat [this values]
-      ; First find the row and column names that aren't yet in the data
-      (let [[missing-rows missing-cols]
-            (reduce
-              (fn [[missing-rows missing-cols] [row col value]]
-                [(if (nil? (index (.row-index this) row))
-                   (conj missing-rows row)
-                   missing-rows)
-                 (if (nil? (index (.col-index this) col))
-                   (conj missing-cols col)
-                   missing-cols)])
-              [[] []]
-              values)
-            ; Construct new rowname and colname hash-indices
-            new-row-index (append-many (.row-index this) missing-rows)
-            new-col-index (append-many (.col-index this) missing-cols)
-            new-row-count (count (set missing-rows))
-            new-col-count (count (set missing-cols))]
-        ; Construct a new NamedMatrix
-        (NamedMatrix.
-          new-row-index
-          new-col-index
-          ; Construct new matrix
-          (as-> (.matrix this) mat
-            (if (= 0 (matrix/dimension-count mat 1))
-              ; If the matrix is empty, just create the shape needed
-              (matrix/coerce [[]]
-                (matrix/broadcast nil [new-row-count new-col-count]))
-              ; OW, add padding of nils for new rows/cols
-              (-> mat
-                (add-padding 1 (count (set missing-cols)))
-                (add-padding 0 (count (set missing-rows)))))
-            ; Next assoc-in all of the new votes
-            (reduce
-              (fn [mat' [row col value]]
-                (let [row-i (index new-row-index row)
-                      col-i (index new-col-index col)]
-                  (assoc-in mat' [row-i col-i] value)))
-              mat
-              values)))))
-    (rownames [this] (get-names (.row-index this)))
-    (colnames [this] (get-names (.col-index this)))
-    (get-matrix [this] (.matrix this))
-    (get-row-index [this] (.row-index this))
-    (get-col-index [this] (.col-index this))
-    (rowname-subset [this names]
-      (let [row-indices (map (partial index (.row-index this)) names)
-            row-index (subset (.row-index this) names)]
-        (NamedMatrix.
-          row-index
-          (.col-index this)
-          (filter-by-index (.matrix this) row-indices))))
-    (colname-subset [this names]
-      (let [col-indices (map (partial index (.col-index this)) names)
-            col-index (subset (.col-index this) names)]
-        (NamedMatrix.
-          (.row-index this)
-          col-index
-          (matrix/select (.matrix this) :all col-indices)))))
+  (update-nmat [this values]
+    ; First find the row and column names that aren't yet in the data
+    (let [[missing-rows missing-cols]
+          (reduce
+            (fn [[missing-rows missing-cols] [row col value]]
+              [(if (nil? (index (.row-index this) row))
+                 (conj missing-rows row)
+                 missing-rows)
+               (if (nil? (index (.col-index this) col))
+                 (conj missing-cols col)
+                 missing-cols)])
+            [[] []]
+            values)
+          ; Construct new rowname and colname hash-indices
+          new-row-index (append-many (.row-index this) missing-rows)
+          new-col-index (append-many (.col-index this) missing-cols)
+          new-row-count (count (set missing-rows))
+          new-col-count (count (set missing-cols))]
+      ; Construct a new NamedMatrix
+      (NamedMatrix.
+        new-row-index
+        new-col-index
+        ; Construct new matrix
+        (as-> (.matrix this) mat
+          (if (= 0 (matrix/dimension-count mat 1))
+            ; If the matrix is empty, just create the shape needed
+            (matrix/coerce [[]]
+              (matrix/broadcast nil [new-row-count new-col-count]))
+            ; OW, add padding of nils for new rows/cols
+            (-> mat
+              (add-padding 1 (count (set missing-cols)))
+              (add-padding 0 (count (set missing-rows)))))
+          ; Next assoc-in all of the new votes
+          (reduce
+            (fn [mat' [row col value]]
+              (let [row-i (index new-row-index row)
+                    col-i (index new-col-index col)]
+                (assoc-in mat' [row-i col-i] value)))
+            mat
+            values)))))
+  (rownames [this] (get-names (.row-index this)))
+  (colnames [this] (get-names (.col-index this)))
+  (get-matrix [this] (.matrix this))
+  (get-row-index [this] (.row-index this))
+  (get-col-index [this] (.col-index this))
+  (rowname-subset [this names]
+    (let [row-indices (map (partial index (.row-index this)) names)
+          row-index (subset (.row-index this) names)]
+      (NamedMatrix.
+        row-index
+        (.col-index this)
+        (filter-by-index (.matrix this) row-indices))))
+  (colname-subset [this names]
+    (let [col-indices (map (partial index (.col-index this)) names)
+          col-index (subset (.col-index this) names)]
+      (NamedMatrix.
+        (.row-index this)
+        col-index
+        (matrix/select (.matrix this) :all col-indices)))))

 (defn named-matrix


fix undeclared ios?

fix undeclared ios?

--- src/status_im/components/react.cljs
+++ src/status_im/components/react.cljs
@@ -3,7 +3,7 @@
             [status-im.components.styles :as st]
             [status-im.utils.utils :as u
              :refer [get-react-property get-class adapt-class]]
-            [status-im.utils.platform :refer [platform-specific]]
+            [status-im.utils.platform :refer [platform-specific ios?]]
             [status-im.i18n :as i18n]))

 (def react-native (js/require "react-native"))


Fix network status change logic and #8951

--- src/status_im/network/net_info.cljs
+++ src/status_im/network/net_info.cljs
@@ -7,12 +7,16 @@
             [status-im.mailserver.core :as mailserver]
             [status-im.chaos-mode.core :as chaos-mode]
             [status-im.native-module.core :as status]
-            [status-im.ui.screens.mobile-network-settings.events :as mobile-network]))
+            [status-im.ui.screens.mobile-network-settings.events :as mobile-network]
+            [status-im.wallet.core :as wallet]))

 (fx/defn change-network-status
   [{:keys [db] :as cofx} is-connected?]
   (fx/merge cofx
             {:db (assoc db :network-status (if is-connected? :online :offline))}
+            (when is-connected?
+              (if-not (= (count (get-in db [:wallet :accounts])) (count (get-in db [:multiaccount :accounts])))
+                (wallet/update-balances nil)))
             (mailserver/network-connection-status-changed is-connected?)))

 (fx/defn change-network-type
@@ -26,12 +30,13 @@

 (fx/defn handle-network-info-change
   {:events [::network-info-changed]}
-  [{:keys [db] :as cofx} {:keys [is-connected type details] :as state}]
+  [{:keys [db] :as cofx} {:keys [isConnected type details] :as state}]
   (let [old-network-status (:network-status db)
-        old-network-type (:network/type db)]
+        old-network-type (:network/type db)
+        connectivity-status (if isConnected :online :offline)]
     (fx/merge cofx
-              (when-not (= is-connected old-network-status)
-                (change-network-status is-connected))
+              (when-not (= connectivity-status old-network-status)
+                (change-network-status isConnected))
               (when-not (= type old-network-type)
                 (change-network-type old-network-type type (:is-connection-expensive details))))))


Fix menu names indexes.

Fix menu names indexes.

--- src/uxbox/ui/workspace/options.cljs
+++ src/uxbox/ui/workspace/options.cljs
@@ -19,10 +19,10 @@
    :builtin/group []})

 (def +menus-by-id+
-  {:menu/measures
+  {:menu/icon-measures
    {:name "Size & position"
     :icon i/infocard
-    :id :menu/measures}
+    :id :menu/icon-measures}

    :menu/fill
    {:name "Fill"


compare and swap 'tested' on repl

compare and swap 'tested' on repl

--- src/etcd_clojure/core.clj
+++ src/etcd_clojure/core.clj
@@ -33,7 +33,7 @@
      `(parse-string (:body (~method ~base ~data)))))

 (defn compose-params
-  [& {:keys [ttl prev-value prev-index prev-exists dir val]}]
+  [& {:keys [ttl prev-value prev-index prev-exist dir val]}]
   (cond->
    {}
    val (assoc :value val)
@@ -41,7 +41,7 @@
    ttl (assoc :ttl ttl)
    prev-value (assoc :prevValue prev-value)
    prev-index (assoc :prevIndex prev-index)
-   (not (nil? prev-exists)) (assoc :prevExists prev-exists)))
+   (not (nil? prev-exist)) (assoc :prevExist prev-exist)))

 (defn connect!
   ([etcd-server-host] (connect! etcd-server-host 4001 7001))
@@ -57,8 +57,14 @@

 (defn set
   "Sets a vaue to key, optional param :ttl"
-  [key val & {:keys [ttl]}]
-  (let [params (compose-params :ttl ttl :val val)
+  [key val & {:keys [ttl prev-value prev-index prev-exist]}]
+  (let
+      [params (compose-params
+                :ttl ttl
+                :val val
+                :prev-value prev-value
+                :prev-index prev-index
+                :prev-exist prev-exist)
         url (str (base-url) "/keys/" key)]
     (get-in (send-json http/put url {:form-params params}) ["node" "value"])))

@@ -103,12 +109,12 @@

 (defn create-dir
   "Creates a dir"
-  [key & {:keys [ttl prev-value prev-index prev-exists]}]
+  [key & {:keys [ttl prev-value prev-index prev-exist]}]
   (let [params (compose-params
                 :ttl ttl
                 :prev-value prev-value
                 :prev-index prev-index
-                :prev-exists prev-exists
+                :prev-exist prev-exist
                 :dir true)
         url (str (base-url) "/keys/" key)]
     (get-in (send-json http/put url {:form-params params}) ["node" "key"])))


slight cleanup

slight cleanup

--- src/frontend/uploads.cljs
+++ src/frontend/uploads.cljs
@@ -58,10 +58,7 @@
   (let [new-uploads-info (handle-upload-slots-change old-state new-state)]
     (if-not (nil? new-uploads-info)
       (do
-
-        (println "NEW UPLOADS INFO:" new-uploads-info)
-        (swap! app-state/app-state (merge @app-state/app-state
-                                          new-uploads-info))))))
+        (swap! app-state/app-state merge new-uploads-info)))))

 (add-watch app-state/app-state :upload-slots  upload-slots-watch-fn!)

@@ -127,7 +124,6 @@

     (swap! app-state/app-state
            merge
-           @app-state/app-state
            (if (< (count (:active-uploads @app-state/app-state))
                          (:upload-slots   @app-state/app-state))
              {:uploads (merge (:uploads @app-state/app-state)
@@ -137,6 +133,7 @@
              {:uploads (merge (:uploads @app-state/app-state)
                               {upload-id new-upload})
               :inactive-uploads (prepend-upload (:inactive-uploads @app-state/app-state)
-                                                upload-id)}))))
+                                                upload-id)}))
+    (println @app-state/app-state)))


Update test for storage.

Update test for storage.

--- web-server/test/clj/hatnik/db/storage_test.clj
+++ web-server/test/clj/hatnik/db/storage_test.clj
@@ -23,6 +23,13 @@
            {:id bar-id
             :email bar-email})
         "Bar should match.")
+
+    (is (= (s/get-user-by-id storage foo-id)
+           {:id foo-id
+            :email foo-email}))
+    (is (= (s/get-user-by-id storage bar-id)
+           {:id bar-id
+            :email bar-email}))

     (is (not= foo-id bar-id) "id should be different")
     (is (= foo-id foo-id-2) "Multiple creation should return same user.")))
@@ -56,6 +63,16 @@
               :user-id user2
               :id id3}})
         "Projects for user 2 should match")
+
+    ; Get by id
+    (is (= (s/get-project storage id1)
+           {:name "Foo project"
+            :user-id user1
+            :id id1}))
+    (is (= (s/get-project storage id2)
+           {:name "Foo project 2"
+            :user-id user1
+            :id id2}))

     (is (= 3 (count (distinct [id1 id2 id3])))
         "All ids are different")


adding the TRUSTED_RESOURCE_URI ContentKind

--- src/soy_clj/core.clj
+++ src/soy_clj/core.clj
@@ -107,6 +107,7 @@
    SanitizedContent$ContentKind/HTML :html
    SanitizedContent$ContentKind/JS :js
    SanitizedContent$ContentKind/TEXT :text
+   SanitizedContent$ContentKind/TRUSTED_RESOURCE_URI :trusted-resource-uri
    SanitizedContent$ContentKind/URI :uri})

 (def ^:private content-kind-enum


Use database credentials in config

Use database credentials in config

--- src/lcmap/aardvark/db.clj
+++ src/lcmap/aardvark/db.clj
@@ -62,7 +62,7 @@
   []
   (let [db-cfg (:database config)]
     (log/debugf "starting db with: %s" db-cfg)
-    (apply alia/cluster (select-keys db-cfg [:contact-points]))))
+    (apply alia/cluster (select-keys db-cfg [:contact-points :credentials]))))

 (defn db-cluster-stop
   "Shutdown cluster connection."


may have fixed issues with fork not getting jvm args and setting if on osx

--- src/leiningen/compile.clj
+++ src/leiningen/compile.clj
@@ -6,6 +6,7 @@
         [leiningen.deps :only [deps]])
   (:refer-clojure :exclude [compile])
   (:import org.apache.tools.ant.taskdefs.Java
+           java.lang.management.ManagementFactory
            (org.apache.tools.ant.types Environment$Variable Path)))

 (defn namespaces-to-compile
@@ -28,39 +29,52 @@
   (filter #(.endsWith (.getName %) ".jar")
           (file-seq (file (:library-path project)))))

-(def native-dir-names
-     {"Mac OS X" "macosx"
-      "Windows" "windows"
-      "Linux" "linux"
-      "SunOS" "solaris"
-      "amd64" "x86_64"
-      "x86_64" "x86_64"
-      "x86" "x86"
-      "i386" "x86"
-      "arm" "arm"
-      "sparc" "sparc"})
+(defn get-by-pattern
+  "Gets a value from map m, but uses the keys as regex patterns,
+  trying to match against k instead of doing an exact match."
+  [m k]
+  (m (first (drop-while #(nil? (re-find (re-pattern %) k))
+                        (keys m)))))

-(defn get-native-dir-name
-  "Gets a value from the native-dir-names map, but uses a regex
-  to check the prop-value for a match against keys instead of just
-  doing a map lookup. Reason for this is that e.g. windows may
-  report different names for different OS versions but will likely
-  always contain the string 'Windows'"
-  [prop-value]
-  (native-dir-names
-   (first (drop-while #(nil? (re-find (re-pattern %) prop-value))
-                      (keys native-dir-names)))))
+(def native-names
+     {"Mac OS X" :macosx
+      "Windows" :windows
+      "Linux" :linux
+      "SunOS" :solaris
+      "amd64" :x86_64
+      "x86_64" :x86_64
+      "x86" :x86
+      "i386" :x86
+      "arm" :arm
+      "sparc" :sparc})
+
+(defn get-os
+  "Returns a keyword naming the host OS."
+  []
+  (get-by-pattern native-names (System/getProperty "os.name")))
+
+(defn get-arch
+  "Returns a keyword naming the host architecture"
+  []
+  (get-by-pattern native-names (System/getProperty "os.arch")))

 (defn find-native-lib-path
   "Returns a File representing the directory where native libs for the
   current platform are located."
   [project]
-  (let [osdir (get-native-dir-name (System/getProperty "os.name"))
-        archdir (get-native-dir-name (System/getProperty "os.arch"))
+  (let [osdir (name (get-os))
+        archdir (name (get-arch))
         f (file "native" osdir archdir)]
     (if (.exists f)
       f
       nil)))
+
+(defn get-jvm-args
+  "Returns a seq of strings with the arguments sent to this jvm instance."
+  []
+  (-> (ManagementFactory/getRuntimeMXBean)
+      (.getInputArguments)
+      (seq)))

 (defn make-path
   "Constructs an ant Path object from Files and strings."
@@ -76,27 +90,31 @@
   with the java task right before executing if you need to customize any of its
   properties (classpath, library-path, etc)."
   [project form & [handler]]
-  (let [java (Java.)]
+  (let [java (Java.)
+        native-path (or (:native-path project)
+                        (find-native-lib-path project))]
     (.setProject java lancet/ant-project)
     (.addSysproperty java (doto (Environment$Variable.)
                             (.setKey "clojure.compile.path")
                             (.setValue (:compile-path project))))
-    (when-let [path (or (:native-path project)
-                        (find-native-lib-path project))]
-      (.setFork java true)
+    (when native-path
       (.addSysproperty java (doto (Environment$Variable.)
                               (.setKey "java.library.path")
                               (.setValue (cond
-                                          (= java.io.File (class path))
-                                          (.getAbsolutePath path)
-                                          (fn? path) (path)
-                                          :default path)))))
+                                          (= java.io.File (class native-path))
+                                          (.getAbsolutePath native-path)
+                                          (fn? native-path) (native-path)
+                                          :default native-path)))))
     (.setClasspath java (apply make-path
                                (:source-path project)
                                (:test-path project)
                                (:compile-path project)
                                (:resources-path project)
                                (find-lib-jars project)))
+    (when (or (= :macosx (get-os)) native-path)
+      (.setFork java true)
+      (doseq [arg (get-jvm-args)]
+        (.setValue (.createJvmarg java) arg)))
     (.setClassname java "clojure.main")
     (.setValue (.createArg java) "-e")
     (.setValue (.createArg java) (prn-str form))


avoid trying to package ws in one-file node bundle dev builds

--- src/main/shadow/build.clj
+++ src/main/shadow/build.clj
@@ -318,7 +318,11 @@
               (assoc :externs-file externs-file)

               js-options
-              (build-api/with-js-options js-options))
+              (build-api/with-js-options js-options)
+
+              (and (= :dev mode)
+                   (:keep-native-requires js-options))
+              (update-in [:js-options :keep-as-require] util/set-conj "ws"))

             ;; should do all configuration necessary
             (process-stage :configure true)


added event listener for location hash changes

--- iwaswhere-web/src/cljs/iwaswhere_web/store.cljs
+++ iwaswhere-web/src/cljs/iwaswhere_web/store.cljs
@@ -16,6 +16,7 @@
   contain information for which entries to show the map, or the edit mode."
   [put-fn]
   (let [current-query (h/query-from-search-hash)]
+    (aset js/window "onhashchange" #(put-fn [:state/get (h/query-from-search-hash)]))
     (put-fn [:state/get current-query])
     {:state (atom {:entries       []
                    :show-maps-for #{}


Convert metabase.api.card to HoneySQL :honey_pot:

--- src/metabase/api/card.clj
+++ src/metabase/api/card.clj
@@ -1,10 +1,10 @@
 (ns metabase.api.card
   (:require [clojure.data :as data]
             [compojure.core :refer [GET POST DELETE PUT]]
-            [korma.core :as k]
-            [metabase.events :as events]
+            [honeysql.helpers :as h]
             [metabase.api.common :refer :all]
-            [metabase.db :refer :all]
+            (metabase [db :as db]
+                      [events :as events])
             (metabase.models [hydrate :refer [hydrate]]
                              [card :refer [Card] :as card]
                              [card-favorite :refer [CardFavorite]]
@@ -14,15 +14,14 @@
                              [label :refer [Label]]
                              [table :refer [Table]]
                              [view-log :refer [ViewLog]])
-            [metabase.util :as u]
-            [metabase.util.korma-extensions :as kx]))
+            [metabase.util :as u]))

 (defn- hydrate-labels
   "Efficiently hydrate the `Labels` for a large collection of `Cards`."
   [cards]
-  (let [card-labels          (sel :many :fields [CardLabel :card_id :label_id])
+  (let [card-labels          (db/select [CardLabel :card_id :label_id])
         label-id->label      (when (seq card-labels)
-                               (sel :many :field->obj [Label :id] (k/where {:id [in (set (map :label_id card-labels))]})))
+                               (db/select-id->obj Label :id [:in (map :label_id card-labels)]))
         card-id->card-labels (group-by :card_id card-labels)]
     (for [card cards]
       (assoc card :labels (for [card-label (card-id->card-labels (:id card))] ; TODO - do these need to be sorted ?
@@ -31,24 +30,24 @@
 (defn- hydrate-favorites
   "Efficiently add `favorite` status for a large collection of `Cards`."
   [cards]
-  (let [favorite-card-ids (set (sel :many :field [CardFavorite :card_id], :owner_id *current-user-id*, :card_id [in (map :id cards)]))]
+  (let [favorite-card-ids (set (db/select-field :card_id CardFavorite, :owner_id *current-user-id*, :card_id [:in (map :id cards)]))]
     (for [card cards]
       (assoc card :favorite (contains? favorite-card-ids (:id card))))))

 (defn- cards:all
   "Return all `Cards`."
   []
-  (sel :many Card, :archived false, (k/order :name :ASC)))
+  (db/select Card, :archived false, {:order-by [[:name :asc]]}))

 (defn- cards:mine
   "Return all `Cards` created by current user."
   []
-  (sel :many Card, :creator_id *current-user-id*, :archived false, (k/order :name :ASC)))
+  (db/select Card, :creator_id *current-user-id*, :archived false, {:order-by [[:name :asc]]}))

 (defn- cards:fav
   "Return all `Cards` favorited by the current user."
   []
-  (->> (hydrate (sel :many [CardFavorite :card_id], :owner_id *current-user-id*)
+  (->> (hydrate (db/select [CardFavorite :card_id], :owner_id *current-user-id*)
                 :card)
        (map :card)
        (filter (complement :archived))
@@ -57,47 +56,44 @@
 (defn- cards:database
   "Return all `Cards` belonging to `Database` with DATABASE-ID."
   [database-id]
-  (sel :many Card (k/order :name :ASC), :database_id database-id, :archived false))
+  (db/select Card, :database_id database-id, :archived false, {:order-by [[:name :asc]]}))

 (defn- cards:table
   "Return all `Cards` belonging to `Table` with TABLE-ID."
   [table-id]
-  (sel :many Card (k/order :name :ASC), :table_id table-id, :archived false))
+  (db/select Card, :table_id table-id, :archived false, {:order-by [[:name :asc]]}))

 (defn- cards-with-ids
   "Return unarchived `Cards` with CARD-IDS.
    Make sure cards are returned in the same order as CARD-IDS`; `[in card-ids]` won't preserve the order."
   [card-ids]
   {:pre [(every? integer? card-ids)]}
-  (let [card-id->card (sel :many :field->obj [Card :id], :id [in card-ids], :archived false)]
+  (let [card-id->card (db/select-id->obj Card, :id [:in card-ids], :archived false)]
     (filter identity (map card-id->card card-ids))))

 (defn- cards:recent
   "Return the 10 `Cards` most recently viewed by the current user, sorted by how recently they were viewed."
   []
-  (cards-with-ids (map :model_id (k/select ViewLog
-                                   (k/aggregate (max :timestamp) :max)
-                                   (k/group :model_id)
-                                   (k/fields :model_id)
-                                   (k/where {:model (kx/literal "card"), :user_id *current-user-id*})
-                                   (k/order :max :DESC)
-                                   (k/limit 10)))))
+  (cards-with-ids (map :model_id (db/select [ViewLog :model_id [:%max.timestamp :max]]
+                                   :model   "card"
+                                   :user_id *current-user-id*
+                                   (-> (h/group :model_id)
+                                       (h/order-by [:max :desc])
+                                       (h/limit 10))))))

 (defn- cards:popular
   "All `Cards`, sorted by popularity (the total number of times they are viewed in `ViewLogs`).
    (yes, this isn't actually filtering anything, but for the sake of simplicitiy it is included amongst the filter options for the time being)."
   []
-  (cards-with-ids (map :model_id (k/select ViewLog
-                                   (k/aggregate (count (k/raw "*")) :count)
-                                   (k/group :model_id)
-                                   (k/fields :model_id)
-                                   (k/where {:model (kx/literal "card")})
-                                   (k/order :count :DESC)))))
+  (cards-with-ids (map :model_id (db/select [ViewLog :model_id [:%count.* :count]]
+                                   :model "card"
+                                   (-> (h/group :model_id)
+                                       (h/order-by [:count :desc]))))))

 (defn- cards:archived
   "`Cards` that have been archived."
   []
-  (sel :many Card, :archived true, (k/order :name :ASC)))
+  (db/select Card, :archived true, {:order-by [[:name :asc]]}))

 (def ^:private filter-option->fn
   "Functions that should be used to return cards for a given filter option. These functions are all be called with `model-id` as the sole paramenter;
@@ -143,7 +139,7 @@
     (checkp (integer? model_id) "id" (format "id is required parameter when filter mode is '%s'" (name f)))
     (case f
       :database (read-check Database model_id)
-      :table    (read-check Database (sel :one :field [Table :db_id] :id model_id))))
+      :table    (read-check Database (db/select-one-field :db_id Table, :id model_id))))
   (cards-for-filter-option f model_id label))

 (defendpoint POST "/"
@@ -152,14 +148,14 @@
   {name         [Required NonEmptyString]
    public_perms [Required PublicPerms]
    display      [Required NonEmptyString]}
-  (->> (ins Card
-            :creator_id             *current-user-id*
-            :dataset_query          dataset_query
-            :description            description
-            :display                display
-            :name                   name
-            :public_perms           public_perms
-            :visualization_settings visualization_settings)
+  (->> (db/insert! Card
+         :creator_id             *current-user-id*
+         :dataset_query          dataset_query
+         :description            description
+         :display                display
+         :name                   name
+         :public_perms           public_perms
+         :visualization_settings visualization_settings)
        (events/publish-event :card-create)))

 (defendpoint GET "/:id"
@@ -182,14 +178,14 @@
    archived               Boolean}
   (let-404 [card (Card id)]
     (write-check card)
-    (upd-non-nil-keys Card id
-                      :dataset_query          dataset_query
-                      :description            description
-                      :display                display
-                      :name                   name
-                      :public_perms           public_perms
-                      :visualization_settings visualization_settings
-                      :archived               archived)
+    (db/update-non-nil-keys! Card id
+      :dataset_query          dataset_query
+      :description            description
+      :display                display
+      :name                   name
+      :public_perms           public_perms
+      :visualization_settings visualization_settings
+      :archived               archived)
     (let [event (cond
                   ;; card was archived
                   (and archived
@@ -205,39 +201,39 @@
   "Delete a `Card`."
   [id]
   (write-check Card id)
-  (let-404 [card (sel :one Card :id id)]
+  (let-404 [card (Card id)]
     (write-check card)
-    (u/prog1 (cascade-delete Card :id id)
+    (u/prog1 (db/cascade-delete! Card id)
       (events/publish-event :card-delete (assoc card :actor_id *current-user-id*)))))

 (defendpoint GET "/:id/favorite"
   "Has current user favorited this `Card`?"
   [id]
   {:favorite (boolean (when *current-user-id*
-                        (exists? CardFavorite :card_id, id :owner_id *current-user-id*)))})
+                        (db/exists? CardFavorite :card_id id, :owner_id *current-user-id*)))})

 (defendpoint POST "/:card-id/favorite"
   "Favorite a Card."
   [card-id]
-  (ins CardFavorite :card_id card-id, :owner_id *current-user-id*))
+  (db/insert! CardFavorite :card_id card-id, :owner_id *current-user-id*))

 (defendpoint DELETE "/:card-id/favorite"
   "Unfavorite a Card."
   [card-id]
-  (let-404 [id (sel :one :id CardFavorite :card_id card-id, :owner_id *current-user-id*)]
-    (del CardFavorite :id id)))
+  (let-404 [id (db/select-one-id CardFavorite :card_id card-id, :owner_id *current-user-id*)]
+    (db/cascade-delete! CardFavorite id)))

 (defendpoint POST "/:card-id/labels"
   "Update the set of `Labels` that apply to a `Card`."
   [card-id :as {{:keys [label_ids]} :body}]
   {label_ids [Required ArrayOfIntegers]}
   (write-check Card card-id)
-  (let [[labels-to-remove labels-to-add] (data/diff (set (sel :many :field [CardLabel :label_id] :card_id card-id))
+  (let [[labels-to-remove labels-to-add] (data/diff (set (db/select-field :label_id CardLabel :card_id card-id))
                                                     (set label_ids))]
-    (doseq [label-id labels-to-remove]
-      (cascade-delete CardLabel :label_id label-id, :card_id card-id))
+    (when (seq labels-to-remove)
+      (db/cascade-delete! CardLabel :label_id [:in labels-to-remove], :card_id card-id))
     (doseq [label-id labels-to-add]
-      (ins CardLabel :label_id label-id, :card_id card-id)))
+      (db/insert! CardLabel :label_id label-id, :card_id card-id)))
   ;; TODO - Should this endpoint return something more useful instead ?
   {:status :ok})


better disaster message

better disaster message

Signed-off-by: Chris Granger <5654cde260ae99bc4d30054171b8bcd902efd19a@gmail.com>

--- lein-light-nrepl/src/lighttable/nrepl/eval.clj
+++ lein-light-nrepl/src/lighttable/nrepl/eval.clj
@@ -89,11 +89,12 @@
            :result msg
            :stack trace
            :ex true})
-        (catch Throwable e22
+        (catch Throwable e2
+          (let [msg (str (.getName (class e)) ": " (.getMessage e) (ex-info e))])
           {:meta (meta f)
            :form f
-           :result (str "ERROR: " e)
-           :stack (str "ERROR: " e)
+           :result msg
+           :stack msg
            :ex true}
           )))))


user.clj: add `set-logback-level!'.

user.clj: add `set-logback-level!'.

--- src/user.clj
+++ src/user.clj
@@ -40,3 +40,7 @@
                 :ip "0.0.0.0"
                 :port 9009
                 :working-dir "resources/public/out"))))
+
+(defn set-logback-level! [level]
+  (doto (org.slf4j.LoggerFactory/getLogger ch.qos.logback.classic.Logger/ROOT_LOGGER_NAME)
+    (.setLevel (ch.qos.logback.classic.Level/toLevel (name level)))))


:nail_care:

--- test/com/wsscode/pathom/connect/graphql_test.cljc
+++ test/com/wsscode/pathom/connect/graphql_test.cljc
@@ -20,7 +20,6 @@
                :args [{:name "owner" :defaultValue nil :type {:kind "SCALAR" :name "String"}}
                       {:name "name" :defaultValue nil :type {:kind "SCALAR" :name "String"}}]
                :type {:kind "OBJECT" :name "Repository" :ofType nil}}
-              {:name "nubankInfo" :args [] :type {:kind "OBJECT" :name "NubankInfo" :ofType nil}}
               {:name "savingsAccount"
                :args [{:name "customerId" :defaultValue nil :type {:kind "SCALAR" :name "ID"}}]
                :type {:kind "OBJECT" :name "SavingsAccount" :ofType nil}}
@@ -186,7 +185,6 @@
                               {:service/banks               {:service.types/bank {}},
                                :service/credit-card-account {:service.types/credit-card-account {}},
                                :service/customer            {:service.types/customer {}},
-                               :service/nubank-info         {:service.types/nubank-info {}},
                                :service/repository          {:service.types/repository {}},
                                :service/savings-account     {:service.types/savings-account {}},
                                :service/viewer              {:service.types/customer {}}}
@@ -208,7 +206,6 @@
                               :service/banks                        {#{} #{com.wsscode.pathom.connect.graphql-test/supposed-resolver}}
                               :service/credit-card-account          {#{} #{com.wsscode.pathom.connect.graphql-test/supposed-resolver}}
                               :service/customer                     {#{} #{com.wsscode.pathom.connect.graphql-test/supposed-resolver}}
-                              :service/nubank-info                  {#{} #{com.wsscode.pathom.connect.graphql-test/supposed-resolver}}
                               :service/repository                   {#{} #{com.wsscode.pathom.connect.graphql-test/supposed-resolver}}
                               :service/savings-account              {#{} #{com.wsscode.pathom.connect.graphql-test/supposed-resolver}}
                               :service/viewer                       {#{} #{com.wsscode.pathom.connect.graphql-test/supposed-resolver}}}
@@ -249,12 +246,12 @@

 (deftest test-index-schema
   (is (= (-> (pcg/index-schema {::pcg/prefix    prefix ::pcg/schema schema
-                             ::pcg/ident-map {"customer"          {"customerId" ["Customer" "id"]}
-                                              "creditCardAccount" {"customerId" ["Customer" "id"]}
-                                              "savingsAccount"    {"customerId" ["Customer" "id"]}
-                                              "repository"        {"owner" ["Customer" "name"]
-                                                                   "name"  ["Repository" "name"]}}
-                             ::pcg/resolver  `supposed-resolver})
+                                ::pcg/ident-map {"customer"          {"customerId" ["Customer" "id"]}
+                                                 "creditCardAccount" {"customerId" ["Customer" "id"]}
+                                                 "savingsAccount"    {"customerId" ["Customer" "id"]}
+                                                 "repository"        {"owner" ["Customer" "name"]
+                                                                      "name"  ["Repository" "name"]}}
+                                ::pcg/resolver  `supposed-resolver})
              (update-in [::pc/index-resolvers `supposed-resolver] dissoc ::pc/compute-output ::pc/resolve)
              (update-in [::pc/index-mutations 'com.wsscode.pathom.connect.graphql.service-mutations/service] dissoc ::pc/mutate))
          indexes)))


add return statement

add return statement

--- test/pjson/number_overflow_test.clj
+++ test/pjson/number_overflow_test.clj
@@ -16,13 +16,17 @@
   ([n]
     (test-num n false))
   ([n is-neg]
-   (Long/parseLong (negate-str is-neg (test-num-str n)))))
+   (try
+     (Long/parseLong (negate-str is-neg (test-num-str n)))
+     (catch NumberFormatException _ (test-num n is-neg)))))

 (defn test-double
   ([n]
     (test-double n false))
   ([n is-neg]
-   (Double/parseDouble (negate-str is-neg (str "0." (test-num-str n))))))
+   (try
+     (Double/parseDouble (negate-str is-neg (str "0." (test-num-str n))))
+     (catch NumberFormatException _ (test-double n is-neg)))))

 (defn test-biginteger
   ([n]


different types of seg

different types of seg

--- ch07-vm/translator/src/translator/code_snippet.clj
+++ ch07-vm/translator/src/translator/code_snippet.clj
@@ -1,4 +1,9 @@
-(ns translator.code-snippet)
+(ns translator.code-snippet
+  (:require [translator.env :as env]))
+
+(defn init-code
+  []
+  '("@256" "D=A" "@SP" "M=D"))

 (defn push-code
   [seg index]
@@ -12,27 +17,66 @@
       (cond
         (= seg "constant") `(~(str "@" index)
                              "D=A")
-        :else `(~(str "@" seg)
-                "D=M"
-                (str "@" index)
-                "A=D+A"
-                "D=M"))
+        (= seg "argument") `(~(str "@ARG")
+                             "D=M"
+                             (str "@" index)
+                             "A=D+A"
+                             "D=M")
+        (= seg "local")    `(~(str "@LCL")
+                             "D=M"
+                             (str "@" index)
+                             "A=D+A"
+                             "D=M")
+        (= seg "this")     `(~(str "@THIS")
+                             "D=M"
+                             (str "@" index)
+                             "A=D+A"
+                             "D=M")
+        (= seg "that")     `(~(str "@THAT")
+                             "D=M"
+                             (str "@" index)
+                             "A=D+A"
+                             "D=M")
+        (= seg "pointer")   `(~(str "@THIS")
+                              "D=A"
+                              (str "@" index)
+                              "A=D+A"
+                              "D=M")
+        (= seg "temp")      `("@R5"
+                              "D=A"
+                              (str "@" index)
+                              "A=D+A"
+                              "D=M")
+        (= seg "static")    `(~(str "@" env/cur-vm-file "." index)
+                              "D=M"))
       assignment)))

 (defn pop-code
   [seg index]
-  `(~(str "@" seg)
-    "D=M"
-    ~(str "@" index)
-    "D=D+A"
-    "@R13"
-    "M=D"
-    "@SP"
-    "AM=M-1"
-    "D=M"
-    "@R13"
-    "A=M"
-    "M=D"))
+  (let
+    [assignment `("D=M"
+                  ~(str "@" index)
+                  "D=D+A"
+                  "@R13"
+                  "M=D"
+                  "@SP"
+                  "AM=M-1"
+                  "D=M"
+                  "@R13"
+                  "A=M"
+                  "M=D")]
+      (cond
+        (= seg "local")     (concat '("@LCL")      assignment)
+        (= seg "argument")  (concat '("@ARG")      assignment)
+        (= seg "this")      (concat '("@THIS")     assignment)
+        (= seg "that")      (concat '("@THAT")     assignment)
+        (= seg "pointer")   (concat '("@POINTER")  assignment)
+        (= seg "temp")      (concat '("@TEMP")     assignment)
+        (= seg "static")    `("@SP"
+                              "AM=M-1"
+                              "D=M"
+                              ~(str "@" env/cur-vm-file "." index)
+                              "M=D"))))

 (defn unary-arith-code
   [cmd]
@@ -75,16 +119,16 @@
       "D=M"
       "A=A-1"
       "D=M-D"
-      ~(str "@FALSE" index)
+      ~(str "@FALSE-" env/cur-vm-file "." index)
       ~(str "D;" op)
       "@SP"
       "A=M-1"
       "M=-1"
-      ~(str "@CONTINUE" index)
+      ~(str "@CONTINUE-" env/cur-vm-file "." index)
       "0;JMP"
-      ~(str "(FALSE" index ")")
+      ~(str "(FALSE" env/cur-vm-file "." index ")")
       "@SP"
       "A=M-1"
       "M=0"
-      ~(str "(CONTINUE" index ")"))))
+      ~(str "(CONTINUE" env/cur-vm-file "." index ")"))))


Add 'sources' RPC call to Websocket reader.

--- src/pubsure_ws/reader.clj
+++ src/pubsure_ws/reader.clj
@@ -19,7 +19,7 @@

 ;;; Exposing a DirectoryReader as a Websocket service.

-;; channels = (atom {http.channel {"topic" async.chan}})
+;; channels = (atom {"sess-id" {"topic" async.chan}})
 (defrecord State [dirreader config channels stop-fn open])

@@ -36,13 +36,12 @@
   "Subscribe the given session to the given topic. This starts a
   go-loop, reading from a sliding-buffer channel."
   [{:keys [dirreader config channels open] :as state} sess-id topic]
-  (prn 'SUB? channels sess-id topic)
-  (when-not (get-in @channels [sess-id topic])
+  (when (and @open (not (get-in @channels [sess-id topic])))
     (let [sourcesc (async/chan (async/sliding-buffer (get config :subscribe-buffer 100)))]
       (swap! channels assoc-in [sess-id topic] sourcesc)
       (async/go-loop []
         (if-let [event (<! sourcesc)]
-          (do (wamp/emit-event! topic event sess-id)
+          (do (wamp/emit-event! topic (dissoc event :topic) sess-id)
               (recur))
           (unsubscribe state sess-id topic)))
       (api/watch-sources dirreader topic :none sourcesc))))
@@ -54,6 +53,22 @@
   [{:keys [channels] :as state} sess-id status]
   (doseq [[topic _] (get @channels sess-id)]
     (unsubscribe state sess-id topic)))
+
+
+(defn- send-sources
+  "Sends the currently known sources to the caller."
+  [{:keys [dirreader open] :as state} topic publish?]
+  (if @open
+    (let [sources (api/sources dirreader topic)]
+      (if publish?
+        (do (doseq [source sources]
+              (wamp/emit-event! topic {:event :joined, :uri source} wamp/*call-sess-id*))
+            {:result (str "Published " (count sources) " sources as events.")})
+        {:result sources}))
+    {:error {:uri topic
+             :message "Server closing"
+             :description (str "The server is closing.")
+             :kill false}}))

 (defn- make-app
@@ -73,7 +88,8 @@
                             :on-subscribe {"*" true
                                            :on-after (partial subscribe state)}
                             :on-unsubscribe (partial unsubscribe state)
-                            :on-close (partial handle-close state)})]
+                            :on-close (partial handle-close state)
+                            :on-call {"sources" (partial send-sources state)}})]
               (when (seq topic)
                 (wamp/topic-subscribe topic sess-id)
                 (subscribe state sess-id topic)))
@@ -107,4 +123,7 @@
   the server and unsubscribe every connection in the DirectoryReader."
   [{:keys [stop-fn open channels] :as state}]
   (reset! open false)
+  (doseq [[sess-id topic-chans] @channels
+          [topic _] topic-chans]
+    (unsubscribe state sess-id topic))
   (@stop-fn :timeout 100))


unmacroify end-shape

unmacroify end-shape

--- src/rosado/processing.clj
+++ src/rosado/processing.clj
@@ -648,12 +648,16 @@

 (defn end-raw [] (.endRaw *applet*))

-(defmacro end-shape
-  "Takes an optinal :close keyword as argument."
-  ([] `(.endShape *applet*))
-  ([kind]
-     (let [kind (tosymb kind)]
-       `(.endShape *applet* (int ~kind)))))
+(defn end-shape
+  "May only be called after begin-shape. When end-shape is called,
+  all of image data defined since the previous call to begin-shape is
+  written into the image buffer. The keyword :close may be passed to
+  close the shape (to connect the beginning and the end)."
+  ([] (.endShape *applet*))
+  ([mode]
+     (when-not (= :close mode)
+       (throw (Exception. (str "Unknown mode value: " mode ". Expected :close"))))
+     (.endShape *applet* CLOSE)))

 ;; $$exec


start filebeat for mesos logs at boot

start filebeat for mesos logs at boot

--- src/terraboot/cluster.clj
+++ src/terraboot/cluster.clj
@@ -21,7 +21,8 @@
                     {:name "install-confd.service" :command "start" :content (snippet "systemd/install-confd.service")}
                     {:name "confd.service" :command "start" :content (snippet "systemd/confd.service") :enable true}
                     {:name "install-awscli.service" :command "start" :content (snippet "systemd/install-awscli.service") :enable true}
-                    {:name "dcos-gen-resolvconf.timer" :command "stop" :mask true}]
+                    {:name "dcos-gen-resolvconf.timer" :command "stop" :mask true}
+                    {:name "filebeat.service" :command "start" :content (snippet "systemd/filebeat.service") :enable true}]
             :update {:reboot-strategy "off"}}
    :write_files [{:path "/etc/mesosphere/setup-packages/dcos-provider-aws--setup/pkginfo.json"
                   :content "{}\n"}


🔥 Remove unneeded snippets

🔥 Remove unneeded snippets

Why:
- because we want to remove congregation/grant!

--- src/territory_bro/api.clj
+++ src/territory_bro/api.clj
@@ -279,26 +279,4 @@
 (comment
   (db/with-db [conn {:read-only? true}]
     (->> (user/get-users conn)
-         (filter #(= "" (:name (:user/attributes %))))))
-
-  (db/with-db [conn {}]
-    (let [user-id (UUID/fromString "")
-          cong-id (UUID/fromString "")]
-      (binding [events/*current-system* "admin"]
-        (congregation/grant! conn cong-id user-id :view-congregation)
-        (congregation/grant! conn cong-id user-id :configure-congregation)
-        (congregation/grant! conn cong-id user-id :gis-access))))
-
-  (db/with-db [conn {}]
-    (binding [events/*current-system* "admin"]
-      (doseq [{:keys [cong-id user-id perms]}
-              (->> (::congregation/congregations (projections/cached-state))
-                   (mapcat (fn [[cong-id cong]]
-                             (map (fn [[user-id perms]]
-                                    {:cong-id cong-id
-                                     :user-id user-id
-                                     :perms perms})
-                                  (:congregation/user-permissions cong)))))]
-        (when (and (:view-congregation perms)
-                   (not (:configure-congregation perms)))
-          (congregation/grant! conn cong-id user-id :configure-congregation))))))
+         (filter #(= "" (:name (:user/attributes %)))))))


Make all events pure functions

Make all events pure functions

--- src/warehouse/events.cljs
+++ src/warehouse/events.cljs
@@ -2,7 +2,7 @@
   (:require
     [warehouse.util :as util]
     [warehouse.index :as index]
-    [re-frame.core :refer [reg-event-db]]))
+    [re-frame.core :refer [reg-event-db reg-cofx reg-event-fx inject-cofx]]))

 (reg-event-db
   :state-loaded
@@ -57,10 +57,16 @@
     [db [_ page]]
     (assoc db :page page)))

-(reg-event-db
+(reg-cofx
+  :search-result
+  (fn [cofx _]
+    (assoc cofx :search-result (js->clj (.search index/index (second (:event cofx)))))))
+
+(reg-event-fx
   :filter-update
+  [(inject-cofx :search-result)]
   (fn
-    [db [_ val]]
-    (assoc db :filter {:val val
-                       :search (js->clj (.search index/index val))})))
+    [cofx [_ val]]
+    {:db (assoc (:db cofx) :filter {:val val
+                                    :search (:search-result cofx)})}))


CMR-5192: Explicitly set the binary type in the test.

--- test/cmr/opendap/tests/system/app/sizing/core.clj
+++ test/cmr/opendap/tests/system/app/sizing/core.clj
@@ -25,7 +25,8 @@
                        (format (str "http://localhost:%s"
                                     "/service-bridge/size-estimate/collection/%s"
                                     "?granules=%s"
-                                    "&variables=%s")
+                                    "&variables=%s"
+                                    "&format=dods")
                                (test-system/http-port)
                                collection-id
                                granule-id


Load data-readers on dev/reload-project! [IMMUTANT-154]

This solution abuses default-data-readers. A better solution would be to
have nrepl middleware that binds *data-readers*. I may wait until we drop
swank support to implement that.

--- modules/core/src/main/clojure/immutant/dev.clj
+++ modules/core/src/main/clojure/immutant/dev.clj
@@ -18,10 +18,11 @@
 (ns immutant.dev
   "Functions useful for repl based development inside an Immutant container. They
 shouldn't be used in production."
-  (:require [immutant.registry          :as reg]
-            [immutant.utilities         :as util]
-            [immutant.runtime.util      :as runtime]
-            [clojure.java.io            :as io])
+  (:require [immutant.registry     :as reg]
+            [immutant.utilities    :as util]
+            [immutant.try          :as try]
+            [immutant.runtime.util :as runtime]
+            [clojure.java.io       :as io])
   (:import org.immutant.core.ApplicationBootstrapUtils
            org.projectodd.polyglot.core.util.ResourceLoaderUtil))

@@ -92,11 +93,28 @@
   []
   (reg/fetch :project))

+
+(defonce ^:private original-default-data-readers (if-let [d (util/try-resolve 'clojure.core/default-data-readers)] @d))
+
+(defn ^:private load-data-readers []
+  ;; The deps may have brought in data readers, so we load them.
+  ;; Since *data-readers* is already bound, altering its root binding won't help,
+  ;; so we instead muck with default-data-readers. From a functionality pov, it
+  ;; should work the same for the user.
+
+  ;; we have to do all the try-resolve muck so this will load under 1.3, but
+  ;; there's probably a better way to do it
+  (if original-default-data-readers
+    (alter-var-root (util/try-resolve 'clojure.core/default-data-readers)
+                    (fn [_]
+                      (reduce (util/try-resolve 'clojure.core/load-data-reader-file)
+                              original-default-data-readers
+                              ((util/try-resolve 'clojure.core/data-reader-urls)))))))
+
 (defn reload-project!
   "Resets the application's class loader to provide the paths and dependencies in the
 from the given project. If no project is provided, the project.clj for the appplication
-is loaded from disk. Returns the project map. This should never be used in production.
-(beta)"
+is loaded from disk. Returns the project map. This should never be used in production. (beta)"
   ([]
      (reload-project! (read-project)))
   ([project]
@@ -107,6 +125,7 @@
            keeper-resources (unmount-resources
                              (get-existing-resources))]
        (reset-classloader-resources (concat new-resources keeper-resources)))
+     (load-data-readers)
      project))

 (defn add-dependencies!


Hour is in EET for now

Hour is in EET for now

--- webapp/src/org/teamweek/webapp/endpoint/views.clj
+++ webapp/src/org/teamweek/webapp/endpoint/views.clj
@@ -64,8 +64,8 @@
            (if (map? schedule)
             (concat (for [[val checked? text] (:days schedule)]
                       [:label.pure-checkbox {:for "val"}
-                       [:input {:type "checkbox" :value val :id val :name val :checked checked?} text]])
-                    [(form/label "hr" "Hour: ")
+                       [:input {:type "checkbox" :value val :id val :name val :checked checked?} " " text]])
+                    [(form/label "hr" "Hour (EET): ")
                      (form/drop-down "hr" (map str (range 24)) (:hr schedule))

                      (form/label "schedule_cron" "Cron expression")


CHANGE-VERSION-BASE: Added extra tests to validate new base for revision-id.

--- int_test/cmr/metadata_db/int_test/concepts/save_test.clj
+++ int_test/cmr/metadata_db/int_test/concepts/save_test.clj
@@ -60,6 +60,21 @@
     (is (= 409 status))
     (is (nil? retrieved-revision))))

+(deftest save-concept-with-low-revision-test
+  (let [concept (util/collection-concept "PROV1" 1)
+        {:keys [concept-id]} (util/save-concept concept)
+        concept-with-bad-revision (assoc concept :concept-id concept-id :revision-id 0)
+        {:keys [status]} (util/save-concept concept-with-bad-revision)
+        {:keys [retrieved-concept]} (util/get-concept-by-id (:concept-id concept))
+        retrieved-revision (:revision-id retrieved-concept)]
+    (is (= 409 status))
+    (is (nil? retrieved-revision))))
+
+(deftest save-concept-with-revision-id-0
+  (let [concept-with-bad-revision (assoc (util/collection-concept "PROV1" 1) :revision-id 0)
+        {:keys [status]} (util/save-concept concept-with-bad-revision)]
+    (is (= 409 status))))
+
 (deftest save-concept-with-missing-required-parameter
   (let [concept (util/collection-concept "PROV1" 1)]
     (are [field] (let [{:keys [status errors]} (util/save-concept (dissoc concept field))]
@@ -77,6 +92,13 @@
     (let [{:keys [status revision-id]} (util/save-concept concept)]
       (is (= 201 status))
       (is (= revision-id 3)))))
+
+(deftest save-concept-after-delete-invalid-revision-id
+  (let [concept (util/collection-concept "PROV1" 1)
+        {:keys [concept-id]} (util/save-concept concept)]
+    (is (= 200 (:status (util/delete-concept concept-id))))
+    (let [{:keys [status revision-id]} (util/save-concept (assoc concept :revision-id 0))]
+      (is (= 409 status)))))

 (deftest save-granule-with-concept-id
   (let [collection (util/collection-concept "PROV1" 1)


removing code that didn't belong yet

removing code that didn't belong yet

--- spec/speclj/main_spec.clj
+++ spec/speclj/main_spec.clj
@@ -76,11 +76,6 @@
       (should= "vigilant" (:runner options))
       (should= ["documentation"] (:reporters options))))

-  (it "allows adding extra reporters when using autotest"
-    (let [options (parse-args "-a" "-f" "progress")]
-      (should= "vigilant" (:runner options))
-      (should= ["documentation" "progress"] (:reporters options))))
-
   (it "parses the --color switch"
     (should= nil (:color (parse-args "")))
     (should= "on" (:color (parse-args "--color")))


change rtn to next-rtn

change rtn to next-rtn

--- ohack/src/ohack/core.clj
+++ ohack/src/ohack/core.clj
@@ -194,7 +194,7 @@
     (let [buf-full? (= 6 (count buf))
           next-rtn (if buf-full? (conj rtn buf) rtn)]
       (if (empty? input)
-        rtn
+        next-rtn
         (let [last-val (last buf)
               cur-val (first input)]
           (recur (rest input)
@@ -208,7 +208,7 @@
                          buf-full?
                          (not= 1 (- cur-val last-val)))
                    [cur-val] ;; fresh buffer
-                   (conj buf cur-val) ;; add to buffer
-                   )
-                 (conj rtn (first input)))))))
+                   (conj buf cur-val)) ;; add to buffer
+                 next-rtn)))))
+
   )


Update dependencies.

Update dependencies.

--- profiles.clj
+++ profiles.clj
@@ -40,10 +40,15 @@
    :test-paths ["test/frontend"]
    :dependencies [[org.clojure/clojurescript "1.7.189"]
                   [funcool/cuerdas "0.7.0"]
-                  [rum "0.6.0"]
+                  [rum "0.6.0" :exclusions [sablono]]
+                  [sablono "0.5.3"]
+                  [cljsjs/react "0.14.3-0"]
+                  [cljsjs/react-dom "0.14.3-1"]
+                  [cljsjs/react-dom-server "0.14.3-0"]
+
                   [bouncer "0.3.3"]
                   [funcool/promesa "0.6.0"]
-                  [funcool/beicon "0.4.0"]
+                  [funcool/beicon "0.5.0"]
                   [cljsjs/moment "2.10.6-0"]
                   [figwheel-sidecar "0.5.0-2" :scope "test"]
                   [bidi "1.21.0"]


bump reactor dep

bump reactor dep

--- profiles.clj
+++ profiles.clj
@@ -3,7 +3,7 @@
                       [lein-cooper "1.2.2" :exclusions [org.clojure/clojure]]]
        :dependencies [[figwheel-sidecar "0.5.8"]
                       [starcity/mailer "0.1.0"]
-                      [starcity/reactor "0.1.2"]
+                      [starcity/reactor "0.1.3"]
                       [binaryage/devtools "0.9.2"]]
        :repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}


[scamp] generalize docstring of "jitter-int"

--- modules/scamp/src/scamp/core.clj
+++ modules/scamp/src/scamp/core.clj
@@ -65,9 +65,9 @@
 (def ^:dynamic *milli-time* deref)

 (defn jitter-int
-  "Given a 'base-duration in some numerical unit of time, and an
+  "Given a 'base-duration in some numerical unit and an
   'agitation-distance the jitter can cover from that 'base-duration,
-  compute a jittered duration and return it as an integer."
+  compute a jittered value and return it as an integer."
   [base-duration agitation-distance]
   (let [agitation (- (*rand* agitation-distance) (/ agitation-distance 2))]
     (int (+ base-duration agitation))))


[scamp] add comment demonstrating use of binding on *rand*

--- modules/scamp/src/scamp/core.clj
+++ modules/scamp/src/scamp/core.clj
@@ -567,4 +567,12 @@
 (comment
   [1] "Peer-to-Peer Membership Management for Gossip-Based Protocols"

+  (binding [scamp.core/*rand* testing-rand*]
+    (reset-rand-state!)
+    (let [world (-> (world-with-subs 243)
+                    core/do-all-comms
+                    (core/instruct-node-to-unsubscribe "node-id9")
+                    core/do-all-comms)]
+      (clojure.pprint/pprint world)))
+
   )


make fn public

make fn public

--- src/neuseg/db.clj
+++ src/neuseg/db.clj
@@ -84,12 +84,12 @@
         merged (concat head coll tail)]
     (partition window 1 merged)))

-(defn- mdot [vecs]
+(defn mdot [vecs]
   (let [mid 4
         mid-vec (nth vecs mid)]
     (map (partial dot mid-vec) (concat (take mid vecs) (drop (inc mid) vecs)))))

-(defn- zip [& colls]
+(defn zip [& colls]
   (map flatten (partition (count colls) (apply interleave colls))))

 (defn vectorize [text]


compute-z-position bug

compute-z-position bug

git-svn-id: 03a8048b5ee8463be5048a3801110fb50f378627@6251 d0ab736e-dc22-4aeb-8dc9-08def0aa14fd

--- acqEngine/src/org/micromanager/acq_engine.clj
+++ acqEngine/src/org/micromanager/acq_engine.clj
@@ -261,7 +261,7 @@
   (if-let [z-drive (:z-drive event)]
     (+ (or (get-in event [:channel :z-offset]) 0)
        (or (:slice event) 0)
-       (if (and (:slice event) (not :relative-z event))
+       (if (and (:slice event) (not (:relative-z event)))
 	 0
          (or (get-z-position (:position event) z-drive)
              (@state :reference-z-position))))))


Sketches of knowledge functions

Sketches of knowledge functions

--- src/skat/game.clj
+++ src/skat/game.clj
@@ -17,8 +17,7 @@

 ;;; Knowledge

-(defrecord Knowledge [cards-played cards-owned])
-(defn add-knowledge [knowledge turn c1 c2 c3] knowledge); TODO: calc knowledge
+(defrecord PlayerKnowledge [self cards-played cards-owned])

 ;;; Players

@@ -27,20 +26,44 @@
 ;;; Turn

 (defrecord Turn [players knowledge order])
-(defn next-players [order winner]
+
+;;; Knowledge update
+
+(defn update-cards [players-cards fun]
+  (let [players (keys players-cards)]
+    (zipmap players (map fun players))))
+
+(defn update-cards-played [cards-played played-now]
+  (letfn [(add-card [player] (conj (cards-played player) (played-now player)))]
+    (update-cards cards-played add-card)))
+
+(defn update-cards-owned [cards-owned played-now]
+  (letfn [(used-now? [player card] (= (played-now player) card))
+          (remove-card [player] (remove (partial used-now? player) (cards-owned player)))]
+    (update-cards cards-owned remove-card)))
+
+(defn update-knowledge [knowledge turn played-now]
+  (-> knowledge
+    (update-in [1 :cards-played] update-cards-played played-now)
+    (update-in [1 :cards-owned] update-cards-owned played-now)))
+
+;;; Turn update
+
+(defn next-turn-order [order winner]
   (let [{:keys [p1 p2 p3]} order]
     (if (= p1 winner) order
       (if (= p2 winner) { :p1 p2 :p2 p3 :p3 p1 }
         (if (= p3 winner) { :p1 p3 :p2 p1 :p3 p2 })))))
 (defn next-turn [turn winner]
   (let [{:keys [order]} turn]
-    (assoc turn :order (next-players order winner))))
+    (assoc turn :order (next-turn-order order winner))))
 (defn play-turn [config {:keys [turn knowledge]}]
   (let [{:keys [players order]} turn
         {:keys [p1 p2 p3]} order
         c1 ((:play-1st-card-fun p1) config (knowledge p1))
         c2 ((:play-2nd-card-fun p2) config (knowledge p2) c1)
         c3 ((:play-3rd-card-fun p3) config (knowledge p3) c1 c2)
+        played-now { :p1 c1 :p2 c2 :p3 c3 }
         winner ((:who-won? config) c1 c2 c3)]
     { :turn (next-turn turn winner)
-      :knowledge (add-knowledge knowledge turn c1 c2 c3)}))
+      :knowledge (update-knowledge knowledge turn played-now)}))


artwork-data is unprintable

artwork-data is unprintable

* need to figure out a better way of doing this

--- src/sledge/db.clj
+++ src/sledge/db.clj
@@ -119,7 +119,7 @@
 (defn write-log [name-map filename]
   (with-open [f (io/writer filename)]
     (binding [*out* f]
-      (dorun (map prn name-map)))))
+      (dorun (map (fn [[k v]] (prn [k (dissoc v :artwork-data)])) name-map)))))

 (defn entries-where [index query]
   (let [data (:data index)]


Conditionally place new number depending on if there is space.

--- src/tfe/core.cljs
+++ src/tfe/core.cljs
@@ -2,7 +2,7 @@

 (def app-state (atom {:state :playing
                       :board [[nil nil nil nil]
-                              [2 nil nil   2]
+                              [  2   2   2   2]
                               [nil nil nil   2]
                               [nil nil nil nil]]}))

@@ -13,10 +13,13 @@
   (take 4 (concat row (repeat nil))))

 (defn collapse [row]
-  row)
+  (cond
+    (empty? row) []
+    (= (first row) (-> row rest first)) (cons (* 2 (first row)) (collapse (-> row rest rest)))
+    :else (cons (first row) (collapse (rest row)))))

 (defn pack [board]
-  (map #(-> % strip collapse pad) board))
+  (vec (map #(-> % strip collapse pad vec) board)))

 (defn rotate [board]
   (apply map vector board))
@@ -24,19 +27,34 @@
 (defn flip [board]
   (map (comp vec reverse) board))

+(defn coordinates []
+  (for [x (range 4) y (range 4)] [x y]))
+
+(defn place [board]
+  (let [index (first (shuffle (filter #(not (get-in board %)) (coordinates))))]
+    (print index)
+    (assoc-in board index 2)))
+
+(defn update [board]
+  (print board)
+  (let [new-board (pack board)]
+    (cond
+      (= board new-board) new-board
+      :else (place new-board))))
+
 (defmulti next-board (fn [d b] d))

 (defmethod next-board :left [_ board]
-  (pack board))
+  (-> board update))

 (defmethod next-board :right [_ board]
-  (-> board flip pack flip))
+  (-> board flip update flip))

 (defmethod next-board :up [_ board]
-  (-> board rotate pack rotate))
+  (-> board rotate update rotate))

 (defmethod next-board :down [_ board]
-  (-> board rotate flip pack flip rotate))
+  (-> board rotate flip update flip rotate))

 (defmethod next-board nil [_ board]
   board)


Translate plus operator

Translate plus operator

--- extended/compiler/compiler.clj
+++ extended/compiler/compiler.clj
@@ -12,6 +12,8 @@
 (def vertical-bar () (list 32 124 32))
 (def colon () (list 32 58 32))
 (def star () (list 32 42 32))
+(def plus () (list 43))
+(def int32-plus () (list 73 110 116 51 50 46 97 100 100))

 (def join (list) (string-join Empty list))

@@ -28,6 +30,11 @@
      (join (list (list 112 97 114 115 101 32 101 114 114 111 114 32)
                  (error-to-string error))))

+(def translate-builtins (name)
+     (match (string-equal? name (plus))
+            True  (int32-plus)
+            False name))
+
 (def translate-expression (expression)
      (match expression
             (Lambda arguments expression _)
@@ -42,7 +49,7 @@
                 (wrap-in-brackets (string-concat (list 73 110 116 51 50 46 111 102 95 105 110 116 32)
                                                  (wrap-in-brackets (string-from-int32 integer))))
             (Identifier name _)
-                name
+                (translate-builtins name)
             _
                 (compile-error)))


Added functionalities of FcaFlint

Added functionalities of FcaFlint

Signed-off-by: Daniel Borchmann <25857343a15bf1edafebc2912e82ecf775c585c1@mailbox.tu-dresden.de>

--- conexp/fca/contexts.clj
+++ conexp/fca/contexts.clj
@@ -6,7 +6,7 @@
    :constructors { [ clojure.lang.PersistentHashSet clojure.lang.PersistentHashSet clojure.lang.IFn ] [] }
    :state state)
   (:use [clojure.contrib.str-utils :only (str-join)]
-	[clojure.set :only (intersection)]
+	clojure.set
 	conexp.base
 	conexp.util))

@@ -30,7 +30,7 @@
 	  max-obj (reduce #(max %1 (count (str %2))) 0 objects)]
       (with-str-out
 	"\n"
-	(ensure-length "" max-obj " ") " |" (for [att attributes] [att " "]) "\n"
+	(ensure-length "" max-obj " ") " |" (for [att attributes] [(str att) " "]) "\n"
 	(ensure-length "" max-obj "-") "-+" (for [att attributes]
 					      (ensure-length "" (inc (count (str att))) "-")) "\n"
 	(for [obj objects]
@@ -155,3 +155,79 @@
 (defn concepts [ctx]
   (set-of [ objs (object-derivation ctx objs) ]
 	  [ objs (context-extends ctx) ]))
+
+;; FcaFlint functionalities
+
+(defn context-union [ctx1 ctx2]
+  (let [new-objs (union (set-of [g_1 1] [g_1 (objects ctx1)])
+			(set-of [g_2 2] [g_2 (objects ctx2)]))
+	new-atts (union (set-of [m_1 1] [m_1 (attributes ctx1)])
+			(set-of [m_2 2] [m_2 (attributes ctx2)]))
+	new-inz  (set-of [[g idx-g] [m idx-m]]
+			 [[g idx-g] new-objs
+			  [m idx-m] new-atts
+			  :when (or ((incidence ctx1) [g m])
+				    ((incidence ctx2) [g m]))])]
+    (make-context new-objs new-atts new-inz)))
+
+(defn context-intersection [ctx1 ctx2]
+  (make-context (intersection (objects ctx1) (objects ctx2))
+		(intersection (attributes ctx1) (attributes ctx2))
+		(intersection (incidence ctx1) (incidence ctx2))))
+
+(defn context-composition [ctx-1 ctx-2]
+  (make-context (objects ctx-1)
+		(attributes ctx-2)
+		(set-of [g m]
+			[g (objects ctx-1)
+			 m (attributes ctx-2)
+			 :when (exists [x (intersection (attributes ctx-1)
+							(objects ctx-2))]
+				       (and ((incidence ctx-1) [g x])
+					    ((incidence ctx-2) [x m])))])))
+
+(defn context-apposition [ctx-1 ctx-2]
+  (if (not= (objects ctx-1) (objects ctx-2))
+    (throw
+     (IllegalArgumentException. (str "Cannot do context apposition, since object sets are not equal."))))
+  (let [new-atts (union (set-of [m 1] [m (attributes ctx-1)])
+			(set-of [m 2] [m (attributes ctx-2)]))
+	new-inz  (union (incidence ctx-1) (incidence ctx-2))]
+    (make-context (objects ctx-1) new-atts new-inz)))
+
+(defn context-subposition [ctx-1 ctx-2]
+  (if (not= (attributes ctx-1) (attributes ctx-2))
+    (throw
+     (IllegalArgumentException. (str "Cannot do context subposition, since attribute sets are not equal."))))
+  (let [new-objs (union (set-of [g 1] [g (objects ctx-1)])
+			(set-of [g 2] [g (objects ctx-2)]))
+	new-inz  (union (incidence ctx-1) (incidence ctx-2))]
+    (make-context new-objs (attributes ctx-1) new-inz)))
+
+(defn transitive-closure
+  ([set-of-pairs]
+     (transitively-close-relation set-of-pairs set-of-pairs #{}))
+  ([set-of-pairs new old]
+     (if (= new old)
+       new
+       (recur set-of-pairs (union new
+				  (set-of [x y]
+					  [[x z_1] (difference new old)
+					   [z_2 y] set-of-pairs
+					   :when (= z_1 z_2)]))
+	      new))))
+
+(defn context-transitive-closure [ctx]
+  (make-context (objects ctx) (attributes ctx) (transitive-closure (incidence ctx))))
+
+(defn one-context [base-set]
+  (make-context base-set base-set (fn [_ _] true)))
+
+(defn null-context [base-set]
+  (make-context base-set base-set (fn [_ _] false)))
+
+(defn diag-context [base-set]
+  (make-context base-set base-set =))
+
+(defn adiag-context [base-set]
+  (make-context base-set base-set not=))


Add fn get-download-modes.

Add fn get-download-modes.

--- src/beebster_clj/core.clj
+++ src/beebster_clj/core.clj
@@ -53,6 +53,18 @@
   [s]
   (remove #(= "" %) (map #(re-find #"^[0-9]*" %) s)))

+(defn get-download-modes
+  "build list of possible download-modes for a given index."
+  [lst]
+  (let [modes (first (filter #(re-find #"modes.*" %) lst))]
+    (remove nil? (list (re-find #"flashhigh" modes)
+                       (re-find #"flashvhigh" modes)
+                       (re-find #"flashhd" modes)
+                       (re-find #"flashlow" modes)))))
+
+
+
+
 (defn old-recordings?
   "Does get-iplayer complain about recorded programmes > 30 days?"
   [lst]


Hook up annealing to showgraph. Click blank network to start! #48

--- samples/twitterbuzz/src/twitterbuzz/showgraph.cljs
+++ samples/twitterbuzz/src/twitterbuzz/showgraph.cljs
@@ -1,11 +1,18 @@
 (ns twitterbuzz.showgraph
   (:require [twitterbuzz.core :as buzz]
+            [twitterbuzz.anneal :as ann]
+            [twitterbuzz.layout :as layout]
             [goog.dom :as dom]
+            [goog.events :as events]
+            [goog.fx.Animation :as anim]
             [goog.graphics :as graphics]))

 ; Drawing configuration
-(def avatar-size 0.15) ; used for both x and y dimensions of avatars
+(def avatar-size 0.07) ; used for both x and y dimensions of avatars
 (def edge-widths [0 0.001 0.005 0.010 0.020]) ; More mentions == thicker edges
+
+; BAD HACK: don't change globals like this -- find a better way:
+(set! anim/TIMEOUT 500)

 (def edge-strokes
   (vec (map #(graphics/Stroke. % "#009") edge-widths)))
@@ -43,8 +50,25 @@
   {"jboner" {:x 0.3 :y 0.8} "sbtourist" {:x 0.3 :y 0.2} "djspiewak" {:x 0.5 :y 0.5}}
   {"jboner" {:x 0.2 :y 0.7} "sbtourist" {:x 0.4 :y 0.1} "djspiewak" {:x 0.7 :y 0.4}})))

-(defn update-graph [tweets]
-  (draw-graph {:locs (peek @test-graph), :mentions test-users})
-  (swap! test-graph pop))
+(def animation (atom nil))

-(buzz/register update-graph)
+;(set! cljs.core/string-print (fn [x] (js* "console.log(~{x})")))
+
+(set! (.cycle animation)
+  (fn [t]
+    (draw-graph (:best (first @animation)))
+    (swap! animation rest)))
+
+(events/listen
+  (dom/getElement "network")
+  (array events/EventType.CLICK)
+  (fn [_]
+    (reset! animation
+      (ann/anneal
+        layout/score
+        (ann/linear-cooling 1000)
+        layout/permute-move
+        ann/standard-prob
+        (layout/init-state test-users)))
+    (anim/registerAnimation animation)))
+


Build word-chain from file

Build word-chain from file


Clean up ns form

Clean up ns form

--- src-cljs/frontend/components/project_settings.cljs
+++ src-cljs/frontend/components/project_settings.cljs
@@ -1,7 +1,6 @@
 (ns frontend.components.project-settings
   (:require [cljs-time.core :as time]
             [cljs-time.format :as time-format]
-            [cljs.core.async :as async :refer [<! >! alts! chan close! sliding-buffer]]
             [clojure.string :as string]
             [frontend.async :refer [raise!]]
             [frontend.components.account :as account]
@@ -13,14 +12,12 @@
             [frontend.components.project.common :as project-common]
             [frontend.config :as config]
             [frontend.datetime :as datetime]
-            [frontend.models.build :as build-model]
             [frontend.models.feature :as feature]
             [frontend.models.plan :as plan-model]
             [frontend.models.project :as project-model]
             [frontend.models.user :as user-model]
             [frontend.routes :as routes]
             [frontend.state :as state]
-            [frontend.stefon :as stefon]
             [frontend.utils :as utils :include-macros true]
             [frontend.utils.bitbucket :as bb-utils]
             [frontend.utils.github :as gh-utils]
@@ -29,8 +26,7 @@
             [frontend.utils.vcs-url :as vcs-url]
             [goog.crypt.base64 :as base64]
             [goog.string :as gstring]
-            [om.core :as om :include-macros true]
-            [om.dom :as dom :include-macros true])
+            [om.core :as om :include-macros true])
   (:require-macros [frontend.utils :refer [html]]))

 (defn branch-names [project-data]


These functions are no longer used

These functions are no longer used

--- src-cljs/frontend/experimental/workflow_spike.cljs
+++ src-cljs/frontend/experimental/workflow_spike.cljs
@@ -1,18 +1,4 @@
 (ns frontend.experimental.workflow-spike)
-
-(defn status-class [{:keys [status] :as workflow}]
-  (case status
-    "fail" "fail"
-    "success" "pass"
-    "running" "busy"
-    "canceled" "stop"))
-
-(defn status-icon [{:keys [status] :as workflow}]
-  (case (status-class workflow)
-    "fail" "Status-Failed"
-    "stop" "Status-Canceled"
-    "pass" "Status-Passed"
-    "busy" "Status-Running"))

 (defn build-status
   "Returns a build status that reflects the status of the workflow. This is a


[#2489] Adapt to PR review

[#2489] Adapt to PR review

--- backend/src/akvo/lumen/component/keycloak.clj
+++ backend/src/akvo/lumen/component/keycloak.clj
@@ -414,11 +414,13 @@
 (defn- lookup-paths [req-opts api-root user-id jwt-paths-cache paths-cache-seconds iat]
   (if-let [paths (get-paths jwt-paths-cache user-id iat)]
     paths
-    (when-let [paths (->>
-                      (user-groups (merge http-client-req-defaults @req-opts) api-root user-id)
-                      (reduce (fn [paths {:strs [path]}]
-                                (conj paths (subs path 12)))
-                              #{}))]
+    (when-let [paths (and
+                      (:headers @req-opts)
+                      (->>
+                       (user-groups (merge http-client-req-defaults @req-opts) api-root user-id)
+                       (reduce (fn [paths {:strs [path]}]
+                                 (conj paths (subs path 12)))
+                               #{})))]
       (-> jwt-paths-cache
           (swap! assoc user-id (with-meta paths {:exp (t/plus (tc/from-date iat) (t/seconds paths-cache-seconds))}))
           (get user-id)))))
@@ -428,11 +430,13 @@
   [req-opts api-root user-id-cache email]
   (if-let [user-id (get-user-id user-id-cache email)]
     user-id
-    (when-let [user-id (-> (http.client/get* (format "%s/users/?email=%s" api-root email) (merge http-client-req-defaults
-                                                                                @req-opts))
-                           :body
-                           json/decode
-                           (active-user email))]
+    (when-let [user-id (and
+                        (:headers @req-opts)
+                        (-> (http.client/get* (format "%s/users/?email=%s" api-root email) (merge http-client-req-defaults
+                                                                                @req-opts))
+                            :body
+                            json/decode
+                            (active-user email)))]
       (-> user-id-cache
           (swap! assoc email user-id)
           (get email)))))


Refactor

Refactor

--- backend/src/akvo/lumen/component/keycloak.clj
+++ backend/src/akvo/lumen/component/keycloak.clj
@@ -259,14 +259,15 @@
 (defn- lookup-user-id
   "Lookup email -> Keycloak user-id, via cached Keycloak API."
   [req-opts api-root user-id-cache email]
-  (if-some [user-id (get-user-id user-id-cache email)]
+  (if-let [user-id (get-user-id user-id-cache email)]
     user-id
-    (let [url (format "%s/users/?email=%s" api-root email)]
-      (let [users (-> (client/get url req-opts) :body json/decode)]
-        (when-some [user-id (active-user users email)]
-          (-> user-id-cache
-              (swap! assoc email user-id)
-              (get email)))))))
+    (when-let [user-id (-> (client/get (format "%s/users/?email=%s" api-root email) req-opts)
+                           :body
+                           json/decode
+                           (active-user email))]
+      (-> user-id-cache
+          (swap! assoc email user-id)
+          (get email)))))

 (defn- allowed-paths
   "Provided an email address from the authentication process dig out the
@@ -282,7 +283,7 @@
      (when-let [headers (request-headers keycloak bare-req-opts)]
        (let [req-opts (assoc bare-req-opts :headers headers :connection-manager connection-manager)]
          (when-let [user-id (lookup-user-id req-opts api-root user-id-cache email)]
-           (->> (client/get (format "%s/users/%s/groups" api-root user-id) req-opts )
+           (->> (client/get (format "%s/users/%s/groups" api-root user-id) req-opts)
                 :body
                 json/decode
                 (reduce (fn [paths {:strs [path]}]


extracting the form params in multipart requests

--- src/bitfondue/handler.clj
+++ src/bitfondue/handler.clj
@@ -6,6 +6,7 @@
             [ring.util.response :refer [response redirect content-type status]]
             (ring.middleware [session :refer [wrap-session]]
                              [params :refer [wrap-params]]
+                             [multipart-params :refer [wrap-multipart-params]]
                              [json :refer [wrap-json-response wrap-json-body]])
             [hiccup.core :as h]
             [clj-time.core :as time]
@@ -65,7 +66,9 @@
              (wrap-authorization auth-backend)
              (wrap-authentication auth-backend)
              (wrap-json-response {:pretty false})
-             (wrap-json-body {:keywords? true :bigdecimals? true})))
+             (wrap-json-body {:keywords? true :bigdecimals? true})
+             (wrap-params)
+             (wrap-multipart-params)))

 (defn -main [port]
   (run-jetty app {:port (read-string port) :join? false}))


fix the variable name for the token-secret

--- src/bitfondue/handler.clj
+++ src/bitfondue/handler.clj
@@ -43,7 +43,7 @@
     (if valid?
       (let [claims {:user (keyword username)
                     :exp (time/plus (time/now) (time/seconds 3600))}
-            token (jwe/encrypt claims secret {:alg :a256kw :enc :a128gcm})]
+            token (jwe/encrypt claims config/token-secret {:alg :a256kw :enc :a128gcm})]
         (ok {:token token}))
       (bad-request {:message "wrong auth data"}))))

@@ -53,7 +53,7 @@
   (POST "/login" [] login)
   (route/resources "/"))

-(def auth-backend (jwe-backend {:secret config/secret
+(def auth-backend (jwe-backend {:secret config/token-secret
                                 :options {:alg :a256kw :enc :a128gcm}}))

 (def app (-> app-routes


add austin for cljsrepl, requires later clojurescript

--- pedestal-app/project.clj
+++ pedestal-app/project.clj
@@ -1,13 +1,14 @@
 (defproject semtag-web "0.0.1-SNAPSHOT"
   :description "FIXME: write description"
   :dependencies [[org.clojure/clojure "1.5.1"]
-                 [org.clojure/clojurescript "0.0-1586"]
+                 [org.clojure/clojurescript "0.0-1847"]
                  [domina "1.0.1"]
                  [crate "0.2.1"]
                  [ch.qos.logback/logback-classic "1.0.7" :exclusions [org.slf4j/slf4j-api]]
                  [io.pedestal/pedestal.app "0.1.10"]
                  [io.pedestal/pedestal.app-tools "0.1.10"]]
-  :profiles {:dev {:source-paths ["dev"]}}
+  :profiles {:dev {:source-paths ["dev"]
+                   :plugins [[com.cemerick/austin "0.1.0"]]}}
   :min-lein-version "2.0.0"
   :source-paths ["app/src" "app/templates"]
   :resource-paths ["config"]


cleanup some default parameters, most of them are set from (search)

--- src/bzzz/index_search.clj
+++ src/bzzz/index_search.clj
@@ -244,15 +244,7 @@

 (defn shard-search
   [& {:keys [^IndexSearcher searcher ^DirectoryTaxonomyReader taxo-reader query analyzer
-             page size explain highlight facets fields facet-config sort spatial-filter]
-      :or {page 0
-           size default-size
-           explain false
-           analyzer nil
-           facets nil
-           fields nil
-           sort nil
-           spatial-filter nil}}]
+             page size explain highlight facets fields facet-config sort spatial-filter]}]
   (let [ms-start (time-ms)
         analyzer ^Analyzer (parse-analyzer analyzer)
         query ^Query (parse-query query analyzer)


Added :trust-all? option to run-jetty

Added :trust-all? option to run-jetty

--- ring-jetty-adapter/src/ring/adapter/jetty.clj
+++ ring-jetty-adapter/src/ring/adapter/jetty.clj
@@ -26,6 +26,7 @@
   (let [context (SslContextFactory.)]
     (.setKeyStorePath context (options :keystore))
     (.setKeyStorePassword context (options :key-password))
+    (.setTrustAll context (boolean (options :trust-all?)))
     (when (options :truststore)
       (.setTruststore context (options :truststore)))
     (when (options :trust-password)
@@ -71,8 +72,9 @@
   :truststore   - a truststore to use for SSL connections
   :trust-password - the password to the truststore
   :max-threads  - the maximum number of threads to use (default 250)
-  :client-auth  - SSL client certificate authenticate, may be set to :need,
-                  :want or :none (defaults to :none)"
+  :client-auth  - SSL client certificate authentication; may be set to :need,
+                  :want or :none (defaults to :none)
+  :trust-all?   - set to true to accept all client certificates"
   [handler options]
   (let [^Server s (create-server (dissoc options :configurator))]
     (when-let [configurator (:configurator options)]


(maint) delete obsolete comment

(maint) delete obsolete comment

--- src/clj/puppetlabs/services/master/master_core.clj
+++ src/clj/puppetlabs/services/master/master_core.clj
@@ -21,8 +21,6 @@
    CA service."
   [request-handler]
   (compojure/routes
-    ; TODO there are a bunch more that we'll need to add here
-    ; https://tickets.puppetlabs.com/browse/PE-3977
     (compojure/GET "/node/*" request
                    (request-handler request))
     (compojure/GET "/facts/*" request


only show thumbnails when entry not active

--- iwaswhere-web/src/cljs/iwaswhere_web/ui/entry.cljs
+++ iwaswhere-web/src/cljs/iwaswhere_web/ui/entry.cljs
@@ -261,9 +261,10 @@
         [:div info])
       [:div
        (when (seq (:linked-entries-list entry))
-         (let [entry-active? (= (:active cfg) (:timestamp entry))
+         (let [ts (:timestamp entry)
+               entry-active? (contains? (set (vals (:active cfg))) ts)
                set-active-fn #(put-fn [:cmd/toggle-active
-                                       {:timestamp (:timestamp entry)
+                                       {:timestamp ts
                                         :query-id (:query-id local-cfg)}])]
            [:span.link-btn {:on-click set-active-fn
                             :class    (when entry-active? "active")}
@@ -292,16 +293,18 @@
   "Renders thumbnails of photos in linked entries. Respects private entries."
   [entry entries-map cfg put-fn]
   (let [ts (:timestamp entry)
+        entry-active? (contains? (set (vals (:active cfg))) (:timestamp entry))
         linked-entries-set (set (:linked-entries-list entry))
         get-or-retrieve (u/find-missing-entry entries-map put-fn)
         with-imgs (filter :img-file (map get-or-retrieve linked-entries-set))
         filtered (if (:show-pvt cfg)
                    with-imgs
                    (filter (u/pvt-filter cfg) with-imgs))]
-    [:div.thumbnails
-     (for [img-entry filtered]
-       ^{:key (str "thumbnail" ts (:img-file img-entry))}
-       [:div [m/image-view img-entry "?width=300"]])]))
+    (when-not entry-active?
+      [:div.thumbnails
+       (for [img-entry filtered]
+         ^{:key (str "thumbnail" ts (:img-file img-entry))}
+         [:div [m/image-view img-entry "?width=300"]])])))

 (defn entry-with-comments
   "Renders individual journal entry. Interaction with application state happens


use-macros with :only support

use-macros with :only support

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -766,17 +766,27 @@
                       (into s xs))
                     s))
                 #{} args)
-        {uses :use requires :require requires-macros :require-macros :as params}
+        {uses :use requires :require uses-macros :use-macros requires-macros :require-macros :as params}
         (reduce (fn [m [k & libs]]
+                  (assert (#{:use :use-macros :require :require-macros} k)
+                          "Only :refer-clojure, :require, :require-macros, :use and :use-macros libspecs supported")
                   (assoc m k (into {}
                                    (mapcat (fn [[lib kw expr]]
-                                          (assert (and expr (or (= :as kw)
-                                                                (= :only kw)))
-                                                  "Only (:require [lib.ns :as alias]*) and (:use [lib.ns :only [names]]*) form supported")
-                                          (if (= :only kw)
-                                            (map vector expr (repeat lib))
-                                            [[expr lib]]))
-                                        libs))))
+                                             (case k
+                                               (:require :require-macros)
+                                               (do (assert (and expr (= :as kw))
+                                                           "Only (:require [lib.ns :as alias]*) form of :require / :require-macros is supported")
+                                                   [[expr lib]])
+                                               (:use :use-macros)
+                                               (do (assert (and expr (= :only kw))
+                                                           "Only (:use [lib.ns :only [names]]*) form of :use / :use-macros is supported")
+                                                   (if (= :use k)
+                                                     (map vector expr (repeat lib))
+                                                     (do (require lib)
+                                                         (->> lib ns-publics
+                                                              (filter (comp :macro meta val))
+                                                              (filter (comp (set expr) key))))))))
+                                           libs))))
                 {} (remove (fn [[r]] (= r :refer-clojure)) args))]
     (set! *cljs-ns* name)
     (require 'cljs.core)
@@ -787,12 +797,13 @@
                            (assoc-in [name :excludes] excludes)
                            (assoc-in [name :uses] uses)
                            (assoc-in [name :requires] requires)
+                           (assoc-in [name :uses-macros] uses-macros)
                            (assoc-in [name :requires-macros]
                                      (into {} (map (fn [[alias nsym]]
                                                      [alias (find-ns nsym)])
                                                    requires-macros)))))
     {:env env :op :ns :name name :uses uses :requires requires
-     :requires-macros requires-macros :excludes excludes}))
+     :uses-macros uses-macros :requires-macros requires-macros :excludes excludes}))

 (defmethod parse 'deftype*
   [_ env [_ tsym fields] _]
@@ -865,7 +876,9 @@
                            :else
                            (-> env :ns :requires-macros (get (symbol nstr))))]
               (.findInternedVar ^clojure.lang.Namespace ns (symbol (name sym))))
-            (.findInternedVar ^clojure.lang.Namespace (find-ns 'cljs.core) sym)))]
+            (if-let [mvar (-> env :ns :uses-macros sym)]
+              mvar
+              (.findInternedVar ^clojure.lang.Namespace (find-ns 'cljs.core) sym))))]
     (when (and mvar (.isMacro ^clojure.lang.Var mvar))
       @mvar)))


returns empty string if no version can be found

--- src/clj/reply/version.clj
+++ src/clj/reply/version.clj
@@ -13,9 +13,11 @@

 (def ^:dynamic *reply-pom-properties* "META-INF/maven/reply/reply/pom.properties")

-(defn get-version []
+(defn get-version
+  "attempts to get reply version from system properties or pom properties file, returns the empty string if neither works"
+  []
   (or (System/getProperty "reply.version")
       (-> *reply-pom-properties*
           map-from-property-filepath
           (get "version"))
-      "version unknown"))+      ""))


Function print-configuration

Function print-configuration

--- src/clj_mrazik/config.clj
+++ src/clj_mrazik/config.clj
@@ -11,6 +11,8 @@
 ;

 (ns clj-mrazik.config)
+
+(require '[clojure.pprint :as pprint])

 (require '[clojure-ini.core :as clojure-ini])

@@ -29,9 +31,14 @@
     "Load configuration from the provided INI file."
     [ini-file-name]
     (-> (clojure-ini/read-ini ini-file-name :keywordize? true)
-        (update-in [:server :port] parse-int)
+        (update-in [:server :port]   parse-int)
         (update-in [:bot :start]     parse-hh-mm-time-as-minutes)
         (update-in [:bot :end]       parse-hh-mm-time-as-minutes)
         (update-in [:bot :frequency] parse-hh-mm-time-as-minutes)
         (update-in [:bot :duration]  parse-hh-mm-time-as-minutes)))

+(defn print-configuration
+    "Print actual configuration to the output."
+    [configuration]
+    (pprint/pprint configuration))
+


CLJS-854: Fix for IE8 cljs.reader to read integers correctly

This change is made because IE8 always returns 0 when cljs.reader reads an integer.

This is caused because the matching pattern in most browsers returns nil for unmatched patterns but IE8 returns "" instead of nil

--- src/cljs/cljs/reader.cljs
+++ src/cljs/cljs/reader.cljs
@@ -112,7 +112,8 @@
 (defn- match-int
   [s]
   (let [groups (re-matches* int-pattern s)
-        zero (aget groups 2)]
+        ie8-fix  (aget groups 2)
+        zero     (if (= ie8-fix "") nil ie8-fix)]
     (if-not (nil? zero)
       0
       (let [a (cond


Make better use of s/pred to make error reports easier to read. Use s/eq instead of our own is?. Use s/if to check whether we have a set or not when validating one-or-many semantics.

--- src/cljx/sptcg/model.cljx
+++ src/cljx/sptcg/model.cljx
@@ -3,18 +3,19 @@
   #+clj (:require [schema.macros :as sm])
   #+cljs (:require-macros [schema.macros :as sm]))

-(defn is? [v] (s/pred #(= v %)))
+(defn at-most [amount] (s/pred (partial >= amount) 'at-most))

-(defn at-most [n] (s/pred (partial >= n)))
-
-(defn total-amount-at-least [n]
+(defn total-amount-at-least [amount]
   (s/pred
    (fn [deck-cards]
      (->> deck-cards
-          (map (fn [deck-card]
-                 (or (:amount deck-card) 1)))
+          (map #(or (:amount %) 1))
           (apply +)
-          (<= n)))))
+          (<= amount)))
+   'total-amount-at-least))
+
+(defn one-or-many [schema]
+  (s/if #(set? %) #{schema} schema))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Cards
@@ -22,7 +23,10 @@
 (def Colours (s/enum :none :green :blue :red :white))

 (def Mana
-  {(s/optional-key :colour) (s/either Colours #{Colours})
+  "Can have no colour at all, a single colour, or any amount of
+   colours. More than one colour makes this mana 'hybrid' mana.
+   A lack of a colour is the same as providing the :none colour."
+  {(s/optional-key :colour) (one-or-many Colours)
    :amount s/Int})

 (def Card
@@ -32,9 +36,9 @@

 (def Land
   (merge Card
-         {:type (is? :land)
+         {:type (s/eq :land)
           :size LandSizes
-          (s/optional-key :produces) (s/either Mana #{Mana})}))
+          (s/optional-key :produces) (one-or-many Mana)}))

 ;; haven't yet specified the speed and size of basic lands.
 ;; not sure about their usage?
@@ -53,8 +57,9 @@
 (def Spell
   (merge Card
          {:cost [Mana]
-          :type (s/either SpellTypes #{SpellTypes})
-          (s/optional-key :sub-type) s/Str}))
+          :type (one-or-many SpellTypes)
+          (s/optional-key :sub-type) s/Str
+          (s/optional-key :produces) (one-or-many Mana)}))

 (def Cards [(s/either BasicLand NonBasicLand Spell)])

@@ -73,7 +78,7 @@
                    (at-most 4))})

 (def LandDeck
-  {:type (is? :land)
+  {:type (s/eq :land)
    :cards (s/both [(s/either BasicLandDeckCard
                              NonBasicLandDeckCard)]
                   (total-amount-at-least 30))})
@@ -84,7 +89,7 @@
                    (at-most 3))})

 (def SpellDeck
-  {:type (is? :spell)
+  {:type (s/eq :spell)
    :cards (s/both [SpellDeckCard]
                   (total-amount-at-least 40))})


Moar.

Moar.

--- src/clojurecraft/core.clj
+++ src/clojurecraft/core.clj
@@ -248,8 +248,8 @@
 (defn read-packet-playerpositionlook [conn]
       (-> {}
           (assoc :x (-read-double conn))
+          (assoc :stance (-read-double conn))
           (assoc :y (-read-double conn))
-          (assoc :stance (-read-double conn))
           (assoc :z (-read-double conn))
           (assoc :yaw (-read-float conn))
           (assoc :pitch (-read-float conn))