correct trading tests for transaction changes

--- test/clj_money/trading_test.clj
+++ test/clj_money/trading_test.clj
@@ -22,6 +22,24 @@
 (def storage-spec (env :db))

 (use-fixtures :each (partial reset-db storage-spec))
+
+(defn items-by-account
+  [account-id]
+  (map #(dissoc %
+                :id
+                :polarized-amount
+                :entity-id
+                :transaction-id
+                :reconciled?
+                :reconciliation-id
+                :created-at
+                :updated-at
+                :reconciliation-status)
+       (transactions/items-by-account
+         storage-spec
+         account-id
+         [(t/local-date 2015 1 1)
+          (t/local-date 2017 12 31)])))

 (def ^:private purchase-context
   {:users [(factory :user)]
@@ -89,6 +107,7 @@
                                        :account-id (:id ira)
                                        :index 1
                                        :memo nil
+                                       :transaction-date (t/local-date 2016 1 2)
                                        :reconciled? false
                                        :reconciliation-id nil}
                                       {:action :debit
@@ -97,6 +116,7 @@
                                        :value 1000M
                                        :account-id (:id apple-account)
                                        :memo nil
+                                       :transaction-date (t/local-date 2016 1 2)
                                        :index 0
                                        :reconciled? false
                                        :reconciliation-id nil}]}
@@ -127,6 +147,10 @@
                                                        :balance)]
     (is (:transaction result)
         "The result contains the transaction associated with the purchase")
+    (when-not (= expected-transaction actual-transaction)
+      (pprint {:expected expected-transaction
+               :actual actual-transaction
+               :diff (diff expected-transaction actual-transaction)}))
     (is (= expected-transaction actual-transaction)
         "The resulting transaction has the correct attributes")
     (is (empty? (-> result :transaction validation/error-messages))
@@ -365,6 +389,7 @@
                               :items [{:action :credit
                                        :account-id (:id ltcg)
                                        :memo "Sell 25 shares of AAPL at 15.000"
+                                       :transaction-date (t/local-date 2017 3 2)
                                        :amount 125M
                                        :value 125M
                                        :balance 125M
@@ -373,6 +398,7 @@
                                        :index 0}
                                       {:action :debit
                                        :account-id (:id ira)
+                                       :transaction-date (t/local-date 2017 3 2)
                                        :amount 375M
                                        :value 375M
                                        :balance 1375M
@@ -382,6 +408,7 @@
                                        :index 2}
                                       {:action :credit
                                        :account-id (:id commodity-account)
+                                       :transaction-date (t/local-date 2017 3 2)
                                        :amount 25M
                                        :balance 75M
                                        :value 250M
@@ -407,6 +434,10 @@
         "The shares-owned value of the original lot is updated")
     (is (:transaction result)
         "The result contains the transaction record")
+    (when-not (= expected-transaction actual-transaction)
+      (pprint {:expected expected-transaction
+               :actual actual-transaction
+               :diff (diff expected-transaction actual-transaction)}))
     (is (= expected-transaction actual-transaction)
         "The transaction contains the correct attributes")
     (is (empty? (-> result :transaction validation/error-messages))
@@ -574,16 +605,7 @@
         _ (trading/sell storage-spec (-> context
                                          sale-attributes
                                          (assoc :shares 25M :value 375M)))
-        gains-items (->> {:i.account-id (:id lt-capital-gains)} ; TODO remove table prefix
-                         (transactions/search-items storage-spec)
-                         (map #(dissoc % :id
-                                         :entity-id
-                                         :transaction-id
-                                         :reconciled?
-                                         :reconciliation-id
-                                         :created-at
-                                         :updated-at
-                                         :reconciliation-status)))
+        gains-items (items-by-account (:id lt-capital-gains))
         expected [{:transaction-date (t/local-date 2017 3 2)
                    :description "Sell 25 shares of AAPL at 15.000"
                    :action :credit
@@ -605,16 +627,7 @@
                                          (assoc :shares 25M
                                                 :value 375M
                                                 :trade-date (t/local-date 2017 3 1))))
-        gains-items (->> {:i.account-id (:id st-capital-gains)}
-                         (transactions/search-items storage-spec)
-                         (map #(dissoc % :id
-                                         :entity-id
-                                         :transaction-id
-                                         :reconciled?
-                                         :reconciliation-id
-                                         :created-at
-                                         :updated-at
-                                         :reconciliation-status)))
+        gains-items (items-by-account (:id st-capital-gains))
         expected [{:transaction-date (t/local-date 2017 3 1)
                    :description "Sell 25 shares of AAPL at 15.000"
                    :action :credit
@@ -634,16 +647,7 @@
         _ (trading/sell storage-spec (-> context
                                          sale-attributes
                                          (assoc :shares 100M :value 850M)))
-        gains-items (->> {:i.account-id (:id capital-loss)}
-                         (transactions/search-items storage-spec)
-                         (map #(dissoc % :id
-                                         :entity-id
-                                         :transaction-id
-                                         :reconciled?
-                                         :reconciliation-id
-                                         :created-at
-                                         :updated-at
-                                         :reconciliation-status)))
+        gains-items (items-by-account (:id capital-loss))
         expected [{:transaction-date (t/local-date 2017 3 2)
                    :description "Sell 100 shares of AAPL at 8.500"
                    :action :debit
@@ -653,7 +657,7 @@
                    :memo "Sell 100 shares of AAPL at 8.500"
                    :balance 150M
                    :index 0}]]
-    (if-not (= expected gains-items)
+    (when-not (= expected gains-items)
       (pprint {:expected expected
                :actual gains-items
                :diff (diff expected gains-items)}))
@@ -788,7 +792,7 @@
                                             :commodity-id (:id commodity)
                                             :account-id (:id ira)
                                             :value 1000M})
-        result (trading/unbuy storage-spec (-> purchase :transaction :id))]
+        result (trading/unbuy storage-spec (:transaction purchase))]
     ; TODO Should we delete the price that was created?
     (testing "the account balance"
       (is (= 2000M (:balance (accounts/reload storage-spec ira)))
@@ -808,7 +812,7 @@
                                             :value 1000M})
         _ (trading/sell storage-spec (sale-attributes context))]
     (is (thrown-with-msg? IllegalStateException #"Cannot undo"
-                          (trading/unbuy storage-spec (-> purchase :transaction :id))))))
+                          (trading/unbuy storage-spec (:transaction purchase))))))

 (deftest undo-a-sale
   (let [context (serialization/realize storage-spec purchase-context)
@@ -820,7 +824,7 @@
                                             :account-id (:id ira)
                                             :value 1000M})
         sale (trading/sell storage-spec (sale-attributes context))
-        result (trading/unsell storage-spec (-> sale :transaction :id))]
+        result (trading/unsell storage-spec (:transaction sale))]
     ; IRA balance balance before purchase: $2,000
     ;                      after purchase: $1,000
     ;                          after sale: $1,375


removed bad test.

removed bad test.

--- test/forma/source/fire_test.clj
+++ test/forma/source/fire_test.clj
@@ -2,8 +2,6 @@
   (:use [forma.source.fire] :reload)
   (:use cascalog.api
         midje.sweet))
-
-(fact (+ 1 1) => 3)

 (def fire-tap
   (memory-source-tap


More testing

More testing

--- test/integration/cache_test.clj
+++ test/integration/cache_test.clj
@@ -22,10 +22,7 @@

 (with-state-changes [(before :facts (do
                                       (loader/load-dataset db)
-                                      (db/drop-db (:database cache))
-                                      #_(reset! worker-agent (c/start-worker worker))))
-                     (after :facts (do true
-                                       #_(swap! worker-agent c/stop-worker)))]
+                                      (db/drop-db (:database cache))))]

   (facts "about cache"
          (fact "the default cache uses the query-cache db"
@@ -42,5 +39,17 @@
            (fact "it adds a document to jobs"
                  (conv/from-db-object (c/add-to-queue cache agg) true)
                  => (contains {:aggmap agg
-                               :status "unprocessed"})))))
+                               :status "unprocessed"})))

+    (facts "about worker"
+           (fact "it will process jobs"
+                 (data/get-aggregation db coll agg)
+                 => (contains {:data :computing})
+
+                 (do
+                   (reset! worker-agent (c/start-worker worker))
+                   (await @worker-agent)
+                   (swap! worker-agent c/stop-worker)
+                   (data/get-aggregation db coll agg))
+                 =not=> (contains {:data :computing})))))
+


generating lists of lists of phones

generating lists of lists of phones

--- src/rhymes/core.clj
+++ src/rhymes/core.clj
@@ -5,10 +5,10 @@
             [rhymes.rhyme])
   (:gen-class))

