Add encoder and decoder protocols.

Add encoder and decoder protocols.

--- src/multicodec/core.clj
+++ src/multicodec/core.clj
@@ -114,3 +114,24 @@
                  (str "Last byte in header is not a newline: "
                       (pr-str (.charAt header (dec (count header))))))))
       (str/trim-newline header))))
+
+
+
+;; ## Codec Protocols
+
+(defprotocol Encoder
+  "An encoder converts values to binary sequences and writes the results to an
+  output stream."
+
+  (encode-to
+    [codec output value]
+    "Write the value as a sequence of bytes to the output stream. Returns the
+    number of bytes written."))
+
+
+(defprotocol Decoder
+  "A decoder reads binary sequences and interpretes them as Clojure values."
+
+  (decode-from
+    [codec input]
+    "Reads bytes from the input stream and returns the read value."))


fix events handling issue when removing remote servers

--- src/node/game/core.cljs
+++ src/node/game/core.cljs
@@ -99,9 +99,15 @@
           (swap! state assoc-in [:corp :servers :remote]
                  (vec (map-indexed
                        (fn [i s]
-                         {:content (for [c (:content s)] (update-in c [:zone] #(assoc (vec %) 2 i)))
-                          :ices (for [c (:ices s)] (update-in c [:zone] #(assoc (vec %) 2 i)))})
-                       (get-in @state [:corp :servers :remote]))))))
+                         (if (< i n) s
+                           {:content (for [c (:content s)] (update-in c [:zone] #(assoc (vec %) 2 i)))
+                            :ices (for [c (:ices s)] (update-in c [:zone] #(assoc (vec %) 2 i)))}))
+                       (get-in @state [:corp :servers :remote]))))
+          (doseq [s (drop n (get-in @state [:corp :servers :remote]))
+                  c (concat (:content s) (:ices s))]
+            (unregister-events state side c)
+            (when-let [events (:events (card-def c))]
+              (register-events state side events c)))))
       moved-card)))

 (defn draw


FIx global range queries.

FIx global range queries.

--- src/onyx/http_query.clj
+++ src/onyx/http_query.clj
@@ -54,10 +54,10 @@

 (defn filter-extents [db wext idx group-id start-time end-time]
   (->> (db/group-extents db idx group-id)
-       (map (partial we/bounds wext))
-       (filter (fn [[start end]]
-                 (and (>= start start-time)
-                      (<= end end-time))))))
+       (filter (fn [extent]
+                 (let [[start end] (we/bounds wext extent)]
+                   (and (>= start start-time)
+                        (<= end end-time)))))))

 (def endpoints
   {{:uri "/network/media-driver"
@@ -268,10 +268,12 @@
                                (catch Throwable _))
                           (get-param request "window-id" :keyword))
                slot-id (get-param request "slot-id" :long)
-               start-time (Long/parseLong (or (get-in request [:query-params "start-time"])
-                                              (str Long/MIN_VALUE)))
-               end-time (Long/parseLong (or (get-in request [:query-params "end-time"])
-                                            (str Long/MAX_VALUE)))
+               start-time (if-let [t (get-in request [:query-params "start-time"])]
+                            (Long/parseLong t)
+                             Double/NEGATIVE_INFINITY)
+               end-time (if-let [t (get-in request [:query-params "end-time"])]
+                          (Long/parseLong t)
+                          Double/POSITIVE_INFINITY)
                store (get @(:state state-store-group) [job-id task slot-id allocation-version])
                {:keys [db state-indices grouped? idx->window]} store
                idx (get state-indices window)
@@ -287,12 +289,12 @@
                    groups (if groups
                             (clojure.edn/read-string groups)
                             (db/groups db))]
-               (println "GROUP" groups)
                {:result {:grouped? grouped?
                          :window (get idx->window idx)
                          :contents (reduce (fn [m group]
                                              (if-let [group-id (db/group-id db group)]
                                                (let [extents (filter-extents db wext idx group-id start-time end-time)]
+                                                 (println "EXTENTS" extents)
                                                  (reduce (fn [m extent]
                                                            (update m
                                                                    group


Removed speak theme

Removed speak theme

Don't like it!

--- build.boot
+++ build.boot
@@ -106,7 +106,7 @@
          :directories #{"src" "resources"}}]
     (comp
      (watch)
-     (speak :theme "ordinance")
+     (speak)
      (with-env
        {:directories #{"sass"}}
        (sass :sass-file "app.scss"


Change lumo invocation

Change lumo invocation

--- build.boot
+++ build.boot
@@ -134,8 +134,8 @@
           (if self-hosted?
             (proc "lumo"
                   "-c" (str "\"" (System/getProperty "fake.class.path") "\"")
-                  ;"-k" "lumo_cache"
-                  "target/mikron/test_runner/node.cljs")
+                  "-k" "lumo_cache"
+                  "src/test/cljs/mikron/test_runner/node.cljs")
             (boot-cljs-test/test-cljs :js-env        :node
                                       :namespaces    cljs-test-namespaces
                                       :optimizations opt
@@ -207,6 +207,7 @@
               "-k" "lumo_cache"
               "-e" (str "\"(require '[mikron.runtime.core :as mikron "
                         ":refer [schema defschema pack unpack gen valid?]])\"")
+              "-v"
               "-r")))

 (deftask generate-docs


Release 0.1.1

Release 0.1.1

--- build.boot
+++ build.boot
@@ -32,7 +32,7 @@
          '[pandeiro.boot-http :refer [serve]])

 (def +project+ 'cljs-audio-utils)
-(def +version+ "0.1.0")
+(def +version+ "0.1.1")

 (bootlaces! +version+ :dont-modify-paths? true)


Update to build with boot 2.rc1; use bootlaces.

--- build.boot
+++ build.boot
@@ -1,34 +1,38 @@
 (set-env!
-  :dependencies '[[org.clojure/clojure "1.6.0" :scope "provided"]
-                  [org.jruby/jruby-complete "1.7.16.1"]]
-  :src-paths    #{"src"}
-  :rsc-paths    #{"resources"})
+  :dependencies   '[[org.clojure/clojure "1.6.0" :scope "provided"]
+                    [org.jruby/jruby-complete "1.7.16.1"]
+                    [adzerk/bootlaces "0.1.5" :scope "test"]])

-  (def +version+ "0.3.0")
+(require '[adzerk.bootlaces :refer :all])
+
+(def +version+ "0.3.0")
+
+(bootlaces! +version+)
+
+;; bootlaces! blindly sets :resource-paths, so we have to set it afterward
+(set-env! :resource-paths #{"src" "resources"})

 (task-options!
-  pom  [:project 'clj.rb
+  pom  {:project 'clj.rb
         :version +version+
         :description "Utils for using JRuby from Clojure"
         :url "https://github.com/tobias/clj.rb"
         :scm {:url "https://github.com/tobias/clj.rb"}
         :license {:name "Apache Software License - v 2.0"
-                  :url "http://www.apache.org/licenses/LICENSE-2.0"}]
-  push [:gpg-sign true
-        :gpg-user-id "toby@tcrawley.org"
-        :repo "clojars"])
+                  :url "http://www.apache.org/licenses/LICENSE-2.0"}})

 (deftask run-tests
   "Run tests"
   []
-  (with-pre-wrap []
-    (set-env! :src-paths #(conj % "test"))
+  (with-pre-wrap fileset
+    (set-env! :resource-paths #(conj % "test"))
     (require 'clojure.test 'clj.rb-test)
     (let [{:keys [fail error] :as result} (eval '(clojure.test/run-tests `clj.rb-test))]
       (when (or (< 0 fail) (< 0 error))
-        (throw (ex-info "Tests failed" result))))))
+        (throw (ex-info "Tests failed" result))))
+    fileset))

 (deftask build
-  "Build and install the artifact."
+  "Run tests; build and install the jar."
   []
-  (comp (run-tests) (pom) (add-src) (jar) (install)))
+  (comp (run-tests) (build-jar)))


fix deps vector

fix deps vector

--- build.boot
+++ build.boot
@@ -3,8 +3,8 @@
 (set-env!
  :source-paths    #{"src/main"}
  :resource-paths  #{"resources"}
+ :dependencies '[[org.clojure/clojurescript   "1.9.216"        :scope "provided"]
                  [org.omcljs/om               "1.0.0-alpha41"  :scope "provided"]
- :dependencies '[[org.clojure/clojurescript   "1.9.216"        :scope "provided"]
                  [com.ladderlife/cellophane   "0.3.5"          :scope "provided"]
                  [com.cognitect/transit-clj   "0.8.288"        :scope "test"]
                  [org.clojure/core.async      "0.2.385"        :scope "test"]


add node_modules on windows?

add node_modules on windows?

--- build.boot
+++ build.boot
@@ -24,6 +24,16 @@

 (import [java.io ByteArrayOutputStream FileInputStream])

+(def windows?
+  (.startsWith (.toLowerCase (System/getProperty "os.name")) "windows"))
+
+(deftask add-node-modules []
+  (with-pre-wrap fileset
+    (let [nm (io/file "node_modules")]
+      (-> fileset
+        (add-resource (io/file ".") :include #{#"^node_modules[\\\/]parinfer"})
+        commit!))))
+
 (deftask testing []
   (set-env! :source-paths #(conj % "test"))
   identity)
@@ -36,6 +46,7 @@
                 (nil? exit?) not)]
     (comp
       (testing)
+      (if windows? (add-node-modules) identity)
       (test-cljs
         :js-env :node
         :namespaces #{'lumo.js-deps-tests 'lumo.repl-tests}
@@ -47,9 +58,6 @@
     (watch)
     (speak)
     (test :exit? false)))
-
-(def windows?
-  (.startsWith (.toLowerCase (System/getProperty "os.name")) "windows"))

 (deftask check-node-modules []
   (with-pass-thru _


Update version

Update version

--- build.boot
+++ build.boot
@@ -1,5 +1,5 @@
 (def project 'rads/kafka.transit)
-(def version "0.1.0")
+(def version "0.2.0-SNAPSHOT")

 (set-env!
   :source-paths #{"src"}


build.boot

build.boot

--- build.boot
+++ build.boot
@@ -27,12 +27,7 @@
         :source-paths #{"src"}
         :filter-namespaces ['thought2.common-imgs]})

-(deftask docs []
-  (comp (codox)
-        (sift :include #{#"doc"}
-              :move {#"^doc/" ""})
-        (target
-         :dir #{"docs"})))
+

 (deftask build-install
   "Build and install the project locally."


add task 'locally', fix task 'monitor'

add task 'locally', fix task 'monitor'

Signed-off-by: Gregg Reynolds <d0f77bc71a9867acdcb4f62f012b858edad79160@norc.org>

--- build.boot
+++ build.boot
@@ -27,11 +27,13 @@
        :license     {"EPL" "http://www.eclipse.org/legal/epl-v10.html"}}
  push {:repo "clojars"})

+(deftask locally
+  "Build and install the project locally."
+  []
+  (comp (pom) (jar) (install)))
+
 (deftask monitor
   "watch etc."
   []
   (comp (watch)
-        (notify :audible true)
-        (pom)
-        (jar)
-        (install)))
+        (notify :audible true)))


Prep v0.0.3 release

Prep v0.0.3 release

--- build.boot
+++ build.boot
@@ -40,7 +40,7 @@
       default-version)))

 (def project 'com.frereth/cp)
-(def version #_"0.0.2" (deduce-version-from-git))
+(def version #_"0.0.3" (deduce-version-from-git))

 ;; TODO: Add a dependency on weald and refactor away the local copy
 ;; of shared.logging.


Start 2.7.1-SNAPSHOT

Start 2.7.1-SNAPSHOT

--- build.boot
+++ build.boot
@@ -43,7 +43,7 @@
 (task-options!
   sift {:include #{#"project.jar$"}}
   pom {:project 'nightcode
-       :version "2.7.0"
+       :version "2.7.1-SNAPSHOT"
        :description "An IDE for Clojure"
        :url "https://github.com/oakes/Nightcode"
        :license {"Public Domain" "http://unlicense.org/UNLICENSE"}}
@@ -69,9 +69,7 @@
     ;; the standard exclusions don't work on windows,
     ;; because we need to use backslashes
     #"(?i)^META-INF\\[^\\]*\.(MF|SF|RSA|DSA)$"
-    #"(?i)^META-INF\\INDEX.LIST$"
-    ;; exclude soundfont file from edna
-    #".*\.sf2$"))
+    #"(?i)^META-INF\\INDEX.LIST$"))

 (deftask build []
   (comp (aot) (pom) (uber :exclude jar-exclusions) (jar) (sift) (target)))


0.1.8 -- make URI matching less strict

0.1.8 -- make URI matching less strict

--- build.boot
+++ build.boot
@@ -5,7 +5,7 @@

 (require '[tailrecursion.boot-useful :refer :all])

-(def +version+ "0.1.7")
+(def +version+ "0.1.8")

 (useful! +version+)


Fix source map paths in development

Fix source map paths in development

That took way too long to figure out

--- build.boot
+++ build.boot
@@ -137,7 +137,6 @@
         (cljs-repl-env)
         (cljs :ids ["js/main"]
               :optimizations :none
-              :source-map true
               :compiler-options {:devcards true
                                  :preloads '[zetawar.dev]
                                  :parallel-build true})


Mejorando mi conocimiento de cats.

Mejorando mi conocimiento de cats.

--- test-lab/cats.clj
+++ test-lab/cats.clj
@@ -5,11 +5,12 @@
               bimap left-map right-map
               unless ap ap-> ap->> as-ap-> curry lift-m lift-a
               ->= ->>= <$> <*> <=< =<< >=> >> >>=
+              as->=
               curry-lift-m
               extract right-map
               ;sequence mapseq forseq filter join  when
-              ]])
-  (require '[cats.builtin])
+              ]] :reload)
+  #_(require '[cats.builtin])
   (require '[cats.monad.maybe :as maybe :refer
              [just nothing cat-maybes from-maybe just? nothing? map-maybe
               maybe->seq maybe? seq->maybe]] :reload)
@@ -46,7 +47,11 @@
 (ap + (just 1) (nothing) (just 2))  ; nothing
 (ap / (just 10) (just 2)) ; just 5
 (ap / (right 10) (left "error!")) ; error!
-(try-either (ap / (right 10) (right 0)))  ; left: divide by zero
+(try-either (/ 10 0))  ; left: divide by zero
+(try-either (/ 10 2))  ; right
+(ap / (right 10) (right 2))
+(ap / (right 10) (right 0))
+

 (fapply (just inc) (just 2))
 (fapply (just inc) (right 3))
@@ -91,3 +96,100 @@
        ]
       (+ a b c))

+;;;;;
+; 20170922
+(comp just inc)
+((comp just inc) 1)
+((comp #(* 2 %) inc) 0)
+
+(just 1)
+
+(defn minc
+  [x]
+  (just (inc x)))
+
+(defn msum
+  [& xs]
+  (just (apply + xs)))
+(msum 1 2 3 4)
+
+
+(minc 2)
+(defn mincn
+  [x]
+  (nothing))
+
+(->= (just 1)
+     minc
+     minc)  ; => just 3
+
+(as->= (just 1) x
+       (mincn x)
+       (minc x)
+       (minc x))  ; => nothing
+
+
+(fapply (just inc) (just 10))
+
+(as->= (just 1) x
+       (fapply (just inc) (just x))
+       (minc x)
+       (minc x))  ; => just 4
+
+(as->= (nothing) x
+       (fapply (just inc) (just x))
+       (minc x))
+
+(as->= (just 1) x
+       (minc x))
+
+(ap + (just 1) (just 2))
+(ap + (just 1) (nothing) (just 2))
+
+
+(fapply (just +) (just 1) (just 2) (just 3))
+(fapply (nothing) (just 1))
+(fapply (just +) (just 1))
+(fapply (just +) (nothing))
+
+(ap-> (just 1)
+      inc
+      inc)
+
+(defn div0
+  [x]
+  (/ x 0))
+
+(ap-> (just 1)
+      inc
+      div0
+      inc)
+
+(ap-> (nothing)
+      inc
+      inc)
+
+
+(defn mget
+  [hs k]
+  (if (nothing? (get hs k))
+    (nothing)
+    (just (get hs k))))
+
+(defn eget
+  [hs k]
+  (if (nothing? (get hs k))
+    (left k)
+    (right (get hs k))))
+
+(defn minc
+  [x]
+  (just (inc x)))
+
+(->= (just {:a 1 :b 2})
+     (mget :c)  ; nothing
+     minc)      ; => nothing
+
+(->= (just {:a 1 :b 2})
+     (mget :b)  ; just 2
+     minc)    ; just 3


Add step* impl for s/merge

Add step* impl for s/merge

--- src/spectrace/trace.cljc
+++ src/spectrace/trace.cljc
@@ -147,6 +147,10 @@
             (get keys key))]
     (step-for-keys state succ fail get-key)))

+(defmethod step* `s/merge [state succ fail]
+  (let [specs (get-in state [:spec :args])]
+    (choose-spec specs state succ fail)))
+
 (defmethod step* `s/cat [state succ fail]
   (step-by-key state succ fail :val-fn nth))


+TODO

+TODO

--- src/babel/reader.clj
+++ src/babel/reader.clj
@@ -119,7 +119,7 @@
         source-expression
         (source-timing-fn (generate source-spec source-model))]
     (let [pairing
-          {:target ((:morph (babel.italiano/medium)) target-expression)
+          {:target ((:morph (babel.italiano/medium)) target-expression) ;; TODO: hard-wired to Italian.
            :pred (unify/strip-refs
                   (unify/get-in target-expression [:synsem :sem :pred]))
            :tense (unify/get-in target-expression [:synsem :sem :tense])


Update util.clj

Update util.clj

--- src/swagger_gen/util.clj
+++ src/swagger_gen/util.clj
@@ -1,7 +1,19 @@
 (ns swagger-gen.util
   (:require
-    [clojure.string :refer [split replace-first lower-case capitalize join]]))
+    [clojure.string :refer
+      [split replace-first lower-case capitalize join]]))

+(defn interpose-map [f sep xs] (->> (map f xs) (interpose sep) (apply str)))
+
+(defn unescape-html
+    "Unescape HTML special entities in mustache templates"
+    [text]
+    (.. ^String text
+      (s/replace "&" "&")
+      (s/replace "<" "<")
+      (s/replace ">" ">")
+      (s/replace """ "\"")))
+
 (defn camelize
   "Convert snake_case string into CamelCase"
   [input-string]


Proper handle observable-like types like Single, Maybe and Completable.

Related issue #42

--- src/beicon/core.cljc
+++ src/beicon/core.cljc
@@ -6,6 +6,8 @@
   #?(:clj  (:import io.reactivex.BackpressureStrategy
                     io.reactivex.Emitter
                     io.reactivex.Flowable
+                    io.reactivex.Completable
+                    io.reactivex.Maybe
                     io.reactivex.Observable
                     io.reactivex.ObservableOnSubscribe
                     io.reactivex.Observer
@@ -39,7 +41,7 @@
 ;; --- Interop Helpers

 #?(:clj
-   (defn as-consumer
+   (defn- as-consumer
      "Wrap the provided function into a Consumer instance."
      ^Consumer
      [f]
@@ -48,7 +50,7 @@
          (f v)))))

 #?(:clj
-   (defn as-action
+   (defn- as-action
      "Wrap the provided function into a Action instance."
      ^Action
      [f]
@@ -57,7 +59,7 @@
          (f)))))

 #?(:clj
-   (defn as-predicate
+   (defn- as-predicate
      "Wrap the provided function into a Predicate instance."
      ^Predicate
      [f]
@@ -66,7 +68,7 @@
          (boolean (f v))))))

 #?(:clj
-   (defn as-function
+   (defn- as-function
      "Wrap the provided function into a Function instance."
      ^Function
      [f]
@@ -75,13 +77,41 @@
          (f v)))))

 #?(:clj
-   (defn as-bifunction
+   (defn- as-bifunction
      "Wrap the provided function into a Function instance."
      ^BiFunction
      [f]
      (reify BiFunction
        (apply [_ v b]
          (f v b)))))
+
+#?(:clj
+   (defn- as-observable
+     "Coerce a object to an observable instance."
+     [ob]
+     (cond
+       (instance? Observable ob) ob
+       (or (instance? Flowable ob)
+           (instance? Single ob)
+           (instance? Maybe ob)
+           (instance? Completable ob)) (.toObservable ob)
+
+       :else
+       (throw (IllegalArgumentException. "object can not be coerced to observable")))))
+
+#?(:clj
+   (defn- as-flowable
+     "Coerce a object to an flowable instance."
+     [ob]
+     (cond
+       (instance? Flowable ob) ob
+       (instance? Observable ob) (.toFlowable ob BackpressureStrategy/BUFFER)
+       (or (instance? Single ob)
+           (instance? Maybe ob)
+           (instance? Completable ob)) (.toFlowable ob)
+
+       :else
+       (throw (IllegalArgumentException. "object can not be coerced to flowable")))))

 (def ^:private noop (constantly nil))

@@ -106,7 +136,11 @@
   "Return true if `ob` is a instance
   of Rx.Observable."
   [ob]
-  (instance? Observable ob))
+  #?(:clj (or (instance? Observable ob)
+              (instance? Single ob)
+              (instance? Maybe ob)
+              (instance? Completable ob))
+     :cljs (instance? Observable ob)))

 (defn disposable?
   "Check if the provided object is disposable (jvm) or subscription (js)."
@@ -117,8 +151,11 @@
 #?(:clj
    (defn flowable?
      "Check if the provided value is Flowable instance."
-     [o]
-     (instance? Flowable o)))
+     [ob]
+     (or (instance? Flowable ob)
+         (instance? Single ob)
+         (instance? Maybe ob)
+         (instance? Completable ob))))

 #?(:clj
    (defn single?
@@ -838,15 +875,28 @@
               (Observable/amb ^Iterable values)))))

 (defn zip
-  "Merges the specified observable sequences or Promises
-  into one observable sequence."
+  "Merges the specified observable sequences or Promises (cljs) into one
+  observable sequence."
   [& items]
   (let [[selector items] (if (ifn? (first items))
                            [(first items) (rest items)]
                            [vector items])
         items (if (vector? items) items (vec items))]
     #?(:cljs (apply Observable.zip (conj items selector))
-       :clj  (Observable/zip ^Iterable items (as-function #(apply selector (seq %)))))))
+       :clj  (let [items (clojure.core/filter identity items)]
+               (cond
+                 (every? observable? items)
+                 (as-> items $
+                   (clojure.core/map as-observable items)
+                   (Observable/zip ^Iterable $ (as-function #(apply selector (seq %)))))
+
+                 (every? flowable? items)
+                 (as-> items $
+                   (clojure.core/map as-flowable items)
+                   (Flowable/zip ^Iterable $ (as-function #(apply selector (seq %)))))
+
+                 :else
+                 (throw (IllegalArgumentException. "items should be a list of observables or flowables")))))))

 (defn concat
   "Concatenates all of the specified observable
@@ -858,13 +908,15 @@
      :clj  (let [more (clojure.core/filter identity more)]
              (cond
                (every? observable? more)
-               (clojure.core/reduce #(Observable/concat %1 %2) more)
+               (->> (clojure.core/map as-observable more)
+                    (clojure.core/reduce #(Observable/concat %1 %2)))

                (every? flowable? more)
-               (clojure.core/reduce #(Flowable/concat %1 %2) more)
+               (->> (clojure.core/map as-flowable more)
+                    (clojure.core/reduce #(Flowable/concat %1 %2)))

                :else
-               (throw (ex-info "Invalid arguments." {}))))))
+               (throw (IllegalArgumentException. "items should be a list of observables or flowables"))))))

 (defn merge
   "Merges all the observable sequences and Promises
@@ -873,9 +925,18 @@
   #?(:cljs (let [more (cljs.core/filter identity more)]
              (cljs.core/reduce #(.merge %1 %2) more))
      :clj  (let [more (clojure.core/filter identity more)]
-             (clojure.core/reduce (fn [a b]
-                                    (Observable/merge a b))
-                                  more))))
+
+             (cond
+               (every? observable? more)
+               (->> (clojure.core/map as-observable more)
+                    (clojure.core/reduce #(Observable/merge %1 %2)))
+
+               (every? flowable? more)
+               (->> (clojure.core/map as-flowable more)
+                    (clojure.core/reduce #(Flowable/merge %1 %2)))
+
+               :else
+               (throw (IllegalArgumentException. "items should be a list of observables or flowables"))))))

 #?(:cljs
    (defn merge-all
@@ -968,10 +1029,29 @@
   single element in the result sequence."
   ([f ob]
    #?(:cljs (.reduce ob #(f %1 %2))
-      :clj  (.reduce ob (as-bifunction f))))
+      :clj  (cond
+              (observable? ob)
+              (-> (.reduce ob (as-bifunction f))
+                  (as-observable))
+
+              (flowable? ob)
+              (-> (.reduce ob (as-bifunction f))
+                  (as-flowable))
+
+              :else (throw (IllegalArgumentException. "`ob` should be observable or flowable")))))
+
   ([f seed ob]
    #?(:cljs (.reduce ob #(f %1 %2) seed)
-      :clj  (.reduce ob seed (as-bifunction f)))))
+      :clj  (cond
+              (observable? ob)
+              (-> (.reduce ob seed (as-bifunction f))
+                  (as-observable))
+
+              (flowable? ob)
+              (-> (.reduce ob seed (as-bifunction f))
+                  (as-flowable))
+
+              :else (throw (IllegalArgumentException. "`ob` should be observable or flowable"))))))

 (defn scan
   "Applies an accumulator function over an observable
@@ -1003,7 +1083,14 @@
    #?(:cljs (.combineLatest ob other f)
       :clj  (let [^Iterable sources (list ob other)
                   ^Function combiner (as-function #(apply f (seq %)))]
-              (Observable/combineLatest sources combiner)))))
+              (cond
+                (every? observable? sources)
+                (Observable/combineLatest sources combiner)
+
+                (every? flowable? sources)
+                (Flowable/combineLatest sources combiner)
+
+                :else (throw (IllegalArgumentException. "only observable or flowable are allowed")))))))

 (defn- unwrap-composite-exception
   [exc]
@@ -1165,7 +1252,9 @@

 (defn transform
   "Transform the observable sequence using transducers."
-  [xform stream]
+  [xform ob]
+  (when-not (observable? ob)
+    (throw (IllegalArgumentException. "Only observables are supported")))
   (letfn [(sink-step [sink]
             (fn
               ([r] (sink end) r)
@@ -1176,9 +1265,9 @@
                            (let [v (xsink nil input)]
                              (when (reduced? v)
                                (xsink @v))))
-                    disposable (on-value stream step)]
-                (on-complete stream #(do (xsink nil)
-                                         (sink end)))
+                    disposable (on-value ob step)]
+                (on-complete ob #(do (xsink nil)
+                                     (sink end)))
                 (fn []
                   (cancel! disposable)))))))


Swapped out incanter in tests; added some wrapped-pca shape tests

--- test/pca_test.clj
+++ test/pca_test.clj
@@ -1,7 +1,8 @@
 (ns pca-test
   (:require [clojure.test :refer :all]
             [polismath.named-matrix :refer :all]
-            [incanter.core :refer :all]
+            [clojure.math.numeric-tower :refer :all]
+            [clojure.core.matrix :as m]
             [polismath.pca :refer :all]))

@@ -11,7 +12,7 @@

 (deftest powerit
   (testing "Should generally work"
-    (let [data (matrix [[ 1 0  0  ]
+    (let [data (m/matrix [[ 1 0  0  ]
                         [-1 1  0.1]
                         [ 0 1  0.1]
                         [ 0 1 -0.1]])
@@ -27,3 +28,17 @@
       (testing "from scratch"
                (is (almost-equal? (pc-from-start [1 1]) expected))))))

+
+(deftest wrapped-pca-test
+  (letfn [(right-shape [data]
+            (let [res (wrapped-pca (m/matrix data) 2)]
+              (and (:center res) (:comps res))))]
+    (testing "Should not fail and have the right shape for for"
+      (testing "1x1"
+        (is (right-shape [[1]])))
+      (testing "1x2"
+        (is (right-shape [[1 0]])))
+      (testing "2x1"
+        (is (right-shape [[1 0]]))))))
+
+


Reshuffle functions in order of calls

Reshuffle functions in order of calls

--- src/tenor/constructs.clj
+++ src/tenor/constructs.clj
@@ -97,6 +97,17 @@
   and musical notes as values."
   (map #(hash-map :pos %, :note (rand-nth scale)) entity))

+(defn generate-piece [measure-count note-count note-value sparseness]
+  "Generate a musical piece with measure-count measures,
+  each of time signature with note-count and note-value."
+  (let [piece (repeatedly
+                measure-count
+                #(segment-measure
+                   (time-signature note-count)
+                   note-value
+                   sparseness))]
+    (string-measures piece note-count)))
+
 (defn generate-entity-map [measure-count note-count
                             & {:keys [note-value sparseness scale]
                                :or {note-value 16
@@ -107,17 +118,6 @@
   (map-entity
     (generate-piece measure-count note-count note-value sparseness)
     scale))
-
-(defn generate-piece [measure-count note-count note-value sparseness]
-  "Generate a musical piece with measure-count measures,
-  each of time signature with note-count and note-value."
-  (let [piece (repeatedly
-                measure-count
-                #(segment-measure
-                   (time-signature note-count)
-                   note-value
-                   sparseness))]
-    (string-measures piece note-count)))

 ;; --- Playback --- ;;


allow project.classpath to contain wildcards for jars

--- src/cake/project.clj
+++ src/cake/project.clj
@@ -12,12 +12,18 @@
 (defn- make-url [file]
   (str "file:" (.getPath file) (if (.isDirectory file) "/" "")))

+(defn- path-files [paths]
+  (mapcat (fn [path]
+            (if-let [[_ path] (re-matches #"(.*)/\*" path)]
+              (fileset-seq {:dir path :includes "*.jar"})
+              [(file path)]))
+          (absorb paths (split (re-pattern File/pathSeparator)))))
+
 (defn classpath []
   (map make-url
-       (concat (map file (into [(System/getProperty "bake.path")
-                                "src/" "src/clj/" "classes/" "resources/" "dev/" "test/" "test/classes/"]
-                               (absorb (get *config* "project.classpath")
-                                       (split (re-pattern File/pathSeparator)))))
+       (concat (map file [(System/getProperty "bake.path")
+                          "src/" "src/clj/" "classes/" "resources/" "dev/" "test/" "test/classes/"])
+               (path-files (get *config* "project.classpath"))
                (fileset-seq {:dir (file "lib")            :includes "*.jar"})
                (fileset-seq {:dir (file "lib/dev")        :includes "*.jar"})
                (fileset-seq {:dir (global-file "lib/dev") :includes "*.jar"}))))


Throw exception on non-default

Throw exception on non-default

--- src/clj/inky/env.clj
+++ src/clj/inky/env.clj
@@ -11,15 +11,17 @@

 (defn env
   "Retrieve environment variables by clojure keyword style.
-   ex. (env :user) ;=> \"zk\""
+   ex. (env :user) ;=> \"zk\". Called w/o default throws an
+  exception."
   [sym & [default]]
   (or (System/getenv (clj->env sym))
-      default))
+      default
+      (throw (Exception. (str "Missing env var " (clj->env sym) ".")))))

 (defn int
   "Retrieve and parse int env var."
   [sym & [default]]
-  (if-let [env-var (env sym)]
+  (if-let [env-var (env sym default)]
     (Integer/parseInt env-var)
     default))

@@ -30,6 +32,6 @@

 (defn bool
   [sym & [default]]
-  (if-let [env-var (env sym)]
+  (if-let [env-var (env sym default)]
     (Boolean/parseBoolean env-var)
     default))


Print cross-validate log.

Print cross-validate log.

--- src/clj_elm/core.clj
+++ src/clj_elm/core.clj
@@ -122,7 +122,7 @@
                         (data/extract-list (:features dataset) a b))
          sample (DataSet. (data/remove-list (:classes dataset) a b)
                           (data/remove-list (:features dataset) a b))]
-     (dorun (println a b))
+     (dorun (println "Data" a "to" b "."))
      (-> (train-model sample L)
          (#(map (fn [feature] (predict % feature)) (:features test)))
          (evaluation (:classes test))))))


[Fix] using ffirst

[Fix] using ffirst

--- src/clj_elm/core.clj
+++ src/clj_elm/core.clj
@@ -28,7 +28,7 @@
 (defn make-ass
   ([d L]
    {:pre [(integer? d) (integer? L)]
-    :post [(coll? %) (coll? (first %)) (float? (first (first %)))]}
+    :post [(coll? %) (coll? (first %)) (float? (ffirst %))]}
    (take L (repeatedly #(make-weights d)))))

 (defn make-bs


dom#classed! should convert keywords into strings.

--- src/cljs/c2/dom.cljs
+++ src/cljs/c2/dom.cljs
@@ -158,7 +158,7 @@
 (defn classed!
   "Add or remove `class` to element based on boolean `classed?`, returning element."
   [el class classed?]
-  (gclasses/enable (->dom el) class classed?))
+  (gclasses/enable (->dom el) (name class) classed?))

 ;;TODO: make these kind of shortcuts macros for better performance.
 (defn add-class! [el class] (classed! el class true))


No need for forward declarations in Go - and it confuses the emitter.

--- src/cljs/go/core.clj
+++ src/cljs/go/core.clj
@@ -59,7 +59,7 @@

 (import-macros clojure.core
  [-> ->> .. assert comment cond
-  declare defn defn-
+  defn defn-
   doto
   extend-protocol fn for
   if-let if-not letfn
@@ -67,6 +67,8 @@
   when when-first when-let when-not while
   cond-> cond->> as-> some-> some->>
   if-some when-some])
+
+(defmacro declare [& names])

 (defmacro defonce [x init]
   `(when-not (exists? ~x)


Fixed typo in sequence-similarity docstring.

--- src/clojush/util.clj
+++ src/clojush/util.clj
@@ -349,7 +349,7 @@
 (defn sequence-similarity
   [sequence1 sequence2]
   "Returns a number between 0 and 1, indicating how similar the sequences are as a normalized,
-  inverted Levenshtein distance, it 1 indicating identity and 0 indicating no similarity."
+  inverted Levenshtein distance, with 1 indicating identity and 0 indicating no similarity."
   (if (and (empty? sequence1) (empty? sequence2))
     1
     (let [dist (levenshtein-distance sequence1 sequence2)


+Sentences about believing,assuming

+Sentences about believing,assuming

--- src/babel/english/demo.cljc
+++ src/babel/english/demo.cljc
@@ -26,6 +26,14 @@
           :synsem {:cat :verb
                    :sem {:pred :think}}}

+         {:demo-name "Sentences about believing"
+          :synsem {:cat :verb
+                   :sem {:pred :believe}}}
+
+         {:demo-name "Sentences about assuming"
+          :synsem {:cat :verb
+                   :sem {:pred :assume}}}
+
          {:synsem {:cat :verb}
           :demo-name "Sentences"}


Fix nucleobase names

Fix nucleobase names

http://en.wikipedia.org/wiki/Nucleobase

--- rna-transcription/rna_transcription_test.clj
+++ rna-transcription/rna_transcription_test.clj
@@ -1,16 +1,16 @@
 (ns rna-transcription.test (:require [clojure.test :refer :all]))
 (load-file "rna_transcription.clj")

-(deftest transcribes-guanosine-to-cytidine
+(deftest transcribes-guanine-to-cytosine
   (is (= "G" (rna-transcription/to-rna "C"))))

-(deftest transcribes-cytidine-to-guanosine
+(deftest transcribes-cytosine-to-guanine
   (is (= "C" (rna-transcription/to-rna "G"))))

-(deftest transcribes-uracil-to-adenosine
+(deftest transcribes-uracil-to-adenine
   (is (= "U" (rna-transcription/to-rna "A"))))

-(deftest it-transcribes-thymidine-to-uracil
+(deftest it-transcribes-thymine-to-uracil
   (is (= "A" (rna-transcription/to-rna "T"))))

 (deftest it-transcribes-all-nucleotides


extract direction->coords helper

extract direction->coords helper

--- src/tile_game/board.cljc
+++ src/tile_game/board.cljc
@@ -53,10 +53,12 @@
   (map (partial coords->tile board)
        (adjacent-coords board (tile->coords board tile))))

+(defn direction->coords [board arg]
+  (coords/add (tile->coords board 0) (dir-delta arg)))
+
 (defn legal-move? [board arg]
   (cond
-    (direction? arg)
-    (bounded-coords? board (coords/add (tile->coords board 0) (dir-delta arg)))
+    (direction? arg) (bounded-coords? board (direction->coords board arg))
     :else (boolean (some #{arg} (adjacent-tiles board 0)))))

 (defn slide-tile [board tile]
@@ -69,8 +71,7 @@
       board)))

 (defn slide-direction [board direction]
-  (let [current-pos (tile->coords board 0)
-        new-pos (coords/add (dir-delta direction) current-pos)]
+  (let [new-pos (direction->coords board direction)]
     (if (bounded-coords? board new-pos)
       (slide-tile board (coords->tile board new-pos))
       board)))


Ensuring we get a correct epoch count even when the network doesn't update.

--- experiment/src/cortex/experiment/train.clj
+++ experiment/src/cortex/experiment/train.clj
@@ -72,7 +72,7 @@
         {:keys [best-network? network]} test-results]
     (if best-network?
       (save-network network network-filename)
-      old-network)))
+      (assoc old-network :epoch-count (get new-network :epoch-count)))))

 (defn backup-trained-network


working on encoding to source maps from our internal rep - should be able to round trip the maps produced by closre compiler

--- src/clj/cljs/source_map.clj
+++ src/clj/cljs/source_map.clj
@@ -2,6 +2,7 @@
   (:require [clojure.java.io :as io]
             [clojure.string :as string]
             [clojure.data.json :as json]
+            [clojure.set :as set]
             [clojure.pprint :as pp]
             [cljs.source-map.base64-vlq :as base64-vlq]))

@@ -75,13 +76,58 @@
              (recur (inc gline) (next lines) (assoc relseg 0 0) result))
            result)))))

+(defn encode-cols [vs source-idx line col names->idx name-idx]
+  (loop [vs (seq vs) lastseg nil cols-segs []]
+    (if vs
+      (let [v (first vs)
+            seg [{:gcol v} source-idx line col]
+            seg (if-let [name (:name seg)]
+                  (let [idx (if-let [idx (get names->idx name)]
+                              idx
+                              (let [cidx @name-idx]
+                                (swap! names->idx assoc name cidx)
+                                (swap! name-idx inc)
+                                cidx))]
+                    (conj seg idx))
+                  seg)
+            col-seg (if lastseg
+                      (into [] (map - seg lastseg))
+                      seg)]
+        (recur (next vs) col-seg (conj (base64-vlq/encode col-seg) cols-segs)))
+      cols-segs)))
+
+(defn encode-source [lines segs source-idx names->idx name-idx]
+  (loop [lines (seq lines) segs segs]
+    (if lines
+      (let [[line cols] (first lines)
+            segs
+            (loop [cols (seq cols) segs segs]
+              (if cols
+                (let [[col vs] (first cols)
+                      col-segs (encode-cols vs source-idx line col names->idx name-idx)]
+                  (recur (next cols) (conj segs col-segs)))
+                segs))]
+        (recur (next lines) segs))
+      segs)))
+
 (defn encode [m opts]
-  (let [source-map {"version" 3
-                    "file" (:file opts)
-                    "lineCount" (:lines opts)
-                    "mappings" nil
-                    "names" nil}]
-    (json/write-str source-map)))
+  (let [names->idx (atom {})
+        name-idx   (atom 0)
+        segs (loop [sources (seq m) source-idx 0 segs []]
+               (if sources
+                 (let [[source lines] (first sources)
+                       segs (encode-source lines segs source-idx names->idx name-idx)]
+                   (recur (next sources) (inc source-idx) segs))
+                 segs))]
+    (json/write-str
+     {"version" 3
+      "file" (:file opts)
+      "sources" (into [] (keys m))
+      "lineCount" (:lines opts)
+      "mappings" (->> segs
+                   (map #(string/join "," (apply str %)))
+                   (string/join ";"))
+      "names" (into [] (map (set/map-invert @names->idx) (range (count @names->idx))))})))

 (defn merge-source-maps
   ([cljs-map closure-map] (merge-source-maps cljs-map closure-map 0))


remove debug print of req

remove debug print of req

--- src/clj/closerve/server.clj
+++ src/clj/closerve/server.clj
@@ -67,7 +67,6 @@

       (or get-result
           (do (prn (str "use handler func for " path))
-              (prn req)
               (handler req))))))
 ;;;;


Fixes `can-be-advanced?` to correctly handle Haas Arcology AI.

--- src/clj/game/core-flags.clj
+++ src/clj/game/core-flags.clj
@@ -120,7 +120,11 @@
   "Returns true if the card can be advanced"
   [card]
   (or (card-is? card :advanceable :always)
+      ;; e.g. Tyrant, Woodcutter
       (and (card-is? card :advanceable :while-rezzed)
            (rezzed? card))
+      ;; e.g. Haas Arcology AI
+      (and (card-is? card :advanceable :while-unrezzed)
+           (not (rezzed? card)))
       (and (card-is? card :type "Agenda")
            (installed? card))))


Undo last temp

Undo last temp

--- src/clj_crud/migrations.clj
+++ src/clj_crud/migrations.clj
@@ -72,8 +72,7 @@
                  db
                  "ALTER TABLE accounts
                    ADD admin INT default 0"))
-          :down (fn [db] nil)
-          #_(fn [db]
+          :down (fn [db]
                   (jdbc/db-do-commands
                    db
                    "ALTER TABLE accounts


Remove wordy calculation

Remove wordy calculation

--- src/cljam/util/sam_util.clj
+++ src/cljam/util/sam_util.clj
@@ -127,19 +127,19 @@
   (let [end (dec end)]
     (cond
      (= (bit-shift-right beg 14) (bit-shift-right end 14))
-     (+ (/ (dec (bit-shift-left 1 15)) 7) (bit-shift-right beg 14))
+     (+ 4681 (bit-shift-right beg 14))

      (= (bit-shift-right beg 17) (bit-shift-right end 17))
-     (+ (/ (dec (bit-shift-left 1 12)) 7) (bit-shift-right beg 17))
+     (+ 585 (bit-shift-right beg 17))

      (= (bit-shift-right beg 20) (bit-shift-right end 20))
-     (+ (/ (dec (bit-shift-left 1 9)) 7) (bit-shift-right beg 20))
+     (+ 73 (bit-shift-right beg 20))

      (= (bit-shift-right beg 23) (bit-shift-right end 23))
-     (+ (/ (dec (bit-shift-left 1 6)) 7) (bit-shift-right beg 23))
+     (+ 9 (bit-shift-right beg 23))

      (= (bit-shift-right beg 26) (bit-shift-right end 26))
-     (+ (/ (dec (bit-shift-left 1 3)) 7) (bit-shift-right beg 26))
+     (+ 1 (bit-shift-right beg 26))

      :else 0)))


Working repl-based parser

Working repl-based parser

--- src/cljs/demtools/core.cljs
+++ src/cljs/demtools/core.cljs
@@ -56,20 +56,29 @@
           (fn [result] (:value result)))))

 (defmethod read "repl"
-  [{:keys [state ast] :as env} k {:keys [:repl/input] :as data}]
+  [{:keys [state ast] :as env} k {:keys [:repl/input :repl/packets] :as data}]
   (case k
     :repl/output
     (let [old-value (get @state k "Loading...")]
+      (js/console.log "hi" "from" input (count (:packets @state)))
       {:value (read-expr input)})))

 (defmethod read "packets"
-  [{:keys [state ast] :as env} k {:keys [idx offset limit]}]
+  [{:keys [state ast] :as env} k {:keys [idx offset limit repl-input]}]
   (case k
     :packets/packet
     {:value (when idx (nth (get @state :packets) idx))}

     :packets/count
     {:value (-> @state :packets count)}
+
+    :packets/repl-output
+    (let [x (read-expr repl-input)]
+      {:value
+       (if (fn? x)
+         (into [] x (:packets @state))
+         x)})
+

     :packets/slice
     (let [packets (get @state :packets)]
@@ -285,6 +294,7 @@
          '[:limit :header :parser-state
            (:packets/packet {:idx ?selected-idx})
            (:packets/slice {:offset ?offset :limit 40})
+           (:packets/repl-output {:repl-input ?repl-input})
            :packets/count
            (:repl/output {:repl/input ?repl-input})
            :file/results
@@ -296,7 +306,8 @@
           props (om/props this)
           {:keys [header limit results parser-state
                   repl/output
-                  packets/packet]} props
+                  packets/packet
+                  packets/repl-output]} props

           packets-count (:packets/count props)
           packets (:packets/slice props)]
@@ -312,7 +323,6 @@
                   (om/update-query!
                    this
                    (fn [s] (assoc-in s [:params :repl-input] new-value)))))})
-        repl-input
         (when packets
           (dom/p nil
                  (str "Loaded " packets-count " packets. " parser-state)))
@@ -349,9 +359,12 @@
                   #js {:width (- 800 150)
                        :header (jsx Cell #js {} "Data")
                        :cell (data-cell offset packets)}))
-        (when output (str "Repl output: " (with-out-str (pprint output))))
+        (when repl-output
+          (str "Packet repl output: " (with-out-str (pprint repl-output))))
         (when packet
-          (dom/div nil (js/JSON.stringify packet)))))))
+          (dom/div nil
+            (dom/h2 "Packet")
+            (js/JSON.stringify packet)))))))

 (def root (om/factory RootComponent))


Attempt to wire in loading page (unsuccessfully)

--- src/cljs/om_sente/core.cljs
+++ src/cljs/om_sente/core.cljs
@@ -45,7 +45,8 @@

 (defmethod handle-event :session/state
   [[_ state] app owner]
-  (om/update! app [:session/state] state))
+  (js/alert (str "session/state: " (name state)))
+  (om/set-state! owner :session/state state))

 (defmethod handle-event :auth/fail
   [_ app owner]
@@ -54,7 +55,7 @@
 (defmethod handle-event :auth/success
   [_ app owner]
   (om/update! app [:notify/error] nil)
-  (om/update! app [:session/state] :secure))
+  (om/set-state! owner :session/state :secure))

 (defn event-loop [app owner]
   (go (loop []
@@ -96,25 +97,38 @@
                              (dom/button #js {:onClick #(login % app owner)}
                                         "Login"))))))

+(defn test-session [owner]
+  (when (= :unknown (om/get-state owner :session/state))
+    (js/alert "will-mount send session/status query")
+    (chsk-send! [:session/status])))
+
 (defn app-view [app owner]
   (reify
+    om/IInitState
+    (init-state [this]
+      {:session/state :unknown})
     om/IWillMount
     (will-mount [this]
-                (event-loop app owner)
-                (when (= :unknown (:session/state app))
-                  (js/alert "will-mount send session/status query")
-                  (chsk-send! [:session/status])))
-    om/IRender
-    (render [this]
-            (js/alert "render app")
-            (if (= :secure (:session/state app))
-              (dom/div nil
-                       (dom/h1 nil "Test Sente")
-                       (om/build field-view app {:opts {:name "data"}})
-                       (om/build data-view app {}))
-              (om/build login-view app {})))))
+      (event-loop app owner))
+    om/IDidMount
+    (did-mount [this]
+      (test-session owner))
+    om/IRenderState
+    (render-state [this state]
+      (case (:session/state state)
+        :secure
+        (dom/div nil
+                 (dom/h1 nil "Test Sente")
+                 (om/build field-view app {:opts {:name "data"}})
+                 (om/build data-view app {}))
+        :open
+        (om/build login-view app {})
+        :unknown
+        (dom/div nil "Loading...")
+        ;;(om/build login-view app {})
+        ))))

-(def app-state (atom {:session/state :unknown}))
+(def app-state (atom {}))

 (om/root app-view
          app-state


add debug

add debug

--- src/cljs/re_dnd/events.cljs
+++ src/cljs/re_dnd/events.cljs
@@ -257,6 +257,14 @@
         drop-zones-being-hit? :dnd/get-colliding-drop-zone-and-index}
        [_ source-draggable-id source-drop-zone-id]]
    (debug drop-zones-being-hit?)
+   (debug "dispatches: "
+          (for [[drop-zone-id [[dropped-element-id index]]] drop-zones-being-hit?]
+            (let [options                  (get-in db [:dnd/state :drop-zone-options drop-zone-id])
+                  drag-target-hit-dispatch (into (:drop-dispatch options)
+                                                 [[source-drop-zone-id source-draggable-id]
+                                                  [drop-zone-id dropped-element-id index]])]
+              drag-target-hit-dispatch)))
+
    {:db         (set-all-draggables-to-idle db)
     :dispatch-n (for [[drop-zone-id [[dropped-element-id index]]] drop-zones-being-hit?]
                   (let [options                  (get-in db [:dnd/state :drop-zone-options drop-zone-id])


Add opensubtitles to welcome text

Add opensubtitles to welcome text

--- src/cljs/subman/search.cljs
+++ src/cljs/subman/search.cljs
@@ -47,11 +47,16 @@
                               [:p "We indexing "
                                [:a {:href "http://www.addic7ed.com/"
                                     :target "_blank"} "addic7ed.com"]
+                               ", "
+                               [:a {:href "http://www.opensubtitles.org/"
+                                    :target "_blank"} "www.opensubtitles.org"]
                                " and "
                                [:a {:href "http://www.podnapisi.net/"
                                     :target "_blank"} "podnapisi.net"]
                                "."]
-                              [:p "Total indexed subtitles count: " @total-count]
+                              [:p "Total indexed subtitles count: "
+                               @total-count
+                               "."]
                               [:a {:href "https://github.com/nvbn/subman"
                                    :target "_blank"}
                                [:i.fa.fa-github] " github"]]


Fix typo

Fix typo

--- src/clojush/meta_errors.clj
+++ src/clojush/meta_errors.clj
@@ -198,7 +198,7 @@
       (if (< (count hist) 2)
         0
         (if (some (fn [[new-err old-err]]
-                    (< new-err older-error))
+                    (< new-err older-err))
                   (map vector (first hist) (second hist)))
           0
           1)))))


Tweak hardocded resilience

Tweak hardocded resilience

--- src/clojush/meta_errors.clj
+++ src/clojush/meta_errors.clj
@@ -163,12 +163,12 @@
     (throw
      (Exception.
       ":print-history must be true for :resilience"))
-    (let [hist (take 3 (:history ind))]
+    (let [hist (take 4 (:history ind))]
       (if (< (count hist) 2)
         0
         (if (> (/ (count (distinct hist))
                   (count hist))
-               1/2)
+               1/4)
           0
           1)))))


upgrade to boot 2.7.1

upgrade to boot 2.7.1

Signed-off-by: Gregg Reynolds <d0f77bc71a9867acdcb4f62f012b858edad79160@norc.org>

--- tasklib/build.boot
+++ tasklib/build.boot
@@ -9,8 +9,8 @@
                 #_["maven-central" "http://mvnrepository.com"]
                 "central" "http://repo1.maven.org/maven2/"}
  :dependencies   '[[org.clojure/clojure "1.8.0" :scope "provided"]
-                   [boot/core "2.6.0-SNAPSHOT" :scope "provided"]
-                   [boot/pod "2.6.0-SNAPSHOT" :scope "provided"]
+                   [boot/core "2.7.1" :scope "provided"]
+                   [boot/pod "2.7.1" :scope "provided"]
                    [me.raynes/fs "1.4.6"]
                    [stencil "0.5.0"]
                    [adzerk/boot-test "1.0.7" :scope "test"]


Made hashCode of Lattice to be the hashCode of the base-set.

This seems better to me than constantly returning 0.

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

--- src/conexp/fca/lattices.clj
+++ src/conexp/fca/lattices.clj
@@ -28,7 +28,7 @@
 		  (order-other [x y]))))))
   (hashCode []
     ;; can't think of a better way ...
-    0))
+    (hash base-set)))

 (defn base-set
   "Returns the base set of lattice."


Tweaks to the generator

Tweaks to the generator

--- src/copycat_jepsen/core.clj
+++ src/copycat_jepsen/core.clj
@@ -177,28 +177,35 @@
 (defn write-gen   [_ _] {:type :invoke, :f :write, :value (rand-int 5)})
 (defn cas-gen [_ _] {:type :invoke, :f :cas, :value [(rand-int 5) (rand-int 5)]})

+(defn recover
+  "A generator which stops the nemesis and allows some time for recovery."
+  []
+  (gen/nemesis
+    (gen/once {:type :info, :f :stop})))
+
+(defn read-once
+  "A generator which reads exactly once."
+  []
+  (gen/clients
+    (gen/once {:type :invoke, :f :read})))
+
 (defn std-gen
   "Takes a client generator and wraps it in a typical schedule and nemesis causing failover."
   [gen]
   (gen/phases
     (->> gen
          (gen/nemesis
-           (gen/seq (cycle [(gen/sleep 2)
+           (gen/seq (cycle [(gen/sleep 5)
                             {:type :info :f :start}
                             (gen/sleep 10)
                             {:type :info :f :stop}])))
          (gen/time-limit 60))
-    ; Recover
-    (gen/nemesis
-      (gen/once {:type :info :f :stop}))
-    ; Wait for resumption of normal ops
-    (gen/clients
-      (->> gen
-           (gen/time-limit 5)))))
+    (recover)
+    (read-once)))

 ; Tests

-(defn copycat-test
+(defn- base-test
   "Returns a map of base test settings"
   [name]
   (let [base-test tests/noop-test
@@ -208,8 +215,7 @@
             :os       debian/os
             :db       (db "1.0" node-set)
             :model   (model/cas-register)
-            :checker   (checker/compose {:html timeline/html
-                                         :linear checker/linearizable})
+            :checker   (checker/compose {:linear checker/linearizable})
             :nemesis  (nemesis/partition-random-halves)
             :ssh      {:private-key-path "/home/vagrant/.ssh/id_rsa"}
             :node-set node-set})))
@@ -217,10 +223,9 @@
 (defn cas-register-test
   "Returns a map of jepsen test configuration for testing cas"
   []
-  (let [base-test (copycat-test "cas")]
+  (let [base-test (base-test "cas")]
     (merge base-test
            {:client    (cas-register-client (:node-set base-test))
-            :generator (->> [read-gen write-gen cas-gen cas-gen cas-gen]
-                            gen/mix
-                            (gen/delay 1)
-                            std-gen)})))+            :generator  (->> gen/cas
+                             (gen/delay 1/4)
+                             std-gen)})))


comment out print cpu state

comment out print cpu state

Signed-off-by: Yen-Chin Lee <082d453d72dce940e12089a4ad48b97cfe1f3ec4@gmail.com>

--- src/emulator_4917/core.cljc
+++ src/emulator_4917/core.cljc
@@ -166,7 +166,7 @@

 (defn run [command]
   (let [cpu (execute command)]
-    (print cpu)
+    ;; (print cpu)
     (recur cpu)))

 (defn to-4bit-array


CMR-2939 Fix mock urs availability endpoint route

--- mock-echo-app/src/cmr/mock_echo/api/urs.clj
+++ mock-echo-app/src/cmr/mock_echo/api/urs.clj
@@ -134,7 +134,7 @@
   (routes
     (context "/urs" []
       ;;availability endpoint
-      (GET "/" [] {:200})
+      (GET "/" [] {:status 200})

       (POST "/login" {:keys [request-context body] :as request}
         (assert-urs-basic-auth-info request)


launched the winning treatment of the useage queue upsell test

--- src-cljs/frontend/components/build_head.cljs
+++ src-cljs/frontend/components/build_head.cljs
@@ -39,13 +39,6 @@
       ;; less than 10 seconds waiting for additional containers (our fault)
       (< run-queued-ms 10000 usage-queued-ms))))

-(defn additional-containers-offer [plan build]
-  [:p#additional_containers_offer
-   "Too much waiting? You can " [:a {:href (routes/v1-org-settings-subpage {:org (:org_name plan)
-                                                                            :subpage "containers"})}
-                                 "add more containers"]
-   " and finish even faster."])
-
 (defn new-additional-containers-offer [plan build]
   (let [run-phrase (if (build-model/finished? build)
                      "ran"
@@ -105,9 +98,7 @@

                (om/build builds-table/builds-table builds {:opts {:show-actions? true}})))
             (when (show-additional-containers-offer? plan build)
-              (if (om/get-shared owner [:ab-tests :new_usage_queued_upsell])
-                (new-additional-containers-offer plan build)
-                (additional-containers-offer plan build)))]))))))
+                (new-additional-containers-offer plan build))]))))))

 (defn build-queue-v2 [data owner]
   (reify


That never existed in VC

That never existed in VC

--- src/grimoire/api.clj
+++ src/grimoire/api.clj
@@ -5,7 +5,6 @@
   different datastores should only need to tweak this namespace."
   (:refer-clojure :exclude [isa?])
   (:require [grimoire.util :as util]
-            [grimoire.types :refer :all]
             [clojure.java.io :as io]
             [clojure.string :as string]
             [clj-semver.core :as semver]))


A touch of documentation

A touch of documentation

--- src/such/relational.clj
+++ src/such/relational.clj
@@ -245,6 +245,15 @@
 (defn combined-index-on
   "Create an index that maps directly from values in the starting index to values
    in the last of the list of indexes, following keys to move from index to index.
+   Example:
+
+      (let [index:countries-by-person-id (subject/combined-index-on index:rulership-by-person-id
+                                                                    :country_code
+                                                                    index:country-by-country-code)]
+        (subject/index-select 1 :using index:countries-by-person-id :keys [:gdp])
+        => [{:gdp 1690}])
+
+   (See ..someplace.. for details..)
   "
   {:arglists '([starting-index foreign-key next-index ...])}
   [starting-index & path-pairs]


Added FIXME because of a bug

Added FIXME because of a bug

--- src/lobos/config.clj
+++ src/lobos/config.clj
@@ -2,7 +2,9 @@
   (:use [lobos.connectivity]
         [heroku-database-url-to-jdbc.core]))

-(defn db [] (or (korma-connection-map (System/getenv "DATABASE_URL"))
+(defn db []
+;; FIXME korma-connection-map throws NPE if DATABASE_URL is not set
+  (or (korma-connection-map (System/getenv "DATABASE_URL"))
               {:classname   "org.postgresql.Driver"
                :subprotocol "postgresql"
                :subname     "//localhost:5432/barmap"}))


Make sure the iso ends up inside the archiving spool dir

--- src/mdr2/archive.clj
+++ src/mdr2/archive.clj
@@ -116,12 +116,17 @@

 (defn copy-files
   "Copy a production to the archive spool dir"
+  ;; FIXME: this fails if there is already an archiving in progress
+  ;; because it will create another copy inside the already existing
+  ;; dam directory
   [{:keys [path iso-path] :as production}]
-  (let [archive-path (container-path production)]
+  (let [archive-path (container-path production)
+        iso-archive-name (str (container-id production) ".iso")
+        iso-archive-path (.getPath (file archive-path iso-archive-name))]
     ;; if the production has an iso archive that, otherwise just
     ;; archive the raw unencoded files
     (if iso-path
-      (fs/copy+ iso-path archive-path)
+      (fs/copy+ iso-path iso-archive-path)
       (fs/copy-dir path archive-path)))
   production)


Loosen up function schema: use ifn?

Loosen up function schema: use ifn?

--- src/onyx/schema.cljc
+++ src/onyx/schema.cljc
@@ -10,7 +10,7 @@

 (def Function
   (s/either (s/pred var? 'var?)
-            (s/pred fn? 'fn?)))
+            (s/pred ifn? 'ifn?)))

 (def TaskName
   (s/pred (fn [v]


prevent repeated requires in dispatch function

--- src/useful/dispatch.clj
+++ src/useful/dispatch.clj
@@ -13,7 +13,8 @@
   namespace and function to call."
   [dispatch-fn & options]
   (let [{:keys [hierarchy wrap default]} (into-map options)
-        wrap (or wrap identity)]
+        wrap    (or wrap identity)
+        require (memoize require)]
     (fn [& args]
       (let [fname   (apply dispatch-fn args)
             default (or default


Added back sine cluster.

Added back sine cluster.

--- test/onyx/peer/simulant/sine_cluster_sim.clj
+++ test/onyx/peer/simulant/sine_cluster_sim.clj
@@ -9,219 +9,219 @@
             [onyx.queue.hornetq-utils :as hq-util]
             [onyx.api]))

-;; (def cluster (atom []))
-
-;; (def in-queue (str (java.util.UUID/randomUUID)))
-
-;; (def out-queue (str (java.util.UUID/randomUUID)))
-
-;; (def n-messages 100000)
-
-;; (def batch-size 1320)
-
-;; (def echo 1000)
-
-;; (def hornetq-host "localhost")
-
-;; (def hornetq-port 5445)
-
-;; (def hq-config {"host" hornetq-host "port" hornetq-port})
-
-;; (hq-util/write-and-cap! hq-config in-queue (map (fn [x] {:n x}) (range n-messages)) echo)
-
-;; (defn my-inc [{:keys [n] :as segment}]
-;;   (assoc segment :n (inc n)))
-
-;; (defn create-multi-births [executor t k]
-;;   (mapcat
-;;    (constantly
-;;     [[{:db/id (d/tempid :test)
-;;        :agent/_actions (u/e executor)
-;;        :action/atTime t
-;;        :action/type :action.type/register-sine-peer}]])
-;;    (range k)))
-
-;; (defn create-multi-deaths [executor t k]
-;;   (mapcat
-;;    (constantly
-;;     [[{:db/id (d/tempid :test)
-;;        :agent/_actions (u/e executor)
-;;        :action/atTime t
-;;        :action/type :action.type/unregister-sine-peer}]])
-;;    (range k)))
-
-;; (defn generate-sine-scaling-data [test executor]
-;;   (let [model (-> test :model/_tests first)
-;;         limit (:test/duration test)
-;;         length (:model/sine-length model)
-;;         rate (:model/peer-rate model)
-;;         reps (:model/sine-reps model)
-;;         height (:model/peek-peers model)
-;;         start (:model/sine-start model)
-;;         end (+ start length)
-;;         unit (/ (* reps Math/PI) length)
-;;         wave (map (fn [x] (int (* height (Math/sin (* unit x)))))
-;;                   (range 0 (+ end rate) rate))
-;;         deltas (map (fn [[a b]] (- b a)) (partition 2 1 wave))]
-;;     (mapcat (fn [[t delta]] (if (>= delta 0)
-;;                              (create-multi-births executor t delta)
-;;                              (create-multi-deaths executor t (Math/abs delta))))
-;;             (map vector (range start end rate) deltas))))
-
-;; (defn create-sine-cluster-test [conn model test]
-;;   (u/require-keys test :db/id :test/duration)
-;;   (-> @(d/transact conn [(assoc test
-;;                            :test/type :test.type/sine-cluster
-;;                            :model/_tests (u/e model))])
-;;       (u/tx-ent (:db/id test))))
-
-;; (defn create-executor [conn test]
-;;   (let [tid (d/tempid :test)
-;;         result @(d/transact conn
-;;                             [{:db/id tid
-;;                               :agent/type :agent.type/executor
-;;                               :test/_agents (u/e test)}])]
-;;     (d/resolve-tempid (d/db conn) (:tempids result) tid)))
-
-;; (defmethod sim/create-test :model.type/sine-cluster
-;;   [conn model test]
-;;   (let [test (create-sine-cluster-test conn model test)
-;;         executor (create-executor conn test)]
-;;     (u/transact-batch conn (generate-sine-scaling-data test executor) 1000)
-;;     (d/entity (d/db conn) (u/e test))))
-
-;; (defmethod sim/create-sim :test.type/sine-cluster
-;;   [sim-conn test sim]
-;;   (-> @(d/transact sim-conn (sim/construct-basic-sim test sim))
-;;       (u/tx-ent (:db/id sim))))
-
-;; (def sim-uri (str "datomic:mem://" (d/squuid)))
-
-;; (def sim-conn (sim-utils/reset-conn sim-uri))
-
-;; (sim-utils/load-schema sim-conn "simulant/schema.edn")
-
-;; (sim-utils/load-schema sim-conn "simulant/coordinator-sim.edn")
-
-;; (def id (str (java.util.UUID/randomUUID)))
-
-;; (def datomic (str "datomic:mem://" id))
-
-;; (def coord-opts
-;;   {:datomic-uri datomic
-;;    :hornetq-host hornetq-host
-;;    :hornetq-port hornetq-port
-;;    :zk-addr "127.0.0.1:2181"
-;;    :onyx-id id
-;;    :revoke-delay 2000})
-
-;; (def peer-opts {:hornetq-host hornetq-host
-;;                 :hornetq-port hornetq-port
-;;                 :zk-addr "127.0.0.1:2181"
-;;                 :onyx-id id})
-
-;; (def catalog
-;;   [{:onyx/name :in
-;;     :onyx/direction :input
-;;     :onyx/consumption :concurrent
-;;     :onyx/type :queue
-;;     :onyx/medium :hornetq
-;;     :hornetq/queue-name in-queue
-;;     :hornetq/host hornetq-host
-;;     :hornetq/port hornetq-port
-;;     :onyx/batch-size batch-size}
-
-;;    {:onyx/name :inc
-;;     :onyx/fn :onyx.peer.simulant.sine-cluster-sim/my-inc
-;;     :onyx/type :transformer
-;;     :onyx/consumption :concurrent
-;;     :onyx/batch-size batch-size}
-
-;;    {:onyx/name :out
-;;     :onyx/direction :output
-;;     :onyx/consumption :concurrent
-;;     :onyx/type :queue
-;;     :onyx/medium :hornetq
-;;     :hornetq/queue-name out-queue
-;;     :hornetq/host hornetq-host
-;;     :hornetq/port hornetq-port
-;;     :onyx/batch-size batch-size}])
-
-;; (def workflow {:in {:inc :out}})
-
-;; (def conn (onyx.api/connect (str "onyx:memory//localhost/" id) coord-opts))
-
-;; (onyx.api/submit-job conn {:catalog catalog :workflow workflow})
-
-;; (def sine-model-id (d/tempid :model))
-
-;; (def sine-cluster-model-data
-;;   [{:db/id sine-model-id
-;;     :model/type :model.type/sine-cluster
-;;     :model/n-peers 10
-;;     :model/peek-peers 15
-;;     :model/peer-rate 500
-;;     :model/sine-length 40000
-;;     :model/sine-start 5000
-;;     :model/sine-reps 8}])
-
-;; (def sine-cluster-model
-;;   (-> @(d/transact sim-conn sine-cluster-model-data)
-;;       (u/tx-ent sine-model-id)))
-
-;; (defmethod sim/perform-action :action.type/register-sine-peer
-;;   [action process]
-;;   (let [peers (onyx.api/start-peers conn 1 peer-opts)]
-;;     (info (count @cluster) "in the cluster")
-;;     (swap! cluster concat peers)))
-
-;; (defmethod sim/perform-action :action.type/unregister-sine-peer
-;;   [action process]
-;;   (let [peer (first @cluster)]
-;;     (swap! cluster rest)
-;;     (info (count @cluster) "left in the cluster")
-;;     (try
-;;       ((:shutdown-fn peer))
-;;       (catch Exception e
-;;         (.printStackTrace e)))))
-
-;; (def sine-cluster-test
-;;   (sim/create-test sim-conn
-;;                    sine-cluster-model
-;;                    {:db/id (d/tempid :test)
-;;                     :test/duration 60000}))
-
-;; (def sine-cluster-sim
-;;   (sim/create-sim sim-conn
-;;                   sine-cluster-test
-;;                   {:db/id (d/tempid :sim)
-;;                    :sim/systemURI (str "datomic:mem://" (d/squuid))
-;;                    :sim/processCount 1}))
-
-;; (sim/create-fixed-clock sim-conn sine-cluster-sim {:clock/multiplier 1})
-
-;; (sim/create-action-log sim-conn sine-cluster-sim)
-
-;; (doseq [n (range 3)]
-;;   (swap! cluster concat (onyx.api/start-peers conn 1 peer-opts)))
-
-;; (def pruns
-;;   (->> #(sim/run-sim-process sim-uri (:db/id sine-cluster-sim))
-;;        (repeatedly (:sim/processCount sine-cluster-sim))
-;;        (into [])))
-
-;; (def results (hq-util/read! hq-config out-queue (inc n-messages) echo))
-
-;; (doseq [prun pruns] (future-cancel (:runner prun)))
-
-;; (onyx.api/shutdown conn)
-
-;; (doseq [peer @cluster]
-;;   (try
-;;     ((:shutdown-fn peer))
-;;     (catch Exception e)))
-
-;; (let [expected (set (map (fn [x] {:n (inc x)}) (range n-messages)))]
-;;   (fact (set (butlast results)) => expected)
-;;   (fact (last results) => :done))
-
+(def cluster (atom []))
+
+(def in-queue (str (java.util.UUID/randomUUID)))
+
+(def out-queue (str (java.util.UUID/randomUUID)))
+
+(def n-messages 100000)
+
+(def batch-size 1320)
+
+(def echo 1000)
+
+(def hornetq-host "localhost")
+
+(def hornetq-port 5445)
+
+(def hq-config {"host" hornetq-host "port" hornetq-port})
+
+(hq-util/write-and-cap! hq-config in-queue (map (fn [x] {:n x}) (range n-messages)) echo)
+
+(defn my-inc [{:keys [n] :as segment}]
+  (assoc segment :n (inc n)))
+
+(defn create-multi-births [executor t k]
+  (mapcat
+   (constantly
+    [[{:db/id (d/tempid :test)
+       :agent/_actions (u/e executor)
+       :action/atTime t
+       :action/type :action.type/register-sine-peer}]])
+   (range k)))
+
+(defn create-multi-deaths [executor t k]
+  (mapcat
+   (constantly
+    [[{:db/id (d/tempid :test)
+       :agent/_actions (u/e executor)
+       :action/atTime t
+       :action/type :action.type/unregister-sine-peer}]])
+   (range k)))
+
+(defn generate-sine-scaling-data [test executor]
+  (let [model (-> test :model/_tests first)
+        limit (:test/duration test)
+        length (:model/sine-length model)
+        rate (:model/peer-rate model)
+        reps (:model/sine-reps model)
+        height (:model/peek-peers model)
+        start (:model/sine-start model)
+        end (+ start length)
+        unit (/ (* reps Math/PI) length)
+        wave (map (fn [x] (int (* height (Math/sin (* unit x)))))
+                  (range 0 (+ end rate) rate))
+        deltas (map (fn [[a b]] (- b a)) (partition 2 1 wave))]
+    (mapcat (fn [[t delta]] (if (>= delta 0)
+                             (create-multi-births executor t delta)
+                             (create-multi-deaths executor t (Math/abs delta))))
+            (map vector (range start end rate) deltas))))
+
+(defn create-sine-cluster-test [conn model test]
+  (u/require-keys test :db/id :test/duration)
+  (-> @(d/transact conn [(assoc test
+                           :test/type :test.type/sine-cluster
+                           :model/_tests (u/e model))])
+      (u/tx-ent (:db/id test))))
+
+(defn create-executor [conn test]
+  (let [tid (d/tempid :test)
+        result @(d/transact conn
+                            [{:db/id tid
+                              :agent/type :agent.type/executor
+                              :test/_agents (u/e test)}])]
+    (d/resolve-tempid (d/db conn) (:tempids result) tid)))
+
+(defmethod sim/create-test :model.type/sine-cluster
+  [conn model test]
+  (let [test (create-sine-cluster-test conn model test)
+        executor (create-executor conn test)]
+    (u/transact-batch conn (generate-sine-scaling-data test executor) 1000)
+    (d/entity (d/db conn) (u/e test))))
+
+(defmethod sim/create-sim :test.type/sine-cluster
+  [sim-conn test sim]
+  (-> @(d/transact sim-conn (sim/construct-basic-sim test sim))
+      (u/tx-ent (:db/id sim))))
+
+(def sim-uri (str "datomic:mem://" (d/squuid)))
+
+(def sim-conn (sim-utils/reset-conn sim-uri))
+
+(sim-utils/load-schema sim-conn "simulant/schema.edn")
+
+(sim-utils/load-schema sim-conn "simulant/coordinator-sim.edn")
+
+(def id (str (java.util.UUID/randomUUID)))
+
+(def datomic (str "datomic:mem://" id))
+
+(def coord-opts
+  {:datomic-uri datomic
+   :hornetq-host hornetq-host
+   :hornetq-port hornetq-port
+   :zk-addr "127.0.0.1:2181"
+   :onyx-id id
+   :revoke-delay 2000})
+
+(def peer-opts {:hornetq-host hornetq-host
+                :hornetq-port hornetq-port
+                :zk-addr "127.0.0.1:2181"
+                :onyx-id id})
+
+(def catalog
+  [{:onyx/name :in
+    :onyx/ident :hornetq/read-segments
+    :onyx/type :input
+    :onyx/medium :hornetq
+    :onyx/consumption :concurrent
+    :hornetq/queue-name in-queue
+    :hornetq/host hornetq-host
+    :hornetq/port hornetq-port
+    :onyx/batch-size batch-size}
+
+   {:onyx/name :inc
+    :onyx/fn :onyx.peer.simulant.sine-cluster-sim/my-inc
+    :onyx/type :transformer
+    :onyx/consumption :concurrent
+    :onyx/batch-size batch-size}
+
+   {:onyx/name :out
+    :onyx/ident :hornetq/write-segments
+    :onyx/type :output
+    :onyx/medium :hornetq
+    :onyx/consumption :concurrent
+    :hornetq/queue-name out-queue
+    :hornetq/host hornetq-host
+    :hornetq/port hornetq-port
+    :onyx/batch-size batch-size}])
+
+(def workflow {:in {:inc :out}})
+
+(def conn (onyx.api/connect (str "onyx:memory//localhost/" id) coord-opts))
+
+(onyx.api/submit-job conn {:catalog catalog :workflow workflow})
+
+(def sine-model-id (d/tempid :model))
+
+(def sine-cluster-model-data
+  [{:db/id sine-model-id
+    :model/type :model.type/sine-cluster
+    :model/n-peers 10
+    :model/peek-peers 15
+    :model/peer-rate 500
+    :model/sine-length 40000
+    :model/sine-start 5000
+    :model/sine-reps 8}])
+
+(def sine-cluster-model
+  (-> @(d/transact sim-conn sine-cluster-model-data)
+      (u/tx-ent sine-model-id)))
+
+(defmethod sim/perform-action :action.type/register-sine-peer
+  [action process]
+  (let [peers (onyx.api/start-peers conn 1 peer-opts)]
+    (info (count @cluster) "in the cluster")
+    (swap! cluster concat peers)))
+
+(defmethod sim/perform-action :action.type/unregister-sine-peer
+  [action process]
+  (let [peer (first @cluster)]
+    (swap! cluster rest)
+    (info (count @cluster) "left in the cluster")
+    (try
+      ((:shutdown-fn peer))
+      (catch Exception e
+        (.printStackTrace e)))))
+
+(def sine-cluster-test
+  (sim/create-test sim-conn
+                   sine-cluster-model
+                   {:db/id (d/tempid :test)
+                    :test/duration 60000}))
+
+(def sine-cluster-sim
+  (sim/create-sim sim-conn
+                  sine-cluster-test
+                  {:db/id (d/tempid :sim)
+                   :sim/systemURI (str "datomic:mem://" (d/squuid))
+                   :sim/processCount 1}))
+
+(sim/create-fixed-clock sim-conn sine-cluster-sim {:clock/multiplier 1})
+
+(sim/create-action-log sim-conn sine-cluster-sim)
+
+(doseq [n (range 3)]
+  (swap! cluster concat (onyx.api/start-peers conn 1 peer-opts)))
+
+(def pruns
+  (->> #(sim/run-sim-process sim-uri (:db/id sine-cluster-sim))
+       (repeatedly (:sim/processCount sine-cluster-sim))
+       (into [])))
+
+(def results (hq-util/read! hq-config out-queue (inc n-messages) echo))
+
+(doseq [prun pruns] (future-cancel (:runner prun)))
+
+(onyx.api/shutdown conn)
+
+(doseq [peer @cluster]
+  (try
+    ((:shutdown-fn peer))
+    (catch Exception e)))
+
+(let [expected (set (map (fn [x] {:n (inc x)}) (range n-messages)))]
+  (fact (set (butlast results)) => expected)
+  (fact (last results) => :done))
+


Show proper user info on user part on header.

--- src/uxbox/ui/users.cljs
+++ src/uxbox/ui/users.cljs
@@ -45,13 +45,8 @@
 ;; User Widget
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-;; FIXME this is a temporal
-(def current-user (atom {:user/fullname "Cirilla"
-                         :user/avatar "/images/favicon.png"}))
-(def menu-open? (atom false))
-
 (def ^:static user-l
-  (as-> (l/in [:user]) $
+  (as-> (l/in [:auth]) $
     (l/focus-atom $ s/state)))

 (defn user-render
@@ -63,7 +58,7 @@
                       :on-mouse-leave #(swap! local assoc :open false)}
       [:span (:fullname user)]
       [:img {:border "0"
-             :src (:avatar user)}]
+             :src (:photo user)}]
       (user-menu (:open @local))])))

 (def user
@@ -76,96 +71,62 @@
 ;; Register
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-(rum/defc register-form < rum/static
-  []
-  [:div.login-content
-   [:input.input-text
-     {:name "name"
-      :placeholder "Name"
-      :type "text"}]
-   [:input.input-text
-     {:name "email"
-      :placeholder "Email"
-      :type "email"}]
-   [:input.input-text
-    {:name "password"
-     :placeholder "Password"
-     :type "password"}]
-   [:input.btn-primary
-    {:name "login"
-     :value "Continue"
-     :type "submit"
-     :on-click #(r/go :dashboard/projects)}]
-   [:div.login-links
-    [:a
-     {:on-click #(r/go :auth/login)}
-     "You already have an account?"]]])
+;; (rum/defc register-form < rum/static
+;;   []
+;;   [:div.login-content
+;;    [:input.input-text
+;;      {:name "name"
+;;       :placeholder "Name"
+;;       :type "text"}]
+;;    [:input.input-text
+;;      {:name "email"
+;;       :placeholder "Email"
+;;       :type "email"}]
+;;    [:input.input-text
+;;     {:name "password"
+;;      :placeholder "Password"
+;;      :type "password"}]
+;;    [:input.btn-primary
+;;     {:name "login"
+;;      :value "Continue"
+;;      :type "submit"
+;;      :on-click #(r/go :dashboard/projects)}]
+;;    [:div.login-links
+;;     [:a
+;;      {:on-click #(r/go :auth/login)}
+;;      "You already have an account?"]]])

-(rum/defc register < rum/static
-  []
-  [:div.login
-   [:div.login-body
-    [:a icons/logo]
-    (register-form)]])
+;; (rum/defc register < rum/static
+;;   []
+;;   [:div.login
+;;    [:div.login-body
+;;     [:a i/logo]
+;;     (register-form)]])

-(rum/defc recover-password-form < rum/static
-  []
-  [:div.login-content
-   [:input.input-text
-     {:name "email"
-      :placeholder "Email"
-      :type "email"}]
-   [:input.btn-primary
-    {:name "login"
-     :value "Continue"
-     :type "submit"
-     :on-click #(r/go :dashboard/projects)}]
-   [:div.login-links
-    [:a
-     {:on-click #(r/go :auth/login)}
-     "You have remembered your password?"]
-    [:a
-     {:on-click #(r/go :auth/register)}
-     "Don't have an account?"]]])
+;; (rum/defc recover-password-form < rum/static
+;;   []
+;;   [:div.login-content
+;;    [:input.input-text
+;;      {:name "email"
+;;       :placeholder "Email"
+;;       :type "email"}]
+;;    [:input.btn-primary
+;;     {:name "login"
+;;      :value "Continue"
+;;      :type "submit"
+;;      :on-click #(r/go :dashboard/projects)}]
+;;    [:div.login-links
+;;     [:a
+;;      {:on-click #(r/go :auth/login)}
+;;      "You have remembered your password?"]
+;;     [:a
+;;      {:on-click #(r/go :auth/register)}
+;;      "Don't have an account?"]]])

-(rum/defc recover-password < rum/static
-  []
-  [:div.login
-    [:div.login-body
-     [:a icons/logo]
-     (recover-password-form)]])
+;; (rum/defc recover-password < rum/static
+;;   []
+;;   [:div.login
+;;     [:div.login-body
+;;      [:a i/logo]
+;;      (recover-password-form)]])

-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Login
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(rum/defc login-form < rum/static
-  []
-  [:div.login-content
-   [:input.input-text
-     {:name "email"
-      :placeholder "Email"
-      :type "email"}]
-   [:input.input-text
-    {:name "password"
-     :placeholder "Password"
-     :type "password"}]
-   [:div.input-checkbox.check-primary
-    [:input#checkbox1 {:value "1"
-                       :type "checkbox"}]
-    [:label {:for "checkbox1"} "Keep Me Signed in"]]
-   [:input.btn-primary
-    {:name "login"
-     :value "Continue"
-     :type "submit"
-     :on-click #(r/go :dashboard/projects)}]
-   [:div.login-links
-    [:a {:on-click #(r/go :auth/recover-password)} "Forgot your password?"]
-    [:a {:on-click #(r/go :auth/register)} "Don't have an account?"]]])
-
-(rum/defc login
-  []
-  [:div.login
-    [:div.login-body
-     [:a icons/logo]
-     (login-form)]])


Add uuid/random helper on uuid ns.

Add uuid/random helper on uuid ns.

--- src/uxbox/util/uuid.clj
+++ src/uxbox/util/uuid.clj
@@ -5,7 +5,12 @@
 ;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>

 (ns uxbox.util.uuid
+  (:require [clj-uuid :as uuid])
   (:import java.util.UUID))
+
+(def random
+  "Alias for clj-uuid/v4."
+  uuid/v4)

 (defn from-string
   "Parse string uuid representation into proper UUID instance."


Fixed unit tests (for good this time I hope)

--- test/pe_apptxn_restsupport/resource_test.clj
+++ test/pe_apptxn_restsupport/resource_test.clj
@@ -14,6 +14,7 @@
             [pe-rest-testutils.core :as rtucore]
             [pe-core-utils.core :as ucore]
             [pe-rest-utils.core :as rucore]
+            [clojure.tools.logging :as log]
             [pe-rest-utils.meta :as rumeta]
             [pe-apptxn-restsupport.test-utils :refer [apptxn-schema-files
                                                       db-uri
@@ -130,17 +131,16 @@
               (is (= (:apptxn/user-agent-device-os apptxn-ent) "iPhone OS"))
               (is (= (:apptxn/user-agent-device-os-version apptxn-ent) "8.1"))
               (let [apptxnlogs (apptxncore/apptxnlogs-for-apptxnid @conn apptxn-id)
-                    apptxnlogs (sort-by :apptxnlog/timestamp apptxnlogs)]
+                    apptxnlogs (map #(into {} (d/entity (d/db @conn) (first %))) apptxnlogs)
+                    apptxnlogs (vec (sort-by :apptxnlog/usecase-event apptxnlogs))]
                 (is (= 2 (count apptxnlogs)))
-                (let [apptxnlog-entid (ffirst apptxnlogs)
-                      apptxnlog-ent (d/entity (d/db @conn) apptxnlog-entid)]
+                (let [[apptxnlog-ent _] apptxnlogs]
                   (is (= 1 (:apptxnlog/usecase-event apptxnlog-ent)))
                   (is (= 42 (:apptxnlog/in-ctx-err-code apptxnlog-ent)))
                   (is (= "Baaad!" (:apptxnlog/in-ctx-err-desc apptxnlog-ent)))
                   (is (= (ucore/rfc7231str->instant "Thu, 15 Jan 2015 13:11:42 EST")
                          (:apptxnlog/timestamp apptxnlog-ent))))
-                (let [apptxnlog-entid (first (second apptxnlogs))
-                      apptxnlog-ent (d/entity (d/db @conn) apptxnlog-entid)]
+                (let [[_ apptxnlog-ent] apptxnlogs]
                   (is (= 2 (:apptxnlog/usecase-event apptxnlog-ent)))
                   (is (nil? (:apptxnlog/in-ctx-err-code apptxnlog-ent)))
                   (is (nil? (:apptxnlog/in-ctx-err-desc apptxnlog-ent)))
@@ -156,26 +156,24 @@
               (is (= (:apptxn/user-agent-device-os apptxn-ent) "iPhone OS"))
               (is (= (:apptxn/user-agent-device-os-version apptxn-ent) "8.0.4"))
               (let [apptxnlogs (apptxncore/apptxnlogs-for-apptxnid @conn apptxn-id)
-                    apptxnlogs (sort-by :apptxnlog/timestamp (vec apptxnlogs))]
+                    apptxnlogs (map #(into {} (d/entity (d/db @conn) (first %))) apptxnlogs)
+                    apptxnlogs (vec (sort-by :apptxnlog/usecase-event apptxnlogs))]
                 (is (= 3 (count apptxnlogs)))
-                (let [[[apptxnlog-entid]] apptxnlogs
-                      apptxnlog-ent (d/entity (d/db @conn) apptxnlog-entid)]
-                  (is (= 3 (:apptxnlog/usecase-event apptxnlog-ent)))
+                (let [[apptxnlog-ent _ _] apptxnlogs]
+                  (is (= 0 (:apptxnlog/usecase-event apptxnlog-ent)))
                   (is (nil? (:apptxnlog/in-ctx-err-code apptxnlog-ent)))
                   (is (nil? (:apptxnlog/in-ctx-err-desc apptxnlog-ent)))
-                  (is (= (ucore/rfc7231str->instant "Mon, 12 Jan 2015 13:11:42 EST")
+                  (is (= (ucore/rfc7231str->instant "Wed, 14 Jan 2015 13:11:42 EST")
                          (:apptxnlog/timestamp apptxnlog-ent))))
-                (let [[_ [apptxnlog-entid]] apptxnlogs
-                      apptxnlog-ent (d/entity (d/db @conn) apptxnlog-entid)]
+                (let [[_ apptxnlog-ent _] apptxnlogs]
                   (is (= 1 (:apptxnlog/usecase-event apptxnlog-ent)))
                   (is (= 99 (:apptxnlog/in-ctx-err-code apptxnlog-ent)))
                   (is (= "Mmmkay" (:apptxnlog/in-ctx-err-desc apptxnlog-ent)))
                   (is (= (ucore/rfc7231str->instant "Tue, 13 Jan 2015 13:11:42 EST")
                          (:apptxnlog/timestamp apptxnlog-ent))))
-                (let [[_ _ [apptxnlog-entid]] apptxnlogs
-                      apptxnlog-ent (d/entity (d/db @conn) apptxnlog-entid)]
-                  (is (= 0 (:apptxnlog/usecase-event apptxnlog-ent)))
+                (let [[_ _ apptxnlog-ent] apptxnlogs]
+                  (is (= 3 (:apptxnlog/usecase-event apptxnlog-ent)))
                   (is (nil? (:apptxnlog/in-ctx-err-code apptxnlog-ent)))
                   (is (nil? (:apptxnlog/in-ctx-err-desc apptxnlog-ent)))
-                  (is (= (ucore/rfc7231str->instant "Wed, 14 Jan 2015 13:11:42 EST")
+                  (is (= (ucore/rfc7231str->instant "Mon, 12 Jan 2015 13:11:42 EST")
                          (:apptxnlog/timestamp apptxnlog-ent))))))))))))


Support for searching in atomic words in DB

--- src/zg/db_interface.clj
+++ src/zg/db_interface.clj
@@ -30,9 +30,10 @@
     "Convert dictionary type (:whitelist, :blacklist) into a one character."
     [dictionary-type]
     (condp = dictionary-type
-        :whitelist "w"
-        :blacklist "b"
-                   "o"))
+        :whitelist    "w"
+        :blacklist    "b"
+        :atomic-typos "a"
+                      "o"))

 (defn insert-word-into-dictionary
     "Try to insert new word into the dictionary. If insert fails, exception


Add a staging template, so the staging build target works

--- backend/src/circle/backend/build/template.clj
+++ backend/src/circle/backend/build/template.clj
@@ -17,7 +17,12 @@
                                :suffix [tag-revision
                                         lb/add-instances
                                         lb/wait-for-healthy
-                                        lb/shutdown-remove-old-revisions]}})
+                                        lb/shutdown-remove-old-revisions]}
+
+                      :staging {:prefix [start-nodes
+                                         checkout
+                                         rvm/trust]
+                                :suffix [tag-revision]}})

 (defn find [name]
   (-> name keyword build-templates))


fix the annoying react key warnings

fix the annoying react key warnings

--- src-cljs/frontend/svg.cljs
+++ src-cljs/frontend/svg.cljs
@@ -28,11 +28,11 @@

 (defn layer->svg-text [layer]
   (merge
+   {:key (:db/id layer)}
    layer
    {:className (str (:className layer) " text-layer")
     :x (+ 1 (:layer/start-x layer))
     :y (:layer/start-y layer)
-    :key (:layer/id layer)
     ;; TODO: defaults for each layer when we create them
     :fontSize   (:layer/font-size layer 20)}))


normalize names

normalize names

--- src/lolteambuilder/core.clj
+++ src/lolteambuilder/core.clj
@@ -144,6 +144,9 @@

 (def regions ["br" "eune" "euw" "kr" "lan" "las" "na" "oce" "ru" "tr"])

+(defn normalize [summoner]
+  (.replace (.toLowerCase summoner) " " ""))
+
 (defn download-matches [region summoner-id]
   (sql/with-db-connection [conn spec]
     (let [history (match-list region summoner-id)
@@ -155,7 +158,7 @@

 (defn search-page [params]
   (let [region (get params "region")
-        summoner-name (.toLowerCase (get params "summoner" ""))
+        summoner-name (normalize (get params "summoner" ""))
         data {:summoner summoner-name
               :region region
               :message "Summoner not found."


input can be a vector or matrix as well

input can be a vector or matrix as well

--- src/mekena/logistic-reg.clj
+++ src/mekena/logistic-reg.clj
@@ -2,7 +2,8 @@
    (:require [incanter.core :as i]))

 (defn sigmoid
-  "sigmoid function: 1/(1+e^-z)"
+  "sigmoid function: 1/(1+e^-z)
+  Input can be a scalar, vector or matrix."
   [z]
-  (/ 1 (inc (i/exp (i/minus z)))))
+  (i/div 1 (i/plus 1 (i/exp (i/minus z)))))


Status bar updates

Status bar updates

--- src/mermaid_ldjam/core.cljs
+++ src/mermaid_ldjam/core.cljs
@@ -5,14 +5,12 @@
 (defn setup []
   ; Set frame rate to 30 frames per second.
   (q/frame-rate 30)
-
-
   {:entities
     {:bucket {:x 50 :y 150 :width 20 :height 50}
      :window {:x 10 :y 10 :width 50 :height 50}
      :look {:x 10 :y (- (q/height) 20) :width 50 :height 20 :label "Look"}
      :flap {:x 60 :y (- (q/height) 20) :width 50 :height 20 :label "Flap"}}
-   :current-status " Hello world 🌅"
+   :current-status "Hello little mermaid."
    :last-clicked []
    })

@@ -20,8 +18,7 @@
   {[:look :window] {:text "You look outside the window and see your home, the mighty ocean." :action ""}
    [:look :bucket] {:text "You see a bucket. Maybe there is something inside." :action ""}
    [:flap :window] {:text "You're too far away for that"}
-   [:flap :bucket] {:text "You flap against the bucket. BÄM. The bucket falls over and stones spill on the floor." :action ""}
-   })
+   [:flap :bucket] {:text "You flap against the bucket. BÄM. The bucket falls over and stones spill on the floor." :action ""}})

 (defn point-in-rect? [entity mx my]
   (and
@@ -30,11 +27,16 @@
    (> my (:y entity))
    (< my (+ (:y entity) (:height entity)))))

+(defn reset-actions [state entity-key]
+  (-> state
+    (assoc :last-clicked [entity-key])
+    (assoc :current-status "What now?")))
+
 (defn handle-click-actions [state entity-key]
   (cond
     (= (last (:last-clicked state)) entity-key) state
     (< (count (:last-clicked state)) 2) (update state :last-clicked conj entity-key)
-    :else (assoc state :last-clicked [entity-key])))
+    :else (reset-actions state entity-key)))

 (defn clicked-on-entity? [mx my state]
   (let [new-state
@@ -81,8 +83,10 @@
   (q/fill 255)
   (q/rect 0 0 (q/width) 30)
   (q/fill 0)
-  (q/text (str "hi " (str (q/key-as-keyword)) "ho") 200 20)
-  (q/text (str (:current-status state) (:last-clicked state)) 10 20))
+  (q/text-align :left)
+  (q/text (:current-status state) 10 20)
+  (q/text-align :right)
+  (q/text (:last-clicked state) (- (q/width) 10) 20))

 (defn draw-state [state]
   (draw-entities state)


Assoc empty entries rather than dissoc entries key for default org.

--- src/oc/storage/api/orgs.clj
+++ src/oc/storage/api/orgs.clj
@@ -71,7 +71,7 @@
 (defn- create-board
   "Create any default boards (from config) and their contents for a new org."
   [conn org board author]
-  (let [board-result (board-res/create-board! conn (board-res/->board (:uuid org) (dissoc board :entries) author))]
+  (let [board-result (board-res/create-board! conn (board-res/->board (:uuid org) (assoc board :entries []) author))]
     (doall (pmap #(create-entry conn % board-result) (:entries board))))) ; create any board entries in parallel

 ;; ----- Actions -----


Show drafts board to viewers with at least one author access board.

--- src/oc/storage/api/orgs.clj
+++ src/oc/storage/api/orgs.clj
@@ -256,7 +256,14 @@
                              boards (board-res/list-boards-by-org conn org-id [:created-at :updated-at :authors :viewers :access])
                              board-access (map #(board-with-access-level org % user) boards)
                              allowed-boards (filter :access-level board-access)
-                             show-draft-board? (and (seq user-id) (access/allow-authors conn slug (:user ctx)))
+                             author-access-boards (filter #(= (:access-level %) :author) board-access)
+                                               ;; Add the draft board
+                             show-draft-board? (and ;; if user is logged in and
+                                                    (seq user-id)
+                                                    ;; or is an author of the org
+                                                    (or (access/allow-authors conn slug (:user ctx))
+                                                        ;; or has at least one board with author access
+                                                        (pos? (count author-access-boards))))
                              draft-entry-count (if show-draft-board? (entry-res/list-entries-by-org-author conn org-id user-id :draft {:count true}) 0)
                              must-see-count (entry-res/list-entries-by-org conn org-id :asc (db-common/current-timestamp) :before (map :uuid allowed-boards) {:must-see true :count true})
                              full-boards (if show-draft-board?


Retrieve follow-ups count only if the user requesting the org is actually part of the team, instead there is no need.

--- src/oc/storage/api/orgs.clj
+++ src/oc/storage/api/orgs.clj
@@ -266,6 +266,7 @@
   :handle-ok (fn [ctx] (let [user (:user ctx)
                              user-id (:user-id user)
                              org (or (:updated-org ctx) (:existing-org ctx))
+                             user-is-part-of-the-team? (when user ((set (:teams user)) (:team-id org)))
                              org-id (:uuid org)
                              boards (board-res/list-boards-by-org conn org-id [:created-at :updated-at :authors :viewers :access])
                              board-access (map #(board-with-access-level org % user) boards)
@@ -280,7 +281,9 @@
                                                         (pos? (count author-access-boards))))
                              draft-entry-count (if show-draft-board? (entry-res/list-entries-by-org-author conn org-id user-id :draft {:count true}) 0)
                              must-see-count (entry-res/list-entries-by-org conn org-id :asc (db-common/current-timestamp) :before (map :uuid allowed-boards) {:must-see true :count true})
-                             follow-ups-count (entry-res/list-all-entries-by-follow-ups conn org-id user-id {:count true})
+                             follow-ups-count (if user-is-part-of-the-team?
+                                                (entry-res/list-all-entries-by-follow-ups conn org-id user-id {:count true})
+                                                0)
                              full-boards (if show-draft-board?
                                             (conj allowed-boards (board-res/drafts-board org-id user))
                                             allowed-boards)


Maps can be used as functions

Maps can be used as functions

--- src/overcode/introvert.cljs
+++ src/overcode/introvert.cljs
@@ -23,11 +23,6 @@
     (.push arr v))
   arr)

-(defn visited? [visited obj]
-  "Check if a collection has been visited. If so, return its JS equivalent."
-  (if (contains? @visited obj)
-    (get @visited obj)))
-
 (defn visit!
   "Marks potentially linked objects as visited to handle circular refs."
   ([visited obj out]
@@ -46,7 +41,7 @@
 (defn seq->js
   "Converts a seq-like value into a JS Array."
   ([obj flat visited]
-   (if-let [was-visited (visited? visited obj)]
+   (if-let [was-visited (@visited obj)]
      (if flat
        "Circular Seq"
        was-visited)
@@ -60,7 +55,7 @@
 (defn map->js
   "Converts a map-like value into a JS Object."
   ([obj flat visited]
-   (if-let [was-visited (visited? visited obj)]
+   (if-let [was-visited (@visited obj)]
      (if flat
        "Circular Map"
        was-visited)
@@ -80,7 +75,7 @@
 (defn ns->js
   "Converts a namespace obj into a JS Object."
   ([obj flat visited]
-   (if-let [was-visited (visited? visited obj)]
+   (if-let [was-visited (@visited obj)]
      (if flat
        "Circular NS"
        was-visited)


improve docstrings

improve docstrings

--- src/overtone/libs/event.clj
+++ src/overtone/libs/event.clj
@@ -65,9 +65,9 @@

 (defn on-event
   "Asynchronously runs handler whenever events of event-type are
-  fired. This asynchronous behaviour can be overridden if required -
-  see sync-event for more information. Events may be triggered with
-  the fns event and sync-event.
+  fired. This asynchronous behaviour can be overridden if required - see
+  sync-event for more information. Events may be triggered with the fns
+  event and sync-event.

   Takes an event-type (name of the event), a handler fn and a key (to
   refer back to this handler in the future). The handler must accept a
@@ -135,14 +135,18 @@

 (defn oneshot-event
   "Add a one-shot handler which will be removed when called. This
-   handler is guaranteed to be called only once."
+   handler is guaranteed to be called only once.
+
+  (oneshot-event \"/foo\" (fn [v] (println v)) ::debug)"
   [event-type handler key]
   (log-event "Registering async self-removing event handler:: " event-type " with key: " key)
   (handlers/add-one-shot-handler! handler-pool event-type key handler))

 (defn oneshot-sync-event
-  "Add a synchronous one-shot handler which will be removed when called. This
-   handler is guaranteed to be called only once."
+  "Add a synchronous one-shot handler which will be removed when
+   called. This handler is guaranteed to be called only once.
+
+  (oneshot-sync-event \"/foo\" (fn [v] (println v)) ::debug)"
   [event-type handler key]
   (log-event "Registering sync self-removing event handler:: " event-type " with key: " key)
   (handlers/add-one-shot-sync-handler! handler-pool event-type key handler))


Fix default-main ids type

Fix default-main ids type

--- src/adzerk/boot_cljs.clj
+++ src/adzerk/boot_cljs.clj
@@ -134,7 +134,7 @@

   If no .cljs.edn exists with given id, creates one. This default .cljs.edn file
   will :require all CLJS namespaces found in the fileset."
-  [i ids IDS str ""]
+  [i ids IDS #{str} ""]
   (let [tmp-main (core/tmp-dir!)]
     (core/with-pre-wrap fileset
       (core/empty-dir! tmp-main)


add application state atom

add application state atom

--- src/cljs/reagent_phonecat_tutorial/core.cljs
+++ src/cljs/reagent_phonecat_tutorial/core.cljs
@@ -1,5 +1,6 @@
 (ns reagent-phonecat.core
-    (:require [reagent.core :as rg])
+    (:require [reagent.core :as rg]
+              [clojure.string :as str])
     )

 (enable-console-print!)
@@ -10,24 +11,68 @@
   (print "Hello," (or name "World") "!"))

 ;; --------------------------------------------
-;; Application data
+;; Application data

-(def hardcoded-phones-data [{:name "Nexus S"
-                             :description "Fast just got faster with Nexus S"}
-                            {:name "Motorola XOOM™ with Wi-Fi"
-                             :description "The Next, Next Generation tablet."}])
+(def hardcoded-phones-data [{:name "Nexus S"
+                             :description "Fast just got faster with Nexus S."
+                             :age 1}
+                            {:name "Motorola XOOM™ with Wi-Fi"
+                             :description "The Next, Next Generation tablet."
+                             :age 2}
+                            {:name "MOTOROLA XOOM™"
+                             :description "The Next, Next Generation tablet."
+                             :age 3}])
+
+;; --------------------------------------------
+;; Search logic
+
+(defn matches-search? "Determines if a phone item matches a text query."
+  [search data]
+  (let [qp (-> search (or "") str/lower-case re-pattern)]
+    (->> (vals data)
+         (filter string?) (map str/lower-case)
+         (some #(re-find qp %))
+         )))
+
+;; --------------------------------------------
+;; State
+
+(def state "Reagent atom that holds our global application state."
+  (rg/atom {:phones hardcoded-phones-data
+            :search ""
+            }))
+
+(defn update-search [state new-search]
+  (assoc state :search new-search))

 ;; --------------------------------------------
 ;; View components

 (declare ;; here we declare our components to define their in an order that feels natural.
-  phones-list
-    phone-item)
+  top-cpnt
+    search-cpnt
+    phones-list
+      phone-item)
+
+(defn top-cpnt []
+  (let [{:keys [phones search]} @state]
+    [:div.container-fluid
+     [:div.row
+      [:div.col-md-2 [search-cpnt search]]
+      [:div.col-md-8 [phones-list phones search]]
+      ]]))
+
+(defn search-cpnt [search]
+  [:span
+   "Search: "
+   [:input {:type "text"
+            :value search
+            :on-change (fn [e] (swap! state update-search (-> e .-target .-value)))}]])

 (defn phones-list "An unordered list of phones"
-  [phones-list]
-  [:ul
-   (for [phone phones-list]
+  [phones-list search]
+  [:ul.phones
+   (for [phone (->> phones-list (filter #(matches-search? search %)))]
      ^{:key (:name phone)} [phone-item phone]
      )])

@@ -40,7 +85,7 @@
 (defn mount-root "Creates the application view and injects ('mounts') it into the root element."
   []
   (rg/render
-    [phones-list hardcoded-phones-data]
+    [top-cpnt]
     (.getElementById js/document "app")))

 (defn init! []