adding in big list of features

adding in big list of features

--- frontend/components/pricing-b.cljs
+++ frontend/components/pricing-b.cljs
@@ -37,7 +37,8 @@
           [:section.pricing-intro
            [:article
             [:h1 "Transparent pricing, built to scale."]
-            [:h3 "The first container is free and each additional one is $50/mo."]]
+            [:h3 "The first container is free and each additional one is $50/mo. "
+                 [:a "Need enterprise pricing?"]]]
            [:div.pricing-calculator
             [:div.pricing-calculator-controls
              [:div.controls-containers
@@ -49,7 +50,7 @@
                [:figure.range-knob]]]
              [:div.controls-parallelism
               [:h2 "Parallelism"]
-              [:h5 "You could run X concurrent builds with X containers and X parallelism. (You can adjust per project.)"]
+              [:h5 "You can run X concurrent builds with X containers and X parallelism. (Adjustable per project.)"]
               [:div.parallelism-options
                [:button "1x"]
                [:button "4x"]
@@ -76,5 +77,32 @@
              [:div.calculator-preview-item
               [:div.item "Cost"]
               [:div.value "0"]]
-             [:a.pricing-action {:role "button"} "Sign Up Free"]]]]]
+             [:a.pricing-action {:role "button"} "Sign Up Free"]]]
+           [:article.pricing-features
+            [:div.pricing-feature
+             [:h3 "Continuous Deployment"]
+             [:p "If your tests work, deploy straight to staging, production, or a QA server.
+                 Deploy anywhere, including Heroku, DotCloud, EngineYard, etc, or using Capistrano, Fabric or custom commands."]]
+            [:div.pricing-feature
+             [:h3 "Easy Debugging"]
+             [:p "When your tests are broken, we help you get them fixed. We automatically warn you about common mistakes, and document how to fix them.
+                 We provide all the information you need to reproduce an error locally.
+                 And if you still can't reproduce it, you can SSH into our VMs to debug it yourself."]]
+            [:div.pricing-feature
+             [:h3 "Personalized Notifications"]
+             [:p "You don't care what John did in his feature branch, but you care what gets pushed to master.
+                 Who cares if the tests pass yet again, you only want notifications when they fail.
+                 Circle intelligently notifies you about the tests you care about, and does it over email, Hipchat, Campfire, FlowDock, IRC and webhooks."]]]
+           [:article
+            [:h2 "How do containers work?"]
+            [:p "Every time you push to GitHub, we checkout your code and run your build inside of a container.
+                 If you don't have enough free containers available, then your builds queue up until other builds finish."]
+            [:p "Everyone gets their first container free and your team can run as many builds as you want with that container.
+                 More containers allows faster builds through parallellism in addition shorter queue times"]
+            [:p "Parallelism is an extrememly powerful feature and allows to dramitcally speed up your test suite.
+                 CircleCI automatically splits your tests across multiple containers, finishing your build in a fraction of the time."]]
+           [:article
+            [:h2 "How many containers do I need?"]
+            [:p "Most of our customers use about 2.5 containers per full-time developer.
+                 Every team is different however and we're happy to set you up with a trial to help you figure out how many works best for you."]]]]
          (common/footer)]))))


DJSON-35 Use Appendable instead of PrintWriter

Signed-off-by: Alex Miller <99328387f8334f68433c424d2dfd83062f62754b@cognitect.com>

--- src/main/clojure/clojure/data/json.clj
+++ src/main/clojure/clojure/data/json.clj
@@ -306,19 +306,19 @@

 (defprotocol JSONWriter
   (-write [object out options]
-    "Print object to PrintWriter out as JSON"))
-
-(defn- ->hex-string [^PrintWriter out cp]
+    "Print object to Appendable out as JSON"))
+
+(defn- ->hex-string [^Appendable out cp]
   (let [cpl (long cp)]
-    (.write out "\\u")
+    (.append out "\\u")
     (cond
       (< cpl 16)
-      (.write out "000")
+      (.append out "000")
       (< cpl 256)
-      (.write out "00")
+      (.append out "00")
       (< cpl 4096)
-      (.write out "0"))
-    (.write out (Integer/toHexString cp))))
+      (.append out "0"))
+    (.append out (Integer/toHexString cp))))

 (def ^{:tag "[S"} codepoint-decoder
   (let [shorts (short-array 128)]
@@ -337,35 +337,35 @@
           (aset shorts i (short 0)))))
     shorts))

-(defn- write-string [^CharSequence s ^PrintWriter out options]
+(defn- write-string [^CharSequence s ^Appendable out options]
   (let [decoder codepoint-decoder]
-    (.write out (codepoint \"))
+    (.append out (codepoint \"))
     (dotimes [i (.length s)]
       (let [cp (int (.charAt s i))]
         (if (< cp 128)
           (case (aget decoder cp)
-            0 (.write out cp)
-            1 (do (.write out (codepoint \\)) (.write out cp))
-            2 (.write out (if (get options :escape-slash) "\\/" "/"))
-            3 (.write out "\\b")
-            4 (.write out "\\f")
-            5 (.write out "\\n")
-            6 (.write out "\\r")
-            7 (.write out "\\t")
+            0 (.append out cp)
+            1 (do (.append out (codepoint \\)) (.append out cp))
+            2 (.append out (if (get options :escape-slash) "\\/" "/"))
+            3 (.append out "\\b")
+            4 (.append out "\\f")
+            5 (.append out "\\n")
+            6 (.append out "\\r")
+            7 (.append out "\\t")
             8 (->hex-string out cp))
           (codepoint-case cp
             :js-separators (if (get options :escape-js-separators)
                              (->hex-string out cp)
-                             (.write out cp))
+                             (.append out cp))
             (if (get options :escape-unicode)
               (->hex-string out cp) ; Hexadecimal-escaped
-              (.write out cp))))))
-    (.write out (codepoint \"))))
-
-(defn- write-object [m ^PrintWriter out options]
+              (.append out cp))))))
+    (.append out (codepoint \"))))
+
+(defn- write-object [m ^Appendable out options]
   (let [key-fn (:key-fn options)
         value-fn (:value-fn options)]
-    (.print out \{)
+    (.append out \{)
     (loop [x m, have-printed-kv false]
       (when (seq x)
         (let [[k v] (first x)
@@ -377,52 +377,52 @@
           (if-not (= value-fn out-value)
             (do
               (when have-printed-kv
-                (.print out \,))
+                (.append out \,))
               (write-string out-key out options)
-              (.print out \:)
+              (.append out \:)
               (-write out-value out options)
               (when (seq nxt)
                 (recur nxt true)))
             (when (seq nxt)
               (recur nxt have-printed-kv)))))))
-  (.print out \}))
-
-(defn- write-array [s ^PrintWriter out options]
-  (.print out \[)
+  (.append out \}))
+
+(defn- write-array [s ^Appendable out options]
+  (.append out \[)
   (loop [x s]
     (when (seq x)
       (let [fst (first x)
             nxt (next x)]
         (-write fst out options)
         (when (seq nxt)
-          (.print out \,)
+          (.append out \,)
           (recur nxt)))))
-  (.print out \]))
-
-(defn- write-bignum [x ^PrintWriter out options]
-  (.print out (str x)))
-
-(defn- write-float [^Float x ^PrintWriter out options]
+  (.append out \]))
+
+(defn- write-bignum [x ^Appendable out options]
+  (.append out (str x)))
+
+(defn- write-float [^Float x ^Appendable out options]
   (cond (.isInfinite x)
         (throw (Exception. "JSON error: cannot write infinite Float"))
         (.isNaN x)
         (throw (Exception. "JSON error: cannot write Float NaN"))
         :else
-        (.print out x)))
-
-(defn- write-double [^Double x ^PrintWriter out options]
+        (.append out (str x))))
+
+(defn- write-double [^Double x ^Appendable out options]
   (cond (.isInfinite x)
         (throw (Exception. "JSON error: cannot write infinite Double"))
         (.isNaN x)
         (throw (Exception. "JSON error: cannot write Double NaN"))
         :else
-        (.print out x)))
-
-(defn- write-plain [x ^PrintWriter out options]
-  (.print out x))
-
-(defn- write-null [x ^PrintWriter out options]
-  (.print out "null"))
+        (.append out (str x))))
+
+(defn- write-plain [x ^Appendable out options]
+  (.append out (str x)))
+
+(defn- write-null [x ^Appendable out options]
+  (.append out "null"))

 (defn- write-named [x out options]
   (write-string (name x) out options))
@@ -514,14 +514,14 @@
         returns itself, the key-value pair will be omitted from the
         output. This option does not apply to non-map collections."
   [x ^Writer writer & options]
-  (-write x (PrintWriter. writer) (merge default-write-options (apply array-map options))))
+  (-write x writer (merge default-write-options (apply array-map options))))

 (defn write-str
   "Converts x to a JSON-formatted string. Options are the same as
   write."
   [x & options]
-  (let [sw (StringWriter.)]
-    (-write x (PrintWriter. sw) (merge default-write-options (apply array-map options)))
+  (let [sw (StringBuilder.)]
+    (-write x sw (merge default-write-options (apply array-map options)))
     (.toString sw)))

 ;;; JSON PRETTY-PRINTER


eliminate reflection warning

eliminate reflection warning

--- src/calfpath/internal.cljc
+++ src/calfpath/internal.cljc
@@ -129,10 +129,10 @@
                {}
                old-map)
              new-map)
-      :clj (.cons ^clojure.lang.APersistentMap (if (nil? old-map)
-                                                 {}
-                                                 old-map)
-             new-map)))
+     :clj (let [^clojure.lang.APersistentMap apmap (if (nil? old-map)
+                                                     {}
+                                                     old-map)]
+            (.cons apmap new-map))))

 #?(:cljs (def reduce-mkv reduce-kv)


remove unused event

remove unused event

--- src_practitioner/practitioner/events.cljs
+++ src_practitioner/practitioner/events.cljs
@@ -61,27 +61,6 @@
   {:uri "/Patient"}
   :mutator #(list-to-map-by-id (map :resource %)))