-(defn fetch-url [url]
+(defn- fetch-url [url]
   (html/html-resource (java.net.URL. url)))

-(defn parse-html
+(defn- parse-html
   [html]
   (-> html
       (html/select [:div.lyricbox])
@@ -24,17 +24,37 @@
        (map html/text)
        first))

-; TODO: lowercase all letters and remove punctuation
+(defn- clean-lyrics-string
+  [s]
+  (-> s
+      ; remove everything between parens
+      (string/replace #"\(.*\)" "")
+      string/lower-case
+      ; remove punctuation
+      (string/replace #"[^a-z '\n]" "")
+      ; remove double spaces
+      (string/replace #" +" " ")))

 (defn fetch-lyrics
   [artist song]
   (let [formatted-artist (string/replace artist #" " "_")
         formatted-song (string/replace song #" " "_")
         url (format "http://lyrics.wikia.com/%s:%s" formatted-artist formatted-song)]
-    (-> url
-        fetch-lyrics-string
-        (string/replace #"\(.*\)" "")
-        split-lines)))
+    (->> url
+         fetch-lyrics-string
+         clean-lyrics-string
+         split-lines
+         (map string/trim))))
+
+(defn- lyric-line->phones
+  [lyric-line]
+  (let [words (string/split lyric-line #"\s+")]
+    (mapv (partial get d) words)))
+
+(defn lyrics->phones
+  "lyrics is a vector of strings"
+  [lyrics]
+  (mapv lyric-line->phones lyrics))

 ; (fetch-lyrics "Eminem" "My Name Is")


Rename namespace

Rename namespace

--- test/kixi/hecuba/parse_test.clj
+++ test/kixi/hecuba/parse_test.clj
@@ -1,4 +1,4 @@
-(ns kixi.hecuba.api.parse-test
+(ns kixi.hecuba.parse-test
   (:use clojure.test)
   (:require [clojure.test.check.generators :as gen]
             [clojure.test.check :as tc]


Update client tests

Update client tests

--- test/karmanaut/client_test.clj
+++ test/karmanaut/client_test.clj
@@ -11,17 +11,14 @@
 (deftest test-body
   (is (instance? clojure.lang.PersistentArrayMap (body "mipadi"))))

-(deftest test-items
-  (is (instance? clojure.lang.PersistentVector (items "mipadi"))))
-
 (deftest test-user-data
   (is (instance? clojure.lang.PersistentHashMap (user-data "mipadi"))))

 (deftest test-user-key
-  (is (= "mipadi" (user-key "mipadi" "user_id"))))
+  (is (= "34agu" (user-key "mipadi" "id"))))

-(deftest test-display-name
-  (is (= "mipadi" (display-name "mipadi"))))
+(deftest test-link-karma
+  (is (instance? Long (link-karma "mipadi"))))

-(deftest test-reputation
-  (is (instance? Long (rep "mipadi"))))
+(deftest test-comment-karma
+  (is (instance? Long (comment-karma "mipadi"))))


remove zipfile size testing code from dev utility ns

--- dev-src/dev/core.clj
+++ dev-src/dev/core.clj
@@ -28,7 +28,7 @@
 (def pipeline
   [set-context
    psql/start-run
-   #(zip/assoc-file % 786432) ;(config [:max-zipfile-size] 3221225472)) ; 3GB
+   #(zip/assoc-file (config [:max-zipfile-size] 3221225472)) ; 3GB
    zip/extracted-contents
    t/remove-invalid-extensions
    t/xml-csv-branch


Add role and premium? keys to the access-level map returned by the access namespace.

--- src/oc/storage/api/access.clj
+++ src/oc/storage/api/access.clj
@@ -20,8 +20,8 @@
       [false {:data user-id}]
       true)
     (catch Exception e
-      (do (timbre/warn "Request body not processable as a user-id: " e)
-        true))))
+      (timbre/warn "Request body not processable as a user-id: " e)
+      true)))

 (defn premium-org? [org user]
   ((set (:premium-teams user)) (:team-id org)))
@@ -62,22 +62,31 @@
         admin (:admin user)
         org-uuid (:uuid org)
         org-authors (set (:authors org))
-        premium? (premium-org? org user)]
+        premium? (premium-org? org user)
+        member? ((set teams) (:team-id org))
+        admin? ((set admin) (:team-id org))
+        role (cond admin?  :admin
+                   member? :member
+                   :else   :anonymous)
+        base-access {:role role :premium? premium?}]
     (cond
       ;; an admin of this org's team
-      ((set admin) (:team-id org)) {:access-level :author :role :admin :premium? premium?}
+      ((set admin) (:team-id org))
+      (merge base-access {:access-level :author})

       ;; a named author of this org
-      (org-authors user-id) {:access-level :author :premium? premium?}
+      (org-authors user-id)
+      (merge base-access {:access-level :author})

       ;; a team member of this org
-      ((set teams) (:team-id org)) {:access-level :viewer :premium? premium?}
+      ((set teams) (:team-id org))
+      (merge base-access {:access-level :viewer})

       ;; public access to orgs w/ at least 1 public board AND that allow public boards
       (and
         (seq (board-res/list-boards-by-index conn "org-uuid-access" [[org-uuid "public"]]))
         (not (-> org :content-visibility :disallow-public-board)))
-      {:access-level :public}
+      (merge base-access {:access-level :public})

       ;; no access
       :else false)))
@@ -113,31 +122,42 @@
         board-access (keyword (:access board))
         board-authors (set (:authors board))
         board-viewers (set (:viewers board))
-        premium? (premium-org? org user)]
+        premium? (premium-org? org user)
+        member? ((set teams) (:team-id org))
+        admin? ((set admin) (:team-id org))
+        role (cond admin?  :admin
+                   member? :member
+                   :else   :anonymous)
+        base-access {:role role :premium? premium?}]
     (cond

       ;; a named author of this private board
-      (and (= board-access :private) (board-authors user-id)) {:access-level :author :premium? premium?}
+      (and (= board-access :private) (board-authors user-id))
+      (merge base-access {:access-level :author})

       (and (= board-access :team)
            (:publisher-board board))
-      {:access-level (if (= (str board-res/publisher-board-slug-prefix user-id) (:slug board)) :author :viewer) :premium? premium?}
+      (merge base-access {:access-level (if (= (str board-res/publisher-board-slug-prefix user-id) (:slug board)) :author :viewer)})

       ;; an admin of this org's team for this non-private board
-      (and (not= board-access :private) ((set admin) (:team-id org))) {:access-level :author :role :admin :premium? premium?}
+      (and (not= board-access :private) ((set admin) (:team-id org)))
+      (merge base-access {:access-level :author})

       ;; an org author of this non-private board
-      (and (not= board-access :private) (org-authors user-id)) {:access-level :author :premium? premium?}
+      (and (not= board-access :private) (org-authors user-id))
+      (merge base-access {:access-level :author})

       ;; a named viewer of this board
-      (and (= board-access :private) (board-viewers user-id)) {:access-level :viewer :premium? premium?}
+      (and (= board-access :private) (board-viewers user-id))
+      (merge base-access {:access-level :viewer})

       ;; a team member on a non-private board
-      (and (not= board-access :private) ((set teams) (:team-id org))) {:access-level :viewer :premium? premium?}
+      (and (not= board-access :private) ((set teams) (:team-id org)))
+      (merge base-access {:access-level :viewer})

       ;; anyone else on a public board IF the org allows public boards
       (and (= board-access :public) (not (-> org :content-visibility :disallow-public-board)))
-      {:access-level :public}
+      (merge base-access {:access-level :public})

       ;; no access
       :else false))))


:bug: Fixes problem with localStorage in web worker


Update cider-nrepl to v0.8.1

Update cider-nrepl to v0.8.1

--- roles/clojure/files/profiles.clj
+++ roles/clojure/files/profiles.clj
@@ -7,7 +7,7 @@
                        [slamhound "1.5.3"]
                        [spyscope "0.1.4"]]

-        :plugins [[cider/cider-nrepl "0.8.0-SNAPSHOT"]
+        :plugins [[cider/cider-nrepl "0.8.1"]
                   [codox "0.6.6"]
                   [jonase/eastwood "0.1.4"]
                   [lein-ancient "0.5.5" :exclusions [commons-codec]]


Implemented/copied output/helper functions.

--- src/semantic_csv/transducers.clj
+++ src/semantic_csv/transducers.clj
@@ -1,7 +1,22 @@
+;; # Core functionality as Transducers
+;;
+
 (ns semantic-csv.transducers
+  "# Transducers API namespace"
   (:require [clojure.java.io :as io]
             [clojure-csv.core :as csv]
             [semantic-csv.impl.core :as impl :refer [?>>]]))
+
+;; # Input processing functions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Note that all of these processing functions return a transducer unless otherwise stated.
+;; This allows for single passes accross collections.
+;;
+
+
+;;

+;; ## mappify

 (defn mappify
   "Takes a sequence of row vectors, as commonly produced by csv parsing libraries, and returns a sequence of
@@ -23,11 +38,33 @@
                 results)
             (rf results (impl/mappify-row @hdr input)))))))))

+;; Here's an example using the mappify transducers.
+;;
+;;     => (with-open [in-file (io/reader "test/test.csv")]
+;;          (transduce
+;;            (mappify)
+;;            conj
+;;            []
+;;            (csv/parse-csv in-file))
+;;
+;;     [{:this "# some comment lines..."}
+;;      {:this "1", :that "2", :more "stuff"}
+;;      {:this "2", :that "3", :more "other yeah"}]
+;;
+;;

+;;
+;; Note that `"# some comment lines..."` was really intended to be left out as a comment.
+;; We can address this with the following function:
+
+
+;;

+;; ## structify
+
 (defn structify
   "Takes a sequence of row vectors, as commonly produced by csv parsing libraries, and returns a sequence of
   structs. By default, the first row vector will be interpreted as a header, and used as the keys for the maps.
   However, this and other behaviour are customizable via an optional `opts` map with the following options:
-
+
   * `:keyify` - bool; specify whether header/column names should be turned into keywords (default: `true`).
   * `:header` - specify the header to use for map keys, preventing first row of data from being consumed as header."
   ([] (structify {}))
@@ -43,6 +80,27 @@
                 results)
             (rf results (apply struct (apply create-struct @hdr) input)))))))))

+;; Here's an example of structify:
+;;
+;;     => (with-open [in-file (io/reader "test/test.csv")]
+;;          (transduce
+;;            (structify)
+;;            conj
+;;            []
+;;            (csv/parse-csv in-file))
+;;
+;;     ({:this "# some comment lines..."}
+;;      {:this "1", :that "2", :more "stuff"}
+;;      {:this "2", :that "3", :more "other yeah"})
+;;
+;;

+;;
+;; Note that `"# some comment lines..."` was really intended to be left out as a comment.
+;; We can address this with the following function:
+
+
+;;

+;; ## remove-comments
 (defn remove-comments
   "Removes rows which start with a comment character (by default, `#`). Operates by checking whether
   the first item of every row in the collection matches a comment pattern. Also removes empty lines.
@@ -66,6 +124,28 @@
             (if (and x (commented? x))
               results
               (rf results input)))))))))
+
+;; Notice the remove-comments is placed before mappify.
+;; We want this done in order.  The order flows from left to right in the compose.
+;; This is a property of transducers.
+;;
+;;     => (with-open [in-file (io/reader "test/test.csv")]
+;;          (transduce
+;;            (comp (remove-comments) (mappify))
+;;            conj
+;;            []
+;;            (csv/parse-csv in-file)))
+;;
+;;     ({:this "1", :that "2", :more "stuff"}
+;;      {:this "2", :that "3", :more "other yeah"})
+;;
+;;

+;; Next, let's observe that `:this` and `:that` point to strings, while they should really be pointing to
+;; numeric values.
+;; This can be addressed with the following function:
+
+;;

+;; ## cast-with

 (defn cast-with
   "Casts the vals of each row according to `cast-fns`, which must either be a map of
@@ -91,17 +171,51 @@
               (do (vreset! fst input) (rf results input))) ;; fst is nil. reset fst and return the results.
             (rf results (impl/cast-row cast-fns input :only only :exception-handler exception-handler)))))))))

