Start ot adjust miconic

Start ot adjust miconic

--- src/angelic/scripts/experiments_11icaps.clj
+++ src/angelic/scripts/experiments_11icaps.clj
@@ -28,18 +28,20 @@

 ;;;;;;; logistics

+(def algs
+  [[[:baseline] "base"]
+   [[:asplan] "bi"]
+   [[:asplan :directed? false] "bi-d"]
+   [[:asplan :greedy? false] "bi-g"]
+   [[:asplan :deadlock? false] "bi-dl"]
+   [[:asplan :dead-vars? false] "bi-dv"]])
+
 (defn make-exp-set []
   (experiments/make-experiment-set
    "logistics"
    [:product
     [:instance (vec (range 27))]
-    [:alg
-      [[:baseline]
-       [:asplan]
-       [:asplan :directed? false]
-       [:asplan :greedy? false]
-       [:asplan :deadlock? false]
-       [:asplan :dead-vars? false]]]]
+    [:alg (map first algs)]]
    (fn [m]
      (let [{[type & args] :alg instance :instance} m
            instance-form `(force (nth sas-problems/ipc2-logistics ~instance))]
@@ -55,75 +57,121 @@
        (experiments/experiment-set-results->dataset
         (experiments/read-experiment-set-results (make-exp-set)))))

+;;;;;;; table
+
+(defn pad-right [x n]
+    (let [xs (str x)
+          s #^String (str "                               " xs)]
+      (assert (<= (.length xs) n))
+      (.substring s (- (.length s) n))))
+
+(defn prob-name [^String x]
+  (.substring x 14 (- (count x) 5)))
+
+
+
+(def *cw* 8)
+(def *w* (+ 4 (* 3 *cw*)))
+(defn make-full-table []
+  (println (apply str (pad-right " " 9) "|" (for [[_ alg] algs] (str (pad-right alg *w*) "|"))))
+  (doseq [i (range 25)]
+    (print (str (prob-name (nth sas-problems/ipc2-logistics-names i)) "   "  " " "|"))
+    (doseq [[algg name] algs
+            :let [result (util/find-first (datasets/ds-fn [instance alg] (and (= instance i) (= alg algg))) *results*)]]
+      (print (str (pad-right (if (:output result) (str " " (pad-right (:next-count result) *cw*) (pad-right  (int (:ms result)) *cw*)) (str ">" (:next-count result))) *w*) "|" )))
+    (println) ))
+
+(defn make-table []
+  (println (apply str (pad-right " " 9) "|" (for [[_ alg] algs] (str (pad-right alg *w*) "|"))))
+  (doseq [[i reward] (sort-by second (map (juxt identity #(- (second (:output (util/find-first (datasets/ds-fn [instance] (= instance %)) *results*))))) (range 10)))]
+    (print (str (prob-name (nth sas-problems/ipc2-logistics-names i)) "   " (pad-right reward 2) " " "|"))
+    (doseq [[algg name] algs
+            :let [result (util/find-first (datasets/ds-fn [instance alg] (and (= instance i) (= alg algg))) *results*)]]
+      (print (str (pad-right (if (:output result) (str " " (pad-right (:next-count result) *cw*) (pad-right  (int (:ms result)) *cw*)) (str ">" (:next-count result))) *w*) "|" )))
+    (println) ))
+
+(defn make-latex-table []
+  (println (apply str (pad-right " " 9) "&" (for [[_ alg] algs] (str (pad-right alg (/ *w* 2)) " &"))))
+  (doseq [[i reward] (sort-by second (map (juxt identity #(- (second (:output (util/find-first (datasets/ds-fn [instance] (= instance %)) *results*))))) (range 10)))]
+    (print (str (prob-name (nth sas-problems/ipc2-logistics-names i)) " & " (pad-right reward 2) " " "&"))
+    (doseq [[algg name] algs
+            :let [result (util/find-first (datasets/ds-fn [instance alg] (and (= instance i) (= alg algg))) *results*)]]
+      (print (str (str " " (pad-right (:next-count result) *cw*) " & " (pad-right  (int (:ms result)) *cw*)) " & " )))
+    (println) ))
+
+
+
+

 (comment
+;;;;;;; miconic

-;;;;;;;;;; Table
+ (def miconic-algs
+      [[[:baseline] "base"]
+       [[:asplan] "bi"]])

-  (defn pad-right [x n]
-    (let [xs (str x)
-          s #^String (str "                               " xs)]
-                                        ;    (assert (<= (.length xs) n))
-      (.substring s (- (.length s) n))))
+ (defn make-exp-set []
+   (experiments/make-experiment-set
+    "miconic"
+    [:product
+     [:instance (vec (range 150))]
+     [:alg (map first algs)]]
+    (fn [m]
+      (let [{[type & args] :alg instance :instance} m
+            instance-form `(force (nth sas-problems/ipc2-logistics ~instance))]
+        (if (= type :baseline)
+          instance-form
+          `(asplan/make-asplan-env ~instance-form ~@args))))
+    (fn [m] `(textbook/uniform-cost-search ~'init))
+    'angelic.scripts.experiments-11icaps 10 600 512 false ::ExpResult))

-  (def *cw* 8)
-  (def *w* (+ 4 (* 3 *cw*)))
-  (defn make-table []
-    (let [results (group-by #(get % :alg) *results*)]
-      (doseq [alg (map first his/aaai-algs)]
-        (let [alg-results (results alg)
-              obj-map (group-by #(get % :objects) alg-results)
-              objects    (sort (keys obj-map))]
-          (println (apply str (pad-right alg 9) "|" (for [o ["s" "progs" "refs"]] (str (pad-right o *w*) "|"))))
-          (println (apply str (repeat (+ 10 (* 3 (inc *w*))) "-")))
-          (doseq [[no n-res] (map (fn [x] [x (obj-map x)]) objects)]
-            (println (apply str (pad-right no 9) "|"
-                            (for [angelic n-res]
-                              (if (:ms exp)
-                                (str (pad-right (/ (int (:ms exp)) 1000.0) *cw*) ", " (pad-right (:next-count exp) *cw*) ", " (pad-right (second (:output exp)) #_(:plan-count exp) *cw*) "|")
-                                (str (pad-right (cond (:memout? exp) "mem" (:timeout? exp) "time") *w*) "|")
-                                ))))))
-        (println "\n\n"))))
+ (defonce *results* nil)
+ (defn read-results []
+   (def *results*
+        (experiments/experiment-set-results->dataset
+         (experiments/read-experiment-set-results (make-exp-set))))))
+
+

 ;;;;;; charts

+(comment
+ (def *alg-order* ["H-UCS" "DH-UCS" "DSH-UCS" "AHA*" "DAHA*" "DASHA*"])
+ (defn order [things key-fn desired-order]
+                                        ;  (println things)
+   (let [m (group-by key-fn things)]
+     (map #(first (util/safe-get m %)) desired-order)))

-  (def *alg-order* ["H-UCS" "DH-UCS" "DSH-UCS" "AHA*" "DAHA*" "DASHA*"])
-  (defn order [things key-fn desired-order]
-                                        ;  (println things)
-    (let [m (group-by key-fn things)]
-      (map #(first (util/safe-get m %)) desired-order)))
-
-  (defn make-charts
-    ([] (make-charts "/Users/jawolfe/Projects/reports/10-aaai-btamp/poster/figs/" ))
-    ([dir]
-       (charts/plot
-        (datasets/ds->chart
-         (datasets/ds-derive #(/ (:ms %) 1000) (filter (datasets/ds-fn [ms] (and ms)) *results*) :secs)
-         [:alg] :objects :secs
-         {:term "solid dashed size 2.4,1.3"   :ylog nil :xrange "[1:6]" :yrange "[0:60]"
+ (defn make-charts
+   ([] (make-charts "/Users/jawolfe/Projects/reports/10-aaai-btamp/poster/figs/" ))
+   ([dir]
+      (charts/plot
+       (datasets/ds->chart
+        (datasets/ds-derive #(/ (:ms %) 1000) (filter (datasets/ds-fn [ms] (and ms)) *results*) :secs)
+        [:alg] :objects :secs
+        {:term "solid dashed size 2.4,1.3"   :ylog nil :xrange "[1:6]" :yrange "[0:60]"
                                         ;        :title "discrete manipulation problems" :xlabel "# of objects" ;:ylabel "runtime (s)"
-          :key "at 4.8, 67 height 3"
-          :extra-commands ["set ylabel \"runtime(s)\" 1,0"
-                           "set xlabel \"# of objects\" 0,.5"]}
-         (let [c (util/counter-from 0)] (fn [& args] (let [v ([2 3 1 5 4.8 6] (c))]  {:lw 3 :pt v :lt v})))
-         #(let [n (first %)] (if (= (last n) \U) (apply str (concat (drop-last n) "-UCS")) (str n "*")))
-         #(order % :title *alg-order*))
-        (str dir "dm-time.pdf") false)
-       #_ (charts/plot
-           (datasets/ds->chart
-            (datasets/ds-derive #(/ (:ms %) 1000) (filter (datasets/ds-fn [ms] (and ms)) *results*) :secs)
-            [:alg] :objects :next-count
-            {:term "solid dashed size 3,1.7"   :ylog nil :xrange "[1:6]" :yrange "[0:60000]"  :key "at 3.6,57000"
+         :key "at 4.8, 67 height 3"
+         :extra-commands ["set ylabel \"runtime(s)\" 1,0"
+                          "set xlabel \"# of objects\" 0,.5"]}
+        (let [c (util/counter-from 0)] (fn [& args] (let [v ([2 3 1 5 4.8 6] (c))]  {:lw 3 :pt v :lt v})))
+        #(let [n (first %)] (if (= (last n) \U) (apply str (concat (drop-last n) "-UCS")) (str n "*")))
+        #(order % :title *alg-order*))
+       (str dir "dm-time.pdf") false)
+      #_ (charts/plot
+          (datasets/ds->chart
+           (datasets/ds-derive #(/ (:ms %) 1000) (filter (datasets/ds-fn [ms] (and ms)) *results*) :secs)
+           [:alg] :objects :next-count
+           {:term "solid dashed size 3,1.7"   :ylog nil :xrange "[1:6]" :yrange "[0:60000]"  :key "at 3.6,57000"
                                         ;   :title "discrete manipulation problems"
-             :extra-commands ["set ylabel \"# of primitive action evaluations(s)\" 1,0"
-                              "set xlabel \"# of objects\" 0,.5"]}
-            (let [c (util/counter-from 0)] (fn [& args] (let [v ([1 2 3 6 5 4] (c))]  {:lw 3 :pt v :lt v})))
-            first #(order % :title *alg-order*))
-           (str dir "dm-prim.pdf") false)
-       ))
+            :extra-commands ["set ylabel \"# of primitive action evaluations(s)\" 1,0"
+                             "set xlabel \"# of objects\" 0,.5"]}
+           (let [c (util/counter-from 0)] (fn [& args] (let [v ([1 2 3 6 5 4] (c))]  {:lw 3 :pt v :lt v})))
+           first #(order % :title *alg-order*))
+          (str dir "dm-prim.pdf") false)
+      ))

 ;(use '[edu.berkeley.ai.util experiments cluster] 'angelic.aaai10)


adding tests

adding tests

--- test/clj/app_test.clj
+++ test/clj/app_test.clj
@@ -11,10 +11,10 @@
 (declare get-comment get-comments)

 (fe/defentity user [name gender birthday]
-  :transform #(assoc % :comments (lazy-seq (get-comments :comment/author (:db/eid %)))))
+  :transform #(assoc %2 :comments (lazy-seq (get-comments %1 :comment/author (:db/eid %2)))))

 (fe/defentity comment [date text author]
-  :transform #(assoc % :users (lazy-seq [(get-user (:comment/author %))])))
+  :transform #(assoc %2 :users (lazy-seq [(get-user %1 (:comment/author %2))])))

 (defonce ^:dynamic *db* (fd/open))
@@ -51,6 +51,41 @@
     (is (< (count pfs) (count fs)))))

+(deftest get-entity-1
+  (let [e (fe/get-entity *ldb* 1)]
+    (is (= e {:db/eid 1
+              :user/name "foo1"
+              :user/gender :f
+              :user/birthday #inst "1999-09-09"}))))
+
+(deftest get-entities-1
+  (let [es (fe/get-entities *ldb* :comment/author 1)
+        [e1 e2] (sort-by :db/eid es)]
+    (is (= (count es) 2))
+    (is (= e1 {:db/eid 3
+               :comment/author 1
+               :comment/text "comment1_1"
+               :comment/date #inst "2017-01-01"}))
+    (is (= e2 {:db/eid 4
+               :comment/author 1
+               :comment/text "comment1_2"
+               :comment/date #inst "2017-02-01"}))))
+
+
+(deftest get-user-1
+  (let [u (get-user *ldb* 1)
+        u-cs (:comments u)
+        u-cs0-us (:users (first u-cs))]
+    (is (not-empty u))
+    (is (#(instance? User %) u)) ;;; wrapped in function call, because otherwise test framework
+                                 ;;; tends to take wrong instance of User after recompiling namespace
+    (is (every? #(instance? Comment %) u-cs))
+    (is (= (count u-cs) 2))
+    (is (every? #(instance? User %) u-cs0-us))
+    (is (= (count u-cs0-us) 1))
+    (is (= (-> u-cs0-us first :db/eid) (:db/eid u)))))
+
+
 #_(fe/get-entity ldb 1)
 #_(get-user ldb 2)


0.2.3

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject riemann "0.2.3-SNAPSHOT"
+(defproject riemann "0.2.3"
   :description
 "A network event stream processor. Intended for analytics, metrics, and alerting; and to glue various monitoring systems together."
   :url "http://github.com/aphyr/riemann"


get rid of all SNAPSHOT deps

get rid of all SNAPSHOT deps

--- project.clj
+++ project.clj
@@ -4,7 +4,7 @@
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}

-  :plugins [[lein-modules-bpk/lein-modules "0.3.13.bpk-SNAPSHOT"]]
+  :plugins [[lein-modules-bpk/lein-modules "0.3.13.bpk-20160816.002513-1"]]

   :pedantic? :abort


Moving all projects to the same version of clojure.data.xml.

--- project.clj
+++ project.clj
@@ -4,14 +4,8 @@
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}

-  ;; Add sonatype repository to pull in the 0.0.8-SNAPSHOT of org.clojure/data.xml
-  ;; We need this snapshot version of data.xml to address this issue: http://dev.clojure.org/jira/browse/DXML-14
-  ;; Once data.xml 0.0.8 is officially released, we should remove this repository
-  :repositories [["snapshots" "https://oss.sonatype.org/content/repositories/snapshots/"]]
-
   :dependencies [[org.clojure/clojure "1.6.0"]
                  [clj-http "0.9.1"]
-                 [org.clojure/data.xml "0.0.8-SNAPSHOT"]
                  [nasa-cmr/cmr-common-lib "0.1.1-SNAPSHOT"]
                  [nasa-cmr/cmr-umm-lib "0.1.0-SNAPSHOT"]
                  [nasa-cmr/cmr-elastic-utils-lib "0.1.0-SNAPSHOT"]


Add database deps

Add database deps

--- project.clj
+++ project.clj
@@ -15,7 +15,11 @@
                  [ch.qos.logback/logback-classic "1.1.2" :exclusions [org.slf4j/slf4j-api]]
                  [org.slf4j/jul-to-slf4j "1.7.7"]
                  [org.slf4j/jcl-over-slf4j "1.7.7"]
-                 [org.slf4j/log4j-over-slf4j "1.7.7"]]
+                 [org.slf4j/log4j-over-slf4j "1.7.7"]
+                 [com.mchange/c3p0 "0.9.2.1"] ; connection pooling
+                 [clj-liquibase "0.5.3"]  ; migrations!
+                 [oss-jdbc      "0.8.0"]  ; for Open Source JDBC drivers
+                 [org.postgresql/postgresql "9.4-1201-jdbc41"]]
   :min-lein-version "2.0.0"
   :resource-paths ["config", "resources"]
   :profiles {:dev {:aliases {"run-dev" ["trampoline" "run" "-m" "subticket.server/run-dev"]}


Allow date in Parse to be an arbitrary type.

--- src/incise/parsers/core.clj
+++ src/incise/parsers/core.clj
@@ -13,7 +13,7 @@
 (defrecord Parse [^String title
                   ^String extension
                   content
-                  ^String date
+                  date
                   ^String layout
                   ^String path
                   ^clojure.lang.Seqable tags


www/case_pages.clj: check norobots when generating pages

--- src/org/altlaw/www/case_pages.clj
+++ src/org/altlaw/www/case_pages.clj
@@ -3,6 +3,7 @@
             [org.altlaw.www.render :as tmpl]
             [org.altlaw.util.courts :as courts]
             [org.altlaw.util.date :as date]
+            [org.altlaw.db.privacy :as priv]
             [clojure.contrib.duck-streams :as duck])
   (:use [clojure.contrib.test-is :only (deftest- with-test is)]))

@@ -84,7 +85,8 @@
     (tmpl/render :xhtml_page
                  :html_title (str (:name escaped) " - AltLaw")
                  :html_head (tmpl/render :default_html_head
-                                         :norobots (= type :citations))
+                                         :norobots (or (= type :citations)
+                                                       (priv/norobots? (:docid doc))))
                  :html_body (gen-case-layout type escaped))))

 (defn all-files [doc]


Relax ugen check for x-fade2 for non-audio rate. Fixes #265.

--- src/overtone/sc/machinery/ugen/metadata/pan.clj
+++ src/overtone/sc/machinery/ugen/metadata/pan.clj
@@ -294,9 +294,7 @@
             :doc "Output level - 0 being silent and 1 being original
                    volume"}]

-    :check [(when-ar (first-n-inputs-ar 2))
-            (nth-input-stream? 0)
-            (nth-input-stream? 1)]
+    :check [(when-ar (first-n-inputs-ar 2))]
     :rates #{:ar :kr}
     :doc "Equal power two channel cross fade"}


CMR-286: Added missing return value for page_num validation.

--- src/cmr/search/services/parameter_validation.clj
+++ src/cmr/search/services/parameter_validation.clj
@@ -40,7 +40,8 @@
   (if-let [page-num (:page_num params)]
     (try (let [page-num-i (Integer. page-num)]
            (if (> 1 page-num-i)
-             ["page_num must be a number greater than or equal to 1"]))
+             ["page_num must be a number greater than or equal to 1"]
+             []))
       (catch NumberFormatException e ["page_num must be a number greater than or equal to 1"]))
     []))


ensure-leadership fixed

ensure-leadership fixed

--- src/clj/backtype/storm/nimbus/elections.clj
+++ src/clj/backtype/storm/nimbus/elections.clj
@@ -22,6 +22,5 @@
     (log-message "Nimbus gained leadership")
     leader-elections))

-(defn ensureLeadership [leader-elections]
-  ;; todo replace RE with some specific exception, supported by Nimbus thrift service
-  (when-not (.hasLeadership leader-elections) (throw (RuntimeException. "Not a leader"))))
+(defn ensure-leadership [leader-elections]
+  (when-not (.hasLeadership leader-elections) (throw (backtype.storm.generated.NotALeaderException.))))


it's probably more correct to show the `last` PR number

--- src-cljs/frontend/components/pages/build.cljs
+++ src-cljs/frontend/components/pages/build.cljs
@@ -75,7 +75,7 @@
   (reify
     om/IRender
     (render [_]
-      (let [pull-request-number (first (build-model/pull-request-numbers build))]
+      (let [pull-request-number (last (build-model/pull-request-numbers build))]
         (html
          [:div.rebuild-container
           [:button.rebuild {:on-click #(raise! owner [:merge-pull-request-clicked (build-model/merge-args build pull-request-number)])}


Add support for adding named attachment to an asset

--- src/io/aviso/twixt/utils.clj
+++ src/io/aviso/twixt/utils.clj
@@ -66,6 +66,14 @@
       (replace-asset-content content-type (as-bytes content))
       (assoc :compiled true :dependencies merged-dependencies))))

+(defn add-attachment
+  "Adds an attachment to an asset."
+  {:since "0.1.13"}
+  [asset name content-type ^bytes content]
+  (assoc-in asset [:attachments name] {:content-type content-type
+                                       :content      content
+                                       :size         (alength content)}))
+
 (defn read-content
   "Reads the content of a provided source (compatible with clojure.java.io/input-stream) as a byte array."
   [source]


remove debug output

remove debug output

--- src/clj/clj_money/api/transaction_items.clj
+++ src/clj/clj_money/api/transaction_items.clj
@@ -22,9 +22,6 @@

 (defn index
   [{params :params}]
-
-  (log/debug "dbk api.transaction-items/index " (prn-str params))
-
   (index-resource transactions/search-items
                   (-> params
                       (rename-keys {:id :account-id})


Fix bugs in user faces

Fix bugs in user faces

--- src/cljs/koeeoadi/components/userfaces.cljs
+++ src/cljs/koeeoadi/components/userfaces.cljs
@@ -61,6 +61,7 @@
      (when (and
              (not= name name-temp)
              (util/valid-face-name? name-temp))
+       (om/update-state! comp assoc :name-temp nil)
        (om/transact! comp `[(user-face/change-name {:new-name ~name-temp}) :palette]))))
   ([comp e]
    (when (= 13 (util/keycode e))
@@ -111,14 +112,14 @@

 (defn face-update-editor [comp e]
   (face-update comp
-    {:face/name   (:face/name comp)
+    {:face/name   (:face/name (om/props comp))
      :face/editor (keyword (util/target-value e))}))

 (defn editor-select [comp]
   (let [{:keys [:face/editor :face/name]} (om/props comp)
         editor-name (clojure.core/name editor)
         editors (keys config/editor-file-map)]
-    (dom/td nil
+    (dom/td #js {:className "user-face-editor-td"}
       (apply dom/select #js {:onChange #(face-update-editor comp %)}
         (map #(util/option (clojure.core/name %) editor-name) editors)))))


Passing true for allow_missing so that a user query with unknown concept ids won't fail.

--- src/cmr/search/services/query_execution.clj
+++ src/cmr/search/services/query_execution.clj
@@ -60,7 +60,7 @@
   [context query]
   (let [{:keys [result-format pretty?]} query
         concept-ids (query->concept-ids query)
-        tresults (t/get-latest-formatted-concepts context concept-ids result-format)
+        tresults (t/get-latest-formatted-concepts context concept-ids result-format true)
         items (map #(select-keys % [:concept-id :revision-id :collection-concept-id :metadata]) tresults)]
     (results/map->Results {:hits (count items)
                            :items items})))


Add shutdown_request handler.

Add shutdown_request handler.

--- src/ipython_clojure/core.clj
+++ src/ipython_clojure/core.clj
@@ -283,6 +283,9 @@
   "returns REPL history, not implemented for now and returns a dummy message"
   {:history []})

+(defn shutdown-reply [message signer]
+  {:restart true})
+
 (defn configure-shell-handler [shell-socket iopub-socket signer]
   (let [execute-request (execute-request-handler shell-socket iopub-socket
                                                  (get-executer))]
@@ -292,6 +295,7 @@
           "kernel_info_request" (kernel-info-reply message shell-socket signer)
           "execute_request" (execute-request message signer)
           "history_request" (history-reply message signer)
+          "shutdown_request" (shutdown-reply message signer)
           "comm_open" (immediately-close-comm message shell-socket signer)
           (do
             (println "Message type" msg-type "not handled yet. Exiting.")


Drop the non-GIN index on catalog_resources(tags)

The non-GIN tags index is never actually used (because nobody ever does
equality comparions on ARRAY columns). That's why we added the GIN index
in the first place, because it massively sped up tag-based queries by
actually looking inside the ARRAY column for a match.

However, I wasn't smart enough to nuke the old, non-GIN index at the
same time...this patch corrects that.

This should save people some disk space and (slightly) improve catalog
storage performance. For larger installations, the space savings could
be considerable; one user reports that old index taking close to 10GB of
disk space!

Signed-off-by: Deepak Giridharagopal <d11186354d1ef01ca06ae37d7e23e827da13e85f@puppetlabs.com>

--- src/com/puppetlabs/puppetdb/scf/migrate.clj
+++ src/com/puppetlabs/puppetdb/scf/migrate.clj
@@ -182,6 +182,13 @@
       (sql/do-commands
         "CREATE INDEX idx_catalog_resources_tags_gin ON catalog_resources USING gin(tags)")
       (log/warn (format "Version %s of PostgreSQL is too old to support fast tag searches; skipping GIN index on tags. For reliability and performance reasons, consider upgrading to the latest stable version." (string/join "." (sql-current-connection-database-version)))))))
+
+(defn drop-old-tags-index
+  "Drops the non-GIN tags index, which is never used (because nobody
+  does equality comparisons against array columns)"
+  []
+  (sql/do-commands
+    "DROP INDEX idx_catalog_resources_tags"))

 (defn drop-classes-and-tags
   "Removes the `classes` and `tags` tables, as this information can be derived
@@ -260,9 +267,10 @@
    3 add-catalog-timestamps
    4 add-certname-facts-metadata-table
    5 add-missing-indexes
-   6 drop-classes-and-tags
-   7 rename-fact-column
-   8 add-reports-tables})
+   6 drop-old-tags-index
+   7 drop-classes-and-tags
+   8 rename-fact-column
+   9 add-reports-tables})

 (def desired-schema-version (apply max (keys migrations)))


Cleaned up thread-last.

Cleaned up thread-last.

It wasn't particularly well-organized, so I refactored it a bit. Hopefully
that's a tad clearer!

--- formatter/src/formatter/extensions/thread_last.clj
+++ formatter/src/formatter/extensions/thread_last.clj
@@ -7,7 +7,6 @@
 (def ^:dynamic *do-not-nest*
   #{"defn" "loop" "let" "if" "and" "or" "fn" "deftest" "is" "testing"})

-; Kind of ugly with that double-if, but hey.
 (defn count-nonlast-nesting
   "Counts the nesting level of the function node"
   [tree]
@@ -25,11 +24,11 @@
       (cond
         (contains? *do-not-nest* (second (first node-vecs)))
           [n nonlast-n]
-        (and (= :Eval (first node)) (vector? (last node-vecs)))
+        (and (= :Eval (first node)))
           (recur (last node-vecs)
                  (inc n)
                  (max nonlast-n
-                      (count-nonlast-nesting (butlast (rest node-vecs)))))
+                      (count-nonlast-nesting (butlast node-vecs))))
         :else
           [n nonlast-n]))))

@@ -39,15 +38,13 @@
   vector of two elements containing trees representing (+3 (* 9 2)) and
   (* 9 2)."
   [tree]
-  (if (sequential? tree)
-      (let [[nesting nonlast-nesting] (count-last-nesting tree)]
-        (if (and (<= nonlast-nesting *max-nonlast-depth*)
-                 (>= nesting *min-depth*))
-            (let [last-of-tree (last (filter vector? tree))
-                  result (mapcat find-nested-nodes (next tree))]
-              (cons tree (remove #(= last-of-tree %) result)))
-            (mapcat #(find-nested-nodes %) (next tree))))
-      nil))
+  (let [[nesting nonlast-nesting] (count-last-nesting tree)
+        tree-nodes (filter vector? tree)
+        result (mapcat find-nested-nodes tree-nodes)]
+    (if (and (<= nonlast-nesting *max-nonlast-depth*)
+             (>= nesting *min-depth*))
+        (cons tree (remove #(= (last tree-nodes) %) result))
+        (mapcat find-nested-nodes tree-nodes))))

 (defn nodes-to-strings
   "Takes a vector or nodes and returns a vector of strings."


Upgrades core.async to 0.3.442 (#287)

Upgrades core.async to 0.3.442 (#287)

--- scheduler/project.clj
+++ scheduler/project.clj
@@ -36,7 +36,7 @@
                  [org.clojure/core.cache "0.6.4"]
                  [org.clojure/core.memoize "0.5.8"]
                  [clj-time "0.9.0"]
-                 [org.clojure/core.async "0.2.374" :exclusions [org.clojure/tools.reader]]
+                 [org.clojure/core.async "0.3.442" :exclusions [org.clojure/tools.reader]]
                  [prismatic/schema "1.1.3"]
                  [clojure-miniprofiler "0.4.0"]
                  [jarohen/chime "0.1.6"]


Rename `parser-stack` -> `parser-queue` to reflect actual behaviour

--- src/taoensso/carmine/protocol.clj
+++ src/taoensso/carmine/protocol.clj
@@ -14,7 +14,7 @@
                       taoensso.carmine.connections/in-stream
                       taoensso.carmine.connections/out-stream)

-(defrecord Context [in-stream out-stream parser-stack])
+(defrecord Context [in-stream out-stream parser-queue])
 (def ^:dynamic *context* nil)
 (def ^:dynamic *parser*  nil)
 (def no-context-error
@@ -94,7 +94,7 @@
     (dorun (map (partial send-arg out) args))
     (.flush out)

-    (when-let [ps (:parser-stack *context*)] (swap! ps conj *parser*))))
+    (when-let [pq (:parser-queue *context*)] (swap! pq conj *parser*))))

 (defn =ba? [^bytes x ^bytes y] (java.util.Arrays/equals x y))

@@ -159,11 +159,11 @@
   [reply-count]
   (let [^DataInputStream in (or (:in-stream *context*)
                                 (throw no-context-error))
-        parsers     @(:parser-stack *context*)
+        parsers     @(:parser-queue *context*)
         reply-count (if (= reply-count :all) (count parsers) reply-count)]

     (when (pos? reply-count)
-      (swap! (:parser-stack *context*) #(subvec % reply-count))
+      (swap! (:parser-queue *context*) #(subvec % reply-count))

       (if (= reply-count 1)
         (->> (get-basic-reply! in)


Small changes to require for Electron 1.0.x

Signed-off-by: Max Gonzih <46091aa16ff6b94a71d5261f2b4e0ca6c3afa9a6@gmail.com>

--- electron_src/electron/core.cljs
+++ electron_src/electron/core.cljs
@@ -1,8 +1,9 @@
 (ns electron.core)

-(def app            (js/require "app"))
-(def browser-window (js/require "browser-window"))
-(def crash-reporter (js/require "crash-reporter"))
+(def electron       (js/require "electron"))
+(def app            (.-app electron))
+(def browser-window (.-BrowserWindow electron))
+(def crash-reporter (.-crashReporter electron))

 (def main-window (atom nil))


Bundle goog.labs.format.csv

Bundle goog.labs.format.csv

--- planck-cljs/src/planck/bundle.cljs
+++ planck-cljs/src/planck/bundle.cljs
@@ -96,6 +96,7 @@
     goog.json.Reviver
     goog.json.Serializer
     goog.json.hybrid
+    goog.labs.format.csv
     goog.locale
     goog.locale.TimeZoneFingerprint
     goog.locale.defaultLocaleNameConstants


Emulate old aeron behaviour where closed pub threw IllegalStateException. I think this is the best path for now as cleaning up the publication manager is done in all the exception handlers anyway.

--- src/onyx/messaging/aeron/publication_manager.clj
+++ src/onyx/messaging/aeron/publication_manager.clj
@@ -16,8 +16,10 @@

 (defn write-to-pub [^Publication pub ^IdleStrategy send-idle-strategy msg]
   (loop [result ^long (.offer ^Publication pub (:buf msg) (:start msg) (:end msg))]
-    (when (neg? result)
-      (.idle send-idle-strategy 0)
+    (when (neg? result)
+      (if (= result Publication/CLOSED)
+        (throw (IllegalStateException. "Publication has been closed"))
+        (.idle send-idle-strategy 0))
       (recur ^long (.offer ^Publication pub (:buf msg) (:start msg) (:end msg))))))

 (defn write-from-buffer [publication-manager pending-ch send-idle-strategy]


link to Circle

link to Circle

--- src/pc/views/blog/diagramming_with_precursor.clj
+++ src/pc/views/blog/diagramming_with_precursor.clj
@@ -48,7 +48,10 @@
       [:img {:src (external-cdn-path "/blog/diagramming-with-precursor/web-part.png")}]]]

     [:article
-     [:p "How did those assets get in the CDN? Somebody pushed some code to GitHub, CircleCI fetched the code, built the assets, ran some tests, then deployed the assets to s3. On the first request, the CDN fetched the assets from s3."]]
+     [:p "How did those assets get in the CDN? Somebody pushed some code to GitHub, "
+      [:a {:href "https://circleci.com"
+           :title "Continuous Integration and Deployment"}
+       "CircleCI"] " fetched the code, built the assets, ran some tests, then deployed the assets to s3. On the first request, the CDN fetched the assets from s3."]]

     [:figure
      [:a.img {:data-caption-black "Hold \"A\" and click the edges of shapes to create arrows."}


Update for new names for ack-message/retry-message

--- src/onyx/plugin/datomic.clj
+++ src/onyx/plugin/datomic.clj
@@ -91,24 +91,24 @@

   p-ext/PipelineInput

-  (ack-message [_ _ message-id]
-    (let [chunk-index (:chunk-index (@pending-messages message-id))]
+  (ack-segment [_ _ segment-id]
+    (let [chunk-index (:chunk-index (@pending-messages segment-id))]
       (swap! pending-chunk-indices disj chunk-index)
       (let [new-top-acked (highest-acked-chunk @top-acked-chunk-index @top-chunk-index @pending-chunk-indices)
             updated-content {:chunk-index new-top-acked :status :incomplete}]
         (extensions/force-write-chunk log :chunk updated-content task-id)
         (reset! top-acked-chunk-index new-top-acked))
-      (swap! pending-messages dissoc message-id)))
+      (swap! pending-messages dissoc segment-id)))

-  (retry-message
-    [_ event message-id]
-    (when-let [msg (get @pending-messages message-id)]
+  (retry-segment
+    [_ event segment-id]
+    (when-let [msg (get @pending-messages segment-id)]
       (>!! read-ch (assoc msg :id (java.util.UUID/randomUUID))))
-    (swap! pending-messages dissoc message-id))
+    (swap! pending-messages dissoc segment-id))

   (pending?
-    [_ _ message-id]
-    (get @pending-messages message-id))
+    [_ _ segment-id]
+    (get @pending-messages segment-id))

   (drained?
     [_ _]


Add simple scale examples.

Add simple scale examples.

--- src/african_polyphony_and_polyrhythm/talk.clj
+++ src/african_polyphony_and_polyrhythm/talk.clj
@@ -1,11 +1,37 @@
 (ns african-polyphony-and-polyrhythm.talk
-  (:require [overtone.live :refer :all :exclude [stop]]
+  (:require [overtone.live :refer :all :exclude [stop scale]]
             [leipzig.melody :refer :all]
             [leipzig.canon :refer [canon]]
-            [leipzig.scale :refer [A B major minor pentatonic high]]
+            [leipzig.scale :refer [scale A B high low]]
             [leipzig.temperament :as temperament]
             [leipzig.live :as live]
             [leipzig.live :refer [stop]]))
+
+; Natural numbers
+(comment
+  (range 0 8))
+
+; Raw frequencies
+(comment
+  (->> (phrase (repeat 1/4) [440 494 554 622 659 740 831 880])
+       live/play))
+
+; Midi
+(comment
+  (->> (phrase (repeat 1/4) [69 71 73 74 76 78 80 81])
+       (where :pitch temperament/equal)
+       live/play))
+
+; Scales
+(def major (scale [2 2 1 2 2 2 1]))
+(def minor (scale [2 1 2 2 1 2 2]))
+(def pentatonic (scale [3 2 2 3 2]))
+(def car (comp high pentatonic -))
+
+(comment
+  (->> (phrase (repeat 1/4) (range 0 8))
+       (where :pitch (comp temperament/equal A major))
+       live/play))

 (defn forever [riff]
   (concat riff (lazy-seq (->> riff forever (after (duration riff))))))
@@ -16,8 +42,7 @@
          (canon #(->> % (take 64) (then (rhythm [1/8])) forever (all :part :clap2))))))

 (comment
-  (live/play (clapping-music))
-  )
+  (live/play (clapping-music)))

 (defmethod live/play-note :clap1 [_]
   ((sample "samples/click2.wav")))
@@ -61,7 +86,7 @@
       (* vol)))

 (defmethod live/play-note :default [{:keys [pitch pan]}]
-  (when pitch (horn :freq pitch :pan pan)))
+  (when pitch (horn :freq pitch :pan (or 0 pan))))

 (defn rand-variations [variations]
   (concat
@@ -133,15 +158,13 @@
          (reduce with)
          (map pan))))

-(def inverse-pentatonic (comp high pentatonic -))
-
 (comment
   (fx-reverb)
   (map fx-chorus [0 1])
   (map fx-distortion [0 1])
   (->>
     balendoro
-    (where :pitch (comp (temperament/just 66) A inverse-pentatonic))
+    (where :pitch (comp temperament/equal A car))
     (tempo (bpm 120))
     (live/play)
     )


Teach sync-event to take a single map as an argument - similar to event

--- src/overtone/libs/event.clj
+++ src/overtone/libs/event.clj
@@ -220,7 +220,10 @@
   (when @monitoring?*
     (swap! monitor* assoc event-type args))
   (binding [overtone.libs.handlers/*log-fn* log/error]
-    (let [event-info (apply hash-map args)]
+    (let [event-info (if (and (= 1 (count args))
+                              (map? (first args)))
+                       (first args)
+                       (apply hash-map args))]
       (apply handlers/sync-event handler-pool event-type event-info))))

 (defn event-debug-on


working on instrument mixers

working on instrument mixers

--- src/overtone/studio/rig.clj
+++ src/overtone/studio/rig.clj
@@ -27,9 +27,11 @@
 (defonce mixer-id*     (ref nil))
 (defonce fx-group*     (ref nil))
 (defonce record-group* (ref nil))
-(defonce MIXER-BUS 49)
+(defonce MIXER-BUS     (audio-bus 2))

 (def RIG-BOOT-DEPS [:server-ready :studio-setup-completed])
+(def DEFAULT-VOLUME 1.0)
+(def DEFAULT-PAN 0.0)

 (defn rig-booted? []
   (deps-satisfied? RIG-BOOT-DEPS))
@@ -49,15 +51,32 @@
 ; A mixer synth for volume, pan, and limiting
 ; TODO: Add basic EQ
 (defonce __MIXER-SYNTH__
-  (defsynth mixer [in-bus 49 out-bus 0
-                   volume 0.5 pan 0.0]
-    (let [source  (in in-bus)]
-      (out out-bus (pan2 source pan volume)))))
+  (defsynth inst-mixer [in-bus 10 out-bus 0 mix -1
+                        low-freq 80 mid-freq 800 hi-freq 2000
+                        band1 -45 band2 -45 band3 -45
+                        volume DEFAULT-VOLUME pan DEFAULT-PAN]
+    (let [dry (in in-bus)
+          wet (b-low-shelf dry low-freq 1 band1)
+          wet (b-peak-eq wet mid-freq 1 band2)
+          wet (b-hi-shelf wet hi-freq 1 band3)
+          mixed (x-fade2 dry wet mix)]
+      (out out-bus (pan2 mixed pan volume)))))

 (defn inst-volume
   "Control the volume for a single instrument."
   [inst vol]
-  (ctl inst :volume vol))
+  (ctl inst :volume vol)
+  (reset! (:volume inst) vol))
+
+(defn inst-pan
+  "Control the pan setting for a single instrument."
+  [inst pan]
+  (ctl inst :pan pan)
+  (reset! (:pan inst) pan))
+
+(defn inst-eq-low
+  [ins freq]
+  ())

 (defn inst-out-bus
   "Set an instruments downstream bus."
@@ -106,13 +125,6 @@
       (alter instruments* assoc-in [ins-name :fx-chain] [])))
   :clear)

-(defn start-mixer []
-  (Thread/sleep 2000)
-  (let [mix (mixer :tgt @mixer-group*)]
-    (dosync (ref-set mixer-id* mix))))
-
-(on-deps :studio-setup-completed ::start-mixer start-mixer)
-
 (defn setup-studio []
   (log/info (str "Creating studio group at head of: " (root-group)))
   (let [g (with-server-sync #(group :head (root-group)))
@@ -148,7 +160,8 @@
     i-name))

 (defn remove-instrument [i-name]
-  (dosync (alter instruments* dissoc i-name)))
+  (dosync (alter instruments* dissoc (name i-name)))
+  (event :inst-removed :inst-name i-name))

 (defn clear-instruments []
   (dosync (ref-set instruments* {})))
@@ -160,20 +173,25 @@
        (binding [*ugens* []
                  *constants* #{}]
          (with-overloaded-ugens
-           (out MIXER-BUS ~@ugen-form)
-           [~sname
-            ~params
-            *ugens*
-            (into [] *constants*)])))))
+           (let [form# ~@ugen-form
+                 n-chans# (count form#)]
+             (out MIXER-BUS form#)
+             [~sname
+              ~params
+              *ugens*
+              (into [] *constants*)
+              n-chans#]))))))

 (defmacro inst
   [sname & args]
-  `(let [[sname# params# ugens# constants#] (pre-inst ~sname ~@args)
+  `(let [[sname# params# ugens# constants# n-chans#] (pre-inst ~sname ~@args)
          sdef# (synthdef sname# params# ugens# constants#)
-         sgroup# (or (:group (get @instruments* sname#))
+         igroup# (or (:group (get @instruments* sname#))
                      (if (server-connected?)
                        (group :tail @inst-group*)
                        nil))
+         imixer-bus# (audio-bus n-chans#)
+         imixer# (inst-mixer :tgt igroup# :pos :head :in-bus in-bus# :out-bus MIXER-BUS)
          arg-names# (map :name params#)
          params-with-vals# (map #(assoc % :value (atom (:default %))) params#)
          s-player# (synth-player sname# params-with-vals#)
@@ -187,7 +205,10 @@
                               :name sname#
                               :ugens ugens#
                               :sdef sdef#
-                              :group sgroup#
+                              :group igroup#
+                              :mixer imixer#
+                              :volume (atom DEFAULT-VOLUME)
+                              :pan (atom DEFAULT-PAN)
                               :out-bus MIXER-BUS
                               :fx-chain []
                               :player player#


Specify parent-with-id for ExternalIdentifiers

--- src/vip/data_processor/db/translations/util.clj
+++ src/vip/data_processor/db/translations/util.clj
@@ -44,6 +44,15 @@
           {:path path
            :simple_path (path->simple-path path)
            :parent_with_id (index-path base-path)
+           :value value})))))
+  ([column-name xml-element parent-with-id]
+   (fn [idx-fn base-path row]
+     (when-let [value (get row column-name)]
+       (let [path (str base-path "." xml-element "." (idx-fn))]
+         (list
+          {:path path
+           :simple_path (path->simple-path path)
+           :parent_with_id parent-with-id
            :value value}))))))

 (defn internationalized-text-ltree [column-name]
@@ -64,17 +73,19 @@
             :value "en"}))))))

 (defn external-identifiers->ltree
-  [idx-fn base-path row]
+  [idx-fn parent-path row]
   (when-let [external-identifier-value (:external_identifier_value row)]
     (let [index (idx-fn)
-          base-path (str base-path
+          base-path (str parent-path
                          ".ExternalIdentifiers."
-                         index)
+                         index
+                         ".ExternalIdentifier.0")
+          parent-with-id (index-path parent-path)
           sub-idx-fn (index-generator 0)]
       (mapcat #(% sub-idx-fn base-path row)
-              [(simple-value-ltree :external_identifier_type "Type")
-               (simple-value-ltree :external_identifier_othertype "OtherType")
-               (simple-value-ltree :external_identifier_value "Value")]))))
+              [(simple-value-ltree :external_identifier_type "Type" parent-with-id)
+               (simple-value-ltree :external_identifier_othertype "OtherType" parent-with-id)
+               (simple-value-ltree :external_identifier_value "Value" parent-with-id)]))))

 (defn ltreeify [row]
   (-> row


[CS] Error on missing zip codes in two spots

Polling locations and early vote sites were missing a validation on
missing zip codes. They have been added at the error level, since their
presence isn't strictly required for display. (However, their absence
will end up with invalid XML, as they are required by the spec... at
least people will know why the XML is invalid.)

--- src/vip/data_processor/validation/data_spec.clj
+++ src/vip/data_processor/validation/data_spec.clj
@@ -162,7 +162,7 @@
               {:name "address_line3"}
               {:name "address_city" :required :critical}
               {:name "address_state" :required :critical}
-              {:name "address_zip"}
+              {:name "address_zip" :required :errors}
               {:name "directions"}
               {:name "voter_services"}
               {:name "start_date" :format format/date :coerce coerce-date}
@@ -260,7 +260,7 @@
               {:name "address_line3"}
               {:name "address_city" :required :critical}
               {:name "address_state" :required :critical}
-              {:name "address_zip"}
+              {:name "address_zip" :required :errors}
               {:name "directions"}
               {:name "polling_hours"}
               {:name "photo_url" :format format/url}]}


Stop checking empty strings in Source validations

Empty strings don't get put into the xml_tree_values table anyway, so we
can just check for truthiness there.

--- src/vip/data_processor/validation/v5/source.clj
+++ src/vip/data_processor/validation/v5/source.clj
@@ -1,7 +1,6 @@
 (ns vip.data-processor.validation.v5.source
   (:require [korma.core :as korma]
-            [vip.data-processor.db.postgres :as postgres]
-            [clojure.string :as str]))
+            [vip.data-processor.db.postgres :as postgres]))

 (defn validate-one-source [{:keys [import-id] :as ctx}]
   (let [result (korma/exec-raw
@@ -28,10 +27,10 @@
                                         postgres/xml-tree-values :path path)))
                         first
                         :value)]
-    (if (str/blank? source-name)
+    (if source-name
+      ctx
       (update-in ctx [:fatal :source path :missing]
-                 conj :missing-name)
-      ctx)))
+                 conj :missing-name))))

 (defn validate-date-time [{:keys [import-id] :as ctx}]
   (let [path "VipObject.0.Source.*{1}.DateTime.*{1}"
@@ -42,7 +41,7 @@
                                              postgres/xml-tree-values :path path)))
                              first
                              :value)]
-    (if (str/blank? source-date-time)
+    (if source-date-time
+      ctx
       (update-in ctx [:fatal :source path :missing]
-                 conj :missing-date-time)
-      ctx)))
+                 conj :missing-date-time))))


Remove fns no longer in use

Remove fns no longer in use

--- src/pinpointer/printer.cljc
+++ src/pinpointer/printer.cljc
@@ -71,16 +71,6 @@
   (let [printer (highlight-printer trace)]
     (with-out-str
       (fipp/pprint-document (visit/visit printer x) {}))))
-
-(defn pr [x])
-
-(defn prn [x]
-  (pr x)
-  (newline))
-
-(defn pr-str [x]
-  (with-out-str
-    (pr x)))

 ;;
 ;; Method implementations of `render`


Fix indentation

Fix indentation

--- src/airhead_frontend/components.cljs
+++ src/airhead_frontend/components.cljs
@@ -8,11 +8,11 @@

 (defn header []
   (let [cursor  (r/cursor app-state [:info])
-                title   (@cursor :name)
-                message (@cursor :greet_message)]
+        title   (@cursor :name)
+        message (@cursor :greet_message)]
     [:header
-      [:h1 title]
-      [:p message]]))
+     [:h1 title]
+     [:p message]]))

 ;; -------------------------
 ;; Player
@@ -20,35 +20,35 @@
 (defn now-playing []
   (let [track (@app-state :now-playing)]
     [:p#player-track
-      [:i.fa.fa-music]
-      [:span (if track
-               (str (:artist track) " - " (:title track))
-               [:em "Nothing is playing."])]]))
+     [:i.fa.fa-music]
+     [:span (if track
+              (str (:artist track) " - " (:title track))
+              [:em "Nothing is playing."])]]))

 (defn player-section []
   (let [audio-ref (r/atom nil)]
     (fn []
       (when-let [url (get-in @app-state [:info :stream_url])]
         [:section#player
-          [:audio {:ref #(reset! audio-ref %)}
-                  [:source {:src url}]]
+         [:audio {:ref #(reset! audio-ref %)}
+          [:source {:src url}]]

-          [:div#player-controls.pure-button-group
-            {:role "group"}
-            (when-let [audio @audio-ref]
-              (if (.-paused audio)
-                [:button.pure-button.pure-button-primary
-                  {:on-click #(.play audio)}
-                  [:i.fa.fa-play] "Play"]
-                [:button.pure-button.pure-button-primary.pure-button-active
-                  {:on-click #(.pause audio)}
-                  [:i.fa.fa-pause] "Pause"]))
+         [:div#player-controls.pure-button-group
+          {:role "group"}
+          (when-let [audio @audio-ref]
+            (if (.-paused audio)
+              [:button.pure-button.pure-button-primary
+               {:on-click #(.play audio)}
+               [:i.fa.fa-play] "Play"]
+              [:button.pure-button.pure-button-primary.pure-button-active
+               {:on-click #(.pause audio)}
+               [:i.fa.fa-pause] "Pause"]))

-            [:a.pure-button {:href url :target "_blank"}
-                            [:i.fa.fa-external-link]
-                            "Open stream"]]
+          [:a.pure-button {:href url :target "_blank"}
+           [:i.fa.fa-external-link]
+           "Open stream"]]

-          [now-playing]]))))
+         [now-playing]]))))

 ;; -------------------------
 ;; Upload
@@ -62,49 +62,49 @@
   (let [form-ref (r/atom nil)]
     (fn []
       [:section#upload
-        [:h2 "Upload"]
+       [:h2 "Upload"]

-        [:form.pure-form
-          {:ref #(reset! form-ref %)}
-          [:input.pure-input-3-4 {:type "file" :name "track"}]
-          [:input.pure-button.pure-button-primary.pure-input-1-4
-            {:type "button" :value "Upload"
-            :on-click #(when-let [form @form-ref] (req/upload! form))}]
-          [progress-bar]]
+       [:form.pure-form
+        {:ref #(reset! form-ref %)}
+        [:input.pure-input-3-4 {:type "file" :name "track"}]
+        [:input.pure-button.pure-button-primary.pure-input-1-4
+         {:type "button" :value "Upload"
+          :on-click #(when-let [form @form-ref] (req/upload! form))}]
+        [progress-bar]]

-        [:p (@app-state :upload-status)]])))
+       [:p (@app-state :upload-status)]])))

 ;; -------------------------
 ;; Tracks

 (defn playlist-add-button [track]
   [:i.fa.fa-plus-square
-    {:on-click #(req/playlist-add! (:uuid track))}])
+   {:on-click #(req/playlist-add! (:uuid track))}])

 (defn playlist-remove-button [track]
   [:i.fa.fa-minus-square
-    {:on-click #(req/playlist-remove! (:uuid track))}])
+   {:on-click #(req/playlist-remove! (:uuid track))}])

 (defn track-tr [track action-button]
   [:tr.track
-    [:td
-      (when action-button
-        [action-button track])]
-    [:td (track :title)] [:td (track :artist)] [:td (track :album)]])
+   [:td
+    (when action-button
+      [action-button track])]
+   [:td (track :title)] [:td (track :artist)] [:td (track :album)]])

 ;; -------------------------
 ;; Playlist

 (defn playlist-section []
   [:section#playlist
-    [:h2 "Playlist"]
-    (if-let [tracks (not-empty (@app-state :playlist))]
-      [:table.pure-table.pure-table-striped
-        [:thead
-          [:tr [:th] [:th  "Title"] [:th "Artist"] [:th "Album"]]]
-        [:tbody (for [track tracks]
-                  ^{:key track} [track-tr track playlist-remove-button])]]
-      "The playlist is empty.")])
+   [:h2 "Playlist"]
+   (if-let [tracks (not-empty (@app-state :playlist))]
+     [:table.pure-table.pure-table-striped
+      [:thead
+       [:tr [:th] [:th  "Title"] [:th "Artist"] [:th "Album"]]]
+      [:tbody (for [track tracks]
+                ^{:key track} [track-tr track playlist-remove-button])]]
+     "The playlist is empty.")])

 ;; -------------------------
 ;; Search
@@ -130,41 +130,41 @@

 (defn sorting-th [field caption]
   [:th {:on-click #(update-sort-field! field)}
-       caption
-       [:span.sorting-arrow (when (= field (@app-state :sort-field))
-                              (if (@app-state :ascending)
-                                " ▲"
-                                " ▼"))]])
+   caption
+   [:span.sorting-arrow (when (= field (@app-state :sort-field))
+                          (if (@app-state :ascending)
+                            " ▲"
+                            " ▼"))]])

 (defn library-section []
   (let [tracks (@app-state :library)]
     [:section#library
-      [:h2 "Library"]
-      [:form#library-search.pure-form
-        [:input {:type "text"
-                :id "query"
-                :placeholder "Search through the library..."
-                :value (@app-state :query)
-                :on-change on-query-change}]
-        [:span (str "Tracks: " (count tracks))]]
-      [:table.pure-table.pure-table-striped
-        [:thead
-          [:tr [:th]
-               [sorting-th :title "Title"]
-               [sorting-th :artist "Artist"]
-               [sorting-th :album "Album"]]]
-        [:tbody (for [track (sort-tracks tracks)]
-                  ^{:key track} [track-tr track playlist-add-button])]]]))
+     [:h2 "Library"]
+     [:form#library-search.pure-form
+      [:input {:type "text"
+               :id "query"
+               :placeholder "Search through the library..."
+               :value (@app-state :query)
+               :on-change on-query-change}]
+      [:span (str "Tracks: " (count tracks))]]
+     [:table.pure-table.pure-table-striped
+      [:thead
+       [:tr [:th]
+        [sorting-th :title "Title"]
+        [sorting-th :artist "Artist"]
+        [sorting-th :album "Album"]]]
+      [:tbody (for [track (sort-tracks tracks)]
+                ^{:key track} [track-tr track playlist-add-button])]]]))

 ;; -------------------------
 ;; Main

 (defn page-component []
   [:main.pure-g
-    [:div.pure-u-1.pure-u-md-1-2
-      [header]
-      [player-section]
-      [upload-section]
-      [playlist-section]]
-    [:div.pure-u-1.pure-u-md-1-2
-      [library-section]]])
+   [:div.pure-u-1.pure-u-md-1-2
+    [header]
+    [player-section]
+    [upload-section]
+    [playlist-section]]
+   [:div.pure-u-1.pure-u-md-1-2
+    [library-section]]])


Added extra states to support welcome page redirects.

--- src/plugboard/plugboard.clj
+++ src/plugboard/plugboard.clj
@@ -37,6 +37,9 @@
       [:C9 true] :D9
       [:D2 false] :D4
       [:D4 false] :G4
+      [:D4 true] :D5
+      [:D5 false] :E5
+      [:D5 true] 301
       [:D9 false] :E9
       [:E9 false] :G10
       [:G4 false] 404


don't run incrementer on load

don't run incrementer on load

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

--- src/aurora/examples/incrementer.cljs
+++ src/aurora/examples/incrementer.cljs
@@ -5,20 +5,27 @@
   (:require-macros [aurora.macros :refer [typeof ainto perf-time rules]]))

-(let [program (env)]
-  (rules program
-         (rule draw-incr
-               (when "incr" {:value value})
-               (draw [:button {:id "incr" :events ["onClick"]} "increment: " 'value]))
+(defn run []
+  (let [program (env)]
+    (rules program
+           (rule draw-incr
+                 (when "incr" {:value value})
+                 (draw [:button {:id "incr" :events ["onClick"]} "increment: " 'value]))

-         (rule clicked
-               (when "ui/onClick" {:elem-id "incr"})
-               (func 'new-val "value + 1")
-               (change "incr" {:value 'value} {:value 'new-val}))
-         )
-  (pre-compile program)
-  (remember program "incr" ["value"] [0])
-  (know program "incr" ["value"] [0])
-  (re-run program)
-  )
+           (rule clicked
+                 (when "ui/onClick" {:elem-id "incr"})
+                 (func 'new-val "value + 1")
+                 (change "incr" {:value 'value} {:value 'new-val}))
+           )
+    (pre-compile program)
+    (remember program "incr" ["value"] [0])
+    (know program "incr" ["value"] [0])
+    (re-run program)
+    ))

+
+(comment
+
+  (run)
+
+ )


GR - add functional tests for questions and answers

--- test/objective8/functional/functional_tests.clj
+++ test/objective8/functional/functional_tests.clj
@@ -22,6 +22,15 @@
       (prn (str ">>>>>>>>>>> Title never appeared:"))
       (prn (str "Expected: " title))
       (prn (str "Actual: " (wd/title)))
+      (throw e))))
+
+(def not-empty? (comp not empty?))
+
+(defn wait-for-element [q]
+  (try
+    (wd/wait-until #(not-empty? (wd/elements q)) 5000)
+    (catch Exception e
+      (prn (str "Could not find element: " q))
       (throw e))))

 (def screenshot-directory "test/objective8/functional/screenshots")
@@ -95,6 +104,43 @@
                       (throw e)))
                =>  "Functional test headline | Objective[8]")

+         (fact "Can add a question"
+               (try (wd/to (:objective-url @journey-state))
+                    (wait-for-title "Functional test headline | Objective[8]")
+                    (screenshot "objective_page")
+
+                    (wd/click "a#clj-objectives-questions")
+                    (wait-for-element "textarea#question")
+                    (screenshot "questions_page")
+
+                    (-> "textarea#question"
+                        (wd/input-text "Functional test question")
+                        (wd/submit))
+
+                    (wait-for-element "textarea#answer")
+                    (screenshot "question_page")
+
+                    (swap! journey-state assoc :question-url (wd/current-url))
+
+                    (catch Exception e
+                      (screenshot "Error-Can-add-questions")
+                      (throw e))))
+
+         (fact "Can answer a question"
+               (try (wd/to (:question-url @journey-state))
+                    (wait-for-element "textarea#answer")
+
+                    (-> "textarea#answer"
+                        (wd/input-text "Functional test answer")
+                        (wd/submit))
+
+                    (wait-for-element ".answer-text p")
+                    (wd/text ".answer-text p")
+                    (catch Exception e
+                      (screenshot "Error-Can-answer-questions")
+                      (throw e)))
+               => "Functional test answer")
+
          (fact "Can invite a writer"
                (try (wd/to (:objective-url @journey-state))
                     (wait-for-title "Functional test headline | Objective[8]")
@@ -195,26 +241,26 @@
                                :page-source (contains SOME_HTML)}))

            (future-fact "Can navigate between drafts"
-                 (try
-                   (wd/to (str (:objective-url @journey-state) "/drafts"))
-                   (wait-for-title "Functional test headline | Objective[8]")
-                   (screenshot "list_of_drafts")
-
-                   (wd/click "#clj-add-a-draft")
-                   (wait-for-title "Add draft | Objective[8]")
-
-                   (wd/input-text "#clj-add-draft-content" SOME_EDITED_MARKDOWN)
-
-                   (wd/click "button[value='submit']")
-
-                   (wd/click "#clj-add-a-draft")
-                   (wait-for-title "Add draft | Objective[8]")
-                   (wd/input-text "#clj-add-draft-content" SOME_MORE_EDITED_MARKDOWN)
-
-                   (wd/click "#clj-go-to-previous-draft")
-
-                   (wd/page-source)
-                   (catch Exception e
-                     (screenshot "ERROR-Can-navigate-between-drafts")
-                     (throw e)))
-                 => (contains SOME_EDITED_MARKDOWN)))))
+                        (try
+                          (wd/to (str (:objective-url @journey-state) "/drafts"))
+                          (wait-for-title "Functional test headline | Objective[8]")
+                          (screenshot "list_of_drafts")
+
+                          (wd/click "#clj-add-a-draft")
+                          (wait-for-title "Add draft | Objective[8]")
+
+                          (wd/input-text "#clj-add-draft-content" SOME_EDITED_MARKDOWN)
+
+                          (wd/click "button[value='submit']")
+
+                          (wd/click "#clj-add-a-draft")
+                          (wait-for-title "Add draft | Objective[8]")
+                          (wd/input-text "#clj-add-draft-content" SOME_MORE_EDITED_MARKDOWN)
+
+                          (wd/click "#clj-go-to-previous-draft")
+
+                          (wd/page-source)
+                          (catch Exception e
+                            (screenshot "ERROR-Can-navigate-between-drafts")
+                            (throw e)))
+                        => (contains SOME_EDITED_MARKDOWN)))))


Versuche

Versuche

--- src/logic/basicfunctions.clj
+++ src/logic/basicfunctions.clj
@@ -29,6 +29,11 @@
    ([x & next]
      (if x false (apply nor next))))

+; ??
+(defmacro nand1
+     [& more]
+     `(not (and ~@more)))
+
 ;;; macro ;;;
 (defmacro nor
   "Logical negated or (!(phi | psi))"
@@ -38,10 +43,21 @@
     `(let [nor# ~x]
        (if nor# false (nor ~@next)))))

+(defmacro nor1
+     [& more]
+     `(not (or ~@more)))
+
 (defn impl
   "Logical implication (phi -> psi)"
   [phi psi]
   (or (not phi) psi))
+
+; besser als Makro, q wird nicht ausgewertet, wenn p false ist
+(defmacro impl1
+  [p q]
+  `(if (not ~p)
+     true
+     ~q))

 (defn nimpl
   "Logical negated implication (!(phi -> psi))"
@@ -63,11 +79,10 @@
    ([] true)
    ([x] true)
    ([x y]
-     `(let [equiv1# ~x, equiv2# ~y]
-        (if (= equiv1# equiv2#) true false)))
-   ([x y & next]
-     `(let [equiv1# ~x, equiv2# ~y]
-        (if (= equiv1# equiv2#) (equiv equiv2# ~@next) false))))
+     `(= ~x ~y))
+   ([x y & more]
+     `(let [y# ~y]
+        (if (= ~x  y#) (equiv y# ~@more) false))))

 (defn rimpl
   "Reverted logical implication (phi <- psi)"


A todo added to websocket ns in order to fix the 204 bug

--- src/clj/hellhound/http/websocket.clj
+++ src/clj/hellhound/http/websocket.clj
@@ -128,7 +128,8 @@
   ;; TODO return the Ring response using a deferred value
   non-websocket-request)

-
+;; TODO: we need to return a correct response in this
+;; interceptor
 (def interceptor
   {:name ::interceptor
    :enter ws})


Refactor functions for dealing with `ModulesMap` JS global

This refactoring prevents _most_ of the abstraction breaking we've
committed while trying to get the code out as soon as possible.

The next patch(es) will continue to work towards the same goal.

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

--- src/cljs/cljs_nusmods/timetable.cljs
+++ src/cljs/cljs_nusmods/timetable.cljs
@@ -67,6 +67,55 @@
   []
   (aget js/window "ModulesMap"))

+(defn- get-module-name-from-module-code
+  "Given a module code, returns the name of the module"
+  [moduleCode]
+  (let [modulesMap (get-ModulesMap)]
+    (get-in modulesMap [moduleCode "name"])))
+
+(defn- get-module-lesson-groups-map
+  "Retrieves the map of lesson group strings to vector of lessons"
+  [moduleCode lessonType]
+  (let [modulesMap (get-ModulesMap)]
+    (get-in modulesMap [moduleCode "lessons" lessonType])))
+
+(defn- module-lesson-type-has-multiple-choices?
+  "Given a module code and a long form lesson type, determines if there are
+   multiple choices of lesson groups for that lesson type (eg. multiple
+   tutorial choices for a module)."
+  [moduleCode lessonType]
+  (let [lessonGroupsMap (get-module-lesson-groups-map moduleCode lessonType)]
+    (> (count lessonGroupsMap) 1)))
+
+(defn- get-all-lesson-types-for-module
+  "Returns a sequence of strings, where each string is a long form lesson type
+   for a module."
+  [moduleCode]
+  (let [modulesMap (get-ModulesMap)]
+    (keys (get-in modulesMap [moduleCode "lessons"]))))
+
+(defn- get-all-lesson-group-strings
+  "Given a module and a lesson type, returns a sequence of all its lesson
+   group strings."
+  [moduleCode lessonType]
+  (let [lessonGroupsMap (get-module-lesson-groups-map moduleCode lessonType)]
+    (keys lessonGroupsMap)))
+
+(defn- get-first-lesson-group-for-module-lesson-type
+  "Given a module and a lesson type, retrieves the 'first' lesson group string
+   for that module.
+   This is used for selecting a random lesson group for a lesson type of a
+   module."
+  [moduleCode lessonType]
+  (first (get-all-lesson-group-strings moduleCode lessonType)))
+
+(defn- module-has-lesson-group?
+  "Given a module code, a lesson type, and a lesson group, determines if the
+   module has such a lesson group."
+  [moduleCode lessonType lessonGroup]
+  (let [lessonGroupsMap (get-module-lesson-groups-map moduleCode lessonType)]
+    (not (nil? (get lessonGroupsMap lessonGroup)))))
+
 (def ^{:doc     "Width in pixels of a half hour timeslot"
        :private true
        }
@@ -547,21 +596,21 @@
   (fn [evt ui]
     (.addClass (aget ui "helper") "lesson-draggable-helper")
     (.css (aget ui "helper") "cursor" "grabbing")
-    (let [ModulesMap         (get-ModulesMap)
-          ; Get all lesson groups
-          allLessonGroupsMap (get-in ModulesMap [moduleCode "lessons"
-                                                 lessonType])
-          ; Exclude the selected lesson group
-          unselectedLessonGroupsMap
-          (dissoc allLessonGroupsMap selectedLessonGroup)
+    (let [allLessonGroups
+          (get-all-lesson-group-strings moduleCode lessonType)
+
+          unselectedLessonGroups
+          (remove #{selectedLessonGroup} allLessonGroups)
+
           ; Add all the <div> elements
           augmentedTTLessonInfoSeq
           (doall
             (flatten
-              (map (fn [[lessonGroup _]]
-                     (add-module-lesson-group moduleCode lessonType lessonGroup
+              (map (fn [unselectedLessonGroup]
+                     (add-module-lesson-group moduleCode lessonType
+                                              unselectedLessonGroup
                                               bgColorCssClass false))
-                   unselectedLessonGroupsMap)))]
+                   unselectedLessonGroups)))]
       (set! Lessons-Created-By-Draggable augmentedTTLessonInfoSeq))))

 (defn- lesson-draggable-stop-evt-handler-maker
@@ -685,11 +734,15 @@
   [moduleCode lessonType lessonLabel bgColorCssClass isActuallySelected?
    & {:keys [ModulesMap]
       :or   {ModulesMap (get-ModulesMap)}}]
-  (let [moduleName          (get-in ModulesMap [moduleCode "name"])
+
+  (let [; TODO: Refactor
         modulesMapLessonSeq (get-in ModulesMap [moduleCode "lessons" lessonType
                                                 lessonLabel])]
-    (if (and moduleName modulesMapLessonSeq)
-        (let [augLessonInfoSeq
+
+    (if (module-has-lesson-group? moduleCode lessonType lessonLabel)
+        (let [moduleName (get-module-name-from-module-code moduleCode)
+
+              augLessonInfoSeq
               (doall (map (fn [modulesMapLesson]
                             (add-module-lesson! moduleCode moduleName
                                                            lessonType
@@ -698,6 +751,7 @@
                                                            bgColorCssClass
                                                            isActuallySelected?))
                           modulesMapLessonSeq))
+
               lessonInfoSeq (map #(dissoc %1 :divElem :moduleCode :lessonType
                                           :lessonGroup)
                                  augLessonInfoSeq)
@@ -724,9 +778,8 @@

                 ; Only lesson types with more than 1 option of lesson group
                 ; will be draggable
-                (if (> (count (get-in ModulesMap [moduleCode "lessons"
-                                                  lessonType]))
-                       1)
+                (if (module-lesson-type-has-multiple-choices? moduleCode
+                                                              lessonType)
                     (make-added-lessons-draggable $divElemSeq moduleCode
                                                   lessonType lessonLabel
                                                   bgColorCssClass)))
@@ -743,7 +796,8 @@
    be added."
   [moduleCode]
   (if (not (contains? ModulesSelected moduleCode))
-      (let [ModulesMap      (get-ModulesMap)
+      (let [; TODO: Refactor
+            ModulesMap      (get-ModulesMap)
             module          (get ModulesMap moduleCode)
             lessonsMap      (get module "lessons")
             bgColorCssClass (get-next-lesson-bg-color-css-class)
@@ -784,9 +838,7 @@
    NOTE: This function should only be called by
          `add-module-lesson-groups-from-url-hash!`"
   [moduleInfoSeq]
-  (let [ModulesMap         (get-ModulesMap)
-
-        moduleLessonGroupsMap
+  (let [moduleLessonGroupsMap
         (reduce (fn [lgMap modInfo]
                   ; Replaces earlier lesson groups with later ones if we
                   ; encounter a duplicate lesson type
@@ -805,12 +857,12 @@
                 {}
                 moduleCodesSeq)

-        ; Similar to `moduleLessonTypes`, but obtained from ModulesMap
+        ; Similar to `moduleLessonTypes`, but contains the full sequence of
+        ; lesson type strings
         moduleLessonTypesFull
         (reduce (fn [lessonTypesMap moduleCode]
                   (assoc lessonTypesMap moduleCode
-                         (keys (get-in ModulesMap
-                                       [moduleCode "lessons"]))))
+                         (get-all-lesson-types-for-module moduleCode)))
                 {}
                 moduleCodesSeq)

@@ -836,11 +888,9 @@
                         (get missingModuleLessonTypes moduleCode)]
                     (reduce
                       (fn [lgMap lessonType]
-                        (let [lessonGroups
-                              (get-in ModulesMap
-                                      [moduleCode "lessons" lessonType])]
-                          (assoc-in lgMap [moduleCode lessonType]
-                                           (first (keys lessonGroups)))))
+                        (assoc-in lgMap [moduleCode lessonType]
+                                  (get-first-lesson-group-for-module-lesson-type
+                                    moduleCode lessonType)))
                       lgMapFinal
                       missingLessonTypes)))
                 moduleLessonGroupsMap
@@ -890,11 +940,8 @@
         ; Sequence of existing lesson groups
         moduleInfoExistent
         (filter
-          (fn [modInfo]
-            (not (nil? (get-in ModulesMap
-                               [(:moduleCode modInfo) "lessons"
-                                (:lessonType modInfo)
-                                (:lessonGroup modInfo)]))))
+          #(module-has-lesson-group? (:moduleCode %1) (:lessonType %1)
+                                     (:lessonGroup %1))
           ; convert matchArrays to maps
           (map (fn [matchArray]
                  {:moduleCode  (get-module-code-from-match-array


[REFACTOR] Use #() reader macro to simplify anonymous function

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

--- src/cljs/cljs_nusmods/timetable.cljs
+++ src/cljs/cljs_nusmods/timetable.cljs
@@ -409,8 +409,7 @@
   "Sorts a sequence of `PreToUrlHashLessonGroup` objects lexicographically by
    `:lessonType`."
   [preToUrlHashLessonGroupSeq]
-  (sort (fn [a b] (< (:lessonType a) (:lessonType b)))
-        preToUrlHashLessonGroupSeq))
+  (sort #(< (:lessonType %1) (:lessonType %2)) preToUrlHashLessonGroupSeq))

 (defn- get-PreToUrlHashLessonGroup-seq-for-selected-module
   "Given the module code of a module that has been selected, returns a sequence


moar idiomatic

moar idiomatic

--- solutions/day01/solution.clj
+++ solutions/day01/solution.clj
@@ -1,20 +1,13 @@
 (def moves (->> (slurp "input.txt")
                 (map #(if (= \( %) 1 -1))))

-(defn part1
-  [moves]
-  (reduce + moves))
+(defn cumsum
+  [s]
+  (reduce
+    (fn [cs x]
+      (conj cs (+ (or (last cs) 0) x)))
+    []
+    s))

-(defn part2
-  [moves]
-  (loop [[move & moves] moves
-         floor 0
-         step 0]
-    (if (= -1 floor)
-      step
-      (recur moves
-             (+ floor move)
-             (inc step)))))
-
-(println "part 1" (part1 moves))
-(println "part 2:" (part2 moves))
+(println "part 1:" (reduce + moves))
+(println "part 2:" (inc (.indexOf (cumsum moves) -1)))


much more sophisticated fast dependency handling

--- support/src/figwheel/client/file_reloading.cljs
+++ support/src/figwheel/client/file_reloading.cljs
@@ -28,9 +28,8 @@
 (defn before-jsload-custom-event [files]
   (utils/dispatch-custom-event "figwheel.before-js-reload" files))

-(defn all? [pred coll]
+#_(defn all? [pred coll]
   (reduce #(and %1 %2) true (map pred coll)))
-

 (defn namespace-file-map? [m]
   (or
@@ -73,9 +72,6 @@
        (partial goog.string/startsWith name)
        ["goog." "cljs." "clojure." "fake." "proto2."])))

-(def ^:dynamic *get-deps* false)
-(def ^:dynamic *path->name* false)
-
 (defn get-requires [ns]
   (->> ns
     name->path
@@ -84,70 +80,78 @@
     (filter #(not (immutable-ns? %)))
     set))

-(defn create-path->name []
-  (let [lookup (into {}
-                     (map (fn [[k v]] [v k])
-                          (js->clj (gobj/filter js/goog.dependencies_.nameToPath
-                                                (fn [v k o]
-                                                  (gstring/startsWith v "../"))))))]
-    (fn [path] (get lookup path))))
-
-;; inverting this early may adversly affect perf
-;; inverting on demand would probably provide better perf
-
-;; should really create an addDependency hook to create this
-;; data structure on the fly
-(defn create-ns->dependents []
-  (let [lookup (reduce
-                (fn [a [k v]]
-                  (reduce (fn [a' [k' v']]
-                            (update-in a' [k'] conj k)) a v))
-                {}
-                (js->clj
-                 (gobj/filter js/goog.dependencies_.requires
-                              (fn [v k o]
-                                (gstring/startsWith k "../")))))]
-    (fn [ns]
-      (set (map *path->name* (reverse (get lookup ns)))))))
-
-(declare topo-sort-helper)
-
-(defn elim-dups [[x & xs]]
-  (if (nil? x)
-    (list)
-    (cons x (elim-dups (map #(difference % x) xs)))))
-
-(defn topo-sort
-  ([deps]
-   (topo-sort deps 0 (atom (sorted-map))))
-  ([deps depth state]
-   (swap! state update-in [depth] (fnil into #{}) deps)
-   (doseq [dep deps]
-     (topo-sort-helper dep (inc depth) state))
-   (when (= depth 0)
-     (elim-dups (reverse (vals @state))))))
-
-;; from cljs.util; will use that one in when it hits mainstream
-(defn topo-sort-helper [x depth state]
-  (let [deps (*get-deps* x)]
-    (when-not (empty? deps) (topo-sort deps depth state))))
-
-;; overkill because we dont need these in order
-;; but the chance that we will soon is pretty high
+(defonce dependency-data (atom {:pathToName {} :dependents {}}))
+
+(defn path-to-name! [path name]
+  (swap! dependency-data update-in [:pathToName path] (fnil clojure.set/union #{}) #{name}))
+
+(defn setup-path->name!
+  "Setup a path to name dependencies map.
+   That goes from path -> #{ ns-names }"
+  []
+  ;; we only need this for dependents
+  (let [nameToPath (gobj/filter js/goog.dependencies_.nameToPath
+                                (fn [v k o] (gstring/startsWith v "../")))]
+    (gobj/forEach nameToPath (fn [v k o] (path-to-name! v k)))))
+
+(defn path->name
+  "returns a set of namespaces defined by a path"
+  [path]
+  (get-in @dependency-data [:pathToName path]))
+
+(defn name-to-parent! [ns parent-ns]
+  (swap! dependency-data update-in [:dependents ns] (fnil clojure.set/union #{}) #{parent-ns}))
+
+(defn setup-ns->dependents!
+  "This reverses the goog.dependencies_.requires for looking up ns-dependents."
+  []
+  (let [requires (gobj/filter js/goog.dependencies_.requires
+                              (fn [v k o] (gstring/startsWith k "../")))]
+    (gobj/forEach
+     requires
+     (fn [v k _]
+       (gobj/forEach
+        v
+        (fn [v' k' _]
+          (doseq [n (path->name k)]
+            (name-to-parent! k' n))))))))
+
+(defn ns->dependents [ns]
+  (get-in @dependency-data [:dependents ns]))
+
+(defn build-topo-sort [get-deps]
+  (let [get-deps (memoize get-deps)]
+    (letfn [(topo-sort-helper* [x depth state]
+              (let [deps (get-deps x)]
+                (when-not (empty? deps) (topo-sort* deps depth state))))
+            (topo-sort*
+              ([deps]
+               (topo-sort* deps 0 (atom (sorted-map))))
+              ([deps depth state]
+               (swap! state update-in [depth] (fnil into #{}) deps)
+               (doseq [dep deps]
+                 (topo-sort-helper* dep (inc depth) state))
+               (when (= depth 0)
+                 (elim-dups* (reverse (vals @state))))))
+            (elim-dups* [[x & xs]]
+              (if (nil? x)
+                (list)
+                (cons x (elim-dups* (map #(difference % x) xs)))))]
+      topo-sort*)))
+
 (defn get-all-dependencies [ns]
-  (binding [*get-deps* (memoize get-requires)]
-    (apply concat (topo-sort [ns]))))
+  (let [topo-sort' (build-topo-sort get-requires)]
+    (apply concat (topo-sort' (set [ns])))))

 (defn get-all-dependents [nss]
-  (binding [*path->name* (create-path->name)
-            *get-deps* (memoize (create-ns->dependents))]
-    (reverse (apply concat (topo-sort nss)))))
-
-#_(prn "dependents" (get-all-dependents [ "example.core" "figwheel.client.file_reloading"]))
+  (let [topo-sort' (build-topo-sort ns->dependents)]
+    (reverse (apply concat (topo-sort' (set nss))))))
+
+#_(prn "dependents" (get-all-dependents [ "example.core" "figwheel.client.file_reloading" "cljs.core"]))

 #_(prn "dependencies" (get-all-dependencies "figwheel.client.file_reloading"))

-#_(time (get-all-dependents [ "example.core" "figwheel.client.file_reloading"]))
+#_(time (get-all-dependents [ "example.core" "figwheel.client.file_reloading" "cljs.core"]))

 (defn unprovide! [ns]
   (let [path (name->path ns)]
@@ -158,6 +162,12 @@
 ;; this matches goog behavior in url resolution should actually just
 ;; use that code
 (defn resolve-ns [ns] (str goog/basePath (name->path ns)))
+
+(defn addDependency [path provides requires]
+  (doseq [prov provides]
+    (path-to-name! path prov)
+    (doseq [req requires]
+      (name-to-parent! req prov))))

 (defn bootstrap-goog-base
   "Reusable browser REPL bootstrapping. Patches the essential functions
@@ -170,25 +180,27 @@
     (set! (.-isProvided__ js/goog) (.-isProvided_ js/goog))
     (set! (.-isProvided_ js/goog) (fn [name] false))
     ;; provide cljs.user
+    (setup-path->name!)
+    (setup-ns->dependents!)
+
+    (set! (.-addDependency__ js/goog) js/goog.addDependency)
+    (set! (.-addDependency js/goog)
+          (fn [& args]
+            (apply addDependency args)
+            (apply (.-addDependency__ js/goog) args)))
+
     (goog/constructNamespace_ "cljs.user")
     ;; we must reuse Closure library dev time dependency management, under namespace
     ;; reload scenarios we simply delete entries from the correct
     ;; private locations
     (set! (.-CLOSURE_IMPORT_SCRIPT goog/global) queued-file-reload)
-    ;; TODO reload-all doesn't work
     (set! (.-require js/goog)
           (fn [src reload]
             (when (= reload "reload-all")
-              (doseq [ns (get-all-dependencies src)] (unprovide! ns))
-              (set! (.-cljsReloadAll_ js/goog) true))
+              (doseq [ns (get-all-dependencies src)] (unprovide! ns)))
             (let [reload? (or reload (.-cljsReloadAll__ js/goog))]
               (when reload? (unprovide! src))
-              (let [ret (.require__ js/goog src)]
-                (when (= reload "reload-all")
-                  (set! (.-cljsReloadAll_ js/goog) false))
-                ret))))))
-
-#_(js/goog.require "figwheel.client.file_reloading" true)
+              (.require__ js/goog src))))))

 (defn patch-goog-base []
   (defonce bootstrapped-cljs (do (bootstrap-goog-base) true)))
@@ -222,7 +234,7 @@
                 (fn [success?]
                   (if success?
                     (do
-                      (utils/debug-prn (str "FigWheel: Successfullly loaded " request-url))
+                      (utils/debug-prn (str "FigWheel: Successfully loaded " request-url))
                       (apply callback [(assoc file-msg :loaded-file true)]))
                     (do
                       (utils/log :error (str  "Figwheel: Error loading file " request-url))
@@ -322,6 +334,7 @@
                  file-msg
                  {:type :namespace :namespace n}))
              deps))))
+

 (defn sort-files [files]
   (let [keep-files (set (keep :namespace files))]
@@ -381,15 +394,16 @@
         (utils/log :debug "Figwheel: NOT loading these files ")
         (let [{:keys [figwheel-no-load not-required]}
               (group-by
-                     (fn [{:keys [meta-data]}]
-                       (cond
-                         (nil? meta-data) :not-required
-                         (contains? meta-data :figwheel-no-load) :figwheel-no-load
-                         :else :not-required))
-                     files-not-loaded)]
+               (fn [{:keys [namespace]}]
+                 (let [meta-data (get @figwheel-meta-pragmas (name namespace))]
+                   (cond
+                     (nil? meta-data) :not-required
+                     (meta-data :figwheel-no-load) :figwheel-no-load
+                     :else :not-required)))
+               files-not-loaded)]
           (when (not-empty figwheel-no-load)
             (utils/log (str "figwheel-no-load meta-data: "
-                            (pr-str (map :file figwheel-no-load)))))
+                            (pr-str (map (comp name->path :namespace) figwheel-no-load)))))
           (when (not-empty not-required)
             (utils/log (str "not required: " (pr-str (map :file not-required))))))))))


Get rid of pseudo-Hungarian notation

Get rid of pseudo-Hungarian notation

--- src/desdemona/launcher/aeron_media_driver.clj
+++ src/desdemona/launcher/aeron_media_driver.clj
@@ -33,8 +33,8 @@
   (let [ctx (doto (MediaDriver$Context.)
               (.dirsDeleteOnStart (options :delete-dirs)))]
     (try (launch-media-driver! ctx)
-         (catch IllegalStateException ise
-           (throw (Exception. aeron-launch-error-message ise))))))
+         (catch IllegalStateException e
+           (throw (Exception. aeron-launch-error-message e))))))

 (defn ^:private run-media-driver-and-block!
   [options]


Resolvers don't need to wrap their return values

--- test-cljs/frontend/test_send.cljs
+++ test-cljs/frontend/test_send.cljs
@@ -302,35 +302,35 @@
 (defn- read-port? [x]
   (implements? async-impl/ReadPort x))

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

 (defn resolve [context root-mapping query]
   (let [ast (om/query->ast query)]
-    (async/map ::root [(resolve* context root-mapping ::root (:children ast))])))
+    (resolve* context root-mapping (:children ast))))

 (def User
   {:user/name
    (fn [context ast]
-     {:user/name (:user/name context)})
+     (:user/name context))

    :user/favorite-color
    (fn [context ast]
      (let [c (async/promise-chan)
            get-user (get-in context [:apis :get-user])]
        (get-user {:user/name (:user/name context)}
-                 #(put! c %))
+                 #(put! c (:user/favorite-color %)))
        c))

    :user/favorite-number
@@ -338,7 +338,7 @@
      (let [c (async/promise-chan)
            get-user (get-in context [:apis :get-user])]
        (get-user {:user/name (:user/name context)}
-                 #(put! c %))
+                 #(put! c (:user/favorite-number %)))
        c))

    :user/favorite-fellow-user
@@ -349,7 +349,6 @@
                  (fn [user]
                    (-> (resolve* (assoc context :user/name (:user/favorite-fellow-user-name user))
                                  User
-                                 (:key ast)
                                  (:children ast))
                        (async/pipe c))))
        c))})
@@ -358,7 +357,7 @@
 (def Root
   {:root/user
    (fn [context ast]
-     (resolve* (assoc context :user/name (:user/name (:params ast))) User :root/user (:children ast)))})
+     (resolve* (assoc context :user/name (:user/name (:params ast))) User (:children ast)))})

 (deftest new-thing-works


Inform how to sign up for weather api in error message.

--- src/forecast/repository/location_forecast.clj
+++ src/forecast/repository/location_forecast.clj
@@ -1,24 +1,26 @@
 (ns forecast.repository.location-forecast
   (:require [clj-http.client :as client]
             [cheshire.core :refer [parse-string]]
-            [clojure.string :refer [split]]
             [clojure.walk :refer [keywordize-keys]]
             )
   (:import [java.util Calendar]))
+
+
+

 (defonce locations (atom {}))
 (defn clear-locations [] (reset! locations {}))

 (defn api
   []
-  (or (System/getenv "WEATHER_API") (throw "Must set WEATHER_API envrionment variable")))
+  (or (System/getenv "WEATHER_API") (throw "Must set WEATHER_API envrionment variable. Sign up at http://www.openweathermap.com/.")))

 (defn tomorrow
+  "return tomorrow's date as a string in yyyy-mm-dd format"
   []
   (.format (java.text.SimpleDateFormat. "yyyy-MM-dd")
            (java.util.Date. (+ (* 1 86400 1000) (.getTime (java.util.Date.))))
            ))
-;; (tomorrow)

 (defn force-location->forecast
   [location]
@@ -38,8 +40,6 @@
         {:error (str "error response for location (" (:status response) ")")}
         ))
     (catch Exception e {:error (str e)})))
-;; (prn (force-location->forecast {:latitude 37.386 :longitude -122.0838}))
-;; (prn (location->forecast {:latitude 37.386 :longitude -122.0838}))

 (defn location->forecast
   [location]


ganska bra va

ganska bra va

--- test/epicea/utils/egraph_test.clj
+++ test/epicea/utils/egraph_test.clj
@@ -1,9 +1,14 @@
 (ns epicea.utils.egraph-test
   (:require [clojure.test :refer :all]
+            [epicea.utils.access :as access]
             [epicea.utils.egraph :refer :all :as egraph]))

 (deftest egraph-test-node?
   (is (node? {:unique-tag ::egraph/node :kattskit 9}))
   (is (node? empty-node))
   (is (not (node? {:unique-tag 9})))
-  (is (node? (primitive-expr :double 9))))
+  (is (node? (primitive-expr :double 9)))
+  (let [a (primitive-expr :double 9)
+        b (primitive-expr :double '(+ 3 4))]
+    (is (access/get a -simple?))
+    (is (not (access/get b -simple?)))))


Explicitly require clojure.edn

Explicitly require clojure.edn

Without require clojure.edn might not be available in the ns.
Also explicit dependency looks better.

--- template/resources/leiningen/new/friboo/user.clj
+++ template/resources/leiningen/new/friboo/user.clj
@@ -4,6 +4,7 @@
   (:require [clojure.java.javadoc :refer [javadoc]]
             [clojure.pprint :refer [pprint]]
             [clojure.reflect :refer [reflect]]
+            [clojure.edn :refer [read-string]]
             [clojure.repl :refer [apropos dir doc find-doc pst source]]
             [clojure.tools.namespace.repl :refer [refresh refresh-all]]
             [com.stuartsierra.component :as component]
@@ -20,7 +21,7 @@
     (slurp file)))

 (defn load-dev-config [file]
-  (clojure.edn/read-string (slurp-if-exists file)))
+  (read-string (slurp-if-exists file)))

 (defn start
   "Starts the system running, sets the Var #'system."


change the emoji on the sync progress bar meter as it progresses

--- src/metabase/driver/sync.clj
+++ src/metabase/driver/sync.clj
@@ -95,7 +95,17 @@

      (sync-progress-meter-string 10 40)
        -> \"[************······································] 25%\""
-  (let [^:const meter-width 50]
+  (let [^:const meter-width 50
+        percent-done->emoji (fn [percent-done]
+                              (cond
+                                (> percent-done 0.90) "😎" ; smiling face with sunglasses
+                                (> percent-done 0.75) "😍" ; smiling face with heart shaped eyes
+                                (> percent-done 0.60) "😋" ; face savouring delicious food
+                                (> percent-done 0.45) "😏" ; smirking face
+                                (> percent-done 0.30) "😐" ; neutral face
+                                (> percent-done 0.15) "😒" ; unamused face
+                                :else                 "😢" ; crying face
+                                ))]
     (fn [tables-finished total-tables]
       (let [percent-done (float (/ tables-finished total-tables))
             filleds      (int (* percent-done meter-width))
@@ -103,7 +113,7 @@
         (str "["
              (apply str (repeat filleds "*"))
              (apply str (repeat blanks "·"))
-             (format "] 😋  %3.0f%%" (* percent-done 100.0)))))))
+             (format "] %s  %3.0f%%" (percent-done->emoji percent-done) (* percent-done 100.0)))))))

 (defn- sync-database-active-tables!
   "Sync active tables by running each of the sync table steps.


Clean up dalap metadata in test file

Clean up dalap metadata in test file

--- src/test/clojure/clojure/tools/cli_test.clj
+++ src/test/clojure/clojure/tools/cli_test.clj
@@ -9,9 +9,9 @@
   #_(:cljs (:require-macros [cemerick.cljs.test :refer [deftest is testing]])))

 ;; Refer private vars
-(def tokenize-args        ^{:cljs cli/tokenize-args}        #'cli/tokenize-args)
-(def compile-option-specs ^{:cljs cli/compile-option-specs} #'cli/compile-option-specs)
-(def parse-option-tokens  ^{:cljs cli/parse-option-tokens}  #'cli/parse-option-tokens)
+(def tokenize-args        (^{:cljs 'do} var cli/tokenize-args))
+(def compile-option-specs (^{:cljs 'do} var cli/compile-option-specs))
+(def parse-option-tokens  (^{:cljs 'do} var cli/parse-option-tokens))

 (deftest test-tokenize-args
   (testing "expands clumped short options"
@@ -81,7 +81,7 @@
     (is (= (compile-option-specs [{:id ::foo :short-opt "-f" :long-opt "--foo"}])
            [{:id ::foo :short-opt "-f" :long-opt "--foo"}])))
   (testing "warns about unknown keys"
-    (^{:cljs 'do} when ^:clj *assert*
+    (^{:cljs 'do} when ^{:clj true} *assert*
       (is (re-find #"Warning:.* :flag"
                    (with-out-str
                      (binding ^{:cljs []} [*err* *out*]


check for bad copy steps

check for bad copy steps

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

--- buildscripts/buildcheck/src/buildcheck/core.clj
+++ buildscripts/buildcheck/src/buildcheck/core.clj
@@ -245,6 +245,17 @@
   []
   (dorun (map fix-output-file-tag (device-vcproj-files))))

+(defn find-copy-step [vcproj]
+  (re-find #"\"copy .+?\"" (slurp vcproj)))
+
+(defn bad-copy-step [vcproj]
+  (not (.contains (or (find-copy-step vcproj) "PlatformName") "PlatformName")))
+
+(defn all-bad-copy-steps
+  "Find all vcproj files with a bad post-build copy step"
+  []
+  (filter bad-copy-step (device-vcproj-files)))
+
 ;;;; checking mac stuff (manual)

 (defn uses-serial-port [file]


don't throw when :analyzer/allow-undefined

--- src/main/clojure/clojure/tools/analyzer/passes/js/validate.clj
+++ src/main/clojure/clojure/tools/analyzer/passes/js/validate.clj
@@ -14,17 +14,19 @@
 (defmulti -validate :op)
 (defmethod -validate :default [ast] ast)

-(defmethod -validate :maybe-class [{:keys [class env] :as ast}]
-  (throw (ex-info (str "Cannot resolve: " class)
-                  (merge {:sym class
-                          :ast (prewalk ast cleanup)}
-                         (source-info env)))) )
+(defmethod -validate :maybe-class [{:keys [class form env] :as ast}]
+  (when-not (:analyzer/allow-undefined (meta form))
+    (throw (ex-info (str "Cannot resolve: " class)
+                    (merge {:sym class
+                            :ast (prewalk ast cleanup)}
+                           (source-info env))))) )

 (defmethod -validate :maybe-host-form [{:keys [form env] :as ast}]
-  (throw (ex-info (str "Cannot resolve: " form)
-                  (merge {:sym form
-                          :ast (prewalk ast cleanup)}
-                         (source-info env)))) )
+  (when-not (:analyzer/allow-undefined (meta form))
+    (throw (ex-info (str "Cannot resolve: " form)
+                    (merge {:sym form
+                            :ast (prewalk ast cleanup)}
+                           (source-info env))))) )

 (defn validate-tag [t {:keys [env] :as ast}]
   (let [tag (ast t)]


worked on alchemy chapter, up to Special Forms

--- brave-true/clojure-noob/src/clojure_noob/alchemy.clj
+++ brave-true/clojure-noob/src/clojure_noob/alchemy.clj
@@ -1,2 +1,170 @@
 (ns clojure-noob.alchemy
   (:require [midje.sweet :refer :all]))
+
+(def addition-list (list + 1 2))
+
+(fact "clojure can evaluate lists"
+
+  (eval addition-list)
+  => 3
+
+  (eval '(+ 1 2))
+  => 3)
+
+(fact "'text' => (reader) => 'data-structures' => (evaluator) => 'value'"
+
+  (if :in-doubt (do "something"))
+  => "something")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; the 'reader'
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; (str "To understand what recursio is," " you must first understand recursion")
+(fact "the result of reading this reader form is a list with 3 members:"
+  (read-string "(+ 8 3)")
+  => '(+ 8 3))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; reader macros
+;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; (#(+ 1 %) 3)
+
+;;(read-string "#(+ 1 %)")  ;;reader macro
+;; => (fn* [p1__13149#] (+ 1 p1__13149#))
+
+(fact "quote special form"
+
+  (read-string "'(a b c)")
+  => '(quote (a b c)))
+
+(fact "the deref reader macro"
+
+  (read-string "@var")
+  => '(clojure.core/deref var))
+
+(fact "The semicolon designates the single-line comment reader macro:"
+
+  (read-string "; ignore!\n(+ 1 2)")
+  => '(+ 1 2))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; evaluation
+;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(fact
+  (def addition-list (list + 1 2))
+  (eval addition-list)
+  => 3)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; things that evaluate to themselves
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(fact "A string evaluates to itself"
+
+  (eval (read-string "\"t\""))
+  => "t")
+
+(fact "accomplishes the same thing"
+
+  (eval "t")
+  => "t")
+
+(fact "bools and keywords"
+
+  (eval (read-string "true"))
+  => true
+
+  (eval (read-string "false"))
+  => false
+
+  (eval (read-string ":huzzah"))
+  => :huzzah)
+
+
+;;;;;;;;;;;;;;;;;
+;; symbols
+;;;;;;;;;;;;;;;;;
+
+(fact "The symbol x is bound to 5. When the evaluator resolves x, it
+       resolves it to the value 5:"
+
+  (let [x 5]
+    (+ x 3))
+  => 8)
+
+(fact "x is mapped to 15. Clojure resolves the symbol x to the value 15:"
+
+  (def x 15)
+  (+ x 3)
+  => 18)
+
+(fact "Now x is mapped to 15, but we introduce a local binding of x to 5.
+       x is resolved to 5:"
+
+  (def x 15)
+  (let [x 5]
+    (+ x 3))
+  => 8)
+
+(fact "The 'closest' binding takes precedence:"
+  (let [x 5]
+    (let [x 6]
+      (+ x 3)))
+  => 9)
+
+(fact "'exclaim' is mapped to a function. Within the function body,
+       'exclamation' is bound to the argument passed to the function"
+
+  (defn exclaim
+    [exclamation]
+    (str exclamation "!"))
+  (exclaim "Hadoken")
+  => "Hadoken!" )
+
+(fact "'map' and 'inc' are both mapped to functions:"
+
+  (map inc [1 2 3])
+  => '(2 3 4))
+
+
+;;;;;;;;;;;;;;;;;;
+;; lists
+;;;;;;;;;;;;;;;;;
+
+(fact "If the data structure is an empty list, it evaluates to an empty list:"
+
+  (eval (read-string "()"))
+  => '())
+
+;; Otherwise, it is a call to the first element of the list:
+
+
+;;;;;;;;;;;;;;;;;;;;;;;
+;; function calls
+;;;;;;;;;;;;;;;;;;;;;;;
+
+(fact "the + symbol resolves to a function. The function is 'called' with
+        the arguments 1 and 2:"
+
+  (+ 1 2)
+  => 3)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; special forms
+;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(fact "You can also call special forms. For example:"
+
+  (eval (read-string "(if true 1 2)"))
+  => 1)
+
+(fact "the 'quote' special form"
+  '(a b c)
+  => (quote (a b c)))


fixed 3961

fixed 3961

Signed-off-by: Eric Dvorsak <96f164ad4d9b2b0dacf8ebee2bb1eeb3aa69adf1@dvorsak.fr>

--- src/status_im/ui/screens/wallet/send/events.cljs
+++ src/status_im/ui/screens/wallet/send/events.cljs
@@ -203,10 +203,13 @@
       (if (and error (string? error) (not (string/blank? error))) ;; ignore error here, error will be handled in :transaction-failed
         {:db db'}
         (merge
-          {:db (-> db'
-                   (assoc-in [:wallet :transactions hash] (prepare-unconfirmed-transaction db now hash id))
-                   (update-in [:wallet :transactions-unsigned] dissoc id)
-                   (update-in [:wallet :send-transaction] merge clear-send-properties))}
+          {:db (cond-> db'
+                       (= method constants/web3-send-transaction)
+                       (assoc-in [:wallet :transactions hash] (prepare-unconfirmed-transaction db now hash id))
+                       true
+                       (update-in [:wallet :transactions-unsigned] dissoc id)
+                       true
+                       (update-in [:wallet :send-transaction] merge clear-send-properties))}
           (if modal?
             (cond-> {:dispatch [:navigate-back]}
                     (= method constants/web3-send-transaction)


use JDBC library to disable autocommit in test

--- test/metabase/test/data/crate.clj
+++ test/metabase/test/data/crate.clj
@@ -3,7 +3,9 @@
   (:require [environ.core :refer [env]]
             metabase.driver.crate
             (metabase.test.data [generic-sql :as generic]
-                                [interface :as i]))
+                                [interface :as i])
+            [metabase.driver.generic-sql :as sql]
+            [clojure.java.jdbc :as jdbc])
   (:import metabase.driver.crate.CrateDriver))

 (def ^:private ^:const field-base-type->sql-type
@@ -18,6 +20,28 @@
    :TextField       "string"
    :TimeField       "timestamp"})

+(defn- escape-field-names
+  "Escape the field-name keys in ROW-OR-ROWS."
+  [row-or-rows]
+  (if (sequential? row-or-rows)
+    (map escape-field-names row-or-rows)
+    (into {} (for [[k v] row-or-rows]
+               {(sql/escape-field-name k) v}))))
+
+(defn- make-load-data-fn
+  "Create a `load-data!` function. This creates a function to actually insert a row or rows, wraps it with any WRAP-INSERT-FNS,
+   the calls the resulting function with the rows to insert."
+  [& wrap-insert-fns]
+  (fn [driver dbdef tabledef]
+    (let [insert! (fn [row-or-rows]
+                    (apply jdbc/insert!
+                           (generic/database->spec driver :db dbdef)
+                           (keyword (get tabledef :table-name))
+                           :transaction? false
+                           (escape-field-names row-or-rows)))
+          rows      (apply list (generic/load-data-get-rows driver dbdef tabledef))]
+      (insert! rows))))
+
 (defn- database->connection-details [_ _ {:keys [_ _]}]
   (merge {:host         "localhost"
           :port         4300}))
@@ -31,7 +55,8 @@
           :pk-sql-type               (constantly "integer primary key")
           :create-db-sql             (constantly nil)
           :add-fk-sql                (constantly nil)
-          :drop-db-if-exists-sql     (constantly nil)})
+          :drop-db-if-exists-sql     (constantly nil)
+          :load-data!                (make-load-data-fn)})
   i/IDatasetLoader
   (merge generic/IDatasetLoaderMixin
          {:database->connection-details database->connection-details


Bump version

Bump version

--- test/obb_rules_api/index_test.clj
+++ test/obb_rules_api/index_test.clj
@@ -10,7 +10,7 @@
       (is (= (:status response) 200))
       (let [result (json/read-str (:body response))]
         (is (= "obb-rules-api" (result "name")))
-        (is (= "1.0.0" (result "version"))))))
+        (is (= "1.1.0" (result "version"))))))

  (testing "not-found route"
     (let [response (app (request :get "/invalid"))]


fix typo in tests

fix typo in tests

--- test/reader_web_app/core_test.clj
+++ test/reader_web_app/core_test.clj
@@ -10,11 +10,11 @@

   (testing "book entity"
     (let [response (app (mock/request :get "/books/1"))]
-      (is (= (:status response) 200))))
+      (is (= (:status response) 200)))))

   ;; I have no idea why this request send
   ;; book inside :params, not inside :body
-
+
   ;(testing "create a book"
   ;  (let [book (slurp "book.fb2")
   ;        response (app (mock/request :post "/books" {:book book}))]


Use order/nth instead of reduce to get the most recent comment.

--- src/oc/storage/db/common.clj
+++ src/oc/storage/db/common.clj
@@ -38,11 +38,9 @@
                                            (r/ge (r/get-field interaction-row "body") "")
                                            (r/ne (r/get-field (r/get-field interaction-row "author") "user-id") user-id))
                                           (r/ge (r/get-field interaction-row "body") ""))))
+                                       (r/order-by (r/desc "created-at"))
                                        (r/coerce-to :array)
-                                       (r/reduce (r/fn [left right]
-                                         (if (r/ge (r/get-field left "created-at") (r/get-field right "created-at"))
-                                           left
-                                           right)))
+                                       (r/nth 0)
                                        (r/default (r/fn [_err]
                                         {"created-at" (r/default
                                                        (r/get-field post-row "published-at")