-;; (reg-event-fx
-;;  :do-load-practitioner-patients
-;;  (fn [{:keys [db]} _]
-;;    (let [user-ref @(subscribe [:user-ref])]
-;;      (assert user-ref)
-;;      {:fetch {:uri (str "/Patient?general-practitioner=" user-ref)
-;;               :success :success-load-practitioner-patients}})))
-
-;; (reg-event-db
-;;  :success-load-practitioner-patients
-;;  (fn [db [_ raw-patients-data]]
-;;    (let [user-ref->user-name (into {} (map #(vector (get-in % [:ref :id]) (:id %))
-;;                                            (:users db)))
-;;          patients-data (->> raw-patients-data
-;;                             :entry
-;;                             (map :resource)
-;;                             (map #(assoc % :username
-;;                                          (user-ref->user-name (:id %)))))]
-;;      (assoc db :patients (list-to-map-by-id patients-data)))))
-
-
 ;;
 (reg-event-db
  :set-current-patient


Prettifies Viktram 1.0

Prettifies Viktram 1.0

--- src/clj/game/cards-ice.clj
+++ src/clj/game/cards-ice.clj
@@ -877,9 +877,7 @@

    "Vikram 1.0"
    {:abilities [{:msg "prevent the Runner from using programs for the remainder of this run"}
-                {:label "Trace 4 - Do 1 brain damage"
-                 :trace {:base 4 :msg "do 1 brain damage"
-                         :effect (effect (damage :brain 1 {:card card}))}}]}
+                (trace-ability 4 (do-brain-damage 1))]}

    "Viktor 1.0"
    {:abilities [(do-brain-damage 1)


Fix for Architect installing top card of R&D in NEH.

--- src/clj/game/cards-ice.clj
+++ src/clj/game/cards-ice.clj
@@ -15,7 +15,7 @@
                  :activatemsg "uses Architect to look at the top 5 cards of R&D"
                  :req (req (not (string? target))) :not-distinct true
                  :choices (req (conj (take 5 (:deck corp)) "No install"))
-                 :effect (effect (corp-install target nil {:no-install-cost true}))}
+                 :effect (effect (corp-install (move state side target :play-area) nil {:no-install-cost true}))}
                 {:msg "install a card from Archives" :choices (req (:discard corp))
                  :prompt "Choose a card to install" :effect (effect (corp-install target nil))}
                 {:msg "install a card from HQ" :choices (req (:hand corp))


Fixed misspelling of Corroder

Fixed misspelling of Corroder

--- src/clj/test/core-game.clj
+++ src/clj/test/core-game.clj
@@ -231,7 +231,7 @@
             (is (not-empty (filter #(= (:title %) "Mimic") all-installed)) "Mimic is in all-installed")
             (is (not-empty (filter #(= (:title %) "Omni-Drive") all-installed)) "Omni-Drive is in all-installed")
             (is (not-empty (filter #(= (:title %) "Knight") all-installed)) "Knight is in all-installed")
-            (is (empty (filter #(= (:title %) "Corroder") all-installed)) "Corrder is not in all-installed")))))))
+            (is (empty (filter #(= (:title %) "Corroder") all-installed)) "Corroder is not in all-installed")))))))

 (deftest counter-manipulation-commands
   "Test interactions of various cards with /counter and /adv-counter commands"


Simplify code

Simplify code

--- src/clj_gatling/report.clj
+++ src/clj_gatling/report.clj
@@ -1,11 +1,14 @@
 (ns clj-gatling.report
   (:require [schema.core :refer [validate]]
+            [clojure.set :refer [rename-keys]]
             [clj-gatling.schema :as schema]
-            [clojure.core.async :as a :refer [thread <!!]]))
+            [clojure.core.async :as a :refer [to-chan thread <!!]]))

 (defn create-result-lines [simulation buffer-size results-channel output-writer]
   (validate schema/Simulation simulation)
-  (let [summary (fn [result] (frequencies (mapcat #(map :result (:requests %)) result)))
+  (let [summary (fn [result]
+                  (rename-keys (frequencies (mapcat #(map :result (:requests %)) result))
+                               {true :ok false :ko}))
         ;Note! core.async/partition is deprecated function.
         ;This should be changed to use transducers instead
         results (a/partition buffer-size results-channel)
@@ -17,9 +20,8 @@
                                     (summary result))]
                             (recur (inc idx) (conj threads t)))
                           threads))]
-    (reduce (fn [m [k v]]
-              (if k
-                (update m :ok + v)
-                (update m :ko + v)))
-            {:ok 0 :ko 0}
+    (reduce (fn [m curr]
+              (println m curr)
+              (merge-with + m (apply hash-map curr)))
+            {}
             (mapcat #(<!! %) write-results))))


tokens are now holding their state

tokens are now holding their state

--- src/clj_highlight/core.clj
+++ src/clj_highlight/core.clj
@@ -13,13 +13,13 @@
 	  (cond
 ;	   (prn token kind) nil
 	   (nil? new-state)
-	    (conj (token-seq* (subs s (count token)) token-def (get token-def state) state states) [kind token])
+	    (conj (token-seq* (subs s (count token)) token-def (get token-def state) state states) [kind token states])
 	    (= new-state :pop)
 	    (let [states (pop states)
 		  state (first states)]
-	      (conj (token-seq* (subs s (count token)) token-def (get token-def state) states states) [kind token]))
+	      (conj (token-seq* (subs s (count token)) token-def (get token-def state) states states) [kind token states]))
 	    :else
-	    (conj (token-seq* (subs s (count token)) token-def (get token-def new-state) new-state (conj states new-state)) [kind token]))
+	    (conj (token-seq* (subs s (count token)) token-def (get token-def new-state) new-state (conj states new-state)) [kind token states]))
 	  (token-seq* s token-def defs state states)))))))

@@ -40,7 +40,7 @@
 			   (if-let [num (re-find number-re)]
 			     num
 			     nil))
-			 (if-let [num (re-find #"^\d+(?:(?:/\d+)|(?:(?:.\d*)?(?:e[+-]\d+)?))" s)]
+			 (if-let [num (re-find #"^\d+(?:(?:/\d+)|(?:(?:\.\d*)?(?:e[+-]\d+)?))" s)]
 			   num
 			   nil)))]
   (def clj-syntax
@@ -63,10 +63,10 @@
 (defn mangle-tokens [kind mangle-fn tokenizer]
   (fn mangle-tokens*
     ([string state]
-       (map (fn [[k t]]
-	 (if (= k kind)
-	   (mangle-fn k t)
-	   [k t]))
+       (map (fn [[k t s]]
+	 (if (or (nil? kind) (= k kind))
+	   (mangle-fn k t s)
+	   [k t s]))
 	    (tokenizer string state)))
     ([string]
        (mangle-tokens* string :initial))))
@@ -80,5 +80,5 @@
 	  ([string]
 	  (tokenizer* string :initial)))]
     (if-let [keywords (:keywords syntax)]
-      (mangle-tokens :identifyer (fn [k t] (if (keywords t) [:keyword t] [k t])) tkn)
+      (mangle-tokens :identifyer (fn [k t s] (if (keywords t) [:keyword t s] [k t s])) tkn)
       tkn)))


Add version with helper macro

Add version with helper macro

--- src/clj_tutorials/core.clj
+++ src/clj_tutorials/core.clj
@@ -39,3 +39,16 @@
       (doseq [c cs]
         (async/close! c))
       results)))
+
+
+(defmacro with-channels [binding & body]
+  `(let [~(first binding) (repeatedly ~(second binding) async/chan)
+    ~'result (do ~@body)]
+    (dorun ~'result) ;Lazy results must be evaluated before channels are closed
+    (doseq [~'c ~(first binding)] (async/close! ~'c))                                                        ~'result))
+
+(defn run-with-macro [number-of-users step]
+  (with-channels [cs number-of-users]
+    (doseq [c cs]
+      (go (>! c (step))))
+    (repeatedly number-of-users #(collect-result cs))))


This checkin may mark the rope across the gorge

Successfully submitting a request to start auth to the server, and
getting back its totally bogus response.

Don't particularly want most of that response to wind up on the web
browser, but it still feels like a very nice milestone.

Getting an error in the browser that "[object  Object] is not ISeqable,"
but I don't have any context for it (except that it happens while the
event loop is waiting for input from the outside.

--- src/cljs/frereth/core.cljs
+++ src/cljs/frereth/core.cljs
@@ -20,8 +20,21 @@
         recv (:recv-chan socket-description)]
     (go
       (loop []
-        (log/debug "Top of websocket event handling loop")
-        (let [[incoming ch] (async/alts! [(async/timeout (* 1000 60 5)) recv])]
+        (log/debug "Top of websocket event handling loop with " (pr-str recv)
+                   " a " (type recv)
+                   "\nout of: " (keys socket-description))
+        (let [event-pair
+              (try
+                (async/alts! [(async/timeout (* 1000 60 5)) recv])
+                (catch js/Error ex
+                  ;; I'm getting an Error that looks like it's happening here
+                  ;; that "[object Object] is not ISeqable"
+                  ;; This isn't the case, since we just yielded control
+                  ;; to wait on the incoming event
+                  (log/error ex "Yep, trying to call alts! is failing")))
+              _ (log/debug "alts! returned: " event-pair)
+              [incoming ch] event-pair]
+          (log/debug "Some sort of message received")
           (if (= recv ch)
             (try
               ;; Or maybe this is the start of a message batch?
@@ -101,7 +114,10 @@
   []
   (repl/start)
   (three/start-graphics js/THREE)
-  (swap! global/app-state  channel-swapper (client-sock)))
+  (go
+    (let [channel-creation-loop (client-sock)]
+      (swap! global/app-state  channel-swapper (async/<! channel-creation-loop)))
+    (log/info "Connected to outside world")))
 ;; Because I'm not sure how to trigger this on a page reload
 ;; (there's a built-in figwheel method precisely for this)
 ;; Really just for scaffolding: I won't want to do this after I'm


Put back attack

Put back attack

--- src/cljs/zetawar/game.cljs
+++ src/cljs/zetawar/game.cljs
@@ -625,6 +625,12 @@
          defender (checked-unit-at db game defender-q defender-r)]
      (battle-tx db game attacker defender attacker-damage defender-damage))))

+(defn attack! [conn game-id attacker-q attacker-r defender-q defender-r]
+  (let [db @conn
+        game (game-by-id db game-id)
+        tx (attack-tx db game attacker-q attacker-r defender-q defender-r)]
+    (d/transact! conn tx)))
+
 ;; TODO: remove attack-tx (superceded by battle-tx)
 (defn attack-tx
   ([db game attacker defender]


add note on why specials were renamed

add note on why specials were renamed

--- src/cljs_api_gen/parse.clj
+++ src/cljs_api_gen/parse.clj
@@ -498,7 +498,10 @@
 (defn special-parse->emit-op
   "The names between the parse/emit methods are not always the same:
    (defmethod parse 'op ...)
-   (defmethod emit* :op ...)"
+   (defmethod emit* :op ...)
+
+   See https://dev.clojure.org/jira/browse/CLJS-1461 for the AST spec
+   "
   [name]
   (get '{"js*"    :js
          "."      :dot


(first (filter ...)) is not the same as (some ...)

This reverts commit 6b1c6b6a5070ff0bc62c7818a1dbc51fb43f0a86.

--- src/cljs_api_gen/parse.clj
+++ src/cljs_api_gen/parse.clj
@@ -584,7 +584,7 @@
   "Get derived syntax forms from the given forms."
   [items]
   (let [make-sub-item (fn [info]
-                        (when-let [parent (some #(= (:syntax-form %) (:parent info)) items)]
+                        (when-let [parent (first (filter #(= (:syntax-form %) (:parent info)) items))]
                           (merge parent (base-syntax-item info))))
         sub-items (->> syntax
                        (filter :parent)
@@ -640,7 +640,7 @@
                 (>= *cljs-num* 0)    (parse-clj-core)
                 :else nil)
         match? #(= "destructure" (:name %))
-        item (some match? items)]
+        item (first (filter match? items))]
     (-> item
         (dissoc :signature)
         (merge (base-syntax-item (syntax-map "destructure")))
@@ -658,7 +658,7 @@

 (defn get-non-excluded-macro-api
   [forms macro-api]
-  (let [ns-form (some #(= 'ns (first %)) forms)
+  (let [ns-form (first (filter #(= 'ns (first %)) forms))
         get-excludes #(match % ([:refer-clojure :exclude x] :seq) x :else nil)
         macro-names (->> ns-form (drop 2) (keep get-excludes) first (map str) set)]
     (remove #(macro-names (:name %)) macro-api)))
@@ -858,7 +858,7 @@
                       (>= *cljs-num* 1933) {:ns "special" :name "try"}
                       (>= *cljs-num* 0)    {:ns "cljs.core" :name "try"}
                       :else nil)
-        try-form (some #(= (select-keys % [:ns :name]) try-ns-name) parsed)
+        try-form (first (filter #(= (select-keys % [:ns :name]) try-ns-name) parsed))
         get-sigs (fn [name-]
                    ;; parse docstring for signature of `catch` and `finally`:
                    ;;


show wrapping-reader source for deref and quote syntax forms (close #71)

--- src/cljs_api_gen/parse.clj
+++ src/cljs_api_gen/parse.clj
@@ -485,7 +485,8 @@
             {:syms [macros
                     dispatch-macros
                     read-symbol
-                    read-number]
+                    read-number
+                    wrapping-reader]
              :as items} (zipmap (map :name parsed) parsed)

             make-items
@@ -496,8 +497,11 @@
                   (when-let [info (info-lookup ch)]
                     (assoc (base-item info)
                        :source (:source map-def)
-                       :extra-sources (when-let [f (get items func)]
-                                        [(:source f)]))))))
+                       :extra-sources (if (and (list? func)
+                                               (= 'wrapping-reader (first func)))
+                                        [(:source wrapping-reader)]
+                                        (when-let [f (get items func)]
+                                          [(:source f)])))))))
             make-single
             (fn [info func]
               (assoc (base-item info)


Make simulations a more realistic

Make simulations a more realistic

--- tobias/src/tobias/core.clj
+++ tobias/src/tobias/core.clj
@@ -51,15 +51,21 @@
        (merge env-features)
        (get-winning-ad ads)))

-(defn run-simulation [image]
-  {:winner (rand-nth ads)})
+(defn map-values [m f]
+  (reduce (fn [m' [k v]] (assoc m' k (f v))) {} m))
+
+(defn run-simulation []
+  (let [winner-ad (rand-nth ads)]
+    {:winner winner-ad
+     :features (->> (map-values features rand-nth)
+                    (merge (select-keys winner-ad [:age :gender])))})) ; merge with winner's age/gender

 (defroutes app-routes
   (GET "/" [] (content-type (resource-response "index.html" {:root "public"}) "text/html"))
   (POST "/auction/new"
         {{{image :tempfile} :file} :params} (response (run-auction image {:location :prime :weather :sunny})))
   (POST "/simulation/new"
-        {{{image :tempfile} :file} :params} (response (run-simulation image)))
+        {{{image :tempfile} :file} :params} (response (run-simulation)))
   (route/resources "/")
   (route/not-found "Not Found"))


allow sym->sym mapping in *alias-map*

allow sym->sym mapping in *alias-map*

--- src/main/clojure/clojure/tools/reader.clj
+++ src/main/clojure/clojure/tools/reader.clj
@@ -32,6 +32,11 @@
          ^:dynamic *default-data-reader-fn*
          ^:dynamic *suppress-read*
          default-data-readers)
+
+(defn ^:private ns-name* [x]
+  (if (instance? Namespace x)
+    (name (ns-name x))
+    (name x)))

 (defn- macro-terminating? [ch]
   (case ch
@@ -628,15 +633,15 @@
     (if-let [ns-str (namespace s)]
       (let [ns (resolve-ns (symbol ns-str))]
         (if (or (nil? ns)
-                (= (name (ns-name ns)) ns-str)) ;; not an alias
+                (= (ns-name* ns) ns-str)) ;; not an alias
           s
-          (symbol (name (ns-name ns)) (name s))))
+          (symbol (ns-name* ns) (name s))))
       (if-let [o ((ns-map *ns*) s)]
         (if (class? o)
           (symbol (.getName ^Class o))
           (if (var? o)
-            (symbol (-> ^Var o .ns .name name) (-> ^Var o .sym name))))
-        (symbol (name (ns-name *ns*)) (name s))))))
+            (symbol (-> ^Var o .ns ns-name*) (-> ^Var o .sym name))))
+        (symbol (ns-name* *ns*) (name s))))))

 (defn- add-meta [form ret]
   (if (and (instance? IObj form)


Added docstrings to the lambda-blog.templates.archives namespace.

--- src/lambda_blog/templates/archives.clj
+++ src/lambda_blog/templates/archives.clj
@@ -4,7 +4,9 @@
             [lambda-blog.utils :refer [format-date pathcat]]
             [s-html.tags :refer [a div h1 hr kbd nav p script span table tbody td th thead tr]]))

-(defn archive-entry [{:keys [path path-to-root summary tags timestamp title]}]
+(defn archive-entry
+  "Creates a single row of the archives table containing various entry details."
+  [{:keys [path path-to-root summary tags timestamp title]}]
   (tr (td (format-date timestamp))
       (td (a {:href (pathcat path)} title))
       (td (map #(a {:class :tag
@@ -14,7 +16,9 @@
                (sort-by :id tags)))
       (td {:class [:hidden-xs :hidden-sm]} summary)))

-(defn archives [{:keys [entries] :as ent}]
+(defn archives
+  "Creates an HTML page containing a table of `entries`."
+  [{:keys [entries] :as ent}]
   (page
    (fn [_]
      [(-> "Archives" h1 text-centered row panel)


actually pass arg to `onHistoryEvent_`

actually pass arg to `onHistoryEvent_`

--- src/leiningen/new/aemette/history.cljs
+++ src/leiningen/new/aemette/history.cljs
@@ -71,7 +71,7 @@
                    #(if (= (.getToken history-imp)
                            (.-_current_token history-imp))
                       (js/console.log "Ignoring duplicate dispatch event to" (.getToken history-imp))
-                      (.onHistoryEvent_ history-imp)))))
+                      (.onHistoryEvent_ history-imp %)))))

 (defn setup-dispatcher!


strip commented old code

strip commented old code

--- src/metabase/events/metabot_lifecycle.clj
+++ src/metabase/events/metabot_lifecycle.clj
@@ -33,12 +33,6 @@
             (nil? slack-token)      (metabot/stop-metabot!)
             (not metabot-enabled)   (metabot/stop-metabot!)
             :else (metabot/restart-metabot!))))
-      ; (let [{:keys [slack-token metabot-enabled]} object]
-      ;   (cond
-      ;     (and (contains? object :metabot-enabled)
-      ;          (not metabot-enabled))      (metabot/stop-metabot!)
-      ;     (and (contains? object :slack-token)
-      ;          (seq slack-token))                  (metabot/start-metabot!)))
       (catch Throwable e
         (log/warn (format "Failed to process driver notifications event. %s" topic) e)))))


grouped a private defn with the defns that use it

--- src/midje/checkers/collection.clj
+++ src/midje/checkers/collection.clj
@@ -22,19 +22,6 @@
   [checker]
   (or (extended-fn? checker)
       (regex? checker)))
-
-(defn- feasible-permutations
-  "Permute the given list if it contains inexact checkers.
-   Only produces all permutations for short lists."
-  [checkers]
-  (cond (not-any? inexact-checker? checkers)
-        [checkers]
-
-        (<= (count checkers) 4)
-        (permutations checkers)
-
-        :else
-        (rotations checkers)))

 (defn- total-match?
   "Have all the expected elements have been discovered?"
@@ -247,22 +234,35 @@
           (recur (rest expected-permutations)
                  (better-of comparison best-so-far)))))))

-(defmethod compare-results ::map [actual expected looseness]
-  (order-free-compare-results expected
-                              (feasible-permutations (keys expected))
-                              (fn [permutation]
-                                (compare-one-map-permutation actual
-                                                             expected
-                                                             permutation))))
-
-(defmethod compare-results [::not-map :in-any-order]
-  [actual expected looseness]
-  (order-free-compare-results expected
-                              (feasible-permutations expected)
-                              (fn [permutation]
-                                (compare-one-seq-permutation actual
-                                                             permutation
-                                                             looseness))))
+(letfn [(feasible-permutations
+  ;; "Permute the given list if it contains inexact checkers.
+  ;;  Only produces all permutations for short lists."
+  [checkers]
+  (cond (not-any? inexact-checker? checkers)
+        [checkers]
+
+        (<= (count checkers) 4)
+        (permutations checkers)
+
+        :else
+        (rotations checkers)))]
+
+  (defmethod compare-results ::map [actual expected looseness]
+    (order-free-compare-results expected
+                                (feasible-permutations (keys expected))
+                                (fn [permutation]
+                                  (compare-one-map-permutation actual
+                                                               expected
+                                                               permutation))))
+
+  (defmethod compare-results [::not-map :in-any-order]
+    [actual expected looseness]
+    (order-free-compare-results expected
+                                (feasible-permutations expected)
+                                (fn [permutation]
+                                  (compare-one-seq-permutation actual
+                                                               permutation
+                                                               looseness)))))

 (defmethod compare-results [::not-map :strict-order]
   [actual expected looseness]


Focus management #38 - :focus-traversal-order performance

--- flatguicore/src/flatgui/focus.clj
+++ flatguicore/src/flatgui/focus.clj
@@ -96,7 +96,7 @@
 ;;;  NOTE:
 ;;; This implementation is slow. For containers that have frequenlty moving children, it's better
 ;;; to wrap it into another function that would call this one in rare cases (e.g. only when :children
-;;; change)
+;;; change, see below)
 (fg/defevolverfn :focus-traversal-order
   (let [accepting-children (get-accepting-children component)]
     (if (pos? (count accepting-children))
@@ -104,6 +104,12 @@
             result (mapcat (fn [i] (map :id (nth lines i))) (range 0 (count lines)))]
         result)
       [])))
+
+(fg/defevolverfn simple-focus-traversal-order-evolver :focus-traversal-order
+  (let [reason (fg/get-reason)]
+    (if (or (nil? reason) (= reason [:this]))
+      (focus-traversal-order-evolver component)
+      old-focus-traversal-order)))

 (fg/defaccessorfn get-child-ids-in-traversal-order [component]
   (if-let [focus-traversal-order (get-property component [:this] :focus-traversal-order)]


Add file and ns metadata to describe

Add file and ns metadata to describe

--- src/main/clojure/lazytest/describe.clj
+++ src/main/clojure/lazytest/describe.clj
@@ -36,6 +36,9 @@
   "Concatenate strings, with spaces in between, skipping nil."
   [& args]
   (apply str (interpose \space (remove nil? args))))
+
+(defn- merged-metadata [form docstring extra-attr-map]
+  (merge {:doc docstring, :file *file*, :ns *ns*} (meta form) extra-attr-map))

 ;;; Local Variable Scope

@@ -91,7 +94,7 @@
 	[attr-map body] (get-arg map? decl)
 	children (vec body)
 	docstring (strcat (when sym (resolve sym)) doc)
-	metadata (merge (meta &form) {:doc docstring} attr-map)]
+	metadata (merged-metadata &form docstring attr-map)]
     `(def-unless-nested (test-group ~children ~metadata))))

 (defmacro given [& decl]
@@ -99,7 +102,7 @@
 	[attr-map decl] (get-arg map? decl)
 	[bindings body] (get-arg vector? decl)
 	children (vec body)
-	metadata (merge (meta &form) {:doc doc} attr-map)]
+	metadata (merged-metadata &form doc attr-map)]
     (assert (vector? bindings))
     (assert (even? (count bindings)))
     (let [binding-forms (firsts bindings)
@@ -114,7 +117,7 @@
 	[attr-map decl] (get-arg map? decl)
 	[bindings body] (get-arg vector? decl)
 	children (vec body)
-	metadata (merge (meta &form) {:doc doc} attr-map)]
+	metadata (merged-metadata &form doc attr-map)]
     (assert (vector? bindings))
     (assert (even? (count bindings)))
     (let [binding-forms (firsts bindings)
@@ -127,7 +130,7 @@
   (let [[sym decl] (get-arg symbol? decl)
 	[doc decl] (get-arg string? decl)
 	[attr-map body] (get-arg map? decl)
-	metadata (merge (meta &form) {:doc doc} attr-map)]
+	metadata (merged-metadata &form doc attr-map)]
     `(def-unless-nested
        (test-case ~(find-locals &env)
 		  (fn ~(find-local-binding-forms &env) ~@body) ~metadata))))


IKVReduce. Closes #80

IKVReduce. Closes #80

--- lib/shin/cljs/cljs/core.cljs
+++ lib/shin/cljs/cljs/core.cljs
@@ -90,6 +90,9 @@
 (defprotocol IReduce
   (-reduce [coll f] [coll f start]))

+(defprotocol IKVReduce
+  (-kv-reduce [coll f init]))
+
 (defprotocol IPrintable
   (-pr-str [o]))

@@ -376,13 +379,34 @@
          v)))))

 (defn reduce
+  "f should be a function of 2 arguments. If val is not supplied,
+  returns the result of applying f to the first 2 items in coll, then
+  applying f to that result and the 3rd item, etc. If coll contains no
+  items, f must accept no arguments as well, and reduce returns the
+  result of calling f with no arguments.  If coll has only 1 item, it
+  is returned and f is not called.  If val is supplied, returns the
+  result of applying f to val and the first item in coll, then
+  applying f to that result and the 2nd item, etc. If coll contains no
+  items, returns val and f is not called."
   ([f coll]
    (let [[x & xs] coll] (reduce f x xs)))
-  ([f z coll]
+  ([f val coll]
    (if (empty? coll)
-     z
+     val
      (let [[x & xs] coll]
-       (reduce f (f z x) xs)))))
+       (reduce f (f val x) xs)))))
+
+(defn reduce-kv
+  "Reduces an associative collection. f should be a function of 3
+  arguments. Returns the result of applying f to init, the first key
+  and the first value in coll, then applying f to that result and the
+  2nd key and value, etc. If coll contains no entries, returns init
+  and f is not called. Note that reduce-kv is supported on vectors,
+  where the keys will be the ordinals."
+  ([f init coll]
+   (if (nil? coll)
+     init
+     (-kv-reduce coll f init))))

 (defn identity [x] x)

@@ -1389,6 +1413,35 @@
   "Returns true if coll satisfies IReduce"
   (satisfies? IReduce coll))

+(defn- array-reduce
+  ([arr f]
+     (let [cnt (alength arr)]
+       (if (zero? (alength arr))
+         (f)
+         (loop [val (aget arr 0), n 1]
+           (if (< n cnt)
+             (let [nval (f val (aget arr n))]
+               (if (reduced? nval)
+                 @nval
+                 (recur nval (inc n))))
+             val)))))
+  ([arr f val]
+     (let [cnt (alength arr)]
+       (loop [val val, n 0]
+         (if (< n cnt)
+           (let [nval (f val (aget arr n))]
+             (if (reduced? nval)
+               @nval
+               (recur nval (inc n))))
+           val))))
+  ([arr f val idx]
+     (let [cnt (alength arr)]
+       (loop [val val, n idx]
+         (if (< n cnt)
+           (let [nval (f val (aget arr n))]
+             (recur nval (inc n)))
+           val)))))
+
 (defn counted? [coll]
   "Returns true if coll implements count in constant time"
   (satisfies? ICounted coll))
@@ -1740,7 +1793,14 @@
   (-reduce [coll f] (ci-reduce coll f start))
   (-reduce [coll f start] (ci-reduce coll f start))

-  ;; TODO: IKVReduce, etc.
+  IKVReduce
+  (-kv-reduce [coll f init]
+    (let [len (-count coll)]
+      (loop [i 0
+             v init]
+        (if (< i len)
+          (recur (inc i) (f v i (-nth i coll)))
+          v))))

   IFn
   (-invoke [coll k]
@@ -1841,6 +1901,20 @@
   IReduce
   (-reduce [coll f start]
     (throw "-reduce on a map: stub"))
+
+  IKVReduce
+  (-kv-reduce [coll f init]
+    (let [pairs (hamt/pairs)
+          len (alength pairs)]
+      (loop [i    0
+             prev init]
+        (if (< i len)
+          (let [pair (aget pairs i)
+                k    (aget pair 0)
+                v    (aget pair 1)]
+            (recur
+              (inc i)
+              (f prev k v)))))))

   IPrintable
   (-pr-str [coll]


Create history

Create history

--- src-cljs/tranjlator/master_view.cljs
+++ src-cljs/tranjlator/master_view.cljs
@@ -21,6 +21,8 @@
         user-name (:user-name @app)]
     (when (not (= new-lang old-lang))
       (do
+        (when (empty? (:translated @app))
+          (om/update! app :translated (into [] (:original @app))))
         (om/update! app :reading-language new-lang)
         (when-not (nil? old-lang)
           (put! sender-ch (m/->language-unsub user-name old-lang)))
@@ -33,7 +35,7 @@

 (defn send-message-click [sender-ch text owner app]
   (do
-    (let [sha (-> text hash hex-string)]
+    (let [sha (-> text .toLowerCase hash hex-string)]
       (post-message sender-ch
                     (assoc (command text)
                       :user-name (:user-name @app)


Adds more test-coverage to complete-nodes*

--- src/the_little_clojurian/todo.clj
+++ src/the_little_clojurian/todo.clj
@@ -125,7 +125,13 @@
          '({:id 1} {:id 2 :complete true})))

   (is (= (complete-nodes* 2 '({:id 1 :nodes ({:id 2})}))
-         '({:id 1 :nodes ({:id 2 :complete true})}))))
+         '({:id 1 :nodes ({:id 2 :complete true})})))
+
+  (is (= (complete-nodes* 2 '({:id 0} {:id 1 :nodes ({:id 2})}))
+         '({:id 0} {:id 1 :nodes ({:id 2 :complete true})})))
+
+  (is (= (complete-nodes* 4 '({:id 0} {:id 1} {:id 2 :nodes ({:id 4 :nodes ({:id 5})})} {:id 3}))
+         '({:id 0} {:id 1} {:id 2 :nodes ({:id 4 :complete true :nodes ({:id 5})})} {:id 3}))))

 (with-test
   (def complete-node*


renamed devtools model keys

renamed devtools model keys

--- src/frontend/devtools.cljs
+++ src/frontend/devtools.cljs
@@ -15,11 +15,11 @@
     :initial-signal component-signal

     ; list of [id signal]
-    :signals        (list)
+    :signal-events  (list)
     :next-signal-id 0

     ; list of {id source-signal-id enabled? action}
-    :actions        (list)
+    :action-events  (list)
     :next-action-id 0

     :persist?       false}
@@ -37,15 +37,15 @@
    :enabled?  true
    :action    action})

-(defn -update-actions*
+(defn -update-action-events*
   [model pred f & args]
-  (s/transform [:actions s/ALL pred]
+  (s/transform [:action-events s/ALL pred]
                #(apply f % args)
                model))

-(defn -update-action
+(defn -update-action-event
   [model id f & args]
-  (apply -update-actions* model #(= (:id %) id) f args))
+  (apply -update-action-events* model #(= (:id %) id) f args))

 ;;;;;;;;;;;;;;;;;;;;;;;; Control
 (defn new-control
@@ -95,7 +95,7 @@
   "Orphaned signal has no actions."
   [model [signal-id _ :as _signal_]]
   (empty? (filter #(= (:signal-id %) signal-id)
-                  (:actions model))))
+                  (:action-events model))))

 (defn new-reconcile
   [component-reconcile]
@@ -103,23 +103,23 @@
     [model action]
     (match action
            :clear-history
-           (assoc model :signals (list)
-                        :actions (list))
+           (assoc model :signal-events (list)
+                        :action-events (list))

            [:record-signal-event signal-event]
            (-> model
-               (update :signals concat [signal-event])
+               (update :signal-events concat [signal-event])
                (update :next-signal-id inc))

            [:toggle-action id]
-           (-update-action model id update :enabled? not)
+           (-update-action-event model id update :enabled? not)

            :replay
            ; applies enabled recorded actions to the initial component model
            (assoc model :component
                         (reduce component-reconcile
                                 (:initial-model model)
-                                (->> (:actions model)
+                                (->> (:action-events model)
                                      (filter :enabled?)
                                      (map :action))))

@@ -128,13 +128,13 @@

            :sweep
            (as-> model m
-                 (update m :actions #(filter :enabled? %))
-                 (update m :signals #(remove (partial -orphaned-signal? m) %)))
+                 (update m :action-events #(filter :enabled? %))
+                 (update m :signal-events #(remove (partial -orphaned-signal? m) %)))

            [:component signal-id a]
            (-> model
                (update :component component-reconcile a)
-               (update :actions concat [(-action-event signal-id (:next-action-id model) a)])
+               (update :action-events concat [(-action-event signal-id (:next-action-id model) a)])
                (update :next-action-id inc))

            ; for bare component actions (e.g. when dispatching from REPL) use an "unknown signal" event
@@ -143,9 +143,9 @@
                                                                        :-unknown-signal)]
              (-> model
                  (update :component component-reconcile a)
-                 (update :signals concat [unknown-signal-event])
+                 (update :signal-events concat [unknown-signal-event])
                  (update :next-signal-id inc)
-                 (update :actions concat [(-action-event singal-id (:next-action-id model) a)])
+                 (update :action-events concat [(-action-event singal-id (:next-action-id model) a)])
                  (update :next-action-id inc))))))

 ;;;;;;;;;;;;;;;;;;;;;;;; View model
@@ -195,7 +195,7 @@

    [:div
     (doall
-      (for [[signal-id signal] (reverse (:signals model))]
+      (for [[signal-id signal] (reverse (:signal-events model))]
         ^{:key signal-id}
         [:div {:title "Signal"}
          "→ "
@@ -204,7 +204,7 @@
            [:strong (pr-str signal)])

          (for [{:keys [id enabled? action]} (filter #(= (:signal-id %) signal-id)
-                                                    (:actions model))]
+                                                    (:action-events model))]
            ^{:key id}
            [:div {:style    {:cursor           "pointer"
                              :margin-left      "10px"


Depend on Metrics 3.0

Depend on Metrics 3.0

--- metrics-clojure-core/project.clj
+++ metrics-clojure-core/project.clj
@@ -1,7 +1,7 @@
 (defproject metrics-clojure "2.0.0-SNAPSHOT"
   :description "A Clojure façade for Coda Hale's metrics library."
   :dependencies [[org.clojure/clojure "1.6.0"]
-                 [com.yammer.metrics/metrics-core "2.2.0"]]
+                 [com.codahale.metrics/metrics-core "3.0.2"]]
   :repositories {"repo.codahale.com" "http://repo.codahale.com"
                  ;; to get Clojure snapshots
                  "sonatype" {:url "http://oss.sonatype.org/content/repositories/releases"


Test against ring 1.3

Test against ring 1.3

--- metrics-clojure-ring/project.clj
+++ metrics-clojure-ring/project.clj
@@ -2,4 +2,4 @@
   :description "Various things gluing together metrics-clojure and ring."
   :dependencies [[cheshire "5.3.1"]
                  [metrics-clojure "2.1.0-SNAPSHOT"]]
-  :profiles {:dev {:dependencies [[ring "1.2.2"]]}})
+  :profiles {:dev {:dependencies [[ring "1.3.0"]]}})


Add function to try and infer the RDFFormat from a filename.

--- src/grafter/rdf/sesame.clj
+++ src/grafter/rdf/sesame.clj
@@ -537,6 +537,12 @@
     (-> parser-class
         .newInstance
         .getParser)))
+
+(defn filename->rdf-format
+  "Given a filename we attempt to return an appropriate RDFFormat
+  object based on the files extension."
+  [fname]
+  (Rio/getParserFormatForFileName fname))

 ;; http://clj-me.cgrand.net/2010/04/02/pipe-dreams-are-not-necessarily-made-of-promises/
 (defn pipe


Use multiple memory registers to implement memory index.

--- src/vault/index/engine/memory.clj
+++ src/vault/index/engine/memory.clj
@@ -4,7 +4,13 @@
     [vault.index.engine :as engine]))

-;;;;; HELPER METHODS ;;;;;
+;;;;; HELPER FUNCTIONS ;;;;;
+
+(defn- update-vals
+  "Maps a function over the values in a map, returning a new map."
+  [m f & args]
+  (reduce (fn [m' [k v]] (assoc m k (apply f v args))) (empty m) m))
+

 (defn- flatten-times
   "Flattens a sorted map into a sequence of values n times."
@@ -16,55 +22,94 @@
   "Like update-in, but creates intermediate maps sorted by Puget."
   [m [k & ks] f & args]
   (if ks
-    (assoc m k (apply update-sorted-in (get m k (sorted-map-by order/rank)) ks f args))
+    (assoc m k (apply update-sorted-in
+                      (get m k (sorted-map-by order/rank))
+                      ks f args))
     (assoc m k (apply f (get m k) args))))

-(defn- update-record
-  "Updates a nested index map with the given record. Creates a sorted set as
-  the leaf value if one is not present already."
-  [index ks record]
-  (update-sorted-in index ks (fnil conj (sorted-set-by order/rank)) record))
+
+;;;;; REGISTER METHODS ;;;;;
+
+(defn- mem-register
+  "Creates a new register map with the given attributes."
+  [attrs]
+  {:attrs (vec attrs)
+   :records (sorted-map-by order/rank)})
+
+
+(defn- update-register
+  "Updates a nested register map with the given record. Creates a sorted set as
+  the leaf value if one is not present already. Returns an updated version of
+  the register."
+  [register record]
+  (let [key-vec (vec (map record (:attrs register)))]
+    (when (some nil? key-vec)
+      (throw (IllegalArgumentException.
+               (str "Cannot update register with record missing required "
+                    "attributes " (pr-str (:attrs register)) " "
+                    (pr-str record)))))
+    (update-in register [:records]
+               update-sorted-in key-vec
+               (fnil conj (sorted-set-by order/rank))
+               record)))
+
+
+(defn- select-register
+  "Given a collection of registers and attributes being searched, select the
+  best register to query for records."
+  [registers attrs]
+  (let [leading-attrs
+        #(->> % :attrs
+              (map (set attrs))
+              (take-while some?)
+              count)]
+    (apply max-key leading-attrs registers)))
+
+
+(defn- search-register
+  "Queries a register to find records matching the given pattern. Returns a seq
+  of the matched records."
+  [register pattern opts]
+  (loop [[attr & more :as attrs] (:attrs register)
+         records (:records register)
+         pattern pattern]
+    ; Find leading attributes present in `pattern`.
+    (if-let [value (get pattern attr)]
+      ; Narrow scope by recursively getting next level of records.
+      (recur more (get records value) (dissoc pattern attr))
+      ; Filter remaining entries by pattern attributes.
+      (filter (partial engine/matches? pattern)
+              (flatten-times records (count attrs))))))

-;;;;; MEMORY SEARCH ENGINE ;;;;;
+;;;;; MEMORY INDEX ;;;;;

-(defrecord MemorySearchEngine [attrs index])
+(defrecord MemoryIndex [registers])

 (extend-type MemoryIndex
   engine/SearchEngine

   (init!
     [this]
-    ; TODO: set up indexes per-lookup type
+    ; no-op
     this)

   (update!
-    [{:keys [attrs index] :as this} record]
-    (let [key-vec (vec (map record attrs))]
-      (when (some nil? key-vec)
-        (throw (IllegalArgumentException.
-                 (str "Cannot update index with record missing required "
-                      "attributes " (pr-str attrs) " " (pr-str record)))))
-      (swap! (:index this) update-record key-vec record))
+    [this record]
+    (swap! (:registers this) update-vals update-register record)
     this)

   (search
     [this pattern opts]
-    (loop [[attr & more :as attrs] (:attrs this)
-           index (deref (:index this))
-           pattern pattern]
-      ; Find leading attributes present in `pattern`.
-      (if-let [value (get pattern attr)]
-        ; Narrow scope by recursively getting next level of indexes.
-        (recur more (get index value) (dissoc pattern attr))
-        ; Filter remaining entries by pattern attributes.
-        (filter (partial engine/matches? pattern)
-                (flatten-times index (count attrs)))))))
+    (-> this :registers vals
+        (select-register (keys pattern))
+        (search-register pattern opts))))

 (defn memory-index
-  [& attrs]
-  {:pre [(seq attrs)]}
-  (MemorySearchEngine. (vec attrs) (atom (sorted-map))))
+  "Creates a new memory-backed index which optimizes the given queries. The
+  argument should be a map of query keyword names to attr vectors."
+  [queries]
+  (MemoryIndex. (atom (update-vals queries mem-register))))


structured data for data downloads

structured data for data downloads

--- src/norman_sicily_static/resources.clj
+++ src/norman_sicily_static/resources.clj
@@ -1,4 +1,5 @@
-(ns norman-sicily-static.resources)
+(ns norman-sicily-static.resources
+  (:require [cheshire.core :as json]))

 (defn render-page
   []
@@ -24,8 +25,46 @@
         [:a {:href "https://github.com/the-norman-sicily-project/vocabulary"}
          "Github."]]
        [:div {:class "credits-header"} "Datasets"]
-       [:p "Currently, the dataset includes Norman monasteries in Sicily.
-           It is available in various formats, including "
+       [:script {:type "application/ld+json"}
+        (json/generate-string
+          {"@context" "http://schema.org"
+           "@type" "Dataset"
+           :name "The Norman Sicily Project Place data"
+           :description "Data about places collected by The Norman Sicily Project"
+           :creator {"@type" "Organization"
+                     :name "The Norman Sicily Project"
+                     :url "http://www.normansicily.org/"}
+           :datePublished "2018-07-27"
+           :dateModified "2018-08-05"
+           :url "http://www.normansicily.org/data/"
+           :sameAs "https://github.com/the-norman-sicily-project/data-dumps/tree/master/2018-08-05"
+           :distribution [{"@type" "DataDownload"
+                           :encodingFormat "text/csv"
+                           :contentUrl "http://www.normansicily.org/data/places-20180805.csv"}
+                          {"@type" "DataDownload"
+                           :encodingFormat "application/geo+json"
+                           :contentUrl "http://www.normansicily.org/data/places-20180805.geojson"}
+                          {"@type" "DataDownload"
+                           :encodingFormat "application/ld+json"
+                           :contentUrl "http://www.normansicily.org/data/places-20180805.jsonld"}
+                          {"@type" "DataDownload"
+                           :encodingFormat "text/n3"
+                           :contentUrl "http://www.normansicily.org/data/places-riot-20180805.n3"}
+                          {"@type" "DataDownload"
+                           :encodingFormat "application/rdf+xml"
+                           :contentUrl "http://www.normansicily.org/data/places-riot-20180805.rdfxml"}
+                          {"@type" "DataDownload"
+                           :encodingFormat "text/turtle"
+                           :contentUrl "http://www.normansicily.org/data/places-riot-20180805.ttl"}]
+           :license "http://creativecommons.org/licenses/by-sa/4.0/"
+           :temporalCoverage "1060/1194"
+           :spatialCoverage {"@type" "Place"
+                             :name "Sicily"
+                             :containedIn {"@type" "Place"
+                                           :name "Italy"}}})]
+       [:p "Currently, the dataset includes Norman monasteries in Sicily from
+           the period beginning 1060 until 1194. It is available in various
+           formats, including "
         [:a {:href "/data/places-20180805.csv"} "CSV"] ", "
         [:a {:href "/data/places-20180805.geojson"} "GeoJSON"] ", "
         [:a {:href "/data/places-20180805.jsonld"} "JSON-LD"] ", "


Main function of Clojure test script actually prints something.

--- clojure/org/gavrog/clojure/identify_nets.clj
+++ clojure/org/gavrog/clojure/identify_nets.clj
@@ -34,4 +34,4 @@
   (let [archive (make-archive "1.0"
                               "org/gavrog/apps/systre/rcsr.arc"
                               "org/gavrog/apps/systre/zeolites.arc")]
-    (identify-all-from-file archive path)))
+    (println (identify-all-from-file archive path))))


no longer using one.browser.history due to gclosure bug

--- src/app/cljs/one/sample/history.cljs
+++ src/app/cljs/one/sample/history.cljs
@@ -1,23 +1,33 @@
-(ns ^{:doc "When this library is loaded, a listener function is added
-  which will be run when a :form or :greeting event is fired. This
-  allows the use of the back button to navigate between views. This is
-  accomplished by using library.browser.history to keep track of views
-  that have previously been visited, and traversing them when
-  navigation events are detected."}
+(ns ^{:doc "This module no longer uses the one.browser.history library due
+  to a buggy implementation of Html5History in the Google Closure library
+  which causes duplicate events to fire (one for hashchange and another for
+  popstate, both of which are involved in any token change). Its replacement
+  is a simple event listener on the hashchange event to detect and
+  dispatch a new token."}
   one.sample.history
-  (:require [one.dispatch :as dispatch]
-            [one.browser.history :as history]))
+  (:require [one.dispatch        :as dispatch]
+            [one.browser.history :as history]
+            [goog.events         :as event]))

-(defn nav-handler
-  "Handle navigation events by firing the appropriate view token."
-  [{:keys [token navigation?]}]
-  (when navigation?
-    (dispatch/fire token)))
+(event/listen js/window goog.events.EventType.HASHCHANGE
+              (fn [e]
+                (if (not= (.-oldURL e) (.-newURL e))
+                  (let [link  (.createElement js/document "a")
+                        url   (set! (.-href link) (.-newURL e))
+                        token (.substr (.-hash link) 1)]
+                    (dispatch/fire (keyword token))))))

-(def ^{:doc "The global history object for this application."}
-  history (history/history nav-handler))
+(comment
+  (defn nav-handler
+    "Handle navigation events by firing the appropriate view token."
+    [{:keys [token navigation?]}]
+    (when navigation?
+      (dispatch/fire token)))

-(comment (dispatch/react-to #{:init}
-                            (fn [t d]
-                              (history/set-token history t))))
+  (def ^{:doc "The global history object for this application."}
+    history (history/history nav-handler))

+  (dispatch/react-to #{:init}
+                     (fn [t d]
+                       (history/set-token history t))))
+


prefer drv over der for deriveative abbr

--- src/org/martinklepsch/derivatives.cljc
+++ src/org/martinklepsch/derivatives.cljc
@@ -41,9 +41,9 @@
   (apply s/union (set ks) (map #(dep/transitive-dependencies graph %) ks)))

 (defn sync-derivatives
-  "Update the derivatives map `der-map` so that all keys passed in `order`
+  "Update the derivatives map `drv-map` so that all keys passed in `order`
    are statisfied and any superfluous keys are removed"
-  [spec der-map order]
+  [spec drv-map order]
   (reduce (fn [m k]
             (let [[direct-deps derive] (-> spec k)]
               (if (get m k)
@@ -53,7 +53,7 @@
                     (prn :creating-new-ref k)
                     (assoc m k (rum/derived-atom (map #(get m %) direct-deps) k derive)))
                   (assoc m k derive)))))
-          (select-keys der-map order)
+          (select-keys drv-map order)
           order))

 (defn derivatives-manager
@@ -71,20 +71,20 @@
         sync! (fn [new-registry]
                 (let [required? (calc-deps graph (keys new-registry))
                       ordered   (filter required? (dep/topo-sort graph))
-                      new-ders  (sync-derivatives spec (:derivatives @state) ordered)]
-                  (swap! state assoc :derivatives new-ders, :registry new-registry)
-                  new-ders))]
-    {:get! (fn get! [der-k token]
+                      new-drvs  (sync-derivatives spec (:derivatives @state) ordered)]
+                  (swap! state assoc :derivatives new-drvs, :registry new-registry)
+                  new-drvs))]
+    {:get! (fn get! [drv-k token]
              (let [registry  (:registry @state)
-                   new-reg   (update registry der-k (fnil conj #{}) token)]
-               (if-let [derivative (get (sync! new-reg) der-k)]
+                   new-reg   (update registry drv-k (fnil conj #{}) token)]
+               (if-let [derivative (get (sync! new-reg) drv-k)]
                  derivative
-                 (throw (ex-info (str "No derivative defined for " der-k) {:key der-k})))))
-     :release! (fn release! [der-k token]
+                 (throw (ex-info (str "No derivative defined for " drv-k) {:key drv-k})))))
+     :release! (fn release! [drv-k token]
               (let [registry  (:registry @state)
-                    new-reg   (if (= #{token} (get registry der-k))
-                                (dissoc registry der-k)
-                                (update registry der-k disj token))]
+                    new-reg   (if (= #{token} (get registry drv-k))
+                                (dissoc registry drv-k)
+                                (update registry drv-k disj token))]
                 (sync! new-reg)
                 nil))}))

@@ -116,39 +116,39 @@
                                     {release-k release! get-k get!}))}))

   (defn drv
-    "Rum mixin to retrieve a derivative for `:der-k` using the functions in the component context
+    "Rum mixin to retrieve a derivative for `:drv-k` using the functions in the component context
      To get the derived-atom use `get-ref` for swappable client/server behavior"
-    [der-k]
+    [drv-k]
     #?(:cljs
        (let [token (rand-int 10000)] ;TODO
          {:class-properties {:contextTypes {get-k     js/React.PropTypes.func
                                             release-k js/React.PropTypes.func}}
           :will-mount    (fn [s]
-                           (let [get-der! (-> s :rum/react-component (gobj/get "context") (gobj/get get-k))]
-                             (assert get-der! "No get! derivative function found in component context")
-                             (assoc-in s [::derivatives der-k] (get-der! der-k))))
+                           (let [get-drv! (-> s :rum/react-component (gobj/get "context") (gobj/get get-k))]
+                             (assert get-drv! "No get! derivative function found in component context")
+                             (assoc-in s [::derivatives drv-k] (get-drv! drv-k))))
           :will-unmount  (fn [s]
-                           (let [release-der! (-> s :rum/react-component (gobj/get "context") (gobj/get release-k))]
-                             (assert release-der! "No release! derivative function found in component context")
-                             (release-der! der-k)
-                             (update s ::derivatives dissoc der-k)))}))))
+                           (let [release-drv! (-> s :rum/react-component (gobj/get "context") (gobj/get release-k))]
+                             (assert release-drv! "No release! derivative function found in component context")
+                             (release-drv! drv-k)
+                             (update s ::derivatives dissoc drv-k)))}))))

 (def ^:dynamic *derivatives* nil)

 (defn get-ref
-  "Get the derivative identified by `der-k` from the component state.
-   When rendering in Clojure this looks for `der-k` in the dynvar `*derivatives`"
-  [state der-k]
-  (or #?(:cljs (get-in state [::derivatives der-k])
-         :clj  (get *derivatives* der-k))
-      (throw (ex-info (str "No derivative found! Maybe you forgot a (drv " der-k ") mixin?")
-                      {:key der-k :derivatives #?(:cljs (keys (::derivatives state))
+  "Get the derivative identified by `drv-k` from the component state.
+   When rendering in Clojure this looks for `drv-k` in the dynvar `*derivatives`"
+  [state drv-k]
+  (or #?(:cljs (get-in state [::derivatives drv-k])
+         :clj  (get *derivatives* drv-k))
+      (throw (ex-info (str "No derivative found! Maybe you forgot a (drv " drv-k ") mixin?")
+                      {:key drv-k :derivatives #?(:cljs (keys (::derivatives state))
                                                   :clj (keys *derivatives*))}))))

 (defn react
   "Like `get-ref` wrapped in `rum.core/react`"
-  [state der-k]
-  (rum/react (get-ref state der-k)))
+  [state drv-k]
+  (rum/react (get-ref state drv-k)))

 (def base (atom 0))


Removing errant _id from ES docs

Removing errant _id from ES docs

--- src/org/spootnik/cyanite/es_client.clj
+++ src/org/spootnik/cyanite/es_client.clj
@@ -34,10 +34,18 @@
                   (when (not= 200 status)
                     (func %))))))

+(defn remove-ids-from-docs
+  [op-or-doc]
+  (if (:tenant op-or-doc)
+    (dissoc op-or-doc :_id)
+    op-or-doc))
+
 (defn multi-update
   [^Connection conn index mapping-type docs func]
   (bulk-with-url (rest/bulk-url conn index mapping-type)
-                 (esrb/bulk-index (map #(assoc % :_id (:path %)
-                                               :_index index
-                                               :_type mapping-type) docs))
+                 (map
+                  remove-ids-from-docs
+                  (esrb/bulk-index (map #(assoc % :_id (:path %)
+                                                :_index index
+                                                :_type mapping-type) docs)))
                  func))


CMR-1033: Add documentation strings for functions

--- common-lib/src/cmr/common/api/web_server.clj
+++ common-lib/src/cmr/common/api/web_server.clj
@@ -30,6 +30,9 @@
   860)

 (defn get-access-log-handler
+  "Setup access logging for each application.  Access log entries will go to stdout similar to
+  application logging.  As a result the access log entries will be in the same log as the
+  application log."
   [existing-handler]
   (doto (RequestLogHandler.)
     (.setHandler existing-handler)
@@ -38,10 +41,12 @@
         (.setLogLatency true)))))

 (defn get-gzip-handler
-  [existing-handler]
+  "Setup gzip compression for responses.  Compression will be used for any response larger than
+  the configured minimum size."
+  [existing-handler min_gzip_size]
   (doto (GzipHandler.)
     (.setHandler existing-handler)
-    (.setMinGzipSize MIN_GZIP_SIZE)))
+    (.setMinGzipSize min_gzip_size)))

 (defrecord WebServer
   [
@@ -72,7 +77,7 @@

         (let [handler
               (when use-compression?
-                (get-gzip-handler (get-access-log-handler (.getHandler server)))
+                (get-gzip-handler (get-access-log-handler (.getHandler server)) MIN_GZIP_SIZE)
                 (get-access-log-handler (.getHandler server)))]
           (doto server
             (.stop)


let's try coercing the `max-zipfile-size` config value and see if that fixes this

--- src/vip/data_processor/validation/zip.clj
+++ src/vip/data_processor/validation/zip.clj
@@ -33,7 +33,7 @@
                                            (into-array FileAttribute []))]
     (log/info "zipfile size: " size " type? " (type size))
     (log/info "max-zipfile-size: " max-zipfile-size " type? " (type max-zipfile-size))
-    (if (> size max-zipfile-size)
+    (if (> size (Long. max-zipfile-size))
       (-> (too-big-msg size max-zipfile-size)
           (ex-info {:msg (too-big-msg size max-zipfile-size)
                     :max-zipfile-size-exceeded true})


Can now switch between apps in appshare and the db schema is changed

This is important as the server side cache for the virtual machine must
be cleared each time as we do not want to keep reloading the virtual
machine. the virtual machine is the javascript container on the client
side

--- src/webapp/framework/server/systemfns.clj
+++ src/webapp/framework/server/systemfns.clj
@@ -1646,6 +1646,12 @@
       (swap! server-side-realtime-clients assoc client-realtime-id (atom {:queries (atom {})    :records (atom {})    :update-request (atom {})})))))

+(defn clear-client-cache [client-realtime-id]
+  (let [client-cache     (get @server-side-realtime-clients  client-realtime-id)
+        ]
+    (if client-cache
+      (swap! server-side-realtime-clients assoc client-realtime-id (atom {:queries (atom {})    :records (atom {})    :update-request (atom {})})))))
+

@@ -2067,7 +2073,6 @@

-
 (defn !getfilecontents [{:keys [id  app-session-id]}]
   (if id
     (let [content-records   (cond
@@ -2083,6 +2088,8 @@
           ]

       (do
+        (clear-client-cache   app-session-id)
+
         (println (str "!getfilecontents        id: "        id))
         (println (str "!getfilecontents  app-schema-id: "   app-schema-id))
         (println (str "" ))


Hosted apps work on Oracle

Hosted apps work on Oracle

Only up to 4000 chars in a file though!

--- src/webapp/framework/server/systemfns.clj
+++ src/webapp/framework/server/systemfns.clj
@@ -1670,8 +1670,13 @@

 (defn !getfilecontents [{:keys [id]}]
   (if id
-    (let [content-records (sql "select  application_code from coils_applications where id = ?" [id])
-          content (get (first content-records) :application_code)
+    (let [content-records (cond
+                             (= *database-type* "postgres" )
+                             (sql-1 "select  application_code as ac from coils_applications where id = ?" [id])
+
+                             (= *database-type* "oracle" )
+                             (sql-1 "select  dbms_lob.substr( application_code, 3992, 1 ) as ac from coils_applications where id = ?" [id]))
+          content (get content-records :ac)
           ]
       (println (str "id: " id))
       {:value content})))
@@ -1681,8 +1686,15 @@

 (defn !loadapp [{:keys [id] }]
   (do
-    (let [content-records  (sql "select  application_code from coils_applications where id = ?" [id])
-          content          (get (first content-records) :application_code)
+    (let [content-records  (cond
+                             (= *database-type* "postgres" )
+                             (sql-1 "select  application_code as ac from coils_applications where id = ?" [id])
+
+                             (= *database-type* "oracle" )
+                             (sql-1 "select  dbms_lob.substr( application_code, 3992, 1 ) as ac from coils_applications where id = ?" [id]))
+
+
+          content   (get content-records :ac)
           start     (slurp (folder "main_view_start.txt"))
           middle    content
           end       (slurp (folder "main_view_end.txt"))
@@ -1694,8 +1706,6 @@
       )

     {:value ""}))
-
-


Execute different code if it is a realtime query

Execute different code if it is a realtime query

--- src/webapp/framework/server/systemfns.clj
+++ src/webapp/framework/server/systemfns.clj
@@ -373,7 +373,24 @@

-
+(defn create-query-key
+[& {:keys [
+         db-table
+         where
+         start
+         end
+         params
+         order
+         ]}]
+         {
+          :db-table db-table
+          :where where
+          :start start
+          :end end
+          :params params
+          :order order
+         }
+)

@@ -392,17 +409,28 @@
   (println "************************************************************************************")
   (println "!get-query-results-v2*   REALTIME = " realtime)

-  (if realtime
-  (do
-  (if (get @cached-queries db-table)
+
+(cond
+   realtime
+  (let [
+  query-key   (create-query-key
+                :db-table db-table
+                :where where
+                :start start
+                :end end
+                :params params
+                :order order
+  )
+  ]
+  (if (get @cached-queries  query-key)
     nil
-    (swap! cached-queries assoc db-table {})
+    (swap! cached-queries assoc  query-key {})
   )
     (println "-------------------------------")
    (println cached-queries)
     (println "-------------------------------")
-  )
-  )
+
+

   (println (str "!get-query-results-v2: "
                 db-table
@@ -413,8 +441,12 @@
                 order " "
                 data-session-id " "
                 realtime " "
-                ))
-
+                )))
+
+
+
+:else
+(do
   (let [
         record-count

@@ -460,7 +492,7 @@
      :records      result-id-vector
       :count       record-count
      }
-    ))
+    ))))


delete refresh-materialized-views function, use destructuring in populate functions

--- src/vip/data_processor/db/postgres.clj
+++ src/vip/data_processor/db/postgres.clj
@@ -266,40 +266,28 @@
      ["select v5_dashboard.populate_locality_table(?)" [id]]))
   ctx)

-(defn refresh-materialized-views
-  [ctx]
-  (log/info "Refreshing materialized views")
-  (doseq [view ["v5_dashboard.sources" "v5_dashboard.elections"]]
-    (korma/exec-raw
-     (:conn xml-tree-values)
-     [(str "refresh materialized view " view)]))
-  ctx)
-
 (defn populate-i18n-table
-  [ctx]
-  (let [id (:import-id ctx)]
-    (log/info "Populating v5_dashboard.i18n table"
-      (korma/exec-raw
-       (:conn xml-tree-values)
-       ["select v5_dashboard.populate_i18n_table(?)" [id]])))
+  [{:keys [import-id] :as ctx}]
+  (log/info "Populating v5_dashboard.i18n table")
+  (korma/exec-raw
+   (:conn xml-tree-values)
+   ["select v5_dashboard.populate_i18n_table(?)" [import-id]])
   ctx)

 (defn populate-sources-table
-  [ctx]
-  (let [id (:import-id ctx)]
-    (log/info "Populating v5_dashboard.sources table"
-      (korma/exec-raw
-       (:conn xml-tree-values)
-       ["select v5_dashboard.populate_sources_table(?)" [id]])))
+  [{:keys [import-id] :as ctx}]
+  (log/info "Populating v5_dashboard.sources table")
+  (korma/exec-raw
+   (:conn xml-tree-values)
+   ["select v5_dashboard.populate_sources_table(?)" [import-id]])
   ctx)

 (defn populate-elections-table
-  [ctx]
-  (let [id (:import-id ctx)]
-    (log/info "Populating v5_dashboard.elections table"
-      (korma/exec-raw
-       (:conn xml-tree-values)
-       ["select v5_dashboard.populate_elections_table(?)" [id]])))
+  [{:keys [import-id] :as ctx}]
+  (log/info "Populating v5_dashboard.elections table")
+  (korma/exec-raw
+   (:conn xml-tree-values)
+   ["select v5_dashboard.populate_elections_table(?)" [import-id]])
   ctx)


Remove duplicate defn

Remove duplicate defn

--- src/refactor_nrepl/ns/dependencies.clj
+++ src/refactor_nrepl/ns/dependencies.clj
@@ -112,12 +112,6 @@
 (defn- get-imports [ns-form]
   (some-> (get-ns-component ns-form :import) extract-imports
           flatten))
-
-(defn- get-class-name [{:keys [op class children] :as node}]
-  (when (and (and class (not= op :import))
-             (not children)
-             (symbol? class))
-    (.getName (:val node))))

 (defn- get-class-name [{:keys [op class type val] :as node}]
   (when-let [c (if (and (= :const op)


Fix new-fs-store.

Fix new-fs-store.

--- src/konserve/filestore.clj
+++ src/konserve/filestore.clj
@@ -12,7 +12,7 @@
                                PKeyIterable
                                -keys
                                -serialize -deserialize]]
-  [superv.async :refer [go-try- <?-]]
+   [superv.async :refer [go-try- <?-]]
    [clojure.core.async :as async
     :refer [<!! <! >! chan go close! put!]])
   (:import
@@ -163,8 +163,9 @@
         buffer    (ByteBuffer/wrap (.toByteArray bos))
         result-ch (chan)]
     (go-try-
-     (.write ac-new buffer start-byte stop-byte (completion-write-handler result-ch {:type :write-edn-error
-                                                                                :key  key}))
+        (.write ac-new buffer start-byte stop-byte
+                (completion-write-handler result-ch {:type :write-edn-error
+                                                     :key  key}))
      (<?- result-ch)
      (finally
        (close! result-ch)
@@ -689,9 +690,11 @@
                   write-handlers (atom {})
                   buffer-size    (* 1024 1024)
                   config         {:fsync true}}}]
-  (let [detect-old-version (when detect-old-file-schema? (atom (detect-old-file-schema path)))
-        _                  (when-not (empty? @detect-old-version)
-                             (prn (str (count @detect-old-version) " old files detected. Migration is necessary.")))
+  (let [detect-old-version (when detect-old-file-schema?
+                             (atom (detect-old-file-schema path)))
+        _                  (when detect-old-file-schema?
+                             (when-not (empty? @detect-old-version)
+                               (prn (str (count @detect-old-version) " old files detected. Migration is necessary."))))
         _                  (check-and-create-folder path)
         store              (map->FileSystemStore {:detect-old-version detect-old-version
                                                   :folder             path


Added main class to jar manifest for ring jar

--- src/leiningen/ring/jar.clj
+++ src/leiningen/ring/jar.clj
@@ -1,7 +1,8 @@
 (ns leiningen.ring.jar
-  (:use [leiningen.ring.util :refer (compile-form ensure-handler-set!)])
   (:require [leiningen.jar :as jar]
-            [leiningen.ring.server :as server]))
+            [clojure.string :as str])
+  (:use [leiningen.ring.util :only (compile-form ensure-handler-set!)]
+        [leiningen.ring.server :only (add-server-dep)]))

 (defn default-main-namespace [project]
   (let [handler-sym (get-in project [:ring :handler])]
@@ -21,8 +22,16 @@
              (ring.server.leiningen/serve
               '~(select-keys project [:ring])))))))

+(defn update-project [project func & args]
+  (vary-meta
+   (apply func project args)
+   update-in [:without-profiles] #(apply func % args)))
+
+(defn add-main-class [project]
+  (update-project project assoc :main (symbol (main-namespace project))))
+
 (defn jar [project]
   (ensure-handler-set! project)
-  (let [project (server/add-server-dep project)]
+  (let [project (-> project add-server-dep add-main-class)]
     (compile-main project)
     (jar/jar project)))


minor edits

minor edits

--- support/src/figwheel/client/utils.cljs
+++ support/src/figwheel/client/utils.cljs
@@ -10,12 +10,9 @@

 (defn node-env? [] (not (nil? goog/nodeGlobalRequire)))

+(defn host-env? [] (if (node-env?) :node :html))
+
 (defn base-url-path [] (string/replace goog/basePath #"(.*)goog/" #(str %2)))
-
-(defn host-env? []
-  (cond
-    (node-env?) :node
-    :else :html))

 (defn dispatch-custom-event [event-name data]
   (when (and (html-env?) (aget js/window "CustomEvent"))
@@ -44,4 +41,4 @@
 (defn eval-helper [code {:keys [eval-fn] :as opts}]
   (if eval-fn
     (eval-fn code opts)
-    (js* "eval(~{code})")))+    (js* "eval(~{code})")))


Refactor - create `get-ModulesMap` function

To abstract away `(aget js/window "ModulesMap")`

Signed-off-by: Pang Yan Han <22594c345857f664c61cd411f607c4d40a9d4af9@gmail.com>

--- src/cljs/cljs_nusmods/timetable.cljs
+++ src/cljs/cljs_nusmods/timetable.cljs
@@ -62,6 +62,11 @@
 ;                                          `:lessonType`
 ;   }

+(defn- get-ModulesMap
+  "Retrieves the `ModulesMap` JavaScript global variable"
+  []
+  (aget js/window "ModulesMap"))
+
 (def ^{:doc     "Width in pixels of a half hour timeslot"
        :private true
        }
@@ -542,7 +547,7 @@
   (fn [evt ui]
     (.addClass (aget ui "helper") "lesson-draggable-helper")
     (.css (aget ui "helper") "cursor" "grabbing")
-    (let [ModulesMap         (aget js/window "ModulesMap")
+    (let [ModulesMap         (get-ModulesMap)
           ; Get all lesson groups
           allLessonGroupsMap (get-in ModulesMap [moduleCode "lessons"
                                                  lessonType])
@@ -679,7 +684,7 @@
    with the `:divElem`, `:moduleCode`, `:lessonType`, `:lessonGroup` keys."
   [moduleCode lessonType lessonLabel bgColorCssClass isActuallySelected?
    & {:keys [ModulesMap]
-      :or   {ModulesMap (aget js/window "ModulesMap")}}]
+      :or   {ModulesMap (get-ModulesMap)}}]
   (let [moduleName          (get-in ModulesMap [moduleCode "name"])
         modulesMapLessonSeq (get-in ModulesMap [moduleCode "lessons" lessonType
                                                 lessonLabel])]
@@ -738,7 +743,7 @@
    be added."
   [moduleCode]
   (if (not (contains? ModulesSelected moduleCode))
-      (let [ModulesMap      (aget js/window "ModulesMap")
+      (let [ModulesMap      (get-ModulesMap)
             module          (get ModulesMap moduleCode)
             lessonsMap      (get module "lessons")
             bgColorCssClass (get-next-lesson-bg-color-css-class)
@@ -779,7 +784,7 @@
    NOTE: This function should only be called by
          `add-module-lesson-groups-from-url-hash!`"
   [moduleInfoSeq]
-  (let [ModulesMap         (aget js/window "ModulesMap")
+  (let [ModulesMap         (get-ModulesMap)

         moduleLessonGroupsMap
         (reduce (fn [lgMap modInfo]
@@ -861,7 +866,7 @@

    NOTE: This function should only be called once."
   [urlHash]
-  (let [ModulesMap         (aget js/window "ModulesMap")
+  (let [ModulesMap         (get-ModulesMap)
         moduleUrlHashArray (.split urlHash "&")

         modUrlHashRegex
@@ -1072,7 +1077,7 @@
         rowNum     (:rowNum removedAugTTLessonInfo)
         startTime  (:startTime removedAugTTLessonInfo)
         endTime    (:endTime removedAugTTLessonInfo)
-        ModulesMap (aget js/window "ModulesMap")
+        ModulesMap (get-ModulesMap)
         ttDay      (get-timetable-day day)

         ; This is the time range freed up by removal of the lesson


clean up formatting

clean up formatting

--- src/cljs/phonecat_re_frame/core.cljs
+++ src/cljs/phonecat_re_frame/core.cljs
@@ -303,7 +303,6 @@
    [storage-and-memory (reaction (:storage @phone))]
    [connectivity (reaction (:connectivity @phone))]
    [android (reaction (:android @phone))]
-;   [size-and-weight (reaction (:sizeAndWeight @phone))]
    [display (reaction (:display @phone))]
    [hardware (reaction (:hardware @phone))]
    [camera (reaction (:camera @phone))]


fill out phone detail page

fill out phone detail page

--- src/cljs/phonecat_re_frame/core.cljs
+++ src/cljs/phonecat_re_frame/core.cljs
@@ -146,12 +146,136 @@
     [:div {:class "col-md-10"}
      [phones-component]]]])

-(defn phone-page [{phone-id :phone-id}]
-  [:div "TBD: detail view for"
-   [:span phone-id]])
-
 (defn current-page []
   [(session/get :current-page) (session/get :params)])
+
+;; -------------------------
+;; Phone details views
+
+(defn phone-info-template
+  [section-title attributes-map]
+  [:li
+   [:span section-title]
+   [:dl
+    (map (fn [attribute]
+           ^{:key attribute} [:div
+                              [:dt (:name attribute)]
+                              [:dd (:value attribute)]])
+         attributes-map)]])
+
+(defn thumbnails
+  [phone]
+  [:ul {:class "phone-thumbs"}
+   (for [image (:images @phone)]
+     ^{:key image} [:li [:img {:src image
+                               :class "phone"}]])])
+
+(defn availability
+  [availability]
+  [:li
+   [:span "Availability and Networks"]
+   [:dl
+    [:dt "Availability"]
+    (for [availability @availability]
+      availability)]])
+
+(defn battery
+  [battery]
+  [phone-info-template "Battery" [{:name "Type"
+                                   :value (:type @battery)}
+                                  {:name "Talk Time"
+                                   :value (:talkTime @battery)}
+                                  {:name "Standby time (max)"
+                                   :value (:standbyTime @battery)}]])
+
+(defn storage-and-memory
+  [storage]
+  [phone-info-template "Storage And Memory"  [{:name "RAM"
+                                               :value (:ram @storage)}
+                                              {:name "Internal Storage"
+                                               :value (:flash @storage)}]])
+
+(defn connectivity
+  [connectivity]
+  [phone-info-template "Connectivity" [{:name "Network Support"
+                                        :value (:cell @connectivity)}
+                                       {:name "Wifi"
+                                        :value (:wifi @connectivity)}
+                                       {:name "Bluetooth"
+                                        :value (:bluetooth @connectivity)}]])
+
+(defn android
+  [android]
+  [phone-info-template "Android" [{:name "OS Version"
+                                   :value (:os @android)}
+                                  {:name "UI"
+                                   :value (:ui @android)}]])
+
+(defn size-and-weight
+  [size-and-weight]
+  [phone-info-template "Size And Weight" [{:name "Dimensions"
+                                           :value (:dimensions @size-and-weight)}
+                                          {:name "Weight"
+                                           :value (:weight @size-and-weight)}]])
+
+(defn display
+  [display]
+  [phone-info-template "Display" [{:name "Screen size"
+                                   :value (:screenSize @display)}
+                                  {:name "Screen resolution"
+                                   :value (:screenResolution @display)}
+                                  {:name "Touch screen"
+                                   :value (:touchScreen @display)}]])
+
+(defn hardware
+  [hardware]
+  [phone-info-template "Hardware" [{:name "CPU"
+                                    :value (:cpu @hardware)}
+                                   {:name "USB"
+                                    :value (:usb @hardware)}
+                                   {:name "Audio / headphone jack"
+                                    :value (:audioJack @hardware)}
+                                   {:name "FM Radio"
+                                    :value (:fmRadio @hardware)}
+                                   {:name "Accelerometer"
+                                    :value (:accelerometer @hardware)}]])
+
+(defn camera
+  [camera]
+  [phone-info-template "Camera" [{:name "Primary"
+                                  :value (:primary @camera)}
+                                 {:name "Features"
+                                  :value (clojure.string/join ", " (:features @camera))}]])
+
+(defn additional-features
+  [additional-features]
+  [:li
+   [:span "Additional Features"]
+   [:dd @additional-features]])
+
+(defn specs
+  [phone]
+  [:ul {:class "specs"}
+   [availability (reaction (:availiability @phone))]
+   [battery (reaction (:battery @phone))]
+   [storage-and-memory (reaction (:storage @phone))]
+   [connectivity (reaction (:connectivity @phone))]
+   [android (reaction (:android @phone))]
+   [display (reaction (:display @phone))]
+   [hardware (reaction (:hardware @phone))]
+   [camera (reaction (:camera @phone))]
+   [additional-features (reaction (:additionalFeatures @phone))]])
+
+(defn phone-page [{phone-id :phone-id}]
+  (let [phone (re-frame/subscribe [:phone-query phone-id])]
+    (fn []
+      [:div
+       [:img {:src (first (:images @phone))
+              :class "phone"}]
+       [:h1 (:name @phone)]
+       [:p (:description @phone)]
+       [thumbnails phone]
+       [specs phone]])))

 ;; -------------------------
 ;; Routes


env -> state to mirror naming convention from api namespaces, various fixes

--- src/main/cljs/cljs/js.cljs
+++ src/main/cljs/cljs/js.cljs
@@ -49,7 +49,7 @@
   (fn [js-source]
     (throw (js/Error. "No *eval-fn* set"))))

-(defn empty-env []
+(defn empty-state []
   (env/default-compiler-env))

 ;; -----------------------------------------------------------------------------
@@ -87,9 +87,9 @@
              (throw
                (ana/error env
                  (ana/error-message :undeclared-ns
-                   {:ns-sym dep :js-provide (name dep)}))))))))))
-
-(declare ns-side-effects)
+                   {:ns-sym name :js-provide (cljs.core/name name)}))))))))))
+
+(declare ns-side-effects analyze-deps)

 (defn analyze* [bound-vars source opts cb]
   (let [rdr  (rt/string-push-back-reader source)
@@ -111,7 +111,8 @@
              (cb))))))))

 (defn load-deps
-  ([bound-vars ana-env lib deps cb] (analyze-deps bound-vars lib deps nil cb))
+  ([bound-vars ana-env lib deps cb]
+   (analyze-deps bound-vars lib deps nil cb))
   ([bound-vars ana-env lib deps opts cb]
    (let [compiler @(:*compiler* bound-vars)]
      (binding [ana/*cljs-dep-set* (vary-meta (conj (:*cljs-dep-set* bound-vars) lib)
@@ -209,7 +210,7 @@
              check-uses-and-load-macros)

            (and (not load) (:*analyze-deps* bound-vars) (seq deps))
-           (analyze-deps bound-vars ana-env lib deps (dissoc opts :macros-ns)
+           (analyze-deps bound-vars ana-env (:name ast) deps (dissoc opts :macros-ns)
              check-uses-and-load-macros)

            :else
@@ -217,12 +218,12 @@
      (cb ast))))

 (defn analyze
-  ([env source cb]
-   (analyze env source nil cb))
-  ([env source opts cb]
+  ([state source cb]
+   (analyze state source nil cb))
+  ([state source opts cb]
    (analyze*
-     {:*compiler*     env
-      :*cljs-ns*      (or (:ns env) 'cljs.user)
+     {:*compiler*     state
+      :*cljs-ns*      'cljs.user
       :*ns*           (create-ns ana/*cljs-ns*)
       :*data-readers* tags/*cljs-data-readers*}
      source opts cb)))
@@ -230,11 +231,12 @@
 ;; -----------------------------------------------------------------------------
 ;; Emit

-(defn emit* [env bound-vars ast cb]
-  (cb (with-out-str (comp/emit ast))))
-
-(defn emit [env ast cb]
-  (emit* env {} ast cb))
+(defn emit* [bound-vars ast cb]
+  (binding [env/*compiler* (:*compiler* bound-vars)]
+    (cb (with-out-str (comp/emit ast)))))
+
+(defn emit [state ast cb]
+  (emit* {:*compiler* state} ast cb))

 ;; -----------------------------------------------------------------------------
 ;; Eval
@@ -252,10 +254,11 @@
               (comp/emit (ana/analyze ana-env form nil opts))))))))

 (defn eval
-  ([env form cb] (eval env form nil cb))
-  ([env form opts cb]
+  ([state form cb]
+   (eval state form nil cb))
+  ([state form opts cb]
    (eval*
-     {:*compiler*     env
+     {:*compiler*     state
       :*cljs-ns*      'cljs.user
       :*ns*           (create-ns 'cljs.user)
       :*data-readers* tags/*cljs-data-readers*
@@ -288,11 +291,11 @@
              (cb (.toString sb)))))))))

 (defn compile
-  ([env source cb]
-   (compile env source nil cb))
-  ([env source opts cb]
+  ([state source cb]
+   (compile state source nil cb))
+  ([state source opts cb]
     (compile*
-      {:*compiler*     env
+      {:*compiler*     state
        :*cljs-ns*      'cljs.user
        :*ns*           (create-ns 'cljs.user)
        :*data-readers* tags/*cljs-data-readers*
@@ -330,11 +333,11 @@
                (cb (*eval-fn* js-source))))))))))

 (defn eval-str
-  ([env source cb]
-   (eval-str env source nil cb))
-  ([env source opts cb]
+  ([state source cb]
+   (eval-str state source nil cb))
+  ([state source opts cb]
    (eval-str*
-     {:*compiler*     env
+     {:*compiler*     state
       :*cljs-ns*      'cljs.user
       :*ns*           (create-ns 'cljs.user)
       :*data-readers* tags/*cljs-data-readers*


formatting

formatting

--- test/atom_finder/classifier_util_test.clj
+++ test/atom_finder/classifier_util_test.clj
@@ -134,7 +134,7 @@
     (testing "line range stuff"
       (let [cases
             [
-             [{:parent? false :intersects? false :contained-by? false :contains? false }
+             [{:parent? false :intersects? false :contained-by? false :contains? false}
               {:lines [1 1] :node [0 1]}] ; ranges are half-open so [1 1) is empty
              [{:parent? false :intersects? true  :contained-by? true  :contains? false}
               {:lines [1 2] :node [0 1]}]
@@ -144,9 +144,9 @@
               {:lines [1 8] :node [0]}]
              [{:parent? false :intersects? false :contained-by? false :contains? false}
               {:lines [1 2] :node [0 2 0]}]
-             [{:parent? false :intersects? true :contained-by? true :contains? false}
+             [{:parent? false :intersects? true  :contained-by? true  :contains? false}
               {:lines [2 3] :node [0 2 0]}]
-             [{:parent? false :intersects? true :contained-by? true :contains? false}
+             [{:parent? false :intersects? true  :contained-by? true  :contains? false}
               {:lines [2 3] :node [0 2 0]}]
              [{:parent? false :intersects? true  :contained-by? true  :contains? false}
               {:lines [4 5] :node [0 2 1 1 0]}]
@@ -154,19 +154,20 @@
               {:lines [2 6] :node [0 2 1 1 0]}]
              [{:parent? true  :intersects? true  :contained-by? false :contains? true }
               {:lines [2 6] :node [0 2]}]
-             [{:parent? false :intersects? true  :contained-by? false :contains? true}
+             [{:parent? false :intersects? true  :contained-by? false :contains? true }
               {:lines [2 5] :node [0]}]
              ]]

-(doseq [[{parent? :parent? intersects? :intersects? contained-by? :contained-by? contains? :contains?}
-        {[start-line end-line] :lines node-path :node}] cases]
- (is (= intersects? (intersects-line-range? (get-in-tree node-path root) start-line end-line))
-     ["intersects-line-range?" intersects? {:line [start-line end-line] :node node-path}])
- (is (= contained-by? (contained-by-line-range? (get-in-tree node-path root) start-line end-line))
-     ["contained-by-line-range?" contained-by? {:line [start-line end-line] :node node-path}])
- (is (= parent? (line-range-parent? (get-in-tree node-path root) start-line end-line))
-     ["line-range-parent?" parent? {:line [start-line end-line] :node node-path}])
- (is (= contains? (contains-line-range? (get-in-tree node-path root) start-line end-line))
-     ["contains-line-range?" contains? {:line [start-line end-line] :node node-path}])
-    )))
-    ))
+        (doseq [[{parent? :parent? intersects? :intersects? contained-by?
+                  :contained-by? contains? :contains?}
+                 {[start-line end-line] :lines node-path :node}] cases]
+          (is (= intersects? (intersects-line-range? (get-in-tree node-path root) start-line end-line))
+              ["intersects-line-range?" intersects? {:line [start-line end-line] :node node-path}])
+          (is (= contained-by? (contained-by-line-range? (get-in-tree node-path root) start-line end-line))
+              ["contained-by-line-range?" contained-by? {:line [start-line end-line] :node node-path}])
+          (is (= parent? (line-range-parent? (get-in-tree node-path root) start-line end-line))
+              ["line-range-parent?" parent? {:line [start-line end-line] :node node-path}])
+          (is (= contains? (contains-line-range? (get-in-tree node-path root) start-line end-line))
+              ["contains-line-range?" contains? {:line [start-line end-line] :node node-path}])
+          ))))
+    )


fix :source-map-inline issue with :chrome-extension

fixes #656

--- src/main/shadow/build/targets/chrome_extension.clj
+++ src/main/shadow/build/targets/chrome_extension.clj
@@ -128,13 +128,13 @@
                       source-map?
                       (output/has-source-map? output)]

-
                   (if (and source-map? source-map-inline?)
                     (str "SHADOW_ENV.evalLoad(\""
                          output-name
                          "\", false, \""
-                         (.escape browser/js-escaper ^String js)
-                         (output/generate-source-map-inline state rc output "")
+                         (.escape browser/js-escaper
+                           (str js
+                                (output/generate-source-map-inline state rc output "")))
                          "\");")
                     (str "SHADOW_ENV.evalLoad(\"" output-name "\", " source-map? " , \"" (.escape browser/js-escaper ^String js) "\");"))
                   )))


RP      | 25 | cleaning up some requires

RP      | 25 | cleaning up some requires

--- src/stonecutter/controller/email_confirmations.clj
+++ src/stonecutter/controller/email_confirmations.clj
@@ -3,11 +3,11 @@
             [ring.util.response :as r]
             [stonecutter.controller.user :as u]
             [stonecutter.db.confirmation :as conf]
+            [stonecutter.db.storage :as storage]
             [stonecutter.db.user :as user]
+            [stonecutter.helper :as sh]
             [stonecutter.routes :as routes]
-            [stonecutter.view.sign-in :as sign-in]
-            [stonecutter.helper :as sh]
-            [stonecutter.db.storage :as storage]))
+            [stonecutter.view.sign-in :as sign-in]))

 (defn show-confirm-sign-in-form [request]
   (sh/enlive-response (sign-in/confirmation-sign-in-form request) (:context request)))


Fix missing BallotName query

Fix missing BallotName query

Needed to compare the hypothetical BallotName paths to *subpaths* of the
actual, because we only care up to the .BallotName portion.

--- src/vip/data_processor/validation/v5/candidate.clj
+++ src/vip/data_processor/validation/v5/candidate.clj
@@ -45,7 +45,7 @@
           AND subltree(path, 0, 4) ~ 'VipObject.0.Candidate.*{1}'
           AND nlevel(subltree(path, 0, 4)) = 4) xtv
     LEFT JOIN (SELECT path FROM xml_tree_values WHERE results_id = ?) xtv2
-    ON xtv.path = xtv2.path
+    ON xtv.path = subltree(xtv2.path, 0, 5)
     WHERE xtv2.path IS NULL")

 (defn missing-ballot-name-query


flesh out budget report test details

flesh out budget report test details

--- test/clj_money/models/reports_test.clj
+++ test/clj_money/models/reports_test.clj
@@ -493,9 +493,9 @@
                            :actual-per-month 2005M}
                           {:caption "Expense"
                            :style :header
-                           :budget 0M
-                           :actual 0M
-                           :difference 0M
+                           :budget 3828M
+                           :actual 3135M
+                           :difference 693M
                            :percent-difference 0M
                            :actual-per-month 0M}
                           {:caption "Groceries"
@@ -504,7 +504,42 @@
                            :actual 904M
                            :difference -4M
                            :percent-difference 0.0044M
-                           :actual-per-month 2005M}]}]
+                           :actual-per-month 2005M}
+                          {:caption "Rent"
+                           :style :data
+                           :budget 1400M
+                           :actual 1400M
+                           :difference 0M
+                           :percent-difference 0M
+                           :actual-per-month 1400M}
+                          {:caption "Medicare"
+                           :style :data
+                           :budget 60M
+                           :actual 45M
+                           :difference 15M
+                           :percent-difference 0.25M
+                           :actual-per-month 22.5M}
+                          {:caption "Social Security"
+                           :style :data
+                           :budget 268M
+                           :actual 186M
+                           :difference 82M
+                           :percent-difference 0.30M
+                           :actual-per-month 93M}
+                          {:caption "FIT"
+                           :style :data
+                           :budget 800M
+                           :actual 600M
+                           :difference 200M
+                           :percent-difference 0.25M
+                           :actual-per-month 300M}
+                          {:caption "Dining"
+                           :style :data
+                           :budget 400M
+                           :actual 0M
+                           :difference 400M
+                           :percent-difference 1M
+                           :actual-per-month 0M}]}]

     #_(pprint {:result actual})


comment out variation-interactor from interaction label

--- src/wb_es/datomic/data/interaction.clj
+++ src/wb_es/datomic/data/interaction.clj
@@ -29,10 +29,10 @@
                     (:interaction/sequence-interactor)
                     (map :interaction.sequence-interactor/sequence)
                     (map (partial data-util/obj-label "sequence")))
-               (->> entity
-                    (:interaction/variation-interactor)
-                    (map :interaction.variation-interactor/variation)
-                    (map (partial data-util/obj-label "variation")))
+               ;; (->> entity
+               ;;      (:interaction/variation-interactor)
+               ;;      (map :interaction.variation-interactor/variation)
+               ;;      (map (partial data-util/obj-label "variation")))
                (->> entity
                     (:interaction/rearrangement)
                     (map :interaction.rearrangement/rearrangement)