-;; TODO: properly implement except first as transducer.  need to take n functions and apply then in order as in ->>.
-;; (defn except-first
-;;   []
-;;   (fn [rf]
-;;     (let [fst (volatile! nil)]
-;;       (fn
-;;         ([] (rf))
-;;         ([results] (rf results))
-;;         ([results input]
-;;          (if @fst
-;;            (rf results)))))))
+;; Let's try casting a numeric column using this function:
+;;
+;;     => (with-open [in-file (io/reader "test/test.csv")]
+;;          (transduce
+;;            (comp
+;;              (remove-comments)
+;;              (mappify)
+;;              (cast-with {:this #(Integer/parseInt %)}))
+;;            conj
+;;            []
+;;            (csv/parse-csv in-file)))
+;;
+;;     ({:this 1, :that "2", :more "stuff"}
+;;      {:this 2, :that "3", :more "other yeah"})
+;;
+;; Alternatively, if we want to cast multiple columns using a single function, we can do so
+;; by passing a single casting function as the first argument.
+;;
+;;     => (with-open [in-file (io/reader "test/test.csv")]
+;;          (transduce
+;;            (comp
+;;              (remove-comments)
+;;              (mappify)
+;;              (cast-with #(Integer/parseInt %) {:only [:this :that]}))
+;;            conj
+;;            []
+;;            (csv/parse-csv in-file)))
+;;
+;;     ({:this 1, :that 2, :more "stuff"}
+;;      {:this 2, :that 3, :more "other yeah"})
+;;
+;; Note that this function handles either map or vector rows.
+;; In particular, if you’ve imported data without consuming a header (by either not using mappify or
+;; by passing `:header false` to `process` or `slurp-csv` below), then the columns can be keyed by their
+;; zero-based index.
+;; For instance, `(cast-with {0 #(Integer/parseInt %) 1 #(Double/parseDouble %)} rows)`
+;; will parse the first column as integers and the second as doubles.
+;;
+;;

+;; It's worth pointing out this function isn't strictly an _input_ processing function, but could be
+;; used for intermediate or output preparation processing.
+
+
+;;

+;; ## process

 (defn process
   "This function wraps together the most frequently used input processing capabilities,
@@ -140,6 +254,19 @@
   ([]
    (process {})))

+;; Using this function, the code we've been building above is reduced to the following:
+;;
+;;     (with-open [in-file (io/reader "test/test.csv")]
+;;       (transduce
+;;         (process {:cast-fns {:this #(Integer/parseInt %)}})
+;;         conj
+;;         []
+;;         (csv/parse-csv in-file)))
+
+
+;;

+;; ## parse-and-process
+
 (defn parse-and-process
   "This is a convenience function for reading a csv file using `clojure/data.csv` and passing it through `process`
   with the given set of options (specified _last_ as kw_args, in contrast with our other processing functions).
@@ -151,6 +278,14 @@
     (transduce (process rest-options) conj []
      (impl/apply-kwargs csv/parse-csv csv-readable parser-opts))))

+;;     (with-open [in-file (io/reader "test/test.csv")]
+;;         (parse-and-process in-file
+;;                            :cast-fns {:this #(Integer/parseInt %)}))
+
+
+;;

+;; ## slurp-csv
+
 (defn slurp-csv
   "This convenience function let's you `parse-and-process` csv data given a csv filename. Note that it is _not_
   lazy, and must read in all data so the file handle can be closed."
@@ -158,3 +293,246 @@
   (let [rest-options (dissoc opts :parser-opts)]
     (with-open [in-file (io/reader csv-filename)]
        (impl/apply-kwargs parse-and-process in-file opts))))
+
+;; For the ultimate in _programmer_ laziness:
+;;
+;;     (slurp-csv "test/test.csv"
+;;                :cast-fns {:this #(Integer/parseInt %)})
+
+
+;;

+;; # Some casting functions for your convenience
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; These functions can be imported and used in your `:cast-fns` specification.
+;; They focus on handling some of the mess of dealing with numeric casting.
+
+;; ## ->int
+
+(defn ->int
+  "Translate to int from string or other numeric. If string represents a non integer value,
+  it will be rounded down to the nearest int."
+  [v]
+  (if (string? v)
+    (-> v clojure.string/trim Double/parseDouble int)
+    (int v)))
+
+;; ## ->long
+
+(defn ->long
+  "Translate to long from string or other numeric. If string represents a non integer value,
+  will be rounded down to the nearest long."
+  [v]
+  (if (string? v)
+    (-> v clojure.string/trim Double/parseDouble long)
+    (long v)))
+
+;; ## ->float
+
+(defn ->float
+  "Translate to float from string or other numeric."
+  [v]
+  (if (string? v)
+    (-> v clojure.string/trim Float/parseFloat)
+    (float v)))
+
+;; ## ->double
+
+(defn ->double
+  "Translate to double from string or other numeric."
+  [v]
+  (if (string? v)
+    (-> v clojure.string/trim Double/parseDouble)
+    (double v)))
+
+;;     (slurp-csv "test/test.csv"
+;;                :cast-fns {:this ->int})
+
+;; Note these functions place a higher emphasis on flexibility and convenience than performance, as you can
+;; likely see from their implementations.
+;; If maximum performance is a concern for you, and your data is fairly regular, you may be able to get away with
+;; less robust functions, which shouldn't be hard to implement yourself.
+;; For most cases though, the performance of those provided here should be fine.
+
+
+;;

+;; # Output processing functions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+;; As with the input processing functions, the output processing functions are designed to be small,
+;; composable pieces which help you push your data through to a third party writer.
+;; And as with the input processing functions, higher level, opinionated, but configurable functions
+;; are offered which automate some of this for you.
+;;
+;; We've already looked at `cast-with`, which can be useful in output as well as input
+;; processing.
+;; Another important function we'll need is one that takes a sequence of maps and turns it into a sequence
+;; of vectors since this is what most of our csv writing/formatting libraries will want.
+
+
+;;

+;; ## vectorize
+
+(defn vectorize
+  "Take a sequence of maps, and transform them into a sequence of vectors. Options:
+
+  * `:header` - The header to be used. If not specified, this defaults to `(-> rows first keys)`. Only
+    values corresponding to the specified header will be included in the output, and will be included in the
+    order corresponding to this argument.
+  * `:prepend-header` - Defaults to true, and controls whether the `:header` vector should be prepended
+    to the output sequence.
+  * `:format-header` - If specified, this function will be called on each element of the `:header` vector, and
+    the result prepended to the output sequence. The default behaviour is to leave strings alone but stringify
+    keyword names such that the `:` is removed from their string representation. Passing a falsey value will
+    leave the header unaltered in the output."
+  ([]
+   (vectorize {}))
+  ([{:keys [header prepend-header format-header]
+     :or {prepend-header true format-header impl/stringify-keyword}}]
+   (fn [rf]
+     (let [hdr (volatile! header)]
+       (fn
+         ([] (rf))
+         ([result] (rf result))
+         ([result input]
+          (if (empty? @hdr)
+            (do (vreset! hdr (into [] (keys input)))
+                (if prepend-header
+                  (rf
+                   (if format-header
+                     (conj result (mapv format-header @hdr))
+                     (conj result @hdr))
+                   (mapv (partial get input) @hdr))))
+            (rf result (mapv (partial get input) @hdr)))
+          ))))))
+
+
+;; Let's see this in action:
+;;
+;;     => (let [data [{:this "a" :that "b"}
+;;                    {:this "x" :that "y"}]]
+;;          (transduce (vectorize) conj [] data))
+;;     (["this" "that"]
+;;      ["a" "b"]
+;;      ["x" "y"])
+;;
+;; With some options:
+;;
+;;     => (let [data [{:this "a" :that "b"}
+;;                    {:this "x" :that "y"}]]
+;;          (transduce (vectorize {:header [:that :this]
+;;                      :prepend-header false})
+;;                     conj
+;;                     []
+;;                     data))
+;;     (["b" "a"]
+;;      ["y" "x"])
+
+
+;;

+;; ## batch
+
+(defn batch
+  "Does not return a transducer. Takes sequence of items and returns a
+  sequence of batches of items from the original sequence, at most `n` long."
+  [n rows]
+  (partition n n [] rows))
+
+;; This function can be useful when working with `clojure-csv` when writing lazily.
+;; The `clojure-csv.core/write-csv` function does not actually write to a file, but just formats the data you
+;; pass in as a CSV string.
+;; If you're working with a lot of data, calling this function would build a single massive string of the
+;; results, and likely crash.
+;; To write _lazily_, you have to take some number of rows, write them, and repeat till you're done.
+;; Our `batch` function helps by giving you a lazy sequence of batches of `n` rows at a time, letting you pass
+;; _that_ through to something that writes off the chunks lazily.
+
+
+;;

+;; And as promised, a function for doing all the dirty work for you:
+
+
+;;

+;; ## spit-csv
+
+(defn spit-csv
+  "Convenience function for spitting out CSV data to a file using `clojure-csv`.
+
+  * `file` - Can be either a filename string, or a file handle.
+  * `opts` - Optional hash of settings.
+  * `rows` - Can be a sequence of either maps or vectors; if the former, vectorize will be
+      called on the input with `:header` argument specifiable through `opts`.
+
+  The Options hash can have the following mappings:
+
+  * `:batch-size` - How many rows to format and write at a time?
+  * `:cast-fns` - Formatter(s) to be run on row values. As with `cast-with` function, can be either a map
+     of `column-name -> cast-fn`, or a single function to be applied to all values. Note that `str` is called
+     on all values just before writing regardless of `:cast-fns`.
+  * `:writer-opts` - Options hash to be passed along to `clojure-csv.core/write-csv`.
+  * `:header` - Header to be passed along to `vectorize`, if necessary.
+  * `:prepend-header` - Should the header be prepended to the rows written if `vectorize` is called?"
+  ([file rows]
+   (spit-csv file {} rows))
+  ([file
+    {:keys [batch-size cast-fns writer-opts header prepend-header]
+     :or   {batch-size 20 prepend-header true}
+     :as   opts}
+    rows]
+   (if (string? file)
+     (with-open [file-handle (io/writer file)]
+       (spit-csv file-handle opts rows))
+     ; Else assume we already have a file handle
+     (let [cast-fn (when cast-fns (cast-with cast-fns))
+           vect-fn (when (-> rows first map?) (vectorize {:header header :prepend-header prepend-header}))
+           vect-rows (transduce (apply comp (remove nil? [cast-fn vect-fn (cast-with str)])))]
+       (->> vect-rows
+            (batch batch-size)
+            (map #(impl/apply-kwargs csv/write-csv % writer-opts))
+            (reduce
+             (fn [w rowstr]
+               (.write w rowstr)
+               w)
+             file))))))
+
+;; Note that since we use `clojure-csv` here, we offer a `:batch-size` option that lets you format and write small
+;; batches of rows out at a time, to avoid constructing a massive string representation of all the data in the
+;; case of bigger data sets.
+
+
+;;

+;; # One last example showing everything together
+;;
+;; Let's see how Semantic CSV works in the context of a little data pipeline.
+;; We're going to thread data in, transform into maps, run some computations for each row and assoc in,
+;; then write the modified data out to a file, all lazily.
+;;
+;; First let's show this with `clojure/data.csv`, which I find a little easier to use for writing:
+;;
+;;     (require '[clojure.data.csv :as cd-csv])
+;;
+;;     (with-open [in-file (io/reader "test/test.csv")
+;;                 out-file (io/writer "test-out.csv")]
+;;       (->>
+;;         (transduce
+;;           (comp
+;;             (remove-comments)
+;;             (mappify)
+;;             (cast-with {:this ->int :that ->float})
+;;             ;; Do your processing...
+;;             (map
+;;               (fn [row]
+;;                 (assoc row :jazz (* (:this row)
+;;                                     (:that row)))))
+;;             (vectorize))
+;;           conj
+;;           []
+;;           (cd-csv/read-csv in-file))
+;;         (cd-csv/write-csv out-file)))
+;;
+;;
+;;

+;; And there you have it.
+;; A simple, composable, and easy to use library for taking you the extra mile with CSV processing in
+;; Clojure.


fix conditional "essere"

fix conditional "essere"

--- src/babel/italiano/lexicon.cljc
+++ src/babel/italiano/lexicon.cljc
@@ -1011,7 +1011,7 @@
                                         :3sing "sarebbe"
                                         :1plur "saremmo"
                                         :2plur "sareste"
-                                        :3plur "sarebberano"}}})]
+                                        :3plur "sarebbero"}}})]
         [;; essere: adjective
          ;; TODO: unify essere-adjective and essere-intensifier into one lexical entry.
          (let [gender (atom :top)


client adjudicator selection for class

client adjudicator selection for class

--- src/tango/cljs/runtime/core.cljs
+++ src/tango/cljs/runtime/core.cljs
@@ -183,11 +183,16 @@
 (defui CreateClassView
   static om/IQuery
   (query [_]
-    [:class/name :class/id {:class/starting [:participant/number]}])
-  Object
-  (render
-    [this]
-    (let [selected-class (om/props this)]
+    [:class/name :class/id {:class/starting [:participant/number]}
+     {:class/adjudicator-panel [:adjudicator-panel/id :adjudicator-panel/name]}])
+  Object
+  (render
+    [this]
+    (let [;selected-class (:selected-class (om/props this))
+          selected-class (om/props this)
+          {:keys [panels]} (om/get-computed this)
+          ;panels (:adjudicator-panels (om/props this))
+          ]
       ;; - Class name
       ;; - Adj Panel
       ;; - Dances
@@ -212,6 +217,33 @@
                                                                     :class/name ~(.. e -target -value)})]))})))

             ;; Adjudicator Panel
+            (dom/div #js {:className "form-group"}
+              (dom/label #js {:className "col-sm-2 control-label"} "Adjudicator Panel")
+              (dom/div #js {:className "col-sm-8"}
+                (dom/div #js {:className "dropdown"}
+                  (dom/button #js {:className   "btn btn-default dropdown-toggle"
+                                   :data-toggle "dropdown"} ""
+                              (dom/span #js {:className "selection"}
+                                (if (:class/adjudicator-panel selected-class)
+                                  (:adjudicator-panel/name (:class/adjudicator-panel selected-class))
+                                  "Select"))
+                              (dom/span #js {:className "caret"}))
+                  (apply dom/ul #js {:className "dropdown-menu" :role "menu"}
+                         (map (fn [panel]
+                                (dom/li #js {:role    "presentation"
+                                             :onClick #(om/transact!
+                                                        this
+                                                        `[(class/update
+                                                            {:class/adjudicator-panel
+                                                             ~(first
+                                                                (filter
+                                                                  (fn [p]
+                                                                    (= (:adjudicator-panel/id p)
+                                                                       (:adjudicator-panel/id panel)))
+                                                                  panels))})
+                                                          :app/selected-class])}
+                                  (dom/a #js {:role "menuitem"} (:adjudicator-panel/name panel))))
+                              panels)))))

             ;; Dances

@@ -539,14 +571,18 @@
                           [(dom/li #js {:className "dropdown-header"}
                              (str "Panel - " (:adjudicator-panel/name panel)))
                            (map (fn [adjudicator]
-                                  (dom/li #js {:role "presentation"
-                                               :onClick     ;#(log (str "Change ajd to " (:adjudicator/name adjudicator)))
-                                                     #(om/transact! reconciler `[(app/set-client-info
-                                                                             {:client/id   ~client-id
-                                                                              :client/name ~client-name
-                                                                              :client/user {:adjudicator/id   ~(:adjudicator/id adjudicator)
-                                                                                :adjudicator/name ~(:adjudicator/name adjudicator)}})
-                                                                           :app/clients])
+                                  (dom/li
+                                    #js {:role "presentation"
+                                         :onClick     ;#(log (str "Change ajd to " (:adjudicator/name adjudicator)))
+                                               #(om/transact!
+                                                 reconciler
+                                                 `[(app/set-client-info
+                                                     {:client/id   ~client-id
+                                                      :client/name ~client-name
+                                                      :client/user
+                                                                   {:adjudicator/id   ~(:adjudicator/id adjudicator)
+                                                                    :adjudicator/name ~(:adjudicator/name adjudicator)}})
+                                                   :app/clients])
                                                }
                                     (dom/a #js {:role "menuitem"} (:adjudicator/name adjudicator))))
                                 (:adjudicator-panel/adjudicators panel))])
@@ -662,9 +698,10 @@
           status (:app/status p)
           selected-page (:app/selected-page p)
           participants (:app/participants p)
+          panels (:competition/panels selected-competition)
           selected-class (:app/selected-class p)]
-      (log "Main Clients :")
-      (log (:app/clients p))
+      (log "Main Selected :")
+      (log selected-class)
       (dom/div nil
         ((om/factory MenuComponent))
         (condp = selected-page
@@ -677,10 +714,12 @@
                      ;(om/computed (:competition/classes selected-competition)
                      ;                       {:selected selected-class})
                      {:classes (:competition/classes selected-competition)
-                      :selected (:app/selected-class p)}
+                      :selected selected-class}
                      )

-          :create-class ((om/factory CreateClassView) (:app/selected-class p))
+          :create-class ((om/factory CreateClassView)
+                          ;                selected-class
+                          (om/computed selected-class {:panels panels}))

           :edit-class-participants ((om/factory SelectClassParticipantsView)
                                      {:participants participants


Add a new route to an admin page

Add a new route to an admin page

--- src/todo_repl_webapp/handler.clj
+++ src/todo_repl_webapp/handler.clj
@@ -53,6 +53,8 @@
             (let [result (load-string evalInput)]
               (println "evals to: " result)
               (views/display result))))))
+  (GET "/admin" request (friend/authorize #{::admin}
+                                          "Admin page"))
   (route/resources "/")
   (route/not-found "Not Found"))


More utils

More utils

--- src/clj/bluebell/utils/test.clj
+++ src/clj/bluebell/utils/test.clj
@@ -1,4 +1,4 @@
 (ns bluebell.utils.test)

 (defn near [a b tol]
-  (< (Math/abs (- a b)) tol))
+  (< (Math/abs (double (- a b))) tol))


slight update to static docs.

slight update to static docs.

--- src/clj/forma/source/static.clj
+++ src/clj/forma/source/static.clj
@@ -3,15 +3,9 @@
         [forma.source.modis :only (wgs84-resolution)]
         [forma.static :only (static-datasets)]
         [forma.reproject :only (wgs84-indexer
-<<<<<<< HEAD
                                 modis-indexer)])
   (:require [cascalog.ops :as c]
             [forma.source.modis :as m]
-=======
-                                modis-indexer)]
-        [clojure.string :only (split)])
-  (:require [forma.source.modis :as m]
->>>>>>> wgs84-indexer now accepts ascii-map in all cases.
             [forma.hadoop.predicate :as p]
             [clojure.contrib.duck-streams :as duck]))


Make parser less agressive

Make parser less agressive

--- src/clj/subman_parser/const.clj
+++ src/clj/subman_parser/const.clj
@@ -26,7 +26,7 @@

 (def update-deep 10)

-(def update-period (* 5 60 1000))
+(def update-period (* 30 60 1000))

 (def crawl-period (* 24 60 60 1000))

@@ -44,4 +44,4 @@

 (def crawl-workers 1)

-(def crawl-limit 100000)
+(def crawl-limit 1000)


deleted multiple dependency

deleted multiple dependency

--- src/cljs/cljs_repl_web/app.cljs
+++ src/cljs/cljs_repl_web/app.cljs
@@ -4,8 +4,7 @@
             [re-frame.core :refer [dispatch subscribe]]
             [re-complete.app :as complete-app]
             [replumb.ast :as ast]
-            [clojure.string :as str]
-            [replumb.ast :as ast]))
+            [clojure.string :as str]))

 (defn gist-showing?
   "Given a db, indicates if the gist login dialog is shown.


New function main-line.

New function main-line.

Adds a new function main-line that takes a game as input and returns a
vector of the main line nodes from the root, ignoring younger children.

--- src/clojure/clj_chess/game.cljc
+++ src/clojure/clj_chess/game.cljc
@@ -1,7 +1,8 @@
 (ns clj-chess.game
   "Tree data structure for representing an annotated game with variations.
   Work in progress, use at your own risk."
-  (:require [clojure.zip :as zip]
+  (:require [clojure.string :as str]
+            [clojure.zip :as zip]
             #?(:clj [clojure.pprint :refer [cl-format]]
                :cljs [cljs.pprint :refer [cl-format]])
             [clj-chess.board :as board]
@@ -451,6 +452,18 @@
   [game]
   (when-not (at-beginning? game)
     (remove-node game)))
+
+
+(defn main-line
+  "Returns a vector of all moves along the main line of the game, beginning
+  with the root and selecting the oldest child until a leaf is reached."
+  [game]
+  (loop [node (:root-node game)
+         result []]
+    (let [child (first (:children node))]
+      (if-not child
+        (conj result node)
+        (recur child (conj result node))))))

 (defn to-uci
@@ -567,3 +580,4 @@
     (-> game (add-san-move-sequence
                (filter string? (-> parsed-pgn (nth 2) rest))))))

+


get-wishlist now returns a map instead of list of map

--- src/wishlistd/models/queries.clj
+++ src/wishlistd/models/queries.clj
@@ -24,7 +24,7 @@
   (sql/with-connection db
 	(sql/with-query-results results
       ["select * from wishlist where code=?" code]
-      (into [] results))))
+      (first (into [] results)))))

 (defn insert-wishlist [wishlist]
   (sql/with-connection db


Remove a debugging println.

Remove a debugging println.

--- src/sparkle/fadecandy_opc.clj
+++ src/sparkle/fadecandy_opc.clj
@@ -39,7 +39,6 @@
    device."
   (doseq [[channel-num pixels] pixel-map]
     (let [pixel-byte-count (* 3 (count pixels))]
-      (println pixels)
       (gloss-io/encode-to-stream set-color-packet @fc-conn
         (seq
           [{:channel-num channel-num


Fix cljs tests.

Fix cljs tests.

--- test/cats/runner.cljs
+++ test/cats/runner.cljs
@@ -3,21 +3,13 @@
             [cljs.test :as test]
             [cats.core-spec]
             [cats.builtin-spec]
-            [cats.applicative.validation]
             [cats.monad.exception-spec]
             [cats.monad.either-spec]
             [cats.monad.maybe-spec]
             [cats.monad.identity-spec]
             [cats.labs.sugar-spec]
-            [cats.labs.continuation-spec]
             [cats.labs.channel-spec]
-            [cats.labs.state-spec]
-            [cats.labs.reader-spec]
-            [cats.labs.writer-spec]
-            [cats.labs.crdt.pncounter-spec]
-            [cats.labs.crdt.gcounter-spec]
-            [cats.labs.crdt.gset-spec]
-            [cats.labs.lens-spec]))
+            [cats.labs.promise-spec]))

 (enable-console-print!)

@@ -26,21 +18,13 @@
    (test/empty-env)
    'cats.core-spec
    'cats.builtin-spec
-   'cats.applicative.validation
    'cats.monad.exception-spec
    'cats.monad.either-spec
    'cats.monad.maybe-spec
    'cats.monad.identity-spec
    'cats.labs.sugar-spec
-   'cats.labs.continuation-spec
-   'cats.labs.state-spec
-   'cats.labs.reader-spec
-   'cats.labs.writer-spec
    'cats.labs.channel-spec
-   'cats.labs.crdt.pncounter-spec
-   'cats.labs.crdt.gcounter-spec
-   'cats.labs.crdt.gset-spec
-   'cats.labs.lens-spec))
+   'cats.labs.promise-spec))

 (defmethod test/report [:cljs.test/default :end-run-tests] [m]
   (when-not (test/successful? m)


prefix-trie is faster now

prefix-trie is faster now

--- perf-test/clj/reitit/prefix_tree_perf_test.clj
+++ perf-test/clj/reitit/prefix_tree_perf_test.clj
@@ -2,7 +2,8 @@
   (:require [clojure.test :refer :all]
             [io.pedestal.http.route.prefix-tree :as p]
             [reitit.segment :as segment]
-            [criterium.core :as cc]))
+            [criterium.core :as cc])
+  (:import (reitit Trie)))

 ;;
 ;; testing
@@ -69,11 +70,13 @@
       (p/insert acc p d))
     nil routes))

-(def reitit-segment
-  (reduce
-    (fn [acc [p d]]
-      (segment/insert acc p d))
-    nil routes))
+(def matcher
+  (.matcher
+    ^Trie
+    (reduce
+      (fn [acc [p d]]
+        (segment/insert acc p d))
+      nil routes)))

 (defn bench! []

@@ -105,8 +108,9 @@
   ;;  1.0µs (Match records)
   ;; 0.63µs (Single sweep path paraµs)
   ;; 0.51µs (Cleanup)
+  ;; 0.33µs (Java)
   (cc/quick-bench
-    (segment/lookup reitit-segment "/v1/orgs/1/topics")))
+    (segment/lookup matcher "/v1/orgs/1/topics")))

 (comment
   (bench!))
@@ -114,4 +118,4 @@
 (comment
   (p/lookup pedestal-tree "/v1/orgs/1/topics")
   #_(trie/lookup reitit-tree "/v1/orgs/1/topics" {})
-  (segment/lookup reitit-segment "/v1/orgs/1/topics"))
+  (segment/lookup matcher "/v1/orgs/1/topics"))


move show-spec from dag_unify to here

move show-spec from dag_unify to here

--- src/babel/cache.cljc
+++ src/babel/cache.cljc
@@ -7,8 +7,9 @@
    [clojure.string :as string]
    #?(:clj [clojure.tools.logging :as log])
    #?(:cljs [babel.logjs :as log])
-   ;; TODO: be more specific in :refer than :all.
-   [dag_unify.core :refer [fail? get-in label-of show-spec unifyc]]
+   [dag_unify.core :refer [fail? dissoc-paths get-in label-of
+                           remove-top-values-log
+                           unifyc]]

    [babel.over :as over]))

@@ -23,6 +24,7 @@

 (def head-cache {})
 (def comp-cache {})
+(declare show-spec)

 (defn specs-to-subsets [lexicon-of-heads lexicon]
   (if (not (empty? lexicon-of-heads))
@@ -212,3 +214,18 @@
             grammar)})))

+(defn show-spec [spec]
+  (cond (seq? spec)
+        (map show-spec spec)
+        true
+        (remove-top-values-log (dissoc-paths spec '((:english :initial)
+                                                    (:italiano :initial)
+                                                    (:synsem :essere)
+                                                    (:synsem :agr)
+                                                    (:synsem :pronoun)
+                                                    (:synsem :sem :tense)
+                                                    (:synsem :sem :obj :tense)
+                                                    (:synsem :sem :mod)
+                                                    (:synsem :infl))))))
+
+


improve logging

improve logging

--- src/babel/parse.cljc
+++ src/babel/parse.cljc
@@ -17,7 +17,9 @@
 (defn over [grammar left right morph]
   "opportunity for additional logging before calling the real (over)"
   (log/trace (str "parse/over: grammar size: " (count grammar)))
-  (log/debug (str "parse/over: left: " (morph left) "; right: " (morph right)))
+  (log/debug (str "parse/over: "
+                  "left: " (vec (set (map morph left)))
+                  "; right: " (vec (set (map morph right)))))
   (over/over grammar left right))

 (defn square-cross-product [x]


~(defn generate-question-and-correct-set): bind babel.generate/lexical-filter

--- src/babel/reader.clj
+++ src/babel/reader.clj
@@ -134,7 +134,11 @@
         target-model @@(get models target-language)
         target-expression
         (target-timing-fn
-         (binding [babel.generate/truncate? true
+         (binding [babel.generate/lexical-filter
+                   (fn [lexeme]
+                     (and (= false (u/get-in lexeme [target-root-keyword :exception] false))
+                          (= false (u/get-in lexeme [:exception] false))))
+                   babel.generate/truncate? true
                    babel.generate/grammar (or target-grammar-subset
                                               (and
                                                (:rule-matcher-reducer target-model)


all multiple writers: create temporary tables for insertion with random names

--- src/babel/writer.clj
+++ src/babel/writer.clj
@@ -275,10 +275,11 @@
                          count
                          (if (> current-target-count 0) " more")
                          " expressions for spec: " spec))
-          (populate count
+          (populate 1
                     source-model
                     target-model
-                    spec table))
+                    spec table)
+          (fill-by-spec spec (- count 1) table source-model target-model))
         (log/debug (str "Since no more are required, not generating any for this spec."))))))

 (defn fill-verb [verb count source-model target-model & [spec table]] ;; spec is for additional constraints on generation.
@@ -360,9 +361,12 @@

 (defn process [units target-language]
   (log/debug "Starting processing with: " (.size units) " instruction(s) for language " target-language)
-  (let [import_table (str "expression_import_" target-language)
-        expression_distinct_table (str "expression_distinct_" target-language)]
-
+
+  ;; cleanup: TODO: use temporary tables
+  (let [import_table (str "expression_import_" target-language "_" (rand-int 1000000))
+        expression_distinct_table (str "expression_distinct_" target-language "_" (rand-int 1000000))]
+
+    ;; cleanup: TODO: use temporary tables
     (exec-raw (str "DROP TABLE IF EXISTS " import_table))

     (exec-raw (str "CREATE TABLE " import_table " (
@@ -411,6 +415,7 @@
                 units))
     (exec-raw [(str "SELECT count(*) FROM " import_table)] :results)

+    ;; cleanup: TODO: use temporary tables
     (exec-raw (str "DROP TABLE IF EXISTS " expression_distinct_table))

     (exec-raw (str "CREATE TABLE " expression_distinct_table " (
@@ -427,6 +432,11 @@
     (exec-raw (str "INSERT INTO expression (language,model,surface,structure,serialized)
                     SELECT language,model,surface,structure,serialized
                       FROM " expression_distinct_table ""))
+
+    ;; cleanup: TODO: use temporary tables
+    (exec-raw (str "DROP TABLE " expression_distinct_table))
+    (exec-raw (str "DROP TABLE " import_table))
+
     ))

 ;; (process accompany care fornire indossare moltiplicare recuperare riconoscere riscaldare)


♻ Destructuring for better names

♻ Destructuring for better names

--- src/territory_bro/permissions.clj
+++ src/territory_bro/permissions.clj
@@ -5,10 +5,10 @@
 (ns territory-bro.permissions
   (:require [medley.core :refer [dissoc-in]]))

-(defn- path [user-id permission]
+(defn- path [user-id [permission-name & resource-ids]]
   (->> nil
-       (cons (first permission))
-       (concat (rest permission))
+       (cons permission-name)
+       (concat resource-ids)
        (cons user-id)
        (cons ::permissions)))


Adds more test-coverage to rightmost-node

--- src/the_little_clojurian/todo.clj
+++ src/the_little_clojurian/todo.clj
@@ -13,8 +13,11 @@
   (is (= (leftmost-node nil)
          nil))

-  (is (= (leftmost-node {:id 1})
+  (is (= (leftmost-node {:id 1})
          {:id 1}))
+
+  (is (= (leftmost-node {:id 2})
+         {:id 2}))

   (is (= (leftmost-node {:id 1 :nodes '({:id 2})})
          {:id 2}))
@@ -34,7 +37,7 @@

   (is (= (rightmost-node nil)
          nil))
-
+
   (is (= (rightmost-node {:id 1})
          {:id 1}))

@@ -45,7 +48,10 @@
          {:id 3}))

   (is (= (rightmost-node {:id 1 :nodes '({:id 2 :nodes ({:id 3})})})
-         {:id 3})))
+         {:id 3}))
+
+  (is (= (rightmost-node {:id 1 :nodes '({:id 2 :nodes ({:id 3})} {:id 4})})
+         {:id 4})))

 (with-test
   (def complete-nodes*


Improve workspace initialization.

Improve workspace initialization.

--- src/uxbox/data/workspace.cljs
+++ src/uxbox/data/workspace.cljs
@@ -59,16 +59,22 @@

 (defn initialize
   "Initialize the workspace state."
-  [projectid pageid]
-  (reify
-    rs/UpdateEvent
-    (-apply-update [_ state]
-      (let [s {:project projectid
-               :flags #{:layers :element-options}
-               :drawing nil
-               :selected #{}
-               :page pageid}]
-        (assoc state :workspace s)))))
+  [project page]
+  (reify
+    rs/UpdateEvent
+    (-apply-update [_ state]
+      (if-let [workspace (:workspace state)]
+        (update state :workspace merge
+                {:project project
+                 :page page
+                 :selected #{}
+                 :drawing nil})
+        (update state :workspace merge
+                {:project project
+                 :page page
+                 :flags #{:layers :element-options}
+                 :selected #{}
+                 :drawing nil})))))

 (defn toggle-flag
   "Toggle the enabled flag of the specified tool."


Set default connection config to freenode for irc adapter

--- src/yetibot/core/adapters/irc.clj
+++ src/yetibot/core/adapters/irc.clj
@@ -180,9 +180,9 @@
   (reset!
     conn
     (irc/connect
-      (:host config)
+      (or (:host config) "irc.freenode.net")
       (read-string (or (:port config) "6667"))
-      (:username config)
+      (or (:username config) (str "yetibot_" (rand-int 1000)))
       :ssl? (boolean (:ssl config))
       :callbacks (callbacks a))))


Cleanup remaining effects

Cleanup remaining effects

--- src/zaffre/animation/wrapper.cljc
+++ src/zaffre/animation/wrapper.cljc
@@ -3,27 +3,15 @@
   (:require
             [clojure.core.async :refer :all :as async :exclude [map into]]
             [zaffre.color :as zcolor]
-            ;[robinson.viewport :as rv]
             [zaffre.terminal :as zat]
-            [zaffre.animation.animatedterminal :as zaat]
             [zaffre.util :as zutil]
             [taoensso.timbre :as log]
-            [overtone.at-at :as atat])
-  #?(:clj
-     (:import  ;zaffre.terminal.Terminal
-               zaffre.animation.animatedterminal.AAnimatedTerminal
-               zaffre.animation.animatedterminal.AId
-               zaffre.animation.animatedterminal.AEffect
-               zaffre.animation.animatedterminal.AFilter
-               zaffre.animation.animatedterminal.AMask
-               zaffre.animation.animatedterminal.ARequiresState
-               zaffre.animation.animatedterminal.APalette)))
+            [overtone.at-at :as atat]))

 #?(:clj
 (set! *warn-on-reflection* true))

-(def frame-count (atom 0))
 (def ^:dynamic *rain-rate* 0.96)

@@ -35,7 +23,7 @@
   (let [[vw vh] (size terminal)]
     (repeat vh (vec (repeat vw nil)))))

-(defn lantern-flicker [opts x y fg]
+#_(defn lantern-flicker [opts x y fg]
   {:post [(vector? %)]}
   (if (get opts :lantern-flicker)
     (let [v                   (int (* 50 (/ (Math/abs (hash @frame-count)) Integer/MAX_VALUE)))
@@ -49,13 +37,6 @@
       (zcolor/darken-rgb fg
                          (min 1 (/ 2 (max 1 distance)))))
     fg))
-
-(defn night-tint [opts x y fg]
-  (if-let [day? (get opts :night-tint)]
-    (zcolor/night-tint fg day?)
-    fg))
-
-(defn no-op-filter [_ _ _ bg] bg)

 ;;; Effects
@@ -172,43 +153,6 @@
            nil)
          (rain-transition advanced-cell old-cell))))))))

-(defn render-rand-fg
-  [terminal layer-id x y cell-opts cell-palette palette]
-  (let [color-ids (get @palette cell-palette)
-        i         (int (/ @frame-count 10))
-        n         (mod (Math/abs (hash (+ x (* 13 y) (* 17 i)))) (count color-ids))
-        color-id  (nth color-ids n)
-        fg-rgb    (->> (zcolor/color->rgb color-id)
-                    (lantern-flicker cell-opts x y)
-                    (vignette cell-opts x y)
-                    (night-tint cell-opts x y))]
-    (zat/set-fg! terminal layer-id x y fg-rgb)))
-
-(defrecord RandFgEffect
-  [terminal mask opts palette]
-  AId
-  (id [this]
-    :rand-fg)
-  AEffect
-  (apply-effect! [this terminal]
-    (let [[vw vh]    (size terminal)]
-      (doseq [[y line mask-line] (map vector (range) @opts @mask)
-              [x cell-opts mask?] (map vector (range) line mask-line)
-              :let               [cell-palette  (get cell-opts :palette)]
-              :when              cell-palette]
-        (render-rand-fg terminal :map x y cell-opts cell-palette palette))))
-  APalette
-  (update-palette! [this f]
-    (swap! palette f)
-    this))
-
-(defn make-rand-fg-effect
-  [terminal opts]
-  (let [[vw vh]   (size terminal)
-        mask      (atom (repeat vh (repeat vw true)))
-        palette   (atom {})]
-    (RandFgEffect. terminal mask opts palette)))
-
 (defprotocol ACmdStream
   (stream [this]))

@@ -238,139 +182,50 @@
     (fn [terminal]
       (RainEffect. terminal layer-id rain-state))))

-(defn swap-rain-mask! [terminal f]
-  (zaat/swap-matching-effect-or-filter! terminal
-                              (fn [fx] (= (zaat/id fx) :rain))
-                              (fn [rain-fx] (zaat/swap-mask! rain-fx f))))
-
-(defn reset-rain-mask! [terminal v]
-  (zaat/swap-matching-effect-or-filter! terminal
-                              (fn [fx] (= (zaat/id fx) :rain))
-                              (fn [rain-fx]
-                                (let [[columns rows] (size terminal)]
-                                  (zaat/reset-mask! rain-fx (repeat rows (repeat columns v)))))))
-
-(defn transform [terminal mask state transforms]
-  #_(println (format "drawing %d transforms" (count transforms)))
-  (doseq [transform transforms]
-    (let [path (zutil/line-segment-fast-without-endpoints (get transform :from-xy) (get transform :to-xy))
-          n    (int (/ @frame-count 1))]
-      (when (< n (count path))
-        #_(log/info "n" n "count path" (count path))
-        (let [[vx vy] path #_(rv/world-xy->screen-xy state (nth path n))]
-          (when (or true (get-in mask [vy vx]))
-            #_(println "drawing * @ " vx vy)
-            ;(zat/set-char! terminal :fx vx vy \*)
-            (zat/set-fg! terminal :fx vx vy (zcolor/color->rgb :white))
-            (zat/set-bg! terminal :fx vx vy (zcolor/color->rgb :black))))))))
-
 (defrecord TransformEffect
-  [terminal mask state]
-  AId
-  (id [this]
-    :transform)
-  AEffect
-  (apply-effect! [this terminal]
-    (dosync
-      (when-let [state @state]
-        (transform terminal @mask state (get-in state [:fx :transform])))))
-  AMask
-  (swap-mask! [this f]
-    (swap! mask f)
-    ;(println "=====================")
-    ;(doseq [line @mask]
-    ;  (println (mapv (fn [v] (if v 1 0)) line)))
-    this)
-  (reset-mask! [this new-mask]
-    (reset! mask new-mask)
-    this)
-  ARequiresState
-  (reset-state! [this new-state]
-    (reset! state new-state)
-    this)
-  Object
-  (toString [this]
-    (format "TransformEffect terminal, mask, state")))
+  [terminal layer-id ch from to duration]
+  ACmdStream
+  (stream [this]
+    (let [path (zutil/line-segment-fast-without-endpoints from to)
+          dt   (* 1000 (/ duration (count path)))]
+      (go-loop [[x y] (first path) xys (next path)]
+        (zat/clear! terminal layer-id)
+        (zat/put-chars! terminal layer-id [(assoc ch :x x :y y)])
+        (zat/refresh! terminal)
+        (<! (timeout dt))
+        (if xys
+          (recur (first xys) (next xys)))))))

 (defn make-transform-effect
-  [terminal cell-opts]
-  (let [[vw vh]    (size terminal)
-        mask       (atom (repeat vh (repeat vw true)))]
-    (TransformEffect. terminal mask (atom nil))))
-
-(defn blink [terminal state blinks]
-  ;(prinln (format "drawing %d blinks" (count blinks)))
-  (doseq [blink blinks]
-    #_(println @frame-count (mod @frame-count 15))
-    (when (< (mod @frame-count 15) 7)
-      (let [[vx vy] (get blink :xy)]
-          #_(println "drawing * @ " vx vy)
-          (zat/put-chars! terminal :fx [{:x vx :y vy :c \space}])))))
+  [terminal layer-id ch from to duration]
+    (fn [terminal]
+      (TransformEffect. terminal layer-id ch from to duration)))

 (defrecord BlinkEffect
-  [terminal state]
-  AId
-  (id [this]
-    :blink)
-  AEffect
-  (apply-effect! [this terminal]
-    (dosync
-      (when-let [state @state]
-        (blink terminal state (get-in state [:fx :blink])))))
-  ARequiresState
-  (reset-state! [this new-state]
-    (reset! state new-state)
-    this)
-  Object
-  (toString [this]
-    (format "BlinkEffect terminal, state")))
+  [terminal layer-id characters initial intervals]
+  ACmdStream
+  (stream [this]
+    (let [dt 1000]
+      (go-loop [state initial]
+        (zat/clear! terminal layer-id)
+        (when state
+          (zat/put-chars! terminal layer-id characters))
+        (zat/refresh! terminal)
+        (<! (timeout dt))
+        (recur (not state))))))

 (defn make-blink-effect
-  [terminal cell-opts]
-  (let [[vw vh]    (size terminal)]
-    (BlinkEffect. terminal (atom nil))))
-
-(defn blip [terminal state blips]
-  (doseq [blip blips]
-    (let [[vx vy] blip #_(rv/world-xy->screen-xy state (get blip :xy))]
-      ;(println "drawing blip" blip "@" vx vy "frame-count" @frame-count)
-      ;; get the last instant before @frame-count
-      (when-let [instant (->> (get blip :instants)
-                              (filter (fn [instant]
-                                        (< (get instant :time) @frame-count)))
-                              (sort-by (fn [instant]
-                                         (get instant :time)))
-                              last)]
-        ;(println "drawing instant" instant)
-        #_(when-let [ch (get instant :ch)]
-          (zat/set-char! terminal :fx vx vy ch))
-        (when-let [fg (get instant :fg)]
-          (zat/set-fg! terminal :fx vx vy fg))
-        (when-let [bg (get instant :bg)]
-          (zat/set-bg! terminal :fx vx vy bg))))))
-
-(defrecord BlipEffect
-  [terminal state]
-  AId
-  (id [this]
-    :blip)
-  AEffect
-  (apply-effect! [this terminal]
-    (dosync
-      (when-let [state @state]
-        (blip terminal state (get-in state [:fx :blip])))))
-  ARequiresState
-  (reset-state! [this new-state]
-    (reset! state new-state)
-    this)
-  Object
-  (toString [this]
-    (format "BlipEffect terminal, state")))
+  ([layer-id characters]
+    (make-blink-effect layer-id characters true))
+  ([layer-id characters initial]
+    (make-blink-effect layer-id characters initial (constantly 1000)))
+  ([layer-id characters initial intervals]
+    (fn [terminal]
+      (BlinkEffect. terminal layer-id characters initial intervals))))

 (defn make-blip-effect
-  [terminal cell-opts]
-  (let [[vw vh]    (size terminal)]
-    (BlipEffect. terminal (atom nil))))
+  [layer-id characters duration]
+  (make-blink-effect layer-id characters [duration]))

 ;;; Queue cmds in a chan and foreard them to dst-chan on `(refresh)`.
 (defrecord WrappedAnimatedTerminal [terminal cmds dst-chan]
@@ -410,7 +265,8 @@
             effects-cmd-chan (chan 1000)
             wrapped-term    (WrappedAnimatedTerminal. terminal (atom []) cmd-chan)
             effects-term    (WrappedAnimatedTerminal. terminal (atom []) cmd-chan)
-            effects         (atom [((make-rain-effect :fx 16 16) effects-term)])]
+            ;effects         (atom [((make-rain-effect :fx 16 16) effects-term)])]
+            effects         (atom [((make-blink-effect :fx [{:x 8 :y 8 :c \* :fg [128 128 0] :bg [0 0 0]}] true) effects-term)])]
         #_(log/info "overriding terminal")
         #_(log/info "effects" @effects "filters" @filters)
         ;; start effects


removed comment

removed comment

--- example/src/example/core.cljs
+++ example/src/example/core.cljs
@@ -128,6 +128,3 @@
                     ;; which will reload even for non-local changes
                     ;; (example.cube/stop-and-start-ex3)
                     ))
-
-
-#_(fw/defonce reloader)


Add tests to ensure that normalize fns are actually fns

--- test/comic_reader/sites_test.clj
+++ test/comic_reader/sites_test.clj
@@ -103,6 +103,16 @@
     page-list-selector
     image-selector))

+(defn test-normalize-functions []
+  (tu/are-with-msg [norm-fn]
+                   (is (function? norm-fn)
+                       "Normalize values should eval to a function.")
+                   comic-link-name-normalize
+                   comic-link-url-normalize
+
+                   chapter-link-name-normalize
+                   chapter-link-url-normalize))
+
 (defn test-extract-image-tag [html image-tag]
   (and
    (tu/ensure-dependencies-defined extract-image-tag)
@@ -221,6 +231,7 @@
         #(and
           (test-regexes)
           (test-enlive-selectors)
+          (test-normalize-functions)
           (if (has-test-folder?)
             (and
              (test-image-page-extraction)


140 wow solution

140 wow solution

--- stuf/src/sandbox/4clojure.clj
+++ stuf/src/sandbox/4clojure.clj
@@ -1208,4 +1208,31 @@
           terms (largest (minterms k-map))]
       (set (map #(set (make-disj g-map %)) terms)))))

-
+;;wow solutuion
+(letfn
+    [(upsym [s]
+       (symbol (clojure.string/upper-case (name s))))
+     (downsym [s]
+       (symbol (clojure.string/lower-case (name s))))
+     (swapsym [s]
+       (if (= s (upsym s))
+         (downsym s)
+         (upsym s)))
+     (independent [sym s sets]
+       (let [indep (disj s sym)
+             swapped (conj indep (swapsym sym))]
+         (if (or (contains? sets indep)
+                 (contains? sets swapped))
+           indep
+           false)))
+     (update-iter [s sets]
+       (if-let [indep (some #(independent % s sets) s)]
+         indep
+         s))
+     (update [sets]
+       (set (map #(update-iter % sets) sets)))]
+  (defn min-set [sets]
+    (if (= (update sets) sets)
+      sets
+      (min-set (update sets)))))
+


Fixing compile error

Fixing compile error

--- common-lib/src/cmr/common/api/errors.clj
+++ common-lib/src/cmr/common/api/errors.clj
@@ -1,5 +1,5 @@
 (ns cmr.common.api.errors
-  (:require [cmr.common.log :refer [error warn]]
+  (:require [cmr.common.log :refer [error warn info debug]]
             [cmr.common.services.errors :as errors]
             [clojure.data.xml :as x]
             [clojure.string :as str]


Test cursor assertion only if assertions are enabled

--- test/reagenttest/testcursor.cljs
+++ test/reagenttest/testcursor.cljs
@@ -469,5 +469,10 @@
     (is (= @spy false))
     (dispose r)))

+(def assert-enabled? (try (assert false)
+                          false
+                          (catch :default _ true)))
+
 (deftest cursor-assert-test
-  (is (thrown-with-msg? :default #"src must be a reactive atom or a function, not nil while attempting to get path: \[:foo :bar\]" (r/cursor nil [:foo :bar]))))
+  (when assert-enabled?
+    (is (thrown-with-msg? :default #"src must be a reactive atom or a function, not nil while attempting to get path: \[:foo :bar\]" (r/cursor nil [:foo :bar])))))


Remove gensymed args from docs for scheduling options.

--- scheduling/src/immutant/scheduling/options.clj
+++ scheduling/src/immutant/scheduling/options.clj
@@ -1,11 +1,11 @@
 ;; Copyright 2014 Red Hat, Inc, and individual contributors.
-;;
+;;
 ;; Licensed under the Apache License, Version 2.0 (the "License");
 ;; you may not use this file except in compliance with the License.
 ;; You may obtain a copy of the License at
-;;
+;;
 ;; http://www.apache.org/licenses/LICENSE-2.0
-;;
+;;
 ;; Unless required by applicable law or agreed to in writing, software
 ;; distributed under the License is distributed on an "AS IS" BASIS,
 ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -34,11 +34,11 @@
 (def resolve-options (comp at until every in singleton))

 (defmacro defoption [sym doc]
-  `(defn ~sym ~doc [& opts#]
-     (let [[m# & opts#] (if (map? (first opts#))
-                          opts#
-                          (cons {} opts#))
-           opts# (if (> (count opts#) 1)
-                   opts#
-                   (first opts#))]
-       (assoc m# ~(keyword (name sym)) opts#))))
+  `(defn ~sym ~doc [& ~'opts]
+     (let [[m# & ~'opts] (if (map? (first ~'opts))
+                          ~'opts
+                          (cons {} ~'opts))
+           ~'opts (if (> (count ~'opts) 1)
+                   ~'opts
+                   (first ~'opts))]
+       (assoc m# ~(keyword (name sym)) ~'opts))))


Always print log entries, if present.

Always print log entries, if present.

--- test/clj/hatnik/selenium/core.clj
+++ test/clj/hatnik/selenium/core.clj
@@ -137,27 +137,24 @@
          (format "http://expirebox.com/download/%s.html"))))

 (defn print-logs [driver type]
-  (println)
-  (println "######### Webdriver" type "log #########")
   (let [entries (.. driver manage logs (get type))]
-    (doseq [entry entries]
-      (println (str entry))))
-  (println))
-
-(defn fail-report [driver]
-  ; Don't print logs. They turned out to be pretty useless.
-  (doseq [log-type selenium-log-types]
-      (print-logs driver log-type))
-  (timbre/error "Screenshot:" (take-screenshot driver)))
+    (when-not (empty? entries)
+      (println)
+      (println "######### Webdriver" type "log #########")
+      (doseq [entry entries]
+        (println (str entry)))
+      (println))))

 (defn run-with-driver [test-fn]
   (let [driver (create-and-login)]
     (try
       (test-fn driver)
       (catch Exception e
-        (fail-report driver)
+        (timbre/error "Screenshot:" (take-screenshot driver))
         (throw e))
       (finally
+        (doseq [log-type selenium-log-types]
+          (print-logs driver log-type))
         (.quit driver)))))


Fix listener test, needed to add tx id to retract

--- test/clj/libx/listeners_test.cljc
+++ test/clj/libx/listeners_test.cljc
@@ -8,22 +8,25 @@
             [libx.tuplerules :refer [def-tuple-rule def-tuple-session]])
   (:import [libx.util Tuple]))

+(defn trace [& args]
+  (comment (apply prn args)))
+
 (def-tuple-rule insert-logical-for-every-a
   [?f <- [?e :attr/a]]
   =>
-  (println "Found " ?f "Inserting logical fact" [?e :attr/logical-insert ?f])
+  (trace "Found " ?f "Inserting logical fact" [?e :attr/logical-insert ?f])
   (util/insert! [?e :attr/logical-insert ?f]))

 (def-tuple-rule retract-a-fact-that-caused-a-logical-insertion
   [[_ :attr/logical-insert ?f]]
   =>
-  (println "Found " ?f " Retracting its condition for existing")
+  (trace "Found " ?f " Retracting its condition for existing")
   (cr/retract! ?f))

 (def-tuple-rule accumulate-count
   [?facts <- (acc/all) :from [:all]]
   =>
-  (println "All facts" ?facts)
+  (trace "All facts" ?facts)
   (do nil))

 (def background-facts (repeatedly 5 #(vector (guid) :junk 42)))
@@ -91,19 +94,18 @@
                   (util/insert
                     (into
                       [[123 :attr/a "state-0"]
-                       [123 :attr/b "state-0"]]
+                       [123 :attr/b "state-0" 2]]
                       background-facts))
                   (fire-rules))
         ops-0 (l/vec-ops state-0)
         ent-0 (q/entityv state-0 123)
         state-1 (-> state-0
                   (l/replace-listener)
-                  (util/retract [123 :attr/b "state-0"])
+                  (util/retract [123 :attr/b "state-0" 2])
                   (util/insert [123 :attr/b "state-1"])
                   (fire-rules))
         ops-1 (l/vec-ops state-1)
         ent-1 (q/entityv state-1 123)
-        _ (println "Ent 1" ent-1)
         state-2 (-> state-1
                   (l/replace-listener)
                   (util/insert [123 :attr/b "state-2"])


Mocked out tests for literals in tag->react

--- test/cljs/hyjinks/react_test.cljs
+++ test/cljs/hyjinks/react_test.cljs
@@ -13,3 +13,10 @@
               "more text")
             (fn [x] (case x :hello "Hi" x)))]
     (is true)))
+
+(deftest literals
+  (testing "literals should have no apparent effect"
+    (let [d0 (tag->react (h/span "<hi>"))
+          d1 (tag->react (h/span (h/literal "<hi>")))]
+      (is true #_ (= "<hi>" (.-textContent d0)))
+      (is true #_ (= "<hi>" (.-textContent d1))))))


Moar updates to plan over view cards and plan header

--- src-cljs/frontend/components/org_settings.cljs
+++ src-cljs/frontend/components/org_settings.cljs
@@ -32,6 +32,7 @@
                    [frontend.utils :refer [html]]))

 (declare osx-overview)
+(declare osx-plan-overview)
 (declare linux-plan-overview)

 (defn non-admin-plan [{:keys [org-name login vcs_type]} owner]
@@ -458,8 +459,11 @@
         (html
           [:div.osx-plans {:data-component `osx-plans-list}
            [:fieldset
-            [:legend (str "OS X Plans")]
-            [:p [:em "Your selection below only applies to OS X service and will not affect Linux Containers."]]
+            (if (pm/osx? plan)
+              [:legend.update-plan "Update macOS plan"]
+              [:legend.update-plan "Choose macOS plan"]
+              )
+            [:p [:em "Your selection below only applies to macOS service and will not affect Linux containers."]]
             (when (and (pm/osx-trial-plan? plan) (not (pm/osx-trial-active? plan)))
               [:p "The OS X trial you've selected has expired, please choose a plan below."])
             (when (and (pm/osx-trial-plan? plan) (pm/osx-trial-active? plan))
@@ -529,7 +533,9 @@
                                          (str "paid " containers-str
                                               (str (when-not (zero? new-total) (str " at $" new-total "/month")))
                                               " + 1 free container"))]]
-                 [:p (str "Our pricing is flexible and scales with you. Add as many containers as you want for $" linux-container-cost "/month each.")]])
+                 [:p (str "Our pricing is flexible and scales with you. Add as many containers as you want for $" linux-container-cost "/month each.")
+                  [:br]
+                  [:em "Changes to your Linux plan will not affect your macOS plan."]]])
               [:fieldset
                (if (and (not piggiebacked?)
                         (or (config/enterprise?)
@@ -588,10 +594,10 @@
          {:tab-row
           (om/build tabs/tab-row {:tabs [{:name :linux
                                           :icon (html [:i.fa.fa-linux.fa-lg])
-                                          :label "Build on Linux"}
+                                          :label "Linux Plan"}
                                          {:name :osx
                                           :icon (html [:i.fa.fa-apple.fa-lg])
-                                          :label "Build on OS X"}]
+                                          :label "macOS Plan"}]
                                   :selected-tab-name selected-tab-name
                                   :on-tab-click #(navigate! owner (routes/v1-org-settings-path {:org org-name
                                                                                :vcs_type vcs-type
@@ -602,6 +608,7 @@
                    (om/build faq linux-faq-items))

            :osx (list
+                 (om/build osx-plan-overview {:plan plan})
                  (om/build osx-plans-list {:plan plan
                                            :org-name (get-in app state/org-name-path)
                                            :vcs-type (get-in app state/org-vcs_type-path)})
@@ -1253,9 +1260,7 @@
                     [:p "The macOS trial you've selected has expired, please choose a plan below."])
                   (when (and (pm/osx-trial-plan? plan) (pm/osx-trial-active? plan))
                     [:p (gstring/format "You have %s left on the macOS trial." (pm/osx-trial-days-left plan))])]
-                 ;; FIXME 1833: ADD LINK TO FAQs
-                 [:p "Questions? "
-                  [:a "Check out the FAQs"]"."]]
+                 [:p "Questions? Check out the FAQs below."]]
                 [:div {:style {:width "49%" :margin-top "1em"}}
                  (om/build osx-usage-table-plan {:plan plan})]]))])))))

@@ -1371,7 +1376,13 @@
                  (when (and (pm/osx-trial-plan? plan) (pm/osx-trial-active? plan))
                    [:p (gstring/format "You have %s left on the macOS trial." (pm/osx-trial-days-left plan))])]]
                [:div
-                (om/build osx-usage-table-plan {:plan plan})]]))])))))
+                (om/build osx-usage-table-plan {:plan plan})]])
+            [:div
+             [:h1 "No macOS plan selected"]
+             [:p
+              [:strong [:a {:href (routes/v1-org-settings-path {:org plan-org-name
+                                                      :vcs_type plan-vcs-type
+                                                      :_fragment "osx-pricing"})} "Choose a macOS plan"]] "."]])])))))

 (defn linux-plan-overview [app owner]
   (om/component
@@ -1422,12 +1433,9 @@
                                  [:strong [:a {:href (routes/v1-org-settings-path {:org (:name plan-org)
                                                                          :vcs_type (:vcs_type plan-org)
                                                                          :_fragment "linux-pricing"})}
-                                 "change your Linux plan"]]
-                                 " below. "
-                                 [:em "It will not affect your macOS plan."]]))
-                            ;; FIXME 1833: ADD LINK TO FAQs
-                            [:p "Questions? "
-                             [:a "Check out the FAQs"]"."]])]
+                                 "update your Linux plan"]]
+                                 " below. "]))
+                            [:p "Questions? Check out the FAQs below."]])]
                 (= containers 1)
                 [:div
                  [:h1 (str "Current Linux plan: Hobbyist (1 container) - $0/month")]
@@ -1438,14 +1446,9 @@
                    [:a {:href (routes/v1-org-settings-path {:org (:name plan-org)
                                                                     :vcs_type (:vcs_type plan-org)
                                                                     :_fragment "linux-pricing"})}
-                            "Add more containers"]]
-                  (str " to gain access to concurrent builds, parallelism, engineering support, insights, build timings, and other cool stuff. ")]
-                 [:p
-                  "You can choose your Linux plan below. "
-                  [:em "It will not affect your macOS plan."]]
-                 ;; FIXME 1833: ADD LINK TO FAQs
-                 [:p "Questions? "
-                  [:a "Check out the FAQs"]"."]]
+                            "Add more containers to update your plan"]]
+                  (str " and gain access to concurrent builds, parallelism, engineering support, insights, build timings, and other cool stuff. ")]
+                 [:p "Questions? Check out the FAQs below."]]
                 :else nil))
         (when (> (pm/trial-containers plan) 0)
           [:p
@@ -1480,6 +1483,55 @@
         (card/titled {:title (html [:span [:i.fa.fa-linux.title-icon] "Linux Plan Overview"])}
                      (html
                        [:div.plan-overview.linux-plan-overview
+                        (if (config/enterprise?)
+                          [:p "Your organization currently uses a maximum of " containers " containers. If your fleet size is larger than this, you should raise this to get access to your full capacity."]
+
+                          (cond (> containers 1)
+                                [:div
+                                 [:h1 (str "Current Linux plan: " containers " containers - $" (pm/current-linux-cost plan) "/month.")]]
+                                (= containers 1)
+                                [:div
+                                 [:h1 (str "Current Linux plan: Hobbyist (1 container) - $0/month")]
+                                 [:p "0 containers are paid. 1 container is free."]
+                                 [:p
+                                  ;; FIXME 1833: THIS SHOULD ANCHOR TO SECTION BELOW
+                                  [:strong
+                                   [:a {:href (routes/v1-org-settings-path {:org (:name plan-org)
+                                                                                :vcs_type (:vcs_type plan-org)
+                                                                                :_fragment "linux-pricing"})}
+                                            "Add more containers to update your plan"]]
+                                  (str " and gain access to concurrent builds, parallelism, engineering support, insights, build timings, and other cool stuff. ")]]
+                                :else nil))
+                        (when (> (pm/trial-containers plan) 0)
+                          [:p
+                           (str (pm/trial-containers plan) " of these are provided by a trial. They'll be around for "
+                                (pluralize (pm/days-left-in-trial plan) "more day")
+                                ".")])
+                        (when (and (not (config/enterprise?))
+                                   (pm/linux? plan))
+                          [:p
+                           (str (pm/paid-linux-containers plan) " of these are paid")
+                           (if piggiebacked? ". "
+                               (list ", at $" (pm/current-linux-cost plan) "/month. "))
+
+                           (when (and (pm/freemium? plan) (> containers 1))
+                             [:span (str (pm/freemium-containers plan) " container is free.")])
+                           [:br ]
+                           (if (pm/grandfathered? plan)
+                             (list "We've changed our pricing model since this plan began, so its current price "
+                                   "is grandfathered in. "
+                                   "It would be $" (pm/linux-cost plan (pm/linux-containers plan)) " at current prices. "
+                                   "We'll switch it to the new model if you upgrade or downgrade. ")
+                             (list
+                              ;; make sure to link to the add-containers page of the plan's org,
+                              ;; in case of piggiebacking.
+                              [:p
+                                [:strong
+                                [:a {:href (routes/v1-org-settings-path {:org (:name plan-org)
+                                                                       :vcs_type (:vcs_type plan-org)
+                                                                       :_fragment "linux-pricing"})}
+                                "Add more containers"]]
+                                " for more parallelism and shorter queue times."]))])
                         (when (config/enterprise?)
                           (om/build linux-plan {:app app}))]))
         (card/titled {:title (html [:span [:i.fa.fa-apple.title-icon] "macOS Plan Overview"])}


Fix docs/kick.clj

Fix docs/kick.clj

Note that the output is different:
- n-params and n-constants are missing / nil.

--- docs/kick.clj
+++ docs/kick.clj
@@ -1,5 +1,7 @@
 (ns doc.kick
-  (:use [overtone.live]))
+  (:use [overtone.live])
+  (:use [overtone.sc.machinery.synthdef])
+  (:use [clojure.pprint]))

 ;;This is an annotated version of this synth definition to help in understanding
 ;; some basics about synths and the synthdef data structure used in Overtone.
@@ -8,7 +10,7 @@
 ;; sin wave, which is like turning the volume knob up and down really quick while playing
 ;; a low tone.
 (defsynth kick [amp 0.5 decay 0.6 freq 65]
-  (let [env (env-gen (perc 0 decay) 1 1 0 1 :free)
+  (let [env (env-gen (perc 0 decay) 1 1 0 1 FREE)
         snd (sin-osc freq (* Math/PI 0.5) amp)]
     (out 0 (pan2 (* snd env) 0))))

@@ -19,7 +21,7 @@
 ;; which get added by default to synths that are rooted by an audio rate ugen that isn't out.
 (definst kick [amp 0.5 decay 0.6 freq 65]
   (* (sin-osc freq (* Math/PI 0.5) amp)
-     (env-gen (perc 0 decay) 1 1 0 1 :free)))
+     (env-gen (perc 0 decay) 1 1 0 1 FREE)))

 ;; Similarly this is also triggered using the name as a function call:
 (kick)


Adding vec spec tests for types

Adding vec spec tests for types

--- test/fogus/me/invariant_tests.clj
+++ test/fogus/me/invariant_tests.clj
@@ -12,7 +12,7 @@
 ;; remove this notice, or any other, from this software.

 (ns fogus.me.invariant-tests
-  (:use [trammel.core :only [defconstrainedrecord]])
+  (:use [trammel.core :only [defconstrainedrecord defconstrainedtype]])
   (:use [clojure.test :only [deftest is]]))

@@ -20,6 +20,9 @@
   [(every? number? [a b])]
   Object
   (toString [this] (str "record Foo has " a " and " b)))
+
+(defconstrainedtype Bar [a b]
+  [(every? number? [a b])])

 (deftest test-constrained-record-with-vector-spec
   (is (= (:a (->Foo)) 1))
@@ -33,6 +36,11 @@
   (is (= (:c (->Foo :a 42 :b 108 :c 36)) 36))
   (is (thrown? Error (->Foo :a :b)))
   (is (thrown? Error (->Foo :a 42 :b nil))))
+
+(deftest test-constrained-type-with-vector-spec
+  (is (= (.a (->Bar 1 2)) 1))
+  (is (= (:b (->Bar 1 2)) 2))
+  (is (thrown? Error (->Bar :a :b))))

 ;; testing default clojure pre/post maps


Fixed data structure with test results

Fixed data structure with test results

--- src/emender_jenkins/results.clj
+++ src/emender_jenkins/results.clj
@@ -121,8 +121,9 @@
              :book-name   (job-name->book-name job-name)
              :job-status  (compute-job-status job-color buildable?)
              :disabled    (compute-job-disabled job-color buildable?)
-             :message     message
-             :results     (parse-test-results message)
+             :test-summary {
+                 :message     message
+                 :results     (parse-test-results message)}
             })))

 (defn reload-all-results


Rename join to join-q and project to project-q

--- src/aurora/compiler/datalog.cljs
+++ src/aurora/compiler/datalog.cljs
@@ -79,7 +79,7 @@
         facts))
     (meta query)))

