style tweaks.

style tweaks.

--- src/metabase/db/migrations.clj
+++ src/metabase/db/migrations.clj
@@ -154,19 +154,19 @@

 ;; deal with dashboard cards which have NULL `:row` or `:col` values
 (defmigration fix-dashboard-cards-without-positions
-  (let [bad-dashboards (k/select DashboardCard (k/fields [:dashboard_id]) (k/modifier "DISTINCT") (k/where (or (= :row nil) (= :col nil))))]
-    (when (not-empty bad-dashboards)
-      (log/info "Looks like we need to fix unpositioned cards in these dashboards:" (mapv :dashboard_id bad-dashboards))
-      ;; we are going to take the easy way out, which is to put bad-cards at the bottom of the dashboard
-      (doseq [{dash-to-fix :dashboard_id} bad-dashboards]
-        (let [max-row   (or (:row (first (k/select DashboardCard (k/aggregate (max :row) :row) (k/where {:dashboard_id dash-to-fix})))) 0)
-              max-size  (or (:size (first (k/select DashboardCard (k/aggregate (max :sizeY) :size) (k/where {:dashboard_id dash-to-fix, :row max-row})))) 0)
-              max-y     (+ max-row max-size)
-              bad-cards (k/select DashboardCard (k/fields :id :sizeY) (k/where {:dashboard_id dash-to-fix}) (k/where (or (= :row nil) (= :col nil))))]
-          (loop [[bad-card & rest] bad-cards
-                 row-target        max-y]
-            (k/update DashboardCard
-              (k/set-fields {:row row-target
-                             :col 0})
-              (k/where      {:id  (:id bad-card)}))
-            (when rest (recur rest (+ row-target (:sizeY bad-card))))))))))
+  (when-let [bad-dashboards (not-empty (k/select DashboardCard (k/fields [:dashboard_id]) (k/modifier "DISTINCT") (k/where (or (= :row nil) (= :col nil)))))]
+    (log/info "Looks like we need to fix unpositioned cards in these dashboards:" (mapv :dashboard_id bad-dashboards))
+    ;; we are going to take the easy way out, which is to put bad-cards at the bottom of the dashboard
+    (doseq [{dash-to-fix :dashboard_id} bad-dashboards]
+      (let [max-row   (or (:row (first (k/select DashboardCard (k/aggregate (max :row) :row) (k/where {:dashboard_id dash-to-fix})))) 0)
+            max-size  (or (:size (first (k/select DashboardCard (k/aggregate (max :sizeY) :size) (k/where {:dashboard_id dash-to-fix, :row max-row})))) 0)
+            max-y     (+ max-row max-size)
+            bad-cards (k/select DashboardCard (k/fields :id :sizeY) (k/where {:dashboard_id dash-to-fix}) (k/where (or (= :row nil) (= :col nil))))]
+        (loop [[bad-card & more] bad-cards
+               row-target        max-y]
+          (k/update DashboardCard
+            (k/set-fields {:row row-target
+                           :col 0})
+            (k/where      {:id  (:id bad-card)}))
+          (when more
+            (recur more (+ row-target (:sizeY bad-card)))))))))


Correction in azulenoid symbol computation.