-(defn project [pattern kn-f]
+(defn project-q [pattern kn-f]
   (let [return-syms (into [] (match/vars pattern))
         return-keys (map keyword return-syms)
         shape (into #{} return-keys)
@@ -94,7 +94,7 @@
       {::shape shape})))

 ;; TODO hashjoin instead
-(defn join [query1 query2]
+(defn join-q [query1 query2]
   (let [shape (union (::shape (meta query1)) (::shape (meta query2)))
         join-shape (intersection (::shape (meta query1)) (::shape (meta query2)))]
     (with-meta
@@ -154,16 +154,16 @@
    (fn [query clause]
      (debug-q
       (condp op? clause
-        '+ed (join query (project (second clause) :asserted))
-        '-ed (join query (project (second clause) :retracted))
+        '+ed (join-q query (project-q (second clause) :asserted))
+        '-ed (join-q query (project-q (second clause) :retracted))
         '? (filter-q query (second clause))
-        'set (join query (set-q (nth clause 1) (nth clause 2) (nthnext clause 3)))
+        'set (join-q query (set-q (nth clause 1) (nth clause 2) (nthnext clause 3)))
         'in (in-q query (nth clause 1) (nth clause 2))
         '+ query ;; handled later
         '+s query ;; handled later
         '- query ;; handled later
         '-s query ;; handled later
-        (join query (project clause to-be)))))
+        (join-q query (project-q clause to-be)))))
    empty-q
    clauses))

@@ -213,11 +213,11 @@

 (comment

-  ((project '[a b] to-be) (Knowledge. #{[1 2] [3 4 5] [6 7]} #{} #{}))
-
-  ((join (project '[a b _] to-be) (project '[_ a b] to-be)) (Knowledge. #{[1 2 3] [2 3 4] [2 4 6] [4 6 8]} #{} #{}))
-
-  ((filter-q (project '[a b] to-be) (fnk [a b] (= a b))) (Knowledge. #{[1 2] [3 4] [6 6]} #{} #{}))
+  ((project-q '[a b] to-be) (Knowledge. #{[1 2] [3 4 5] [6 7]} #{} #{}))
+
+  ((join-q (project-q '[a b _] to-be) (project-q '[_ a b] to-be)) (Knowledge. #{[1 2 3] [2 3 4] [2 4 6] [4 6 8]} #{} #{}))
+
+  ((filter-q (project-q '[a b] to-be) (fnk [a b] (= a b))) (Knowledge. #{[1 2] [3 4] [6 6]} #{} #{}))

   (query* ['[a b _] '[_ a b] (list '? (fnk [a] (integer? a))) (list '+ (fnk [a b] (+ a b)))])


lein: cider-nrepl bump

lein: cider-nrepl bump

--- lein_profiles.clj
+++ lein_profiles.clj
@@ -2,7 +2,7 @@
                   [lein-ring "0.9.3"]
                   [lein-ancient "0.6.5"]
                   [jonase/eastwood "0.2.1"]
-                  [cider/cider-nrepl "0.8.2"]
+                  [cider/cider-nrepl "0.9.0-SNAPSHOT"]
                   ]}}
 {:dev {:dependencies
        [[com.cemerick/pomegranate "0.3.0"]]


Fixed join-str bugs

Fixed join-str bugs

--- lib/compojure.clj
+++ lib/compojure.clj
@@ -36,8 +36,13 @@

 (defn join-str
   "Join a sequence of strings together with an optional separator string."
-  ([coll]     (join-str coll ""))
-  ([coll sep] (reduce (fn [a x] (str a sep x)) coll)))
+  ([coll]
+    (apply str coll))
+  ([coll sep]
+    (reduce
+      (fn [a b] (str a sep b))
+      (str (first coll))
+      (rest coll))))

 (defn chunks
   "Group n consecutive items in a sequence together.


Make the bot name a bit more memorable

Make the bot name a bit more memorable

--- airesources/Clojure/src/MyBot.clj
+++ airesources/Clojure/src/MyBot.clj
@@ -17,7 +17,8 @@
                *planets* (:planets m#)]
        ~@body)))

-(def my-bot-name "mybot") ;; Replace this with your bot name here.
+;; Here we set the bot name to Hickey.
+(def my-bot-name "Hickey")
 (defmacro initialize-game
   [& body]
   `(let [prelude# (io/read-prelude)


fully implement Starlight Crusade Funding

--- src/clj/game/cards-resources.clj
+++ src/clj/game/cards-resources.clj
@@ -509,7 +509,13 @@
    {:events {:agenda-scored {:msg "trash the top card of R&D" :effect (effect (mill :corp))}}}

    "Starlight Crusade Funding"
-   {:events {:runner-turn-begins {:msg "lose [Click]" :effect (effect (lose :click 1))}}}
+   {:msg "ignore additional costs on Double events"
+    :effect (req (swap! state assoc-in [:runner :register :double-ignore-additional] true))
+    :events {:runner-turn-begins
+             {:msg "lose [Click] and ignore additional costs on Double events"
+              :effect (req (lose state :runner :click 1)
+                           (swap! state assoc-in [:runner :register :double-ignore-additional] true))}}
+    :leave-play (req (swap! state update-in [:runner :register] dissoc :double-ignore-additional))}

    "Stim Dealer"
    {:events {:runner-turn-begins


clean up post-edit for entities

clean up post-edit for entities

--- src/cljs/clj_money/entities.cljs
+++ src/cljs/clj_money/entities.cljs
@@ -19,15 +19,28 @@
   [entity]
   (reset! editing-entity entity))

-(defn- finish-edit
+(defn- relay-updated-entity
+  "Accepts an entity and replaces the corresponding enty
+  in all-entities"
+  [entity]
+  (swap! all-entities
+         #(map (fn [e]
+                 (if (= (:id e)  (:id entity))
+                   entity
+                   e))
+               %)))
+
+(defn- finalize-edit
+  [entity]
+  (relay-updated-entity entity)
+  (reset! editing-entity nil))
+
+(defn- submit-edit
   []
   ; TODO Add something to show the user the save is happening in the background
-  (let [updated (data/update-entity @editing-entity (constantly true) #(notify/danger %))]
-    (swap! all-entities #(map (fn [e]
-                               (if (= (:id e)  (:id updated))
-                                 updated
-                                 e)))))
-  (reset! editing-entity nil))
+  (data/update-entity @editing-entity
+                      finalize-edit
+                      #(notify/danger %)))

 (defn- cancel-edit
   []
@@ -48,7 +61,7 @@
   [:form
    (text-input :name required)
    (radio-buttons :settings.inventory-method ["fifo" "lifo"])
-   [:button.btn.btn-primary {:type :button :on-click finish-edit}
+   [:button.btn.btn-primary {:type :button :on-click submit-edit}
     [:span.glyphicon.glyphicon-ok {:aria-hidden "true"}]
     (util/space) "Save"]
    (util/space)


Remove println.

Remove println.

--- frontend/src/uxbox/main/data/shapes.cljs
+++ frontend/src/uxbox/main/data/shapes.cljs
@@ -293,7 +293,6 @@
 (deftype UpdateAttrs [id attrs]
   ptk/WatchEvent
   (watch [_ state stream]
-    (println "update-attrs" id attrs)
     (let [{:keys [type] :as shape} (get-in state [:shapes id])]
       (if (= type :group)
         (rx/from-coll (map #(UpdateAttrs. % attrs) (:items shape)))


bump refactor-nrepl version

bump refactor-nrepl version

--- extra/profiles.clj
+++ extra/profiles.clj
@@ -1,6 +1,6 @@
 {:user
  {:plugins [[cider/cider-nrepl "0.15.0-SNAPSHOT"]
             [lein-pprint "1.1.1"]
-            [refactor-nrepl "2.3.0-SNAPSHOT"]
+            [refactor-nrepl "2.4.0-SNAPSHOT"]
             [venantius/ultra "0.4.1"]]
   :dependencies [[org.clojure/tools.nrepl "0.2.12"]]}}


allow explicit target entity values

allow explicit target entity values

--- src/er_cassandra/model/types.clj
+++ src/er_cassandra/model/types.clj
@@ -56,7 +56,9 @@
   (let [BaseDenormalizationRelationshipSchema
         {;; namespace qualified keyword referencing the target Entity var.
          ;; will be dynamically deref'd
-         :target s/Keyword
+         :target (s/conditional
+                  keyword? s/Keyword
+                  :else {s/Keyword s/Any})
          ;; the fields to be denormalized
          :denormalize DenormalizeSchema
          ;; what to do with target records if a source record


reporter: don't use ':or' in 'match'

reporter: don't use ':or' in 'match'

--- src/fowles/yt_fetch/reporter.clj
+++ src/fowles/yt_fetch/reporter.clj
@@ -50,11 +50,13 @@
 (defn mk-pusher
   [host port]
   (let [pusher (util/mk-pusher host port)]
-    ;; acc is seq of 'resp-body', each a clj data structure (not json).
+    ;; acc is seq of 'resp-body', each a clj data structure (not json str).
     (fn [{:keys [request resp-bodies]}]
       (match (:query-type request)
-             (:or :channels :videos) (push-items pusher request resp-bodies)
-             :activities  (push-activities-fancy pusher request resp-bodies)
-             :playlistItems       (push-playlist pusher request resp-bodies)
+             ;; Don't use `:or`, as it doesn't always seem to work!?
+             :channels      (push-items pusher request resp-bodies)
+             :videos        (push-items pusher request resp-bodies)
+             :activities    (push-activities-fancy pusher request resp-bodies)
+             :playlistItems (push-playlist pusher request resp-bodies)
              ;; throw!
              :else nil))))