--- clojure/org/gavrog/clojure/azulenoids.clj
+++ clojure/org/gavrog/clojure/azulenoids.clj
@@ -52,23 +52,25 @@
   (new DSymbol "1.1:16 1:2 4 6 8 10 12 14 16,16 3 5 7 9 11 13 15:8"))

 (def boundary-mappings
-  (let [start (fn [p] (mod (- 20 p) 16))
+  (let [offset (fn [p] (mod (- 19 p) 16))
         box (fn [i] (Integer. i))
         template-boundary (boundary-chambers template (box 1) 0 1 2)
         octagon-boundary (cycle (map box (range 1 17)))
-        mapping (fn [p] (zipmap (drop (start p) octagon-boundary)
+        mapping (fn [p] (zipmap (drop (offset p) octagon-boundary)
                                 (take 16 template-boundary)))]
     (map mapping (range 1 16 2))))

 (defn apply-to-template [ds oct2tmp]
   (let [tmp2oct (clojure.set/map-invert oct2tmp)
         tmp (DynamicDSymbol. template)
-        finish (fn [D]
+        set-op (fn [D]
                  (if (not (.definesOp tmp 2 D))
-                   (.redefineOp tmp 2 D (oct2tmp (.op ds 2 (tmp2oct D)))))
-                 (if (not (.definesV tmp 1 2 D))
-                   (.redefineV tmp 1 2 D (.v ds 1 2 (tmp2oct D)))))]
-    (doall (map finish (keys tmp2oct)))
+                   (.redefineOp tmp 2 D (oct2tmp (.op ds 2 (tmp2oct D))))))
+        set-v (fn [D]
+                (if (not (.definesV tmp 1 2 D))
+                  (.redefineV tmp 1 2 D (.v ds 1 2 (tmp2oct D)))))]
+    (doall (map set-op (keys tmp2oct)))
+    (doall (map set-v (keys tmp2oct)))
     (-> tmp .dual .minimal .canonical)))

 (defn octa-sets [] (filter (fn [ds] (-> ds max-curvature .isNegative not))


Fixed merge error in drpc.clj

Fixed merge error in drpc.clj

--- storm-core/src/clj/backtype/storm/daemon/drpc.clj
+++ storm-core/src/clj/backtype/storm/daemon/drpc.clj
@@ -208,10 +208,10 @@
           ;; invocations that will unblock those threads
           handler-server (when (> drpc-port 0)
                            (ThriftServer. conf
-                             (DistributedRPC$Processor. service-handler)
+                             (DistributedRPC$Processor. drpc-service-handler)
                              ThriftConnectionType/DRPC))
           invoke-server (ThriftServer. conf
-                          (DistributedRPCInvocations$Processor. service-handler)
+                          (DistributedRPCInvocations$Processor. drpc-service-handler)
                           ThriftConnectionType/DRPC_INVOCATIONS)
           http-creds-handler (AuthUtils/GetDrpcHttpCredentialsPlugin conf)]
       (.addShutdownHook (Runtime/getRuntime) (Thread. (fn []


Added blur to util.clj

Added blur to util.clj


Set default value of named-matrix update entries to nil instead of zero, so our min-votes code works as intended.

--- src/polismath/named_matrix.clj
+++ src/polismath/named_matrix.clj
@@ -22,8 +22,8 @@
             [rows cols] (map (fn [xs x i] (if (= -1 i) (conj xs x) xs))
                           [rows cols] [row col] [row-index col-index])
             ; If necessary, insert new columns and/or rows of zeros
-            matrix (if (= -1 col-index) (mapv #(conj % 0) matrix) matrix)
-            matrix (if (> (count rows) (count matrix)) (conj matrix (into [] (repeat (count cols) 0))) matrix)
+            matrix (if (= -1 col-index) (mapv #(conj % nil) matrix) matrix)
+            matrix (if (> (count rows) (count matrix)) (conj matrix (into [] (repeat (count cols) nil))) matrix)
             ; Get indices of matrix position to be updated (note typed-indexof above gives -1 if item not in coll)
             indices (mapv (fn [xs i] (if (= -1 i) (- (count xs) 1) i))
                           [rows cols] [row-index col-index])


Don't print-dup for :edn encoding [IMMUTANT-170]

--- namespaces/common/src/main/clojure/immutant/codecs.clj
+++ namespaces/common/src/main/clojure/immutant/codecs.clj
@@ -25,15 +25,12 @@

 (defmethod encode :clojure [data & _]
   "Stringify a clojure data structure"
-  (with-out-str
-    (binding [*print-dup* true]
-      (pr data))))
+  (binding [*print-dup* true]
+    (pr-str data)))

 (defmethod encode :edn [data & _]
   "Stringify an edn data structure"
-  (with-out-str
-    (binding [*print-dup* true]
-      (pr data))))
+  (pr-str data))

 (defmethod encode :json [data _]
   "Stringify a json data structure"


Refactor test

Refactor test

--- test/expound/alpha_test.cljc
+++ test/expound/alpha_test.cljc
@@ -4195,13 +4195,11 @@
             {:print-specs? false}))))

   (testing "messages can be fetched from parent specs"
-    (reset! @#'expound/registry-ref {})
-
-    (s/def :defmsg-test/parent-string string?)
-    (s/def :defmsg-test/parent-foo :defmsg-test/parent-string)
-    (s/def :defmsg-test/parent-bar :defmsg-test/parent-foo)
-
-    (expound/defmsg :defmsg-test/parent-string "should be a string")
+    (s/def :defmsg-test/string string?)
+    (s/def :defmsg-test/identifier :defmsg-test/string)
+    (s/def :defmsg-test/name :defmsg-test/identifier)
+
+    (expound/defmsg :defmsg-test/string "should be a string")
     (is (= "-- Spec failed --------------------

   :oak
@@ -4211,22 +4209,22 @@
 -------------------------
 Detected 1 error\n"
            (expound/expound-str
-            :defmsg-test/parent-string
+            :defmsg-test/string
             :oak
             {:print-specs? false})

            (expound/expound-str
-            :defmsg-test/parent-foo
+            :defmsg-test/identifier
             :oak
             {:print-specs? false})

            (expound/expound-str
-            :defmsg-test/parent-bar
+            :defmsg-test/name
             :oak
             {:print-specs? false})))

     ;; until a msg is set more precisely
-    (expound/defmsg :defmsg-test/parent-foo "should be a foo")
+    (expound/defmsg :defmsg-test/identifier "should be a foo")
     (is (= "-- Spec failed --------------------

   :oak
@@ -4236,11 +4234,11 @@
 -------------------------
 Detected 1 error\n"
            (expound/expound-str
-            :defmsg-test/parent-foo
+            :defmsg-test/identifier
             :oak
             {:print-specs? false})))

-    (expound/defmsg :defmsg-test/parent-bar "should be a bar")
+    (expound/defmsg :defmsg-test/name "should be a bar")
     (is (= "-- Spec failed --------------------

   :oak
@@ -4250,7 +4248,7 @@
 -------------------------
 Detected 1 error\n"
            (expound/expound-str
-            :defmsg-test/parent-bar
+            :defmsg-test/name
             :oak
             {:print-specs? false})))

@@ -4270,8 +4268,9 @@
             {:print-specs? false})))

     ;; clean registry from this last spec, or we get failures on other tests
-    (is (= 1 2)
-        (expound/undefmsg 'clojure.core/string?))))
+    (expound/undefmsg :defmsg-test/identifier)
+    (expound/undefmsg :defmsg-test/name)
+    (expound/undefmsg 'clojure.core/string?)))

 (deftest printer
   (st/instrument ['expound/printer])


Revert "Remove cljs-testrunners from tests code."

This reverts commit 3a1936bb27584ba7668ec882793dc280803e9e74.

--- test/promesa/core_tests.cljs
+++ test/promesa/core_tests.cljs
@@ -1,5 +1,6 @@
 (ns promesa.core-tests
-  (:require [cljs.test :as t]
+  (:require [cljs-testrunners.node :as node]
+            [cljs.test :as t]
             [promesa.core :as p]
             [cats.core :as m]))

@@ -104,3 +105,7 @@
       (p/then p1 (fn [x]
                    (t/is (= x 3))
                    (done))))))
+
+
+(defn main [] (node/run-tests))
+(set! *main-cli-fn* main)


Fix common headers

Fix common headers

--- src/rester/core.clj
+++ src/rester/core.clj
@@ -245,7 +245,7 @@
                                      (or (get exp-headers "Content-Type") "")))]
       (-> test (update :url replace-opts opts)
           (update :headers str->map #":" opts false)
-          (update :headers merge (options "commonHeaders"))
+          (update :headers merge (opts "commonHeaders"))
           (update :params str->map  [#"&|(\s*,\s*)" #"\s*=\s*"] opts true)
           (update :payload #(-> % (replace-opts opts)
                                 ((if (:dont_parse_payload options) identity json->clj))))
@@ -409,7 +409,8 @@
                            (do (log/warn "argument key expected to start with :" k) k)
                            (subs k 1))]
                    (assoc result k v))) {})
-       ((fn[m] (update m "commonHeaders" str->map #"=")))))
+       ((fn[m] (update m "commonHeaders" str->map #"=")))
+       ((fn[m] (log/info "common headers:" (m "commonHeaders")) m))))

 (defn run-tests [args]
   (let [pool-size (Integer/parseInt (or (System/getProperty "thread-pool-size") "4"))]


Add a modifiable classloader for pomegranate.

--- src/riemann/bin.clj
+++ src/riemann/bin.clj
@@ -9,6 +9,7 @@
             [cemerick.pomegranate :as pom]
             [clojure.java.io :as io]
             [clojure.tools.logging :refer :all])
+  (:import (clojure.lang DynamicClassLoader))
   (:gen-class :name riemann.bin))

 (def config-file
@@ -105,6 +106,13 @@
         (run-tests-with-format test-name-pattern)))
     (run-tests-with-format test-name-pattern)))

+(defn ensure-dynamic-classloader
+  []
+  (let [thread (Thread/currentThread)
+        cl (.getContextClassLoader thread)]
+    (when-not (instance? DynamicClassLoader cl)
+      (.setContextClassLoader thread (DynamicClassLoader. cl)))))
+
 (defn -main
   "Start Riemann. Loads a configuration file from the first of its args."
   ([]
@@ -113,6 +121,7 @@
    (-main "start" config))
   ([command config & [test-name]]
    (logging/init)
+   (ensure-dynamic-classloader)
    (case command
      "start" (try
                (info "PID" (pid))


Debug the parser for the AST grammar.

Debug the parser for the AST grammar.

--- src/skylark/ast.clj
+++ src/skylark/ast.clj
@@ -3,32 +3,31 @@

 (def parse-ast-grammar
   (insta/parser
-   "grammar = <w> def ( <w '\\n\\n' w> def )* <w>
+   "<grammar> = <w> def ( <w '\\n\\n' w> def )* <w>

     w = whitespace*
-    whitespace = #'\\s+' | comment
-    comment = #'--.*$'
+    whitespace = #'[ \f\t\r\n]+' | comment
+    comment = #'--[^\n]*\n'
     cw = whitespace w

-    def = var <w> '=' <w> expr
-    var = #'[a-z_]+'
-    constant = #'[A-Z][a-zA-Z_]+'
-    expr = sum | product
+    def = var <w '=' w> expr
+    <var> = #'[a-z_]+'
+    <constant> = #'[A-Z][a-zA-Z_]+'
+    <expr> = sum | product
     sum = nodes <w> attributes
-    <nodes> = node ( <w> | <w> node )*
+    <nodes> = node ( <w '|' w> node )*
     node = constant <w> sequence?
     <attributes> = ( <'attributes' w> sequence )?
     product = sequence
-    sequence = '(' field (<w ',' w> field)* ')'
+    sequence = <'('> field (<w ',' w> field)* <')'>
     field = type <cw> var
     <type> = var | optional | repeated
     optional = type <w '?'>
     repeated = type <w '*'>
 "))

-;; AST for Python: https://docs.python.org/2/library/ast.html
-
-
+;; AST for Python, as copied verbatim from:
+;; https://docs.python.org/2/library/ast.html

 (def ast-grammar
   (parse-ast-grammar "
@@ -143,3 +142,9 @@
         -- import name with optional 'as' alias.
         alias = (identifier name, identifier? asname)
 "))
+
+(defmacro define-ast-nodes []
+  `(do
+     nil))
+
+(define-ast-nodes)


[#2634] Refactor

[#2634] Refactor

--- backend/src/akvo/lumen/lib/aggregation/commons.clj
+++ backend/src/akvo/lumen/lib/aggregation/commons.clj
@@ -47,7 +47,3 @@
                                        (:aggregationColumn %)]))))
    flatten
    vec))
-
-
-
-


These tests had prerequisites that were never actually used.

--- test/midje/util/t_colorize.clj
+++ test/midje/util/t_colorize.clj
@@ -39,20 +39,16 @@
   (provided
     (getenv "MIDJE_COLORIZE") => anything :times 0))

+
+
 (fact
   (colorize-deftest-output "FAIL in deftest failure message")
-     => "\u001b[31mFAIL\u001b[0m in deftest failure message"
-  (provided
-      (fail "FAIL") => "\u001b[31mFAIL\u001b[0m" ))
+     => "\u001b[31mFAIL\u001b[0m in deftest failure message")

 (fact
   (colorize-deftest-output "ERROR in deftest failure message")
-     => "\u001b[31mERROR\u001b[0m in deftest failure message"
-  (provided
-      (fail "ERROR") => "\u001b[31mERROR\u001b[0m" ))
+     => "\u001b[31mERROR\u001b[0m in deftest failure message")

 (fact
   (colorize-deftest-output "ERROR in deftest failure message ERROR")
-     =not=> "\u001b[31mERROR\u001b[0m in deftest failure message \u001b[31mERROR\u001b[0m"
-  (provided
-      (fail "ERROR") => "\u001b[31mERROR\u001b[0m" ))+     =not=> "\u001b[31mERROR\u001b[0m in deftest failure message \u001b[31mERROR\u001b[0m")


Added context inversion

Added context inversion

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

--- conexp/fca/contexts.clj
+++ conexp/fca/contexts.clj
@@ -108,7 +108,7 @@
 						    (attribute-derivation ctx #{n}))
 				    (inz [g n]))))])))

-(defn up-down-arrows [ctx]
+(defn up-down-arrows [ctx] ; faster version?
   (intersection (up-arrows ctx) (down-arrows ctx)))

 (defn reduce-context [ctx]
@@ -121,7 +121,7 @@
 	  new-inz (filter #(and (new-obj (first %))
 				(new-att (second %)))
 			  inz)]
-    (make-context new-obj new-att new-inz))))
+    (make-context new-obj new-att (set new-inz)))))

 (defn reduced? [ctx]
   (let [obj (objects ctx)
@@ -136,6 +136,11 @@

 (defn transpose-context [ctx]
   (make-context (attributes ctx) (objects ctx) (set-of [m g] [[g m] (incidence ctx)])))
+
+(defn invert-context [ctx]
+  (make-context (objects ctx) (attributes ctx) (set-of [g m] [g (objects ctx)
+							      m (attributes ctx)
+							      :when (not ((incidence ctx) [g m]))])))

 (defn context-object-closure [ctx set-of-objects]
   (attribute-derivation ctx (object-derivation ctx set-of-objects)))


Update dev dependencies.

Update dev dependencies.

--- profiles.clj
+++ profiles.clj
@@ -5,6 +5,6 @@
             :target "doc/dist/latest/api"
             :src-uri "http://github.com/funcool/buddy-core/blob/master/"
             :src-uri-prefix "#L"}
-  :plugins [[funcool/codeina "0.3.0"]
-            [lein-ancient "0.6.7"]]}
+  :plugins [[funcool/codeina "0.5.0"]
+            [lein-ancient "0.6.10"]]}
  :1.7 {:dependencies [[org.clojure/clojure "1.7.0"]]}}


Fix hashCode implementation in nav regions and storages.

--- src/clojure/uncomplicate/neanderthal/internal/navigation.clj
+++ src/clojure/uncomplicate/neanderthal/internal/navigation.clj
@@ -20,7 +20,7 @@
 (deftype BandRegion [^long m ^long n ^long kl ^long ku ^long uplo ^long diag]
   Object
   (hashCode [a]
-    (-> (hash-combine :BandRegion) (hash-combine m) (hash-combine n) (hash-combine kl) (hash-combine ku)))
+    (-> (hash :BandRegion) (hash-combine m) (hash-combine n) (hash-combine kl) (hash-combine ku)))
   (equals [a b]
     (or (identical? a b)
         (and (instance? BandRegion b)
@@ -101,7 +101,7 @@
 (deftype GERegion [^long m ^long n]
   Object
   (hashCode [a]
-    (-> (hash-combine :GERegion) (hash-combine m) (hash-combine n)))
+    (-> (hash :GERegion) (hash-combine m) (hash-combine n)))
   (equals [a b]
     (or (identical? a b)
         (and (instance? GERegion b)
@@ -266,7 +266,7 @@
      :capacity (.capacity s)})
   Object
   (hashCode [a]
-    (-> (hash-combine :FullStorage) (hash-combine sd) (hash-combine fd) (hash-combine ld)))
+    (-> (hash :FullStorage) (hash-combine sd) (hash-combine fd) (hash-combine ld)))
   (equals [a b]
     (or (identical? a b)
         (and (instance? StripeFullStorage b) (= sd (.sd ^StripeFullStorage b))
@@ -317,7 +317,7 @@
      :capacity (.capacity s)})
   Object
   (hashCode [a]
-    (-> (hash-combine :BandStorage) (hash-combine ld) (hash-combine kl) (hash-combine ku)))
+    (-> (hash :BandStorage) (hash-combine ld) (hash-combine kl) (hash-combine ku)))
   (equals [a b]
     (or (identical? a b)
         (and (instance? BandStorage b) (= h (.h ^BandStorage b))
@@ -372,7 +372,7 @@
      :capacity (.capacity s)})
   Object
   (hashCode [a]
-    (-> (hash-combine :TopPackedStorage) (hash-combine n)))
+    (-> (hash :TopPackedStorage) (hash-combine n)))
   (equals [a b]
     (or (identical? a b)
         (and (instance? TopPackedStorage b) (= n (.n ^TopPackedStorage b)))))
@@ -399,7 +399,7 @@
      :capacity (.capacity s)})
   Object
   (hashCode [a]
-    (-> (hash-combine :BottomPackedStorage) (hash-combine n)))
+    (-> (hash :BottomPackedStorage) (hash-combine n)))
   (equals [a b]
     (or (identical? a b)
         (and (instance? BottomPackedStorage b) (= n (.n ^BottomPackedStorage b)))))
@@ -434,7 +434,7 @@
      :capacity (.capacity s)})
   Object
   (hashCode [a]
-    (-> (hash-combine :TridiagonalStorage) (hash-combine n)))
+    (-> (hash :TridiagonalStorage) (hash-combine n)))
   (equals [a b]
     (or (identical? a b) (and (instance? TridiagonalStorage b) (= n (.n ^TridiagonalStorage b)))))
   (toString [a]
@@ -460,7 +460,7 @@
      :capacity (.capacity s)})
   Object
   (hashCode [a]
-    (-> (hash-combine :BidiagonalStorage) (hash-combine n)))
+    (-> (hash :BidiagonalStorage) (hash-combine n)))
   (equals [a b]
     (or (identical? a b) (and (instance? BidiagonalStorage b) (= n (.n ^BidiagonalStorage b)))))
   (toString [a]


Temporarily removed testcase for EL-gfp-exploration

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

--- src/conexp/contrib/tests/dl/languages/EL_gfp_exploration.clj
+++ src/conexp/contrib/tests/dl/languages/EL_gfp_exploration.clj
@@ -88,7 +88,7 @@
        grandparent-model 32))

 (defn test-ns-hook []
-  (model-gcis-returns-correct-result)
+;  (model-gcis-returns-correct-result)
   (model-gcis-returns-correct-count))

 ;;;


Release template 0.6.2

Release template 0.6.2

--- modules/template/project.clj
+++ modules/template/project.clj
@@ -1,6 +1,6 @@
 ;; Copyright © 2014 JUXT LTD.

-(defproject juxt.modular/template "0.6.1-SNAPSHOT"
+(defproject juxt.modular/template "0.6.2"
   :description "A modular extension that provides support for templates (Mustache, etc.)"
   :url "https://github.com/juxt/modular/tree/master/modules/template"
   :license {:name "The MIT License"


Make watch verbose so I can tell if boot is getting slow...

--- build.boot
+++ build.boot
@@ -89,7 +89,7 @@
   (comp
    (fix)
    (solver)
-   (watch)
+   (watch :verbose true)
    (test)))

 (deftask watch-tests []


Filter cljs builds

Filter cljs builds

Boot-reload still has problems with multiple cljs builds

--- build.boot
+++ build.boot
@@ -65,10 +65,11 @@
     (if use-sass
       (sass)
       (less))
-    (reload :open-file "vim --servername saapas --remote-silent +norm%sG%s| %s")
+    (reload :open-file "vim --servername saapas --remote-silent +norm%sG%s| %s"
+            :ids #{"js/main"})
     ; This starts a repl server with piggieback middleware
-    (cljs-repl)
-    (cljs)
+    (cljs-repl :ids #{"js/main"})
+    (cljs :ids #{"js/main"})
     (start-app :port port)
     (if speak (boot.task.built-in/speak) identity)))


Increment version

Increment version

--- build.boot
+++ build.boot
@@ -1,6 +1,6 @@
 (task-options!
   pom {:project     'uno-scoreboard
-       :version     "0.1.1"
+       :version     "0.2.0"
        :description "A simple scoreboad for the Uno game"
        :url         "https://gsnewmark.github.io/uno-scoreboard"
        :scm         {:url "https://github.com/gsnewmark/uno-scoreboard"}


Drop the unnecessary use of the target task in boot dev

--- build.boot
+++ build.boot
@@ -91,8 +91,7 @@
     (watch)
     (reload :on-jsload 'workflo.macros.examples.screen-app/reload)
     (build-dev)
-    (target)
-    (serve :dir "target")
+    (serve)
     (repl :server true)))

 (deftask production


Bump boot-semver to fix a bug

Bump boot-semver to fix a bug

--- build.boot
+++ build.boot
@@ -3,10 +3,10 @@
                  [adzerk/boot-cljs            "1.7.228-1" :scope "test"]
                  [pandeiro/boot-http          "0.7.1-SNAPSHOT" :scope "test"]
                  [adzerk/boot-reload          "0.4.4" :scope "test"]
-                 [degree9/boot-semver "1.2.0"]
+                 [degree9/boot-semver         "1.2.1" :scope "test"]

                  ;; Repl
-                 [adzerk/boot-cljs-repl       "0.3.0"]
+                 [adzerk/boot-cljs-repl       "0.3.0"  :scope "test"]
                  [com.cemerick/piggieback     "0.2.1"  :scope "test"]
                  [weasel                      "0.7.0"  :scope "test"]
                  [org.clojure/tools.nrepl     "0.2.12" :scope "test"]


got basic app written for quick tour guide

--- src/tutorial/untangled_tutorial/A_Quick_Tour.cljs
+++ src/tutorial/untangled_tutorial/A_Quick_Tour.cljs
@@ -1,13 +1,182 @@
 (ns untangled-tutorial.A-Quick-Tour
-  (:require-macros [cljs.test :refer [is]])
+  (:require-macros [cljs.test :refer [is]]
+                   [untangled-tutorial.tutmacros :refer [untangled-app]])
   (:require [om.next :as om :refer-macros [defui]]
             [om.dom :as dom]
-            [devcards.core :as dc :refer-macros [defcard defcard-doc]]))
+            [untangled.client.core :as uc]
+            [untangled.client.impl.network :as un]
+            [devcards.core :as dc :refer-macros [defcard defcard-doc]]
+            [untangled.client.mutations :as m]
+            [untangled.client.logging :as log]
+            [untangled.client.data-fetch :as df]))
+
+(defui ^:once Counter
+  static uc/InitialAppState
+  (uc/initial-state [this {:keys [id start]
+                           :or   {id 1 start 1}
+                           :as   params}] {:counter/id id :counter/n start})
+  static om/IQuery
+  (query [this] [:counter/id :counter/n])
+  static om/Ident
+  (ident [this props] [:counter/by-id (:counter/id props)])
+  Object
+  (render [this]
+    (let [{:keys [counter/id counter/n]} (om/props this)
+          onClick (om/get-computed this :onClick)]
+      (dom/div #js {:className "counter"}
+        (dom/span #js {:className "counter-label"}
+          (str "Current count for counter " id ":  "))
+        (dom/span #js {:className "counter-value"} n)
+        (dom/button #js {:onClick #(onClick id)} "Increment")))))
+
+(def ui-counter (om/factory Counter {:keyfn :counter/id}))
+
+(defmethod m/mutate 'counter/inc [{:keys [state] :as env} k {:keys [id] :as params}]
+  {:remote true
+   :action (fn [] (swap! state update-in [:counter/by-id id :counter/n] inc))})
+
+(defmethod m/mutate 'add-counters-to-panel [{:keys [state] :as env} k {:keys [id] :as params}]
+  {:action (fn []
+             (let [ident-list (get @state :all-counters)]
+               (js/console.log :idents ident-list :state @state)
+               (swap! state update-in [:panels/by-kw :counter] assoc :counters ident-list)))})
+
+(defui ^:once CounterPanel
+  static uc/InitialAppState
+  (uc/initial-state [this params]
+    {:counters [(uc/initial-state Counter {:id 1 :start 1})]})
+  static om/IQuery
+  (query [this] [{:counters (om/get-query Counter)}])
+  static om/Ident
+  (ident [this props] [:panels/by-kw :counter])
+  Object
+  (render [this]
+    (let [{:keys [counters]} (om/props this)
+          click-callback (fn [id] (om/transact! this `[(counter/inc {:id ~id}) :counter-sum]))]
+      (dom/div nil
+        (dom/style nil ".counter { width: 400px; padding-bottom: 20px; } button { margin-left: 10px; }")
+        (map #(ui-counter (om/computed % {:onClick click-callback})) counters)))))
+
+(def ui-counter-panel (om/factory CounterPanel))
+
+(defui ^:once CounterSum
+  static uc/InitialAppState
+  (uc/initial-state [this params] {})
+  static om/IQuery
+  (query [this] [[:counter/by-id '_]])
+  Object
+  (render [this]
+    (let [{:keys [counter/by-id]} (om/props this)
+          total (reduce (fn [total c] (+ total (:counter/n c))) 0 (vals by-id))]
+      (dom/div nil
+        (str "Grand total: " total)))))
+
+(def ui-counter-sum (om/factory CounterSum))
+
+(defui ^:once Root
+  static uc/InitialAppState
+  (uc/initial-state [this params]
+    {:panel (uc/initial-state CounterPanel {})})
+  static om/IQuery
+  (query [this] [:ui/loading-data
+                 {:panel (om/get-query CounterPanel)}
+                 {:counter-sum (om/get-query CounterSum)}])
+  Object
+  (render [this]
+    (let [{:keys [ui/loading-data counter-sum panel]} (om/props this)]
+      (dom/div nil
+        (when loading-data
+          (dom/span #js {:style #js {:float "right"}} "Loading..."))
+        (ui-counter-panel panel)
+        (ui-counter-sum counter-sum)))))
+
+;; Simulated Server
+
+; Servers could keep state in RAM
+(defonce server-state (atom {:counters {1 {:counter/id 1 :counter/n 44}
+                                        2 {:counter/id 2 :counter/n 23}
+                                        3 {:counter/id 3 :counter/n 99}}}))
+
+; The server queries are handled by returning a map with a :value key, which will be placed in the appropriate
+; response format
+(defn read-handler [{:keys [ast state]} k p]
+  (log/info "SERVER query for " k)
+  (case k
+    ; When querying for :all-counters, return the complete set of values in our server counter db (atom in RAM)
+    :all-counters {:value (-> (get @state :counters) vals vec)}
+    nil))
+
+; The server mutations are handled by returning a map with a :action key whose value is the function that will
+; cause the change on the server
+(defn write-handler [env k p]
+  (log/info "SERVER mutation for " k " with params " p)
+  (case k
+    ; When asked to increment a counter on the server, do so by updating in-memory atom database
+    'counter/inc (let [{:keys [id]} p]
+                   {:action (fn [] (swap! server-state update-in [:counters id :counter/n] inc))})
+    nil))
+
+; Om Next query parser. Calls read/write handlers with keywords from the query
+(def server-parser (om/parser {:read read-handler :mutate write-handler}))
+
+; Simulated server. You'd never write this part
+(defn server [env tx]
+  (server-parser (assoc env :state server-state) tx))
+
+; Networking that pretends to talk to server. You'd never write this part
+(defrecord MockNetwork [complete-app]
+  un/UntangledNetwork
+  (send [this edn ok err]
+    (let [resp (server {} edn)]
+      ; simulates a network delay:
+      (js/setTimeout #(ok resp) 300)))
+  (start [this app]
+    (assoc this :complete-app app)))

 (defcard-doc
   "# Quick Tour

-  -
+  Untangled is meant to be as simple as possible, but as Rich would tell you:
+  simple does not mean easy. Fortunately, hard vs. easy is something you can fix just by learning.
+
+  Om Next (the lower layer of Untangled) takes a very progressive approach
+  to web development, and as such requires that you understand some new
+  concepts. This is *by far* the most difficult part of adapting to Untangled.
+
+  In this quick tour our intention is to show you a full-stack Untangled
+  application. We hope that as you read this Quick Start you will
+  start to comprehend how simple the resulting structure is:
+
+  - No controllers are needed, ever.
+  - Networking becomes completely transparent.
+  - Server and client code structure are identical. In fact, this tour leverages this fact to simulate server code in
+  the browser that is identical to what you'd *put* on the server.
+  - The reasoning at the UI layer can be completely local.
+  - The reasoning at the model layer can be completely local.
+  - The render refresh story is mostly automatic, and where it isn't, it
+  is completely abstracted from the UI structure to ease developer reasoning.
+
+  If you're coming from Om Next, realize that Untangled is *not* a competing project. Untangled is a set of
+  thin libraries that
+  provide default implementations of all of the artifacts you'd normally have to write to make an Om Next application. In
+  many cases Untangled is required to 'make a call' about how to do something. When it does, our documentation tries to
+  discuss the relative merits and costs.
+
+  ##

-  ")
+
+  "
+  (dc/mkdn-pprint-source Counter)
+  (dc/mkdn-pprint-source ui-counter)
+  (dc/mkdn-pprint-source CounterPanel)
+  (dc/mkdn-pprint-source ui-counter-panel))
+
+(defcard SampleApp
+         (untangled-app Root
+                        :started-callback (fn [{:keys [reconciler] :as app}]
+                                            (log/info "Application (re)started")
+                                            (df/load-data reconciler [{:all-counters (om/get-query Counter)}]
+                                                          :post-mutation 'add-counters-to-panel))
+                        :networking (map->MockNetwork {}))
+         {})


Correct formatting

Correct formatting

--- test/clojure/contrib/inflect_test.cljc
+++ test/clojure/contrib/inflect_test.cljc
@@ -13,9 +13,9 @@

   (testing "Zero is considered plural"
     (are [noun expected-noun] (= expected-noun (pluralize-noun 0 noun))
-               "kiss" "kisses"
-               "robot" "robots"
-                "ox" "oxen"))
+                              "kiss" "kisses"
+                              "robot" "robots"
+                              "ox" "oxen"))

   (testing "Testing nouns ending in a sibilant sound."
     (is (= (pluralize-noun 2 "kiss") "kisses"))


Mods to cider lein profile.

Mods to cider lein profile.

--- lein/.lein/profiles.d/cider.clj
+++ lein/.lein/profiles.d/cider.clj
@@ -1,11 +1,13 @@
 {:plugins [[cider/cider-nrepl "0.14.0"]
+           [jonase/eastwood "0.2.3"
+            :exclusions [org.clojure/clojure]]
            [refactor-nrepl "2.2.0"]]
- :dependencies [[cider/cider-nrepl "0.14.0"]]
+ :dependencies [[acyclic/squiggly-clojure "0.1.6"]]
  :env {:squiggly
               ;; Quote options to avoid warnings
               ;; introduced with `lein-environ 1.1.0` plugin
               "{:checkers [:eastwood]
-               :eastwood-exclude-linters [:unlimited-use]}"}}
+                :eastwood-exclude-linters [:unlimited-use :no-ns-form-found]}"}}


Add tests for multisubst.

Add tests for multisubst.

--- test/little_clojurer/chapter3_test.clj
+++ test/little_clojurer/chapter3_test.clj
@@ -63,4 +63,8 @@

 (deftest multisubst-test
   (testing
-    (is true)))
+    (is (= '() (multisubst :new :old '())))
+    (is (= '(:x :y :z) (multisubst :new :old '(:x :y :z))))
+    (is (= '(:new :new :new :new) (multisubst :new :old '(:old :old :old :old))))
+    (is (= '(:new :new :new :new) (multisubst :new :old '(:old :old :old :new))))
+    (is (= '(:x :new :new) (multisubst :new :old '(:x :old :old))))))


whitespace

whitespace

--- test/onyx/plugin/output_bench_test.clj
+++ test/onyx/plugin/output_bench_test.clj
@@ -18,7 +18,6 @@
             [onyx.plugin.kafka]
             [onyx.api]
             [taoensso.timbre :as log]))
-

 (def compress-opts {:v1-compatibility? false :compressor nil :encryptor nil :password nil})


Add a reset function to frontend-dev ns

Add a reset function to frontend-dev ns

--- dev-src/clj/comic_reader/frontend_dev.clj
+++ dev-src/clj/comic_reader/frontend_dev.clj
@@ -1,6 +1,7 @@
 (ns comic-reader.frontend-dev
   (:require [clojure.java.browse :refer [browse-url]]
             [clojure.repl :refer :all]
+            [clojure.tools.namespace.repl :refer [refresh]]
             [comic-reader.system :refer [go start stop]]
             [figwheel-sidecar.repl-api :refer :all]))

@@ -33,3 +34,7 @@
   (stop-autobuild)
   (stop-figwheel!)
   (stop))
+
+(defn reset []
+  (stop-dev!)
+  (refresh :after 'comic-reader.frontend-dev/start-dev!))


removed shim, doesn't affect production, only development

--- src-cljs/flyer/core.cljs
+++ src-cljs/flyer/core.cljs
@@ -12,7 +12,3 @@
 ;;the window gets refreshed
 (when (not (nil? (.-opener js/window)))
   (register-external))
-
-;;IE-shiv..., just in case
-(when (not (fn? (aget js/console "log")))
-  (aset js/console "log" (fn [x & xs] nil)))


fixed test names to represent what they are testing in controls_test

--- test-cljs/frontend/controllers/controls_test.cljs
+++ test-cljs/frontend/controllers/controls_test.cljs
@@ -66,7 +66,7 @@

 (defn failed-event [] "failed")

-(deftest button-ajax-success-event-works
+(deftest button-ajax-failed-event-works
   (testing "button-ajax correctly sends a failed event on failed"
     (async done
            (go
@@ -82,7 +82,7 @@
                    (is (= 1 (-> failed-event bond/calls count)))
                    (done))))))))

-(deftest button-ajax-failed-event-works
+(deftest button-ajax-success-event-works
   (testing "button-ajax correctly sends a success event on success"
     (async done
            (go


Correct error messages for html page absence

--- test/comic_reader/sites_test.clj
+++ test/comic_reader/sites_test.clj
@@ -128,7 +128,7 @@
               (extract-chapters-list html ""))))
       (is false
           (str "There must be a sample chapter list html page "
-               "at `resources/test/" site-name "/image.html'")))))
+               "at `resources/test/" site-name "/chapter_list.html'")))))

 (defn test-extract-comic-list []
   (let [results (try-read-file
@@ -140,7 +140,7 @@
               (extract-comics-list html))))
       (is false
           (str "There must be a sample chapter list html page "
-               "at `resources/test/" site-name "/image.html'")))))
+               "at `resources/test/" site-name "/comic_list.html'")))))

 (defn testdef-form [site-name]
   `(deftest ~(symbol (str site-name "-test"))


Add ability to target node.js

Add ability to target node.js

--- src/adzerk/boot_cljs.clj
+++ src/adzerk/boot_cljs.clj
@@ -44,6 +44,7 @@
   (Replace 'out', 'main.js', and 'my-namespace' with your own configuration.)"

   [d output-dir NAME     str  "Subdirectory name for GClosure intermediate files."
+   n node-target         bool "Target Node.js for compilation"
    o output-path PATH    str  "The output js file path relative to docroot."
    O optimizations LEVEL kw   "The optimization level."
    p pretty-print        bool "Pretty-print compiled JS."
@@ -76,7 +77,9 @@
         ;; src-map: see https://github.com/clojure/clojurescript/wiki/Source-maps
         smap-opts   {:source-map-path js-parent
                      :source-map      (.getPath smap)}
-        cljs-opts   (merge base-opts (when source-map smap-opts))
+        cljs-opts   (merge base-opts
+                           (when source-map smap-opts)
+                           (when node-target {:target :nodejs}))
         ->res       (partial map core/resource-path)
         p           (-> (core/get-env)
                       (update-in [:dependencies] into cljs-deps)


Fix default-main with deps.cljs files

Fix default-main with deps.cljs files

Deps.cljs files should not be required in default-main

--- src/adzerk/boot_cljs.clj
+++ src/adzerk/boot_cljs.clj
@@ -75,10 +75,6 @@
         (throw (util/deserialize-exception exception)))
       (-> result (update-in [:dep-order] #(->> (conj % (:output-to opts)) (map rel-path)))))))

-(defn- cljs-files
-  [fileset]
-  (->> fileset core/input-files (core/by-ext [".cljs" ".cljc"]) (sort-by :path)))
-
 (defn- macro-files-changed
   [diff]
   (->> (core/input-files diff)
@@ -138,7 +134,7 @@
       (core/empty-dir! tmp-main)
       (if (seq (main-files fileset ids))
         fileset
-        (let [cljs     (cljs-files fileset)
+        (let [cljs     (->> fileset core/input-files (core/by-ext [".cljs" ".cljc"]) (core/by-name ["deps.cljs"] true) (sort-by :path))
               out-main (str (or (first ids) "main") ".cljs.edn")
               out-file (io/file tmp-main out-main)]
           (info "Writing %s...\n" (.getName out-file))


Bump number of auto-retries for BigQuery data loading a bit :cry:

--- test/metabase/test/data/bigquery.clj
+++ test/metabase/test/data/bigquery.clj
@@ -179,7 +179,7 @@
   {:pre [(seq database-name) (sequential? table-definitions)]}
   (let [database-name (normalize-name-and-add-prefix database-name)]
     (when-not (contains? @created-databases database-name)
-      (u/auto-retry 3
+      (u/auto-retry 5
         (u/ignore-exceptions
           (destroy-dataset! database-name))
         (create-dataset! database-name)


Wrap up iterator specs

Wrap up iterator specs

--- src/aurora/language.cljs
+++ src/aurora/language.cljs
@@ -57,11 +57,19 @@

 ;; FLOWS

-(deftype Join [input-types input-args output-kinds output-names output-fields]
+(deftype MagicIterator [kind name fields index vars]
+  Object
+  (iter [this]
+        (join/magic-iterator index vars)))
+
+(defn magic-iterator [kn kind name fields vars]
+  (let [index (.get-or-create-index kn kind name fields)]
+    (MagicIterator. kind name fields index vars)))
+
+(deftype Join [input-iterables output-kinds output-names output-fields]
   Object
   (run [this kn]
-       (let [input-iters (amap input-types i _
-                               (.apply (aget js/aurora.join (aget input-types i)) nil (aget input-args i)))
+       (let [input-iters (amap input-iterables i _ (.iter (aget input-iterables i)))
              join-iter (join/join-iterator input-iters)
              facts (btree/iterator->keys join-iter)]
          (dotimes [i (alength output-kinds)]
@@ -109,12 +117,12 @@
   (.add-facts kn "know" "edge" #js ["x" "y"] #js [#js ["a" "b"] #js ["b" "c"] #js ["c" "d"] #js ["d" "b"]])

   (def edge-flow
-    (Join. #js ["magic_iterator"] #js [#js [(.get-or-create-index kn "know" "edge" #js ["x" "y"]) #js [0 1]]]
+    (Join. #js [(magic-iterator kn "know" "edge" #js ["x" "y"] #js [0 1])]
            #js ["know"] #js ["connected"] #js [#js ["x" "y"]]))

   (def connected-flow
-    (Join. #js ["magic_iterator" "magic_iterator"] #js [#js [(.get-or-create-index kn "know" "edge" #js ["x" "y"]) #js [0 1 nil]]
-                                                        #js [(.get-or-create-index kn "know" "connected" #js ["x" "y"]) #js [nil 0 1]]]
+    (Join. #js [(magic-iterator kn "know" "edge" #js ["x" "y"] #js [0 1 nil])
+                (magic-iterator kn "know" "connected" #js ["x" "y"] #js [nil 0 1])]
            #js ["know"] #js ["connected"] #js [#js ["x" nil "y"]]))

   (def transitive-flow


Fix RR.

Fix RR.

--- src/onyx/log/commands/common.clj
+++ src/onyx/log/commands/common.clj
@@ -63,7 +63,11 @@

 (defn round-robin-next-job [replica]
   (let [counts (job->peers replica)]
-    (ffirst (sort-by count counts))))
+    (->> (:jobs replica)
+         (reduce #(conj %1 {:job %2 :n (count (get counts %2))}) [])
+         (sort-by :n)
+         (first)
+         :job)))

 (defn saturated-cluster? [replica]
   (let [balanced (balance-jobs replica)


Fix repl state.

Fix repl state.

[ci skip]

--- src/onyx/windowing/window_id.clj
+++ src/onyx/windowing/window_id.clj
@@ -102,17 +102,17 @@
 ;; `wids` is defined in section 3.4 of the paper. This is the variant
 ;; of the algorithm that also covers the case where range and slide
 ;; are defined on the same value.
-(defn wids-lower [min-windowing-attr t]
+(defn wids-lower [min-windowing-attr w-slide t]
   (dec (int (Math/floor (/ (- (:window-attr t)
                               min-windowing-attr) w-slide)))))

-(defn wids-upper [min-windowing-attr t]
+(defn wids-upper [min-windowing-attr w-range w-slide t]
   (dec (int (Math/floor (/ (- (+ (:window-attr t) w-range)
                               min-windowing-attr) w-slide)))))

-(defn wids [min-windowing-attr t]
-  (let [lower (wids-lower min-windowing-attr t)
-        upper (wids-upper min-windowing-attr t)]
+(defn wids [min-windowing-attr w-range w-slide t]
+  (let [lower (wids-lower min-windowing-attr w-slide t)
+        upper (wids-upper min-windowing-attr w-range w-slide t)]
     (range (inc lower) (inc upper))))

 ;; The follow code runs through 30 segments with
@@ -121,7 +121,7 @@
 ;; up with both tables we looked at above.
 ;;
 ;; (doseq [n (range 30)]
-;;   (println n "=>" (wids 0 {:window-attr n})))
+;;   (println n "=>" (wids 0 20 5 {:window-attr n})))

 ;; 0 => (0 1 2 3)
 ;; 1 => (0 1 2 3)
@@ -153,3 +153,40 @@
 ;; 27 => (5 6 7 8)
 ;; 28 => (5 6 7 8)
 ;; 29 => (5 6 7 8)
+
+;; Now we will tackle a more general case - where the range
+;; and slide values aren't defined on the same attribute.
+;; Instead of :window-attr, we now use :range-attr and :slide-attr.
+;; As noted by the paper, a common case of this is a timestamp range,
+;; and a slide-by-tuple of 1 for slide. This is back in section 3.3.
+
+;;; WIP....
+;; (defn var-2-n-windows [t r-attr w-slide])
+
+;; (defn var-2-extent-lower [w-range w]
+;;   (- w w-range))
+
+;; (defn var-2-extent-upper [w]
+;;   w)
+
+;; ;; Yields all values of :range-attr which belong to window w
+;; ;; with range of length w-range.
+;; (defn var-2-extents [w-range w]
+;;   (range (inc (var-2-extent-lower w-range w))
+;;          (inc (var-2-extent-upper w))))
+
+;; (var-2-extents 20 25)
+
+;; (defn var-wids-lower [t]
+;;   (get t (:range-attr t)))
+
+;; (defn var-wids-upper [t w-range]
+;;   (+ (get t (:range-attr t)) w-range))
+
+;; (defn var-2-wids [t]
+;;   (var-wids-lower t))
+
+;; (var-2-wids {:range-attr :ts :ts 30})
+
+
+;; (var-wids-upper {:range-attr :ts :ts 30} 10)


Fix error in Carbon

Fix error in Carbon

--- src/org/spootnik/cyanite/tcp.clj
+++ src/org/spootnik/cyanite/tcp.clj
@@ -55,7 +55,7 @@
                                                   sd
                                                   (new ReadTimeoutHandler readtimeout)
                                                   putter])))))
-        (.option ChannelOption/CONNECT_TIMEOUT_MILLIS connecttimeout)
+        (.option ChannelOption/CONNECT_TIMEOUT_MILLIS (int connecttimeout))
         (.childOption ChannelOption/SO_KEEPALIVE true))))

 (defn start-tcp-server


Add markov-pat-loop

Add markov-pat-loop

--- src/overtone_workspace/beats.clj
+++ src/overtone_workspace/beats.clj
@@ -16,7 +16,7 @@
 ;;                        }).add;
 (definst fmchord01 [freq 440 amp 0.2 dur 2]
   (let [index-env (env-gen (perc 0.0001 0.2 1 -4))
-        amp-env (env-gen (perc 0.0001 1 dur -4) :action FREE)
+        amp-env (env-gen (perc 0.0001 dur 1 -4) :action FREE)
         snd (pm-osc freq (* freq 1.02) (* index-env 2))
         reverb (free-verb (* snd amp-env) 0.5 0.8 0.9)]
     (pan2 (* amp reverb))))
@@ -30,12 +30,12 @@
       (let [idx (Math/floor (* x (count logistics-scale)))
             note (nth logistics-scale idx)
             freq (midi->hz note)
-            dur (* (rand) 4/8 (/ 60.0 (metro :bpm)))
+            dur (* 4/8 (/ 60.0 (metro :bpm)))
             next-beat (+ 2/8 beat)
             next-x (* logistics-r x (- 1 x))] ;; x = r * x * (1 - x)
         (if (< 0 (rand-int 3))
           (at (metro beat)
-              (fmchord01 :freq freq :dur dur :amp (+ 5 (rand 2)))))
+              (fmchord01 :freq freq :dur dur :amp (+ 3 (rand 1)))))
         (apply-by (metro next-beat) #'logistics-loop [metro next-beat next-x])
         )))

@@ -71,14 +71,36 @@
     (at (metro beat)
         (doseq [n notes]
           (let [freq (midi->hz n)]
-            (fmchord01 :freq freq :dur dur :amp 0.3))))
+            (fmchord01 :freq freq :dur dur :amp 1.0))))
     (apply-by (metro next-beat) #'markov-loop [metro next-beat dict next-deg])
     ))
-;; (markov-loop sequencer-metro (sequencer-metro) chord-chain-dict :I)
+(defn markov-pat-loop [metro beat dict deg]
+  (let [mi (deg DEGREE)
+        sc (if mi :minor :major)
+        d (if mi deg (deg MAJORDEGREE))
+        notes (chord-degree d :C3 sc)
+        dur (* 6 (/ 60.0 (metro :bpm)))
+        next-beat (+ 4 beat)
+        next-deg (choose (deg dict))]
+    (doseq [[idx n] (map-indexed vector (take 3 notes))]
+      (at (metro (+ (* idx 1/2) beat))
+          (let [freq (midi->hz n)]
+            (fmchord01 :freq freq :dur dur :amp 1.0))
+          ))
+    (apply-by (metro next-beat) #'markov-pat-loop [metro next-beat dict next-deg])
+    ))
+(comment
+  (do
+    (logistics-loop sequencer-metro (sequencer-metro) 0.1)
+    (markov-loop sequencer-metro (sequencer-metro) chord-chain-dict :I)
+    (markov-pat-loop sequencer-metro (sequencer-metro) chord-chain-dict :I))
+  (stop))
+
+;; (markov-pat-loop sequencer-metro (sequencer-metro) chord-chain-dict :I)
 ;; (chord-degree :i :c4 :major)
 ;; (stop)

-(volume (/ 25 127))
+(volume (/ 50 127))

 (defn player [metro beat rates]
   (let [rates (if (empty? rates)
@@ -127,7 +149,7 @@
 (def d {:amp 5.0 :dur 0.25})
 (def g {:freq-mul 1})

-(volume 0.25)
+;;(volume 0.25)
 (sequencer-metro :bpm)

 (def beat-per-pattern 4)


Use var-quote to access private pr-writer-impl function

Fixes #225.

--- src/day8/re_frame_10x/utils/pretty_print_condensed.cljs
+++ src/day8/re_frame_10x/utils/pretty_print_condensed.cljs
@@ -199,7 +199,7 @@
 (defn pr-writer-impl [obj writer opts]
   (if (-limited? writer)
     writer
-    (cljs.core/pr-writer-impl obj writer opts)))
+    (#'cljs.core/pr-writer-impl obj writer opts)))

 (defn- pr-writer
   "Prefer this to pr-seq, because it makes the printing function


Make start-app behave better if system start fails

If `go` threw an exception delay would cache the exception and throw the same one for each subsequent call. Instead we want to execute go until it succeeds. This way user can fix the error causing problems in REPL.

--- src/clj/backend/boot.clj
+++ src/clj/backend/boot.clj
@@ -7,9 +7,13 @@
 (deftask start-app
   [p port   PORT int  "Port"
    r reload      bool "Add reload mw"]
-  (let [f (delay
-            (setup-app! {:port port
-                        :reload reload
-                        :reload-dirs (get-env :directories)})
-            (go))]
-    (with-post-wrap fileset @f fileset)))
+  (let [x (atom nil)]
+    (with-post-wrap fileset
+      (swap! x (fn [x]
+                  (if x
+                    x
+                    (do (setup-app! {:port port
+                                     :reload reload
+                                     :reload-dirs (get-env :directories)})
+                        (go)))))
+      fileset)))


Only use :url-min under :advanced optimizations for foreign deps

--- src/clj/cljs/closure.clj
+++ src/clj/cljs/closure.clj
@@ -916,9 +916,11 @@
 (defn add-header [opts js]
   (str (make-preamble opts) js))

-(defn foreign-deps-str [sources]
+(defn foreign-deps-str [opts sources]
   (letfn [(to-js-str [ijs]
-            (let [url (or (:url-min ijs) (:url ijs))]
+            (let [url (or (and (= (:optimizations opts) :advanced)
+                               (:url-min ijs))
+                          (:url ijs))]
               (slurp url)))]
     (apply str (map to-js-str sources))))

@@ -1077,7 +1079,7 @@
                                    [(-compile (io/resource "cljs/nodejscli.cljs") all-opts)]))))
                  optim (:optimizations all-opts)
                  ret (if (and optim (not= optim :none))
-                       (let [fdeps-str (foreign-deps-str
+                       (let [fdeps-str (foreign-deps-str opts
                                          (filter foreign-source? js-sources))
                              all-opts (assoc all-opts
                                         :foreign-deps-line-count


really fixed static.clj to reflect true border corner point


Use lazy pmap for lazy-depth

Use lazy pmap for lazy-depth

--- src/cljam/algo/depth.clj
+++ src/cljam/algo/depth.clj
@@ -1,6 +1,7 @@
 (ns cljam.algo.depth
   "Provides algorithms for calculating simple depth of coverage."
   (:require [com.climate.claypoole :as cp]
+            [com.climate.claypoole.lazy :as lazy]
             [cljam.common :as common]
             [cljam.util :as util]
             [cljam.io.sam :as sam]
@@ -34,10 +35,10 @@
                    (if (= n-threads 1)
                      (map (fn [[start end]]
                             (count-for-positions (read-fn rdr start end) start end)) xs)
-                     (cp/pmap (dec n-threads)
-                              (fn [[start end]]
-                                (with-open [r (sam/clone-bam-reader rdr)]
-                                  (count-for-positions (read-fn r start end) start end))) xs)))]
+                     (lazy/pmap (dec n-threads)
+                                (fn [[start end]]
+                                  (with-open [r (sam/clone-bam-reader rdr)]
+                                    (count-for-positions (read-fn r start end) start end))) xs)))]
     (->> (util/divide-region start end step)
          count-fn
          (apply concat))))


disable charts

disable charts

--- src/cljs/ceres/core.cljs
+++ src/cljs/ceres/core.cljs
@@ -386,7 +386,8 @@
    (listen
     :on-click
     (fn [e]
-      (let [[ws-in _] (:ws-chs @app)
+      (.log js/console "HE'S DEAD, JIM!")
+      #_(let [[ws-in _] (:ws-chs @app)
             out (:stats-ch @app)]
         (go
           (>! ws-in {:topic :tweets-count :data ""})


Update gampg.core with some temporary debugging infrastructure

--- src/cljs/gampg/core.cljs
+++ src/cljs/gampg/core.cljs
@@ -15,6 +15,7 @@
             [gampg.learn-gamma.lesson-08 :as lg08]
             [gampg.learn-gamma.lesson-09 :as lg09]
             [gampg.learn-gamma.lesson-10 :as lg10]
+            [gampg.learn-gamma.gltf :as lg-gltf]
             [goog.webgl :as ggl]
             [om.core :as om :include-macros true]
             [om.dom :as dom :include-macros true]))
@@ -25,9 +26,9 @@
 ;;
 ;; XXX: We're not properly reusing gl context's here, hurts fighweel's
 ;; reloadability
-(def title   lg01/title)
-(def prog    lg01/program-source)
-(def gl-main lg01/main)
+(def title   lg-gltf/title)
+(def prog    lg-gltf/program-source)
+(def gl-main lg-gltf/main)

 (defonce app-state (atom {:live {}}))

@@ -46,32 +47,42 @@
                       :style #js{:width "100%"
                                  :border (str "2px solid " (rand-nth ["black" "blue" "green" "pink"]))}}))))

+(defn main* []
+  (let [node (js/document.getElementById "glcanvas")
+        gl   (.getContext node "webgl")]
+    (om/root
+     (fn [app owner]
+       (reify
+         om/IRender
+         (render [_]
+           (dom/div nil
+                    (dom/h2 #js{:onClick (fn [event] (om/transact! app :reverse? not))}
+                            title)
+                    (dom/small nil
+                               (dom/pre #js{:style #js{:float "left"
+                                                       :borderRight "1px dotted black"
+                                                       :width "45%"
+                                                       :overflow "hidden"}}
+                                        "Vertex Shader:\n--------------\n\n"
+                                        (get-in prog [:vertex-shader :glsl])))
+                    (dom/small nil
+                               (dom/pre #js{:style #js{:width "50%"
+                                                       :float "left"
+                                                       :marginLeft 4
+                                                       :paddingLeft 4}}
+                                        "Fragment Shader:\n----------------\n"
+                                        (get-in prog [:fragment-shader :glsl])))))))
+     app-state
+     {:target (. js/document (getElementById "app"))})
+    (gl-main gl node)))
+
+;; Temporarily here for debugging
+
 (defn main []
-  (om/root
-   (fn [app owner]
-     (reify
-       om/IRender
-       (render [_]
-         (dom/div nil
-                  (dom/h2 #js{:onClick (fn [event] (om/transact! app :reverse? not))}
-                          title)
-                  (om/build canvas (:text app) {:opts {:cb (fn [gl node]
-                                                             (gl-main gl node))}})
-                  (dom/small nil
-                             (dom/pre #js{:style #js{:float "left"
-                                                     :borderRight "1px dotted black"
-                                                     :width "45%"
-                                                     :overflow "hidden"}}
-                                      "Vertex Shader:\n--------------\n\n"
-                                      (get-in prog [:vertex-shader :glsl])))
-                  (dom/small nil
-                             (dom/pre #js{:style #js{:width "50%"
-                                                     :float "left"
-
-                                                     :marginLeft 4
-                                                     :paddingLeft 4}}
-                                      "Fragment Shader:\n----------------\n"
-                                      (get-in prog [:fragment-shader :glsl])))
-                  ))))
-   app-state
-   {:target (. js/document (getElementById "app"))}))
+  (let [node (js/document.getElementById "glcanvas")
+        gl   (.getContext node "webgl")]
+    (main*)))
+
+(set! (.-reinstallApp js/window)
+      (fn []
+        (main*)))


Add GET-edn function

Add GET-edn function

--- src/cljs/gtfve/data.cljs
+++ src/cljs/gtfve/data.cljs
@@ -62,3 +62,6 @@
              :stops stops
              :stop-times stop-times
              :trips trips))))
+
+(defn GET-edn [url & {:as args}]
+  (GET url (merge args {:response-format :edn})))


Remove marker on unmount

Remove marker on unmount

--- src/cljs/gtfve/maps.cljs
+++ src/cljs/gtfve/maps.cljs
@@ -76,6 +76,8 @@
                               (let [[_ opts gmap] (r/argv this)
                                     m-opts (merge @opts {:map gmap})]
                                 (.setOptions marker (clj->js m-opts))))
+      :component-will-unmount (fn [this]
+                                (.setMap marker nil))
       :component-function (fn [opts]
                             [:noscript])})))


Add :features option for defsketch. Add :no-start feature option.

--- src/cljs/quil/sketch.clj
+++ src/cljs/quil/sketch.clj
@@ -5,11 +5,20 @@
      ~@body))

+(def ^{:private true}
+	supported-features
+	#{:no-start :no-loop})
+
+
 (defmacro defsketch
   [app-name & options]
-  `(do
-     (defn ^:export ~app-name []
-       (quil.sketch/make-processing ~@options))
-
-     ~(when (not (false? (:start options)))
-     	`(quil.sketch/add-sketch-to-init-list ~app-name))))
+  (let [opts (apply hash-map options)
+        features (let [user-features (set (:features opts))]
+                   (reduce #(assoc %1 %2 (contains? user-features %2)) {}
+                           supported-features))]
+    `(do
+       (defn ^:export ~app-name []
+         (quil.sketch/make-processing ~@(apply concat (seq (merge (dissoc opts :features) features)))))
+
+       ~(when (not (:no-start features))
+          `(quil.sketch/add-sketch-to-init-list ~app-name)))))


fix back button on login

fix back button on login

--- src-cljs/frontend/controllers/controls.cljs
+++ src-cljs/frontend/controllers/controls.cljs
@@ -1048,7 +1048,7 @@

 (defmethod post-control-event! :track-external-link-clicked
   [target message {:keys [path event properties]} previous-state current-state]
-  (let [redirect #(js/window.location.replace path)]
+  (let [redirect #(set! js/window.location path)]
     (go (alt!
          (mixpanel/managed-track event properties) ([v] (do (utils/mlog "tracked" v "... redirecting")
                                                             (redirect)))


Add missing recur

Add missing recur

--- src/asciinema/vt.cljc
+++ src/asciinema/vt.cljc
@@ -441,8 +441,8 @@
 (defn execute-actions [vt actions input]
   (loop [vt vt
          actions actions]
-    (if-let [action (first actions)]
-      ((action-mapping action) vt input)
+    (if actions
+      (recur ((action-mapping (first actions)) vt input) (next actions))
       vt)))

 (defn feed [vt inputs]


improve error message to find what post file is missing uuid


reorganize pipeline-presentation history test.

--- test/clj/lambdacd/presentation/pipeline_state_test.clj
+++ test/clj/lambdacd/presentation/pipeline_state_test.clj
@@ -16,38 +16,39 @@
     (is (= [{:build-number 5
              :status :running
              :most-recent-update-at after-stop-time
-             :first-updated-at start-time }
-            {:build-number 6
+             :first-updated-at start-time }]
+           (history-for {5  {[0]   { :status :success :most-recent-update-at stop-time :first-updated-at start-time }
+                             [1]   { :status :running :most-recent-update-at after-stop-time :first-updated-at start-time}}})))
+    (is (= [{:build-number 6
              :status :success
              :most-recent-update-at stop-time
-             :first-updated-at start-time}
-            {:build-number 7
+             :first-updated-at start-time}]
+           (history-for { 6  {[0]   { :status :success :most-recent-update-at stop-time :first-updated-at start-time}}})))
+    (is (= [{:build-number 7
              :status :failure
              :most-recent-update-at stop-time
-             :first-updated-at before-start-time}
-            {:build-number 8
-             :status :waiting
-             :most-recent-update-at stop-time
-             :first-updated-at start-time}
-            {:build-number 9
-             :status :unknown
-             :most-recent-update-at stop-time
-             :first-updated-at start-time}
-            {:build-number 10
+             :first-updated-at before-start-time}]
+           (history-for { 7  {[0 2] { :status :running :most-recent-update-at stop-time :first-updated-at start-time}
+                              [0 1] { :status :failure :most-recent-update-at stop-time :first-updated-at before-start-time}}})))
+    (is (= [{:build-number 10
              :status :success
              :most-recent-update-at stop-time
-             :first-updated-at start-time}
-            ] (history-for { 5  {[0]   { :status :success :most-recent-update-at stop-time :first-updated-at start-time }
-                                 [1]   { :status :running :most-recent-update-at after-stop-time :first-updated-at start-time}}
-                             6  {[0]   { :status :success :most-recent-update-at stop-time :first-updated-at start-time}}
-                             7  {[0 2] { :status :running :most-recent-update-at stop-time :first-updated-at start-time}
-                                 [0 1] { :status :failure :most-recent-update-at stop-time :first-updated-at before-start-time}}
-                             8  {[0]   { :status :waiting :most-recent-update-at stop-time :first-updated-at start-time}}
-                             9  {[0]   { :no :status      :most-recent-update-at stop-time :first-updated-at start-time}}
-                             10 {[1 1] { :status :killed  :most-recent-update-at stop-time :first-updated-at long-before-start-time :has-been-waiting true}
-                                 [2 1] { :status :success :most-recent-update-at long-after-stop-time :first-updated-at start-time :has-been-waiting true}
-                                 [1]   { :status :success :most-recent-update-at stop-time :first-updated-at start-time}
-                                 [2]   { :status :success :most-recent-update-at stop-time :first-updated-at start-time}}})))))
+             :first-updated-at start-time}]
+           (history-for {10 {[1 1] { :status :killed  :most-recent-update-at stop-time :first-updated-at long-before-start-time :has-been-waiting true}
+                             [2 1] { :status :success :most-recent-update-at long-after-stop-time :first-updated-at start-time :has-been-waiting true}
+                             [1]   { :status :success :most-recent-update-at stop-time :first-updated-at start-time}
+                             [2]   { :status :success :most-recent-update-at stop-time :first-updated-at start-time}}})))
+    (testing "that more than one item works and a missing status leads to status unknown"
+      (is (= [{:build-number 8
+               :status :waiting
+               :most-recent-update-at stop-time
+               :first-updated-at start-time}
+              {:build-number 9
+               :status :unknown
+               :most-recent-update-at stop-time
+               :first-updated-at start-time}]
+             (history-for {8  {[0]   { :status :waiting :most-recent-update-at stop-time :first-updated-at start-time}}
+                           9  {[0]   { :no :status      :most-recent-update-at stop-time :first-updated-at start-time}}}))))))

 (deftest most-recent-build-test
   (testing "that it returns the most recent build number in the pipeline-state"


todomvc: bump carry-history dep version

todomvc: bump carry-history dep version

--- examples/todomvc/project.clj
+++ examples/todomvc/project.clj
@@ -29,7 +29,7 @@
              :clojars-deps {:dependencies [[carry "0.7.0"]
                                            [carry-atom-sync "0.4.0"]
                                            [carry-debugger "0.7.0"]
-                                           [carry-history "0.5.0"]
+                                           [carry-history "0.6.0"]
                                            [carry-logging "0.3.0"]
                                            [carry-persistence "0.5.0"]
                                            [carry-reagent "0.7.0"]


CMR-2357: Added test support for tag associations in mdb

--- metadata-db-app/int_test/cmr/metadata_db/int_test/utility.clj
+++ metadata-db-app/int_test/cmr/metadata_db/int_test/utility.clj
@@ -206,6 +206,22 @@
      ;; no provider-id should be specified for tags
      (dissoc (concept nil :tag uniq-num attributes) :provider-id))))

+(defn tag-association-concept
+  "Creates a tag association concept"
+  ([concept tag uniq-num]
+   (tag-association-concept uniq-num {}))
+  ([concept tag uniq-num attributes]
+   (let [{:keys [concept-id revision-id]} concept
+         tag-id (:native-id tag)
+         user-id (str "user" uniq-num)
+         native-id (str tag-id (char 29) concept-id (char 29) revision-id)
+         attributes (merge {:user-id user-id
+                            :format "application/edn"
+                            :native-id native-id}
+                           attributes)]
+     ;; no provider-id should be specified for tag associations
+     (dissoc (concept nil :tag-association uniq-num attributes) :provider-id))))
+
 (defn group-concept
   "Creates a group concept"
   ([provider-id uniq-num]
@@ -509,6 +525,19 @@
              (assert-no-errors (save-concept concept)))
          {:keys [concept-id revision-id]} (save-concept concept)]
      (assoc concept :concept-id concept-id :revision-id revision-id))))
+
+(defn create-and-save-tag-association
+  "Creates, saves, and returns a tag concept with its data from metadata-db"
+  ([concept tag uniq-num]
+   (create-and-save-tag-association concept tag uniq-num 1))
+  ([concept tag uniq-num num-revisions]
+   (create-and-save-tag-association concept tag uniq-num num-revisions {}))
+  ([concept tag uniq-num num-revisions attributes]
+    (let [concept (tag-association-concept concept tag uniq-num attributes)
+          _ (dotimes [n (dec num-revisions)]
+              (assert-no-errors (save-concept concept)))
+          {:keys [concept-id revision-id]} (save-concept concept)]
+      (assoc concept :concept-id concept-id :revision-id revision-id))))

 (defn create-and-save-service
   "Creates, saves, and returns a service concept with its data from metadata-db."


CMR-2900 updates comment and fixes demos

--- umm-lib/src/cmr/umm/acl_matchers.clj
+++ umm-lib/src/cmr/umm/acl_matchers.clj
@@ -99,7 +99,7 @@
          (or (nil? collection-identifier)
              (coll-matches-collection-identifier? coll collection-identifier)))))

-;; Functions for preparing concepts to be passed to functions above... copied here from search
+;; Functions for preparing concepts to be passed to functions above.

 (defmulti add-acl-enforcement-fields-to-concept
   "Adds the fields necessary to enforce ACLs to the concept. Temporal and access value are relatively


Make register-via-invite-email not ask need password

Since the create-user-txn ignores the password argument anyway

--- src/braid/core/server/routes/api/public.clj
+++ src/braid/core/server/routes/api/public.clj
@@ -107,11 +107,9 @@
     (edn-response (not (group/group-with-slug-exists? (get-in req [:params :slug])))))

   ; accept an email invite to join a group
-  (POST "/register" [token invite_id password email now hmac :as req]
+  (POST "/register" [token invite_id email now hmac :as req]
     (let [fail {:status 400 :headers {"Content-Type" "text/plain"}}]
       (cond
-        (string/blank? password) (assoc fail :body "Must provide a password")
-
         (not (invites/verify-hmac hmac (str now token invite_id email)))
         (assoc fail :body "Invalid HMAC")

@@ -122,20 +120,17 @@
         (let [invite (invitation/invite-by-id (java.util.UUID/fromString invite_id))]
           (if-let [err (:error (invites/verify-invite-nonce invite token))]
             (assoc fail :body "Invalid invite token")
-            (let [user-id (db/uuid)
-                  referer (get-in req [:headers "referer"] (config :site-url))
-                  [proto _ referrer-domain] (string/split referer #"/")]
+            (let [user-id (db/uuid)]
               (do
                 (db/run-txns!
                   (user/create-user-txn {:id user-id
-                                         :email email
-                                         :password password}))
+                                         :email email}))
                 (events/user-join-group! user-id (invite :group-id))
                 (db/run-txns!
                   (concat
                     (invitation/retract-invitation-txn (invite :id)))))
               {:status 302
-               :headers {"Location" (str proto "//" referrer-domain)}
+               :headers {"Location" (config :site-url)}
                :session (assoc (req :session) :user-id user-id)
                :body ""}))))))


Removing dummy collection id which causes errors.

--- test/cmr/system_int_test/search/granule_search_test.clj
+++ test/cmr/system_int_test/search/granule_search_test.clj
@@ -351,8 +351,7 @@
         gran2-cid (get-in gran2 [:concept-id])
         gran3-cid (get-in gran3 [:concept-id])
         gran4-cid (get-in gran4 [:concept-id])
-        gran5-cid (get-in gran5 [:concept-id])
-        dummy-cid "D1000000004-PROV2"]
+        gran5-cid (get-in gran5 [:concept-id])]
     (index/refresh-elastic-index)
     (testing "echo granule id search"
       (are [items cid options]
@@ -363,7 +362,6 @@

            [gran1] gran1-cid {}
            [gran5] gran5-cid {}
-           [] dummy-cid {}
            ;; Multiple values
            [gran1 gran2 gran3 gran4 gran5] [gran1-cid gran2-cid gran3-cid gran4-cid gran5-cid] {}
            [gran1 gran5] [gran1-cid gran5-cid] {:and false}
@@ -377,7 +375,6 @@

            [gran1] gran1-cid {}
            [gran5] gran5-cid {}
-           [] dummy-cid {}
            ;; Multiple values
            [gran1 gran2 gran3 gran4 gran5] [gran1-cid gran2-cid gran3-cid gran4-cid gran5-cid] {}
            [] (s/lower-case gran1-cid) {:ignore-case false}))
@@ -425,7 +422,6 @@
              (d/refs-match? items (search/find-refs :granule params)))
            [gran1] gran1-cid {}
            [gran5] gran5-cid {}
-           [] dummy-cid {}
            ;; Multiple values
            [gran1 gran2 gran3 gran4 gran5] [gran1-cid gran2-cid gran3-cid gran4-cid gran5-cid] {}
            [] [gran1-cid gran5-cid] {:and true}))


Fix overlapping and alignment problems with trolley preview

--- src/cljs/ikea_clojure_cup/select_items.cljs
+++ src/cljs/ikea_clojure_cup/select_items.cljs
@@ -164,9 +164,10 @@
         (* scale (+
                   (reduce + (map (fn [{:keys [width height length]}] (min width height length)) packages))
                   (* (count packages) 2)))
-        max-width (* scale (apply max (map (fn [{:keys [width height length]}] (max width height length)) packages)))]
+        max-width (* scale (or (apply max (map (fn [{:keys [width height length]}] (max width height length)) packages)) 0))]
     [:svg {:width "100%" :height "80%"
-           :view-box (clojure.string/join " " [0 0 max-width (+ 2 total-height)])}
+           :view-box (clojure.string/join " " [0 0 max-width total-height])
+           :preserve-aspect-ratio "xMinYMax"}
      [:g {:stroke :black
           :stroke-width (* scale 1)}
       (:rects
@@ -178,7 +179,7 @@
                 (update :rects conj
                         [:rect {:key (hash package)
                                 :x 0
-                                :y offset
+                                :y (- offset box-height)
                                 :height box-height
                                 :width box-width
                                 :fill (if (= (:id item) selected-flatpack-item) :black :transparent)}])


Move slurp / spit down

Move slurp / spit down

Former-commit-id: 658dd2fd513bbf074c615d54c2427274eb56468f

--- planck-cljs/src/planck/io.cljs
+++ planck-cljs/src/planck/io.cljs
@@ -67,17 +67,6 @@
   *err*
   (Writer. js/PLANCK_RAW_WRITE_STDERR js/PLANCK_RAW_FLUSH_STDERR))

-(defn slurp
-  "Slurps a file"
-  [filename]
-  (or (js/PLANCK_READ_FILE filename)
-    (throw (js/Error. filename))))
-
-(defn spit
-  "Spits a file"
-  [filename content]
-  (js/PLANCK_WRITE_FILE filename content)
-  nil)

 (defn- fission! [atom f & args]
   "Breaks an atom's value into two parts. The supplied function should
@@ -109,4 +98,16 @@
                                       residual))
                                   (subs s 0 n)]))))
     (when (reset! buffer (-read *in*))
-      (recur))))+      (recur))))
+
+(defn slurp
+  "Slurps a file"
+  [filename]
+  (or (js/PLANCK_READ_FILE filename)
+    (throw (js/Error. filename))))
+
+(defn spit
+  "Spits a file"
+  [filename content]
+  (js/PLANCK_WRITE_FILE filename content)
+  nil)


cleanup

cleanup

--- Clojure-Websockets/MainApp/src/cljs/birdwatch/core.cljs
+++ Clojure-Websockets/MainApp/src/cljs/birdwatch/core.cljs
@@ -29,36 +29,31 @@
                                            {:in-chan [:sliding 1]
                                             :out-chan [:buffer 1]
                                             :in-timeout 1000}))
-(sub state-pub :app-state (:in-chan ts-comp))
-(pipe (:out-chan ts-comp) state-in-chan)

 (def state-comp (toolbox/make-component c/make-state c/handle-incoming nil))
+

 (def wc-c-comp (toolbox/single-in-single-out (partial wc-c/init-component 25)
                                              {:in-chan [:sliding 1]
                                               :out-chan [:buffer 1]
                                               :in-timeout 1000}))

-(sub state-pub :app-state (:in-chan wc-c-comp))
-(pipe (:out-chan wc-c-comp) state-in-chan)
-
 (def wc-comp (toolbox/single-in-single-out (partial cloud/init-component 250)
                                              {:in-chan [:sliding 1]
                                               :out-chan [:buffer 1]
                                               :in-timeout 5000}))
+
+(sub state-pub :app-state (:in-chan wc-c-comp))
+(pipe (:out-chan wc-c-comp) state-in-chan)
+
+(sub state-pub :app-state (:in-chan ts-comp))
+(pipe (:out-chan ts-comp) state-in-chan)
+
 (sub state-pub :app-state (:in-chan wc-comp))
 (pipe (:out-chan wc-comp) state-in-chan)

-#_(def state-comp (toolbox/single-in-multiple-out
-                  state/init-component
-                  {:in-chan [:buffer 1]
-                   :out-chans {:state-pub-out [:sliding 1] :qry-out [:buffer 1]}}
-                  #(match % [:app-state _] :state-pub-out :else :qry-out)))
-
 (pipe state-in-chan (:in-chan state-comp))
-;(pipe (-> state-comp :out-chans :qry-out) qry-chan)
 (pipe (:out-chan state-comp) qry-chan)
-;(pipe (-> state-comp :out-chans :state-pub-out) state-pub-chan)
 (pipe (:sliding-out-chan state-comp) state-pub-chan)

 ;;; Initialization of WebSocket communication.


Add colors

Add colors


Refactor to extract question and answer out

--- src/juzi/core.clj
+++ src/juzi/core.clj
@@ -21,6 +21,12 @@
 (defn say [chinese]
   (future (sh "/usr/bin/say" chinese)))

+(defn question [{:keys [en]}]
+  (str "What's Chinese for \"" en "\"?"))
+
+(defn answer [{:keys [pi zh]}]
+  (str pi (when zh (do (say zh) (str " (" zh ")")))))
+
 (defn start []
   (clear-screen)
   (let [cr (ConsoleReader.)]
@@ -28,12 +34,12 @@
     (loop [s (s/make-session (expand-data (load-sources)))]
       (if-let [w (s/next-word s)]
         (let [{:keys [id en pi zh]} w]
-          (println (str "What's Chinese for \"" en "\"?"))
+          (println (question w))
           (println)
           (println "Press any key to see the answer ...")
           (.readCharacter cr)
           (println)
-          (println "Answer:" pi (when zh (do (say zh) (str "(" zh ")"))))
+          (println "Answer:" (answer w))
           (println)
           (println "Were you correct ? [y/n]")
           (let [i (.readCharacter cr)]


fapply docstring updates

fapply docstring updates

--- src/cats/core.cljc
+++ src/cats/core.cljc
@@ -146,9 +146,10 @@
        (p/fmap f fv))))

 (defn fapply
-  "Given function inside af's context and value inside
-  av's context, applies the function to value and return
-  a result wrapped in context of same type of av context.
+  "Given a function wrapped in a monadic context `af`,
+  and a value wrapped in a monadic context `av`,
+  apply the unwrapped function to the unwrapped value
+  and return the result, wrapped in the same context as `av`.

   This function is variadic, so it can be used like
   a Haskell-style left-associative fapply."


Only display deltas if there are some.

Only display deltas if there are some.

--- src/cbfg/core.cljs
+++ src/cbfg/core.cljs
@@ -298,7 +298,7 @@
             deltas ((get (get vis-event-handlers verb) step) vis actx args)]
         (set-el-innerHTML (str el-prefix "-event")
                           (str num-events ": " (last actx) " " verb " " step " " args))
-        (when (and (not (zero? @event-delay)) (not-empty deltas))
+        (when (and (not (zero? @event-delay)) (some #(not (:after %)) deltas))
           (>! render-ch [@vis deltas false])
           (when (> @event-delay 0) (<! (timeout @event-delay)))
           (when (< @event-delay 0) (<! step-ch)))


even more testing

even more testing

--- src/mafia_votecount/scraper/team_liquid.clj
+++ src/mafia_votecount/scraper/team_liquid.clj
@@ -49,13 +49,18 @@
       ((fn [pages] (remove string? pages)))
       ((fn [pages] (map #(first (get % :content)) pages)))))

+(defn parse-int [v]
+   (try
+     (Integer/parseInt v)
+     (catch NumberFormatException e 1)))
+
 (defn- get-page-numbers [content]
   (let [page-number-bar (get-page-number-bar content)
         last-page  (->> (reverse page-number-bar)
                         (filter #(Character/isDigit (first %))) ;; Filter is lazy
-                        (first))
-        last-page-number (if (integer? (Integer/parseInt last-page)) (Integer/parseInt last-page) 1)]
-    (vec (range 1 (inc last-page-number)))))
+                        (first)
+                        (parse-int))]
+    (vec (range 1 (inc last-page)))))

 (defn- has-quote? [part]
   (and (map? (:attrs part))


Resolve issue with PR #228 -- accept either url or stream

- Note that we sometimes have nested with-opens now, but I think it's ok
  - The io/input-stream function will just return its argument if it's
    already an InputStream; it won't create a new InputStream.
  - I think it's fine to close() an InputStream multiple times, which is
    what happens when with-opens are nested the way we do here, eg:

        (with-open [x (io/input-stream url)]
          (with-open [y (io/input-stream x)]
            ...))

    We'd have (identical? x y) => true, so presumably that InputStream
    is being closed twice.

--- boot/pod/src/boot/pod.clj
+++ boot/pod/src/boot/pod.clj
@@ -342,13 +342,14 @@
    [#".*"                   first-wins-merger]])

 (defn merge-duplicate-jar-entry
-  [mergers curr-file new-path new-stream & {:keys [merged-url]}]
+  [mergers curr-file new-path new-stream-or-url & {:keys [merged-url]}]
   (let [merged-url (or merged-url curr-file)]
     (when-let [merger (some (fn [[re v]] (when (re-find re new-path) v)) mergers)]
       (util/dbug "Merging duplicate jar entry (%s)\n" new-path)
       (let [out-file (File/createTempFile (.getName curr-file) nil
                                           (.getParentFile curr-file))]
         (with-open [curr-stream (io/input-stream curr-file)
+                    new-stream  (io/input-stream new-stream-or-url)
                     out-stream  (io/output-stream out-file)]
           (merger curr-stream new-stream out-stream))
         (Files/move (.toPath out-file) (.toPath merged-url)


CMR-657: Modified code to only return score field when score is available.

--- src/cmr/search/results_handlers/reference_results_handler.clj
+++ src/cmr/search/results_handlers/reference_results_handler.clj
@@ -48,7 +48,7 @@
                (x/element :id {} concept-id)
                (x/element :location {} location)
                (x/element :revision-id {} (str revision-id))
-               (x/element :score {} score))))
+               (when score (x/element :score {} score)))))

 (defmethod qs/search-results->response :xml
   [context query results]


Fix #18. Fix shim when loaded using relative src.

Shim now guesses if it was loaded e.g. using src="../shim.js" and uses the same
prefix (../) for script tags it created.
This way shim can be loaded from index.html and posts/foobar.html and
it generates proper relative script tags.

--- src/adzerk/boot_cljs.clj
+++ src/adzerk/boot_cljs.clj
@@ -40,20 +40,38 @@

 (defn- write-src
   [inc]
-  (format "document.write(\"<script src='%s'></script>\");\n" inc))
+  (format "document.write(\"<script src='\" + prefix + \"%s'></script>\");\n" inc))

 (defn- write-body
   [code]
   (format "document.write(\"<script>%s</script>\");\n" code))

+(def ^:private shim-js
+"// boot-cljs shim
+(function() {
+  var shimRegex = new RegExp('(.*)%s$');
+  function findPrefix() {
+    var els = document.getElementsByTagName('script');
+    for (var i = 0; i < els.length; i++) {
+      var match = els[i].getAttribute('src').match(shimRegex);
+      if (match) {
+        return match[1];
+      }
+    }
+    return '';
+  }
+  var prefix = findPrefix();
+%s%s})();
+")
+
 (defn- write-shim!
   [f shim-path incs cljs output-path output-dir]
-  (let [output-dir (replace-path shim-path output-dir)]
-    (spit f "// boot-cljs shim\n")
-    (doseq [inc incs] (spit f (write-src inc) :append true))
-    (spit f (write-src (.getPath (io/file output-dir "goog" "base.js"))) :append true)
-    (spit f (write-src output-path) :append true)
-    (spit f (write-body (apply str (sort (map file->goog cljs)))) :append true)))
+  (let [output-dir (replace-path shim-path output-dir)
+        scripts  (concat incs [(.getPath (io/file output-dir "goog" "base.js")) output-path])]
+    (spit f (format shim-js
+                    (.getName f)
+                    (apply str (map write-src scripts))
+                    (write-body (apply str (sort (map file->goog cljs))))))))

 (defn- cljs-opts!
   [{:keys [output-dir node-target output-to optimizations


[PDOK-2477] removed comment that a end-point /api/delete exists.

--- src/featured_gml/api.clj
+++ src/featured_gml/api.clj
@@ -133,7 +133,7 @@
                (GET "/ping" [] (r/response {:pong (tl/local-now)}))
                (GET "/get/:file" request handle-getjson-req)
                (POST "/xml2json" request (partial handle-xml2json-req cc)))
-             (route/not-found "Featured-gml: Unknown operation. Try /api/info, /api/ping, /api/get, /api/xml2json or /api/delete")))
+             (route/not-found "Featured-gml: Unknown operation. Try /api/info, /api/ping, /api/get, /api/xml2json")))

 (defn wrap-exception-handling
   [handler]


don't add col if it doesn't already exist

--- src/er_cassandra/model/callbacks/distinct_vector_callback.clj
+++ src/er_cassandra/model/callbacks/distinct_vector_callback.clj
@@ -1,6 +1,9 @@
-(ns er-cassandra.model.callbacks.distinct-vector-callback)
+(ns er-cassandra.model.callbacks.distinct-vector-callback
+  (:require
+   [plumbing.core :refer :all]))

 (defn create-distinct-vector-callback
   [col]
   (fn [r]
-    (assoc r col (vec (distinct (get r col))))))
+    (let [v (get r col)]
+      (assoc-when r col (when v (vec (distinct v)))))))


Refactor

Refactor

--- src-cljs/frontend/components/insights/project.cljs
+++ src-cljs/frontend/components/insights/project.cljs
@@ -52,27 +52,42 @@
       (html
        [:div.build-time-visualization]))))

+(defn median-build-time [[build-date builds]]
+  [(time-format/parse build-date) (->> builds
+                                       (map :build_time_millis)
+                                       insights/median)])
+
+(defn daily-median-build-time [builds]
+    (js/console.log (clj->js (->> builds
+       (group-by #(-> % :start_time time-format/parse time/at-midnight str))
+       )))
+  (->> builds
+       (group-by #(-> % :start_time time-format/parse time/at-midnight str))
+       (map median-build-time)))
+
 (defn build-time-line-chart [builds owner]
   (reify
     om/IDidMount
     (did-mount [_]
-      (let [el (om/get-node owner)
-            build-times (map (fn [[build-date builds]]
-                               [build-date (->> builds
-                                                (map :build_time_millis)
-                                                insights/median)])
-                             (group-by #(-> % :start_time time-format/parse time/at-midnight) builds))]
-        (js/c3.generate (clj->js {:bindto el
-                                  :padding {:top 10}
-                                  :data {:x "date"
-                                         :type "spline"
-                                         :columns [(concat ["date"] (map first build-times))
-                                                   (concat ["Median Build Time"] (map last build-times))]}
-                                  :legend {:hide true}
-                                  :grid {:y {:show true}}
-                                  :zoom {:enabled true}
-                                  :axis {:x {:type "timeseries"
-                                             :tick {:format "%m/%d"}}}}))))
+     (let [el (om/get-node owner)
+           build-times (daily-median-build-time builds)]
+       #_(->> build-times
+            (map first)
+            (map str)
+            sort
+            clj->js
+            js/console.log)
+       (js/c3.generate (clj->js {:bindto el
+                                 :padding {:top 10}
+                                 :data {:x "date"
+                                        :type "spline"
+                                        :columns [(concat ["date"] (map first build-times))
+                                                  (concat ["Median Build Time"] (map last build-times))]}
+                                   :legend {:hide true}
+                                    :grid {:y {:show true}}
+                                    :zoom {:enabled true}
+                                    :axis {:x {:type "timeseries"
+                                               :tick {:format "%m/%d"}}}}))))
     om/IRender
     (render [_]
       (html


add pre checks for query fns (#262)

add pre checks for query fns (#262)

--- src/etaoin/api.clj
+++ src/etaoin/api.clj
@@ -518,6 +518,7 @@

 (defmethod find-element-from* :firefox
   [driver el locator term]
+  {:pre [(some? el)]}
   (-> (execute {:driver driver
                 :method :post
                 :path   [:session (:session @driver) :element el :element]
@@ -528,6 +529,7 @@

 (defmethod find-element-from* :safari
   [driver el locator term]
+  {:pre [(some? el)]}
   (-> (execute {:driver driver
                 :method :post
                 :path   [:session (:session @driver) :element el :element]
@@ -538,6 +540,7 @@

 (defmethod find-element-from* :default
   [driver el locator term]
+  {:pre [(some? el)]}
   (-> (execute {:driver driver
                 :method :post
                 :path   [:session (:session @driver) :element el :element]
@@ -549,6 +552,7 @@

 (defmethod find-elements-from* :default
   [driver el locator term]
+  {:pre [(some? el)]}
   (->> (execute {:driver driver
                  :method :post
                  :path   [:session (:session @driver) :element el :elements]
@@ -619,12 +623,14 @@
 (defn child
   "Finds a single element under given root element."
   [driver ancestor-el q]
+  {:pre [(some? ancestor-el)]}
   (let [[loc term] (query/expand driver q)]
     (find-element-from* driver ancestor-el loc term)))

 (defn children
   "Finds multiple elements under given root element."
   [driver ancestor-el q]
+  {:pre [(some? ancestor-el)]}
   (let [[loc term] (query/expand driver q)]
     (find-elements-from* driver ancestor-el loc term)))

@@ -721,6 +727,7 @@
 (defn click-el
   "Click on an element having its system id."
   [driver el]
+  {:pre [(some? el)]}
   (execute {:driver driver
             :method :post
             :path   [:session (:session @driver) :element el :click]}))
@@ -752,6 +759,7 @@
 (defmethods double-click-el
   [:chrome :phantom]
   [driver el]
+  {:pre [(some? el)]}
   (execute {:driver driver
             :method :post
             :path   [:session (:session @driver) :element el :doubleclick]}))
@@ -854,6 +862,7 @@
 (defmethods get-element-size-el
   [:chrome :edge :phantom]
   [driver el]
+  {:pre [(some? el)]}
   (-> (execute {:driver driver
                 :method :get
                 :path   [:session (:session @driver) :element el :size]})
@@ -862,6 +871,7 @@

 (defmethod get-element-size-el :firefox
   [driver el]
+  {:pre [(some? el)]}
   (-> (execute {:driver driver
                 :method :get
                 :path   [:session (:session @driver) :element el :rect]})
@@ -870,6 +880,7 @@

 (defmethod get-element-size-el :safari
   [driver el]
+  {:pre [(some? el)]}
   (-> (execute {:driver driver
                 :method :get
                 :path   [:session (:session @driver) :element el :rect]})
@@ -890,6 +901,7 @@
 (defmethods get-element-location-el
   [:chrome :edge :phantom]
   [driver el]
+  {:pre [(some? el)]}
   (-> (execute {:driver driver
                 :method :get
                 :path   [:session (:session @driver) :element el :location]})
@@ -898,6 +910,7 @@

 (defmethod get-element-location-el :firefox
   [driver el]
+  {:pre [(some? el)]}
   (-> (execute {:driver driver
                 :method :get
                 :path   [:session (:session @driver) :element el :rect]})
@@ -906,6 +919,7 @@

 (defmethod get-element-location-el :safari
   [driver el]
+  {:pre [(some? el)]}
   (-> (execute {:driver driver
                 :method :get
                 :path   [:session (:session @driver) :element el :rect]})
@@ -971,6 +985,7 @@

 (defn- get-element-property-el
   [driver el property]
+  {:pre [(some? el)]}
   (:value (execute {:driver driver
                     :method :get
                     :path   [:session (:session @driver) :element el :property (name property)]})))
@@ -1006,6 +1021,7 @@

 (defn get-element-attr-el
   [driver el attr]
+  {:pre [(some? el)]}
   (:value (execute {:driver driver
                     :method :get
                     :path   [:session (:session @driver) :element el :attribute (name attr)]})))
@@ -1051,6 +1067,7 @@

 (defn- get-element-css-el
   [driver el name*]
+  {:pre [(some? el)]}
   (-> (execute {:driver driver
                 :method :get
                 :path   [:session (:session @driver) :element el :css (name name*)]})
@@ -1100,6 +1117,7 @@
 (defn get-element-inner-html-el
   "Returns element's inner text by its identifier."
   [driver el]
+  {:pre [(some? el)]}
   (:value (execute {:driver driver
                     :method :get
                     :path   [:session (:session @driver) :element el :property :innerHTML]})))
@@ -1120,6 +1138,7 @@
 (defn get-element-tag-el
   "Returns element's tag name by its identifier."
   [driver el]
+  {:pre [(some? el)]}
   (:value (execute {:driver driver
                     :method :get
                     :path   [:session (:session @driver) :element el :name]})))
@@ -1132,6 +1151,7 @@
 (defn get-element-text-el
   "Returns element's inner text by its identifier."
   [driver el]
+  {:pre [(some? el)]}
   (:value (execute {:driver driver
                     :method :get
                     :path   [:session (:session @driver) :element el :text]})))
@@ -1151,6 +1171,7 @@
 (defn- get-element-value-el
   "Low level: returns element's value by its identifier."
   [driver el]
+  {:pre [(some? el)]}
   (:value (execute {:driver driver
                     :method :get
                     :path   [:session (:session @driver) :element el :value]})))
@@ -1877,12 +1898,14 @@

 (defmethod displayed-el? :default ;;TODO it's only for jwp
   [driver el]
+  {:pre [(some? el)]}
   (:value (execute {:driver driver
                     :method :get
                     :path   [:session (:session @driver) :element el :displayed]})))

 (defmethod displayed-el? :safari
   [driver el]
+  {:pre [(some? el)]}
   (cond
     (= (get-element-css-el driver el :display)
        "none")
@@ -1906,7 +1929,9 @@
 (def ^{:doc "Oppsite to `visible?`."}
   invisible? (complement visible?))

-(defn enabled-el? [driver el]
+(defn enabled-el?
+  [driver el]
+  {:pre [(some? el)]}
   (:value (execute {:driver driver
                     :method :get
                     :path   [:session (:session @driver) :element el :enabled]})))
@@ -1937,6 +1962,7 @@

 (defn has-class-el?
   [driver el class]
+  {:pre [(some? el)]}
   (let [classes (get-element-attr-el driver el "class")]
     (cond
       (nil? classes) false
@@ -2321,6 +2347,7 @@
 (defmethod fill-el
   :default
   [driver el text & more]
+  {:pre [(some? el)]}
   (execute {:driver driver
             :method :post
             :path   [:session (:session @driver) :element el :value]
@@ -2329,6 +2356,7 @@
 (defmethod fill-el
   :firefox ;; todo support the old version for :default
   [driver el text & more]
+  {:pre [(some? el)]}
   (execute {:driver driver
             :method :post
             :path   [:session (:session @driver) :element el :value]
@@ -2337,6 +2365,7 @@
 (defmethod fill-el
   :safari
   [driver el text & more]
+  {:pre [(some? el)]}
   (execute {:driver driver
             :method :post
             :path   [:session (:session @driver) :element el :value]
@@ -2404,6 +2433,7 @@

 (defn fill-human-el
   [driver el text opt]
+  {:pre [(some? el)]}
   (let [{:keys [mistake-prob pause-max]
          :or   {mistake-prob 0.1
                 pause-max    0.2}} opt
@@ -2450,6 +2480,7 @@
 (defn clear-el
   "Clears an element by its identifier."
   [driver el]
+  {:pre [(some? el)]}
   (execute {:driver driver
             :method :post
             :path   [:session (:session @driver) :element el :clear]}))


Cosmetics.

Cosmetics.

--- src/flare/core.clj
+++ src/flare/core.clj
@@ -59,9 +59,14 @@
   (clojure.string/join
    " "
    (-> []
-       (cond-> (seq only-in-a) (conj (str "expected to contain: " (pr-str (flatten-when-single only-in-a)) ", but not found.")))
-       (cond-> (seq only-in-b) (conj (str "contained: " (pr-str (flatten-when-single only-in-b)) ", but not expected"))))))
-
+       (cond-> (seq only-in-a)
+               (conj (str "expected to contain: "
+                          (pr-str (flatten-when-single only-in-a))
+                          ", but not found.")))
+       (cond-> (seq only-in-b)
+               (conj (str "contained: "
+                          (pr-str (flatten-when-single only-in-b))
+                          ", but not expected"))))))

 (defrecord SetDiff [only-in-a only-in-b]
   Report
@@ -78,10 +83,16 @@
   (clojure.string/join
    " "
    (-> []
-       (cond-> (seq only-in-a) (conj (str "expected to contain " (pluralize "key" only-in-a) ": "
-                                          (pr-str (flatten-when-single only-in-a)) ", but not found.")))
-       (cond-> (seq only-in-b) (conj (str "contained " (pluralize "key" only-in-b) ": "
-                                          (pr-str (flatten-when-single only-in-b)) ", but not expected"))))))
+       (cond-> (seq only-in-a)
+               (conj (str "expected to contain "
+                          (pluralize "key" only-in-a) ": "
+                          (pr-str (flatten-when-single only-in-a))
+                          ", but not found.")))
+       (cond-> (seq only-in-b)
+               (conj (str "contained "
+                          (pluralize "key" only-in-b) ": "
+                          (pr-str (flatten-when-single only-in-b))
+                          ", but not expected"))))))

 (defrecord MapEntryDiff [only-in-a only-in-b]
   Report
@@ -121,7 +132,6 @@
     (when-not (empty? diffs)
       (MapDiffs. (set diffs)))))

-
 ;; Vector

 (defn report-vector
@@ -138,7 +148,6 @@
                     (map-indexed (fn [i [a b]] (when (not= a b) [i (diff a b)])))
                     (remove nil?)
                     (into {}))))
-

 ;; String


In the process of adding apply-contracts -- name will likely change

--- src/fogus/me/provide.clj
+++ src/fogus/me/provide.clj
@@ -20,7 +20,7 @@

 (defn- funcify [args cnstr]
   (vec (map (fn [e]
-              (if (symbol? e)
+              (if (or (symbol? e) (keyword? e))
                 (list* e args)
                 e))
             cnstr)))
@@ -34,7 +34,7 @@
 (defn- build-contract
   [cnstr]
   (let [[args pre-post-map] cnstr]
-    (list (into '[f] args)
+    (list (into '(f) args)
           pre-post-map
           (list* 'f args))))

@@ -55,3 +55,27 @@
   ([f c] (partial c f))
   ([f c & more]
      (apply with-constraints (with-constraints f c) more)))
+
+
+(defmacro apply-contracts [& contracts]
+  (let [fn-names  (map first contracts)
+        contracts (for [c contracts] (if (vector? (second c)) (list* `contract c) (second c)))]
+    `(do
+      ~@(for [[n# c#] (zipmap fn-names contracts)]
+          (list `alter-var-root (list `var n#)
+                (list `fn '[f c] (list `with-constraints 'f 'c)) c#))
+      nil)))
+
+(comment
+(defn sqr [n]
+  (* n n))
+
+(apply-contracts [sqr [n] number? (not= 0 n) => pos? number?])
+)
+
+
+;; constraint functions and multimethods
+
+(def all-numbers?  #(every? number? %))
+(def all-positive? #(and (all-numbers? %) (every? pos? %)))
+(def all-negative? #(and (all-numbers? %) (every? (complement pos?) %)))


Use wrap-reload so you don't have to manually reload the repl when you make changes

--- src/foreclojure/core.clj
+++ src/foreclojure/core.clj
@@ -6,7 +6,8 @@
         [foreclojure.register]
         [foreclojure.users]
         [ring.adapter jetty]
-        [somnium.congomongo])
+        [somnium.congomongo]
+        [ring.middleware.reload :only [wrap-reload]])
   (:require [compojure.route :as route]
             [compojure.handler :as handler]
             [sandbar.stateful-session :as session]
@@ -41,7 +42,8 @@

 (def app
   (handler/site
-   (session/wrap-stateful-session main-routes)))
+   (session/wrap-stateful-session
+    (wrap-reload #'main-routes '(foreclojure.core)))))

 (defn run []
   (run-jetty (var app) {:join? false :ssl? true :port 8080 :ssl-port 8443


Fixed web error

Fixed web error

--- src/ganja_jedi/ganja.clj
+++ src/ganja_jedi/ganja.clj
@@ -15,15 +15,19 @@
 (defroutes app-routes
   (GET "/" []
        (splash))
+  (GET "/about" []
+       {:status 200
+        :headers {"Content-Type" "text/plain"}
+        :body "About us ..."})
   (ANY "*" []
        (route/not-found (slurp (io/resource "404.html")))))

 (def app
   (wrap-defaults app-routes site-defaults))

-;; (defn -main [& [port]]
-;;   (let [port (Integer. (or port (env :port) 6666))]
-;;     (jetty/run-jetty (handler/site #'app) {:port port :join? false})))
+(defn -main [& [port]]
+  (let [port (Integer. (or port (env :port) 6666))]
+    (jetty/run-jetty (handler/site #'app) {:port port :join? false})))

 ;; For interactive development:
 ;; (.stop server)