Removed bootlaces

Removed bootlaces

--- build.boot
+++ build.boot
@@ -1,15 +1,14 @@
-(def +version+ "0.2.6")
-
 (task-options!
- pom   {:project 'rum
-        :version +version+
+  pom { :project     'rum
+        :version     "0.2.6"
         :description "ClojureScript wrapper for React"
-        :url     "https://github.com/tonsky/rum"
-        :scm     {:url "https://github.com/tonsky/rum"}
-        :license {"Eclipse Public License" "http://www.eclipse.org/legal/epl-v10.html"}})
+        :url         "https://github.com/tonsky/rum"
+        :scm         {:url "https://github.com/tonsky/rum"}
+        :license     {"Eclipse Public License" "http://www.eclipse.org/legal/epl-v10.html"} })

 (set-env!
-  :source-paths #{"src"}
+  :source-paths   #{"src"}
+  :resource-paths #{"src"}
   :dependencies '[
     [org.clojure/clojure       "1.7.0-alpha5" :scope "provided"]
     [org.clojure/clojurescript "0.0-2985"     :scope "provided"]
@@ -20,16 +19,14 @@
     [adzerk/boot-reload "0.2.4"          :scope "test"]
     [tonsky/boot-anybar "0.1.0"          :scope "test"]
     [pandeiro/boot-http "0.6.3-SNAPSHOT" :scope "test"]
-    [adzerk/bootlaces   "0.1.11"         :scope "test"]])
+])

 (require
   '[adzerk.boot-cljs   :refer [cljs]]
   '[adzerk.boot-reload :refer [reload]]
   '[tonsky.boot-anybar :refer [anybar]]
   '[pandeiro.boot-http :refer [serve]]
-  '[adzerk.bootlaces :refer :all])
-
-(bootlaces! +version+)
+)

 (def compiler-opts
   {:warnings {:single-segment-namespace false}})


Add dev task that includes the test folder in the classpath

--- build.boot
+++ build.boot
@@ -55,6 +55,11 @@
   (merge-env! :source-paths #{"test"})
   identity)

+(deftask dev []
+  "Sets up a development environment"
+  (comp (testing-helper)
+        (repl)))
+
 (ns-unmap 'boot.user 'test)

 (deftask test


Use stable boot-cljs and reload

Use stable boot-cljs and reload

--- build.boot
+++ build.boot
@@ -3,9 +3,9 @@
   :resource-paths #{"src/clj" "src/cljc"}
   :dependencies '[[org.clojure/clojure    "1.7.0"]
                   [org.clojure/clojurescript "1.7.48"]
-                  [adzerk/boot-cljs       "1.7.48-5-SNAPSHOT" :scope "test"]
+                  [adzerk/boot-cljs       "1.7.48-5"   :scope "test"]
                   [adzerk/boot-cljs-repl  "0.2.0"      :scope "test"]
-                  [adzerk/boot-reload     "0.3.3-SNAPSHOT" :scope "test"]
+                  [adzerk/boot-reload     "0.4.0"      :scope "test"]
                   [deraen/boot-less       "0.4.1"      :scope "test"]
                   [deraen/boot-sass       "0.1.0"      :scope "test"]
                   [deraen/boot-ctn        "0.1.0"      :scope "test"]
@@ -65,7 +65,7 @@
     (if use-sass
       (sass)
       (less))
-    (reload :on-jsload 'frontend.core/start! :open-file "vim --servername saapas --remote-silent +norm%sG%s| %s")
+    (reload :open-file "vim --servername saapas --remote-silent +norm%sG%s| %s")
     ; This starts a repl server with piggieback middleware
     (cljs-repl)
     (cljs)


Change to snapshot version

Change to snapshot version

--- build.boot
+++ build.boot
@@ -1,5 +1,5 @@
 (def project 'proud/boot-template)
-(def version "0.1.2")
+(def version "0.1.3-SNAPSHOT")

 (set-env! :resource-paths #{"resources" "src"}
           ;; uncomment this if you write tests for your template:


Sift out all the .java files from the final jar

--- build.boot
+++ build.boot
@@ -6,11 +6,12 @@

 (def +version+ "0.1.0-SNAPSHOT")

+(require '[radicalzephyr.bootlaces  :refer :all]
+         '[radicalzephyr.boot-junit :refer [junit]])
+
 (bootlaces! +version+)
 (set-env! :resource-paths #{}) ;; Must undo bootlaces! adding "src" to
                                ;; the resource-paths. Will be fixed in 0.1.15
-
-(require '[radicalzephyr.boot-junit :refer [junit]])

 (task-options!
  pom {:project 'http-server
@@ -20,7 +21,9 @@
       :scm {:url "https://github.com/RadicalZephyr/http-server.git"}
       :licens {"MIT" "http://opensource.org/licenses/MIT"}}
  jar {:file "server.jar"
-      :manifest {"Main-Class" "net.zephyrizing.http_server.HttpServer"}})
+      :manifest {"Main-Class" "net.zephyrizing.http_server.HttpServer"}}
+ sift {:invert true
+       :include #{#"\.java$"}})

 ;;; This prevents a name collision WARNING between the test task and
 ;;; clojure.core/test, a function that nobody really uses or cares
@@ -39,4 +42,5 @@
   []
   (comp (javac)
         (pom)
+        (sift)
         (jar)))


Updated dependencies

Updated dependencies

Signed-off-by: Tom Marble <b248307e886b80bf9cb4014595572a835b049bf4@info9.net>

--- build.boot
+++ build.boot
@@ -40,15 +40,15 @@
                     [aleph "0.4.2-alpha4"]
                     ;; client
                     [com.cognitect/transit-cljs "0.8.237"]
-                    [cljsjs/react-dom-server "15.0.2-0"]  ;; for sablono
-                    [cljsjs/react-dom "15.0.2-0"] ;; for sablono
-                    [org.omcljs/om "1.0.0-alpha35"]
+                    [cljsjs/react-dom-server "15.1.0-0"]  ;; for sablono
+                    [cljsjs/react-dom "15.1.0-0"] ;; for sablono
+                    [org.omcljs/om "1.0.0-alpha36"]
                     [sablono "0.7.1"]
                     ;; cljs-dev
                     [com.cemerick/piggieback "0.2.1"     :scope "test"]
                     [weasel                 "0.7.0"      :scope "test"]
                     [org.clojure/tools.nrepl "0.2.12"    :scope "test"]
-                    [adzerk/boot-reload     "0.4.7"      :scope "test"]
+                    [adzerk/boot-reload     "0.4.8"      :scope "test"]
                     [pandeiro/boot-http "0.7.3" :scope "test"]
                     [adzerk/boot-cljs       "1.7.228-1"  :scope "test"]
                     [adzerk/boot-cljs-repl  "0.3.0"      :scope "test"]


Update to my latest and greatest bootlaces

--- build.boot
+++ build.boot
@@ -4,7 +4,7 @@
  :dependencies '[[org.clojure/clojure     "1.6.0" :scope "provided"]
                  [boot/core               "2.1.0" :scope "provided"]
                  [junit                   "4.12"  :scope "test"]
-                 [radicalzephyr/bootlaces "0.1.12"]])
+                 [radicalzephyr/bootlaces "0.1.15-SNAPSHOT"]])

 (require '[radicalzephyr.bootlaces :refer :all]
          '[radicalzephyr.boot-junit :refer [junit]])


Fix run-commands

Fix run-commands

--- build.boot
+++ build.boot
@@ -36,23 +36,6 @@

 (def windows?
   (.startsWith (.toLowerCase (System/getProperty "os.name")) "windows"))
-
-(defn format-commands
-  [& commands]
-  (->> (interleave commands (repeat [(if windows? "&" ";")]))
-       (butlast)
-       (apply concat)
-       ((fn [commands]
-          (if windows?
-            commands
-            [(str "'" (string/join " " commands) "'")])))
-       (into (if windows? ["cmd" "/c"] ["sh" "-c"]))))
-
-(defn run-commands
-  [& commands]
-  (->> commands
-       (apply format-commands)
-       (apply util/dosh)))

 (defn fix-slashes
   [^String s]
@@ -147,21 +130,16 @@
         (with-pass-thru _
           (host-process
             (conch/proc
-              (format-commands
-                ["lumo"
-                 "-c" (System/getProperty "fake.class.path")
-                 "-k" "lumo_cache"
-                 "target/mikron/node.cljs"])))))
+              "lumo"
+              "-c" (System/getProperty "fake.class.path")
+              "-k" "lumo_cache"
+              "target/mikron/node.cljs"))))
       (comp
         (compile-cljs :id "node/index")
         (target)
         (with-pass-thru _
-          (util/dosh "cd" "target")
-          (util/dosh "ls" "-l")
-          (util/info "C\n")
-          (util/dosh "bash" "-c" "'cd target ; ls -l'"))))))
-        ;(with-pass-thru _
-        ;  (run-commands ["cd" "target/node"] ["node" "index.js"]))))))
+          (binding [util/*sh-dir* "target"]
+            (util/dosh "node" "index.js")))))))

 (deftask autotest
   "Runs the specified tests."
@@ -210,11 +188,10 @@
     (target)
     (with-pass-thru _
       (host-process
-        (apply conch/proc
-          (format-commands
-            ["lumo"
-             "-c" (str "\"" (System/getProperty "fake.class.path") "\"")
-             "-k" "lumo_cache"
-             "-e" (str "\"(require '[mikron.core :as mikron "
-                       ":refer [schema defschema pack unpack gen valid?]])\"")
-             "-r"]))))))
+        (conch/proc
+          "lumo"
+          "-c" (str "\"" (System/getProperty "fake.class.path") "\"")
+          "-k" "lumo_cache"
+          "-e" (str "\"(require '[mikron.core :as mikron "
+                    ":refer [schema defschema pack unpack gen valid?]])\"")
+          "-r")))))


Update play-cljs template

Update play-cljs template

--- build.boot
+++ build.boot
@@ -11,7 +11,7 @@
                   [org.clojure/clojure "1.9.0-alpha14"]
                   [leiningen "2.7.0" :exclusions [leiningen.search]]
                   [ring "1.4.0"]
-                  [play-cljs/lein-template "0.6.6"]
+                  [play-cljs/lein-template "0.7.0"]
                   [eval-soup "1.1.1" :exclusions [org.clojure/core.async]]])

 (require '[adzerk.boot-cljs :refer [cljs]])


Fix blog index rendering to work with new version of Perun

Page layout was getting rendered twice because the lastest version of
Perun uses the rendered output when creating the index. Rendering the
posts after the index fixes the problem.

--- build.boot
+++ build.boot
@@ -89,6 +89,13 @@
         (markdown)
         (slug :slug-fn zetawar.site/slug-fn)
         (permalink :permalink-fn zetawar.site/permalink-fn)
+        (collection :renderer 'zetawar.views.site/render-index
+                    :out-dir "."
+                    :page "index.html")
+        (collection :renderer 'zetawar.views.site/render-blog-index
+                    :filterer zetawar.site/post?
+                    :out-dir "."
+                    :page "blog/index.html")
         (render :renderer 'zetawar.views.site/render-page
                 :filterer zetawar.site/page?
                 :out-dir ".")
@@ -97,14 +104,7 @@
                 :out-dir ".")
         (render :renderer 'zetawar.views.site/render-devcards
                 :filterer zetawar.site/devcards?
-                :out-dir ".")
-        (collection :renderer 'zetawar.views.site/render-index
-                    :out-dir "."
-                    :page "index.html")
-        (collection :renderer 'zetawar.views.site/render-blog-index
-                    :filterer zetawar.site/post?
-                    :out-dir "."
-                    :page "blog/index.html")))
+                :out-dir ".")))

 (deftask build-cljs
   "Build Zetawar ClojureScript for deployment."


update deps

update deps

--- build.boot
+++ build.boot
@@ -6,7 +6,7 @@
  :dependencies (vec
                 (concat (->>
                          '[[adzerk/bootlaces "0.1.11"]
-                           [adzerk/boot-cljs "0.0-2411-5"]
+                           [adzerk/boot-cljs "0.0-3308-0"]
                            [adzerk/boot-cljs-repl "0.1.7"]
                            [adzerk/boot-reload "0.2.0"]
                            [deraen/boot-cljx "0.2.0"]
@@ -18,12 +18,12 @@
                            [om "0.8.0-beta3"]
                            [sablono "0.2.22" :exclusions [com.facebook/react]]]
                          (mapv #(conj % :scope "test")))
-                        '[[org.clojure/clojure "1.7.0-alpha4"]
-                          [org.clojure/clojurescript "0.0-2411"]
-                          [org.clojure/core.async "0.1.346.0-17112a-alpha"]
-                          [org.clojure/core.match "0.2.2"]
-                          [clj-time "0.8.0"]
-                          [com.andrewmcveigh/cljs-time "0.2.4"]]))
+                        '[[org.clojure/clojure "1.7.0"]
+                          [org.clojure/clojurescript "0.0-3308"]
+                          [org.clojure/core.async "0.1.338.0-5c5012-alpha"]
+                          [org.clojure/core.match "0.3.0-alpha4"]
+                          [clj-time "0.10.0"]
+                          [com.andrewmcveigh/cljs-time "0.3.10"]]))
  :source-paths  #{"src"}
  :resource-paths #{"resources" "src"})


Implement color/blend and gradient.

Implement color/blend and gradient.

--- src/org/playasophy/wonderdome/util/color.clj
+++ src/org/playasophy/wonderdome/util/color.clj
@@ -49,18 +49,32 @@

-;;;;; GRADIENT FUNCTIONS ;;;;;
+;;;;; COLOR GRADIENTS ;;;;;
+
+(defn blend
+  "Generates a color which is linearly interpolated between two colors."
+  [p x y]
+  {:pre [(<= 0.0 p 1.0)]}
+  (let [xc (rgb-components x)
+        yc (rgb-components y)]
+    (->>
+      (map - yc xc)
+      (map (partial * p))
+      (map + xc)
+      (apply rgb))))
+

 (defn gradient   ; FIXME
-  "Assigns a color based on the position through a gradient of color points."
-  ; TODO: don't require a blend-color function, do it locally.
-  [blend-color colors value]
+  "Assigns a color based on the position through a gradient of color points.
+  Each color in the sequence occupies an equal amount of space in the cycle,
+  such that p of 0.0 and 1.0 both give the first color in the sequence."
+  [colors p]
   (let [s  (count colors)
         t  (* (- value (int value)) s)
         t0 (int t)
         t1 (if (>= (inc t0) s) 0 (inc t0))
         p  (- t t0)]
-    (blend-color (colors t0) (colors t1) p)))
+    (blend p (nth colors t0) (nth colors t1))))

 ; TODO: less-angry rainbow!


Reordered things so that changing the frequency of the tri synth would make a noticeable difference

--- src/overtone/examples/busses/getonthebus.clj
+++ src/overtone/examples/busses/getonthebus.clj
@@ -74,13 +74,7 @@
 ;; Fun fact: These two examples are key features
 ;; of AM and FM radio transmitters, respectively.

-;; Change the frequency of the triangle wave on the tri-bus
-;; This causes the modulation of the volume to happen more slowly
-(comment
-  (ctl tri-synth-inst :freq 0.5)
-  )
-
-;; Switch the bus that is modulating the frequency and volume
+;; Switch the bus that is modulating the frequency
 ;; to be the triangle bus.
 ;;
 ;; Note that we have to use its id because OSC (or maybe supercollider)
@@ -88,6 +82,17 @@
 ;; feel free to correct this if it's something else happening).
 (comment
   (ctl mft :freq-bus (:id tri-bus))
+  )
+
+;; Change the frequency of the triangle wave on the tri-bus
+;; This causes the modulation of the volume to happen more slowly
+(comment
+  (ctl tri-synth-inst :freq 0.5)
+  )
+
+;; Switch the modulated-vol-tri instance to be modulated by the triangle
+;; bus as well.
+(comment
   (ctl mvt :vol-bus (:id tri-bus))
   )

@@ -98,7 +103,8 @@
     (kill mvt))
   )

-;; At this point, the busses are still carrying data from the tri-synth and sin-synth; you'll have to kill them as well explicitly or invoke (stop) if you want them to stop.
+;; At this point, the busses are still carrying data from the tri-synth and sin-synth;
+;; you'll have to kill them as well explicitly or invoke (stop) if you want them to stop.

 ;; Or can re-use them!
 (comment


Fix extension parsing for paths with a dot in the directory - close #1755

--- src/lt/objs/files.cljs
+++ src/lt/objs/files.cljs
@@ -88,9 +88,7 @@
         (recur (rest parts) (conj acc (string/join "." parts)))))))

 (defn ext [path]
-  (let [i (.lastIndexOf path ".")]
-    (when (> i 0)
-      (subs path (inc i) (count path)))))
+  (.extname fpath path))

 (defn without-ext [path]
   (let [i (.lastIndexOf path ".")]


Test for function send-error-response with pretty-print option set to true

--- test/emender_jenkins/rest_api_test.clj
+++ test/emender_jenkins/rest_api_test.clj
@@ -994,3 +994,19 @@
                     {:status  501
                      :headers {"Content-Type" "application/json"}
                      :body    "{\"response\":\"error\"}"}))))
+
+(deftest test-send-error-response-pretty-print
+    "Check the function emender-jenkins.rest-api/send-error-response."
+    (testing "the function emender-jenkins.rest-api/send-error-response."
+        (let [request       {:configuration {:jenkins {:currently-building-view "Building"
+                                                      :jenkins-url "http://10.20.30.40:8080/"}
+                                             :config  {:pretty-print true}}}]
+             (is (= (send-error-response {:response :ok} request :ok)
+                    {:status  200
+                     :headers {"Content-Type" "application/json"}
+                     :body    "{\"response\":\"ok\"}\n"}))
+             (is (= (send-error-response {:response {:deep {:structure :ok}}} request :ok)
+                    {:status  200
+                     :headers {"Content-Type" "application/json"}
+                     :body    "{\"response\":{\"deep\":{\"structure\":\"ok\"}}}\n"})))))
+


Simplify reading cljs.edn file

Simplify reading cljs.edn file

--- src/adzerk/boot_reload.clj
+++ src/adzerk/boot_reload.clj
@@ -71,11 +71,10 @@
         ~changed))))

 (defn- add-init!
-  [client-ns in-file out-file]
-  (let [client-ns (symbol client-ns)
-        spec (-> in-file slurp read-string)]
+  [client-ns spec out-file cljs-edn-path]
+  (let [client-ns (symbol client-ns)]
     (when (not= :nodejs (-> spec :compiler-options :target))
-      (util/info "Adding :require %s to %s...\n" client-ns (.getName in-file))
+      (util/info "Adding :require %s to %s...\n" client-ns cljs-edn-path)
       (io/make-parents out-file)
       (-> spec
         (update-in [:require] conj client-ns)
@@ -135,10 +134,9 @@
           (let [path     (tmp-path f)
                 spec     (-> f tmp-file slurp read-string)
                 client-ns (str "adzerk.boot-reload." (rutil/path->ns path))
-                in-file  (tmp-file f)
                 out-file (io/file tmp path)]
             (write-cljs! tmp client-ns url ws-host (get spec :on-jsload on-jsload) asset-host)
-            (add-init! client-ns in-file out-file)))
+            (add-init! client-ns spec out-file path)))
         (reset! prev-pre fileset)
         (let [fileset (-> fileset (add-resource tmp) commit!)
               fileset (try


Spruce up API documentation.

Spruce up API documentation.

--- src/afterglow/channels.clj
+++ src/afterglow/channels.clj
@@ -3,7 +3,17 @@
   {:author "James Elliott"}
   (:require [com.evocomputing.colors :as colors]))

-(defn channel [offset]
+(defn channel
+  "Creates a minimal channel specification, containing just the
+  address offset within the fixture's list of channels. The first
+  channel used by a fixture is, by convention, given offset 1.
+
+  You probably want to use [[fine-channel]] rather than this function
+  to create even channels which do not have a `:fine-offset` because
+  of the other helpful features it offers, such as setting up the
+  channel function specification for you."
+  {:doc/format :markdown}
+  [offset]
   {:offset offset})

 (defn- assign-channel [universe start-address raw-channel]
@@ -22,14 +32,15 @@
          :fixture fixture :id (id-fn)))

 (defn- patch-heads
-  "Assigns the heads of a fixture to a DMX universe and starting channel; resolves all of
-  their channel assignments."
+  "Assigns the heads of a fixture to a DMX universe and starting
+  channel; resolves all of their channel assignments."
   [fixture channel-assigner id-fn]
   (let [assigner (partial patch-head channel-assigner fixture id-fn)]
     (update-in fixture [:heads] #(map assigner %))))

 (defn patch-fixture
-  "Assign a fixture to a DMX universe and starting channel; resolves all of its channel assignments."
+  "Assign a fixture to a DMX universe and starting channel; resolves
+  all of its channel assignments."
   [fixture universe start-address id-fn]
   (let [assigner (partial assign-channel universe start-address)]
     (update-in (patch-heads fixture assigner id-fn) [:channels] #(map assigner %))))
@@ -72,9 +83,40 @@
          (when var-label {:var-label var-label})))

 (defn fine-channel
-  "Defines a channel for which sometimes multi-byte values are
-  desired, via a separate channel which specifies the fractional value
-  to be added to the main channel."
+  "Defines a channel of type `chan-type` which may be paired with a
+  second channel in order to support multi-byte values. When a value
+  is passed in with `:fine-offset`, the channel specified by `offset`
+  is understood as containing the most-significant byte of a two-byte
+  value, with the least-significant byte carried in the channel whose
+  offset followed `:fine-offset`.
+
+  Automatically creates a [function
+  specification](https://github.com/brunchboy/afterglow/blob/master/doc/fixture_definitions.adoc#function-specifications)
+  which spans all the legal DMX values for the channel. By default,
+  the function type is taken to be the same as `chan-type`, but this
+  can be changed by passing in a different keyword with
+  `:function-type`.
+
+  Similarly, the name of the function created is, by default, a
+  capitalized version of the function type (without its leading
+  colon). Since this name is displayed in the [web
+  interface](https://github.com/brunchboy/afterglow/blob/master/doc/README.adoc#the-embedded-web-interface)
+  as the text label in the cue grid cell for [Function
+  Cues](https://github.com/brunchboy/afterglow/blob/master/doc/cues.adoc#creating-function-cues)
+  created for the function, you may wish to specify a more readable
+  name, which you can do by passing it with `:function-name`.
+
+  Finally, you may specify a label to be used when creating a user
+  interface for adjusting the value associated with this
+  function. [Function
+  Cues](https://github.com/brunchboy/afterglow/blob/master/doc/cues.adoc#creating-function-cues)
+  will use this as the label for the cue-local variable they create,
+  and it will appear in places like the [Ableton Push Effect Control
+  interface](https://github.com/brunchboy/afterglow/blob/master/doc/mapping_sync.adoc#effect-control).
+  You can specify what this variable label should be with
+  `:var-label`; if you do not, the generic label `Level` will be
+  used."
+  {:doc/format :markdown}
   [chan-type offset & {:keys [fine-offset function-type function-name var-label] :or {function-type chan-type}}]
   {:pre (some? chan-type) (integer? offset) (<= 1 offset 512)}
   (let [chan-type (keyword chan-type)
@@ -171,19 +213,33 @@
   "Defines a channel whose values are divided up into different ranges
   which perform different functions. After the channel type and DMX
   offset, pass a list of starting values and function specifications.
+
   The simplest form of specification is a keyword or string
   identifying the function type; this will be expanded into a
   variable-range (for keywords) or fixed-range (for strings) function
-  of that type. For more complex functions, pass in a map containing
-  the :type keyword and any other settings you need to
-  make (e.g. :label, :range, :var-label), and the rest will be filled
-  in for you. The ranges need to be in order of increasing starting
+  of that type.
+
+  For more complex functions, pass in a map containing the `:type`
+  keyword and any other settings you need to make (e.g. `:label`,
+  `:range`, `:var-label`), and the rest will be filled in for you.
+
+  To skip a range, pass `nil` for its specification.
+
+  The ranges need to be in order of increasing starting
   values, and the ending values for each will be figured out by
   context, e.g.
+
+  ```
   (functions :strobe 40
              0 nil
              10 \"strobe-random\"
-             20 :strobe"
+             20 :strobe)
+  ```
+
+  See the [online
+  documentation](https://github.com/brunchboy/afterglow/blob/master/doc/fixture_definitions.adoc#function-channels)
+  for more details and examples."
+  {:doc/format :markdown}
   [chan-type offset & functions]
   {:pre (some? chan-type) (integer? offset) (<= 1 offset 512)}
   (let [chan-type (keyword chan-type)]
@@ -245,8 +301,26 @@
    (fine-channel :dimmer offset :fine-offset fine-offset :range-label "Intensity")))

 (defn color
-  "A channel which controls a color component, with an optional second
-  channel for fine control."
+  "A channel which controls a color component. If `:hue` is supplied
+  along with a hue value, this channel will participate in color
+  mixing even if `color` is not one of the standard values `:red`,
+  `:green`, `:blue`, or `:white` whose hues and contributions to color
+  mixing are automatically understood.
+
+  By default, the function created for the channel uses the name of
+  the `color` keyword as its function label. Since this label is
+  displayed in the [web
+  interface](https://github.com/brunchboy/afterglow/blob/master/doc/README.adoc#the-embedded-web-interface)
+  as the text label in the cue grid cell for [Function
+  Cues](https://github.com/brunchboy/afterglow/blob/master/doc/cues.adoc#creating-function-cues)
+  created for the function, you may wish to specify a more readable
+  name, which you can do by passing it in with `:function-label`.
+
+  If the fixture uses two-byte values for this color component, pass
+  the offset of the channel containing the most-significant byte in
+  `offset`, and specify the offset of the channel containing the
+  least-significant byte with `:fine-offset`."
+  {:doc/format :markdown}
   [offset color & {:keys [hue function-label fine-offset]}]
   {:pre (some? color)}
   (let [color (keyword color)]


More testes around exec-plugin-actions

More testes around exec-plugin-actions

--- test/com/wsscode/pathom/core_test.cljc
+++ test/com/wsscode/pathom/core_test.cljc
@@ -564,13 +564,23 @@
             ::p/plugins        [{:some-fn "x"}]}))))

 (deftest test-exec-plugin-actions
-  (is (= (p/exec-plugin-actions {::p/plugin-actions {:some-fn [(fn [orig]
-                                                                 (fn [x]
-                                                                   (inc (orig x))))]}}
-           :some-fn
-           #(+ 5 %)
-           2)
-         8)))
+  (testing "does the same when there are no plugins"
+    (is (= (p/exec-plugin-actions {}
+             :some-fn
+             #(+ 5 %)
+             2)
+           7)))
+  (testing "run the plugin actions"
+    (is (= (p/exec-plugin-actions {::p/plugin-actions {:some-fn [(fn [orig]
+                                                                   (fn [x]
+                                                                     (inc (orig x))))
+                                                                 (fn [orig]
+                                                                   (fn [x]
+                                                                     (- (orig x) 2)))]}}
+             :some-fn
+             #(+ 5 %)
+             2)
+           6))))

 ;;;;;;;;;;;


Add search box

Add search box

--- src/airhead_cljs/core.cljs
+++ src/airhead_cljs/core.cljs
@@ -5,7 +5,8 @@

 (def state (r/atom {:server "http://localhost:8080"
                     :playlist []
-                    :tracks []}))
+                    :tracks []
+                    :query ""}))

 (defn update-state! [k value]
   (swap! state assoc k value))
@@ -17,7 +18,8 @@

 (defn get-tracks []
   (GET (str (@state :server) "/api/tracks")
-       {:handler #(update-state! :tracks (% "items"))
+       {:params {:q (@state :query)}
+        :handler #(update-state! :tracks (% "items"))
         :response-format :json}))

 (defn enqueue-track [track]
@@ -47,9 +49,16 @@
   [:input {:type "button" :value "Enqueue"
            :on-click #(enqueue-track track)}])

+(defn search-box []
+  [:input {:type "text"
+           :value (@state :query)
+           :on-change #(update-state! :query
+                                      (-> % .-target .-value))}])
+
 (defn tracks-div []
-  (js/setTimeout get-tracks 1000)
+  (get-tracks)
   [:div [:h2 "Tracks"]
+   [search-box]
    [:ul (for [track (@state :tracks)]
           [:li
            (enqueue-button track)


Update with polling

Update with polling

--- src/airhead_cljs/core.cljs
+++ src/airhead_cljs/core.cljs
@@ -35,18 +35,27 @@
 (defn playlist-remove [id]
   (DELETE (str "/api/playlist/" id)))

+
+(defn polling-callback []
+  (info-get)
+  (playlist-get)
+  (library-get))
+
+(js/setInterval polling-callback 1000)
+
 ;; -------------------------
 ;; Views

 (defn info-component []
-  (let [title   (get-in @state [:info "name"])
-        message (get-in @state [:info "greet_message"])
-        url     (get-in @state [:info "stream_url"])]
-    [:div.info
-     [:h1 title]
-     [:div.greet-message message]
-     [:div.player [:audio {:src url
-                           :controls "controls"}]]]))
+  (fn []
+    (let [title   (get-in @state [:info "name"])
+          message (get-in @state [:info "greet_message"])
+          url     (get-in @state [:info "stream_url"])]
+      [:div.info
+       [:h1 title]
+       [:div.greet-message message]
+       [:div.player [:audio {:src url
+                             :controls "controls"}]]])))

 (defn playlist-add-component [uuid]
   [:input.add-button
@@ -65,22 +74,20 @@
    ])

 (defn playlist-component []
-  (let [tracks (@state :playlist)]
-    [:div.library
-     [:h2 "Playlist"]
-     [:ul (for [uuid tracks]
-            [:li
-             [playlist-remove-component uuid]
-             [track-component uuid]])]]))
+  [:div.library
+   [:h2 "Playlist"]
+   [:ul (for [uuid (@state :playlist)]
+          [:li
+           [playlist-remove-component uuid]
+           [track-component uuid]])]])

 (defn library-component []
-  (let [tracks (@state :library)]
-    [:div.library
-     [:h2 "Library"]
-     [:ul (for [uuid tracks]
-            [:li
-             [playlist-add-component uuid]
-             [track-component uuid]])]]))
+  [:div.library
+   [:h2 "Library"]
+   [:ul (for [uuid (@state :library)]
+          [:li
+           [playlist-add-component uuid]
+           [track-component uuid]])]])

 (defn page-component []
   [:div.page
@@ -92,10 +99,6 @@
 ;; Initialize app

 (defn mount-root []
-  (info-get)
-  (playlist-get)
-  (library-get)
-
   (r/render [page-component] (.getElementById js/document "app")))

 (defn init! []


Follow change in api

Follow change in api

--- src/airhead_cljs/core.cljs
+++ src/airhead_cljs/core.cljs
@@ -10,7 +10,7 @@

 (defn enqueue-track [track]
   (let [uuid (track "uuid")]
-    (PUT (str "/api/enqueue/" uuid))))
+    (PUT (str "/api/queue/" uuid))))

 ;; -------------------------
 ;; Views


bug in process-channel

bug in process-channel

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

--- acqEngine/src/org/micromanager/sequence_generator.clj
+++ acqEngine/src/org/micromanager/sequence_generator.clj
@@ -93,7 +93,7 @@
     #(or
        (nil? (% :channel))
        (-> % :channel :skip-frames zero?)
-       (not= 0 (mod (% :frame) (-> % :channel :skip-frames inc))))
+       (zero? (mod (% :frame) (-> % :channel :skip-frames inc))))
     events))

 (defn process-use-autofocus [events use-autofocus autofocus-skip]


fix object id

fix object id

--- src/ontrail/mutate.clj
+++ src/ontrail/mutate.clj
@@ -117,7 +117,7 @@
 (defn delete-own-comment [user ex-id comment-id]
   (.debug logger (str user " deleting own comment " comment-id " from ex " ex-id ))
   (mc/update-by-id EXERCISE
-    (ObjectId. (:id ex-id))
+    (ObjectId. ex-id)
     { "$set" {:lastModifiedDate (time/now)}
       "$pull" {:comments {:id comment-id :user user}}})
   (get-ex ex-id))
@@ -125,7 +125,7 @@
 (defn delete-own-ex-comment [user ex-id comment-id]
   (.debug logger (str user " deleting comment " comment-id " from own ex " ex-id))
   (mc/update-by-id EXERCISE
-    (ObjectId. (:id ex-id))
+    (ObjectId. ex-id)
     { :user user
       "$set" {:lastModifiedDate (time/now)}
       "$pull" {:comments {:id comment-id}}})


fix tab behavior (close #5)

fix tab behavior (close #5)

--- src/parinfer/core.cljs
+++ src/parinfer/core.cljs
@@ -8,8 +8,6 @@

     [cljsjs.codemirror]
     [cljsjs.codemirror.mode.clojure]
-    [cljsjs.codemirror.keymap.vim]
-    [cljsjs.codemirror.addon.edit.matchbrackets]

     [parinfer.formatter :refer [format-text]]

@@ -98,11 +96,20 @@
     (update-text! cm))
   (reset! frame-updated? false))

+(defn on-tab
+  "Indent selection or insert two spaces when tab is pressed.
+  from: https://github.com/codemirror/CodeMirror/issues/988#issuecomment-14921785"
+  [cm]
+  (if (.somethingSelected cm)
+    (.indentSelection cm)
+    (let [n (.getOption cm "indentUnit")
+          spaces (apply str (repeat n " "))]
+      (.replaceSelection cm spaces))))
+
 (def editor-opts
   {:lineNumbers true
    :mode "clojure"
-   :keyMap "vim"
-   :matchBrackets true
+   :extraKeys {:Tab on-tab}
    })

 (defn setup-editor


Dirty hack to temporarily deactivate eventlog

--- src/photon/streams.clj
+++ src/photon/streams.clj
@@ -244,11 +244,14 @@
   (process-event! [this msg]
                   ;; Think about the order of store+send to taps
                   (println "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " (pr-str msg))
-                  (update-streams! this (get msg "stream-name"
-                                             (get msg :stream-name)))
-                  (go (>! (:channel (global-channel this)) msg)
-                      (>! (:channel (publisher this)) msg))
-                  (db/store db msg)
+                  (let [stream-name (get msg "stream-name"
+                                         (get msg :stream-name))]
+                    (when (not= (:stream-name msg) "eventlog")
+                      (update-streams! this (get msg "stream-name"
+                                                 (get msg :stream-name)))
+                      (go (>! (:channel (global-channel this)) msg)
+                          (>! (:channel (publisher this)) msg))
+                      (db/store db msg)))
                   {:correct "true"}))

 (defmethod stream "cold" [a-stream params]


another check for valid email format.

another check for valid email format.

--- src/metabase/api/org.clj
+++ src/metabase/api/org.clj
@@ -54,7 +54,7 @@

 (defendpoint POST "/:id/members" [id :as {{:keys [first_name last_name email admin]} :body}]
   ; we require 4 attributes in the body
-  (check-400 (and first_name last_name email admin))
+  (check-400 (and first_name last_name email admin (util/is-email? email)))
   ; user must have admin perms on org to proceed
   (write-check Org id)
   (let [user-id (:id (or (sel :one [User :id] :email email)                ; find user with existing email - if exists then grant perm


Add some useful extended goals

Add some useful extended goals

--- src/micro_logic/core.clj
+++ src/micro_logic/core.clj
@@ -285,3 +285,39 @@
   (if (seq s)
     (lcons (first s) (seq->lcons (rest s)))
     empty-lcons))
+
+
+;;; extended goals
+
+(defn conso [first rest seq]
+  (=== (lcons first rest) seq))
+
+(defn firsto [first seq]
+  (fresh [rest]
+    (conso first rest seq)))
+
+(defn resto [rest seq]
+  (fresh [first]
+    (conso first rest seq)))
+
+(defn emptyo [x]
+  (=== empty-lcons x))
+
+(defn nilo [x]
+  (=== nil x))
+
+(defn repeato [n x]
+  (conde
+    [(emptyo x)]
+    [(fresh [rest]
+       (conso n rest x)
+       (repeato n rest))]))
+
+(defn iterateo [gc x]
+  (conde
+    [(emptyo x)]
+    [(fresh [val rest]
+       (gc val)
+       (conso val rest x)
+       (iterateo gc rest))]))
+


Fix rebase

Fix rebase

--- backend/src/akvo/lumen/endpoint/user.clj
+++ backend/src/akvo/lumen/endpoint/user.clj
@@ -2,6 +2,7 @@
   (:require [akvo.lumen.endpoint.commons.http :as http]
             [akvo.lumen.lib.user :as user]
             [akvo.lumen.lib :as lib]
+            [akvo.lumen.protocols :as p]
             [clojure.tools.logging :as log]
             [clojure.spec.alpha :as s]
             [integrant.core :as ig]))
@@ -44,7 +45,7 @@
                                       (user/demote-user-from-admin authorizer tenant jwt-claims id)
                                       (promote-user? body)
                                       (user/promote-user-to-admin authorizer tenant jwt-claims id)
-                                      :else http/not-implemented {}))}
+                                      :else (http/not-implemented {})))}
                  :delete {:parameters {:path-params {:id string?}}
                           :handler (fn [{tenant :tenant
                                          jwt-claims :jwt-claims


flush out the unit tests for `(process-revision-event ...)` function which handles new events related to revision tracking.

--- test/metabase/events/revision_test.clj
+++ test/metabase/events/revision_test.clj
@@ -3,11 +3,135 @@
             [korma.core :as k]
             [metabase.db :as db]
             [metabase.events.revision :refer :all]
-            (metabase.models [user :refer [User]]
-                             [view-log :refer [ViewLog]])
+            (metabase.models [card :refer [Card]]
+                             [dashboard :refer [Dashboard]]
+                             [dashboard-card :refer [DashboardCard]]
+                             [revision :refer [Revision revisions]]
+                             [revision-test :refer [with-fake-card]])
             [metabase.test.data :refer :all]
+            [metabase.test.data.users :refer :all]
             [metabase.test.util :refer [expect-eval-actual-first with-temp random-name]]
             [metabase.test-setup :refer :all]))

-;; TODO - come back and fill this out with direct tests of the `(process-revision-event)` function
-;;        this isn't needed right now because our API tests for revisions are covering this functionality
+(defn- create-test-card []
+  (let [rand-name (random-name)]
+    (db/ins Card
+      :name                   rand-name
+      :description            rand-name
+      :public_perms           2
+      :display                "table"
+      :dataset_query          {}
+      :visualization_settings {}
+      :creator_id             (user->id :crowberto))))
+
+(defn- create-test-dashboard []
+  (let [rand-name (random-name)]
+    (db/ins Dashboard
+      :name                   rand-name
+      :description            rand-name
+      :public_perms           2
+      :creator_id             (user->id :crowberto))))
+
+;; :card-create
+(expect-let [{card-id :id :as card} (create-test-card)]
+  {:model        "Card"
+   :model_id     card-id
+   :user_id      (user->id :crowberto)
+   :is_reversion false
+   :is_creation  true}
+  (do
+    (process-revision-event {:topic :card-create
+                             :item  card})
+    (-> (db/sel :one Revision :model "Card" :model_id card-id)
+        (select-keys [:model :model_id :user_id :is_reversion :is_creation]))))
+
+;; :card-update
+(expect-let [{card-id :id :as card} (create-test-card)]
+  {:model        "Card"
+   :model_id     card-id
+   :user_id      (user->id :crowberto)
+   :is_reversion false
+   :is_creation  false}
+  (do
+    (process-revision-event {:topic :card-update
+                             :item  card})
+    (-> (db/sel :one Revision :model "Card" :model_id card-id)
+        (select-keys [:model :model_id :user_id :is_reversion :is_creation]))))
+
+;; :dashboard-create
+(expect-let [{dashboard-id :id :as dashboard} (create-test-dashboard)]
+  {:model        "Dashboard"
+   :model_id     dashboard-id
+   :user_id      (user->id :crowberto)
+   :is_reversion false
+   :is_creation  true}
+  (do
+    (process-revision-event {:topic :dashboard-create
+                             :item  dashboard})
+    (-> (db/sel :one Revision :model "Dashboard" :model_id dashboard-id)
+        (select-keys [:model :model_id :user_id :is_reversion :is_creation]))))
+
+;; :dashboard-update
+(expect-let [{dashboard-id :id :as dashboard} (create-test-dashboard)]
+  {:model        "Dashboard"
+   :model_id     dashboard-id
+   :user_id      (user->id :crowberto)
+   :is_reversion false
+   :is_creation  false}
+  (do
+    (process-revision-event {:topic :dashboard-update
+                             :item  dashboard})
+    (-> (db/sel :one Revision :model "Dashboard" :model_id dashboard-id)
+        (select-keys [:model :model_id :user_id :is_reversion :is_creation]))))
+
+;; :dashboard-add-cards
+(expect-let [{dashboard-id :id} (create-test-dashboard)
+             {card-id :id}      (create-test-card)
+             dashcard           (db/ins DashboardCard :card_id card-id :dashboard_id dashboard-id)]
+  {:model        "Dashboard"
+   :model_id     dashboard-id
+   :user_id      (user->id :crowberto)
+   :is_reversion false
+   :is_creation  false}
+  (do
+    (process-revision-event {:topic :dashboard-add-cards
+                             :item  {:id       dashboard-id
+                                     :actor_id (user->id :crowberto)
+                                     :dashcards [dashcard]}})
+    (-> (db/sel :one Revision :model "Dashboard" :model_id dashboard-id)
+        (select-keys [:model :model_id :user_id :is_reversion :is_creation]))))
+
+;; :dashboard-remove-cards
+(expect-let [{dashboard-id :id} (create-test-dashboard)
+             {card-id :id}      (create-test-card)
+             dashcard           (db/ins DashboardCard :card_id card-id :dashboard_id dashboard-id)
+             _                  (db/del DashboardCard :id (:id dashcard))]
+  {:model        "Dashboard"
+   :model_id     dashboard-id
+   :user_id      (user->id :crowberto)
+   :is_reversion false
+   :is_creation  false}
+  (do
+    (process-revision-event {:topic :dashboard-remove-cards
+                             :item  {:id       dashboard-id
+                                     :actor_id (user->id :crowberto)
+                                     :dashcards [dashcard]}})
+    (-> (db/sel :one Revision :model "Dashboard" :model_id dashboard-id)
+        (select-keys [:model :model_id :user_id :is_reversion :is_creation]))))
+
+;; :dashboard-reposition-cards
+(expect-let [{dashboard-id :id} (create-test-dashboard)
+             {card-id :id}      (create-test-card)
+             dashcard           (db/ins DashboardCard :card_id card-id :dashboard_id dashboard-id)]
+  {:model        "Dashboard"
+   :model_id     dashboard-id
+   :user_id      (user->id :crowberto)
+   :is_reversion false
+   :is_creation  false}
+  (do
+    (process-revision-event {:topic :dashboard-reeposition-cards
+                             :item  {:id       dashboard-id
+                                     :actor_id (user->id :crowberto)
+                                     :dashcards [(assoc dashcard :sizeX 4)]}})
+    (-> (db/sel :one Revision :model "Dashboard" :model_id dashboard-id)
+        (select-keys [:model :model_id :user_id :is_reversion :is_creation]))))


Incorrect + use

Incorrect + use

--- test/onyx/peer/multi_peer_mem_test.clj
+++ test/onyx/peer/multi_peer_mem_test.clj
@@ -53,7 +53,7 @@

 (def maximum-retried-segments 500)

-(def out-chan (chan (sliding-buffer (+ n-messages maximum-retried-segments + 1))))
+(def out-chan (chan (sliding-buffer (+ n-messages maximum-retried-segments 1))))

 (defn inject-in-ch [event lifecycle]
   {:core.async/chan in-chan})


Fix a format bug in logging

Fix a format bug in logging

--- src/mdr2/util.clj
+++ src/mdr2/util.clj
@@ -14,14 +14,14 @@
 ;; delete we try again a bit harder. For some inspiration see
 ;; https://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/util/FileUtils.java?view=markup.
 (defn try-hard-to-delete [directory]
-  (log/warnf "Directory not empty %s. Trying harder")
+  (log/warnf "Directory not empty %s. Trying harder" directory)
   (System/gc) ; do garbage collection
   ;; wait
   (try
     (Thread/sleep delete-retry-millis)
     (catch InterruptedException e))
   ;; and then try to delete again
-  (log/warnf "Now trying again to delete %s")
+  (log/warnf "Now trying again to delete %s" directory)
   (try
     (nio/delete! directory)
     (catch DirectoryNotEmptyException e


Implement copy-directory! using nio/walk-file-tree

--- src/mdr2/util.clj
+++ src/mdr2/util.clj
@@ -3,7 +3,8 @@
   (:require [org.tobereplaced.nio.file :as nio]
             [clojure.tools.logging :as log])
   (:import (java.nio.file FileSystemException
-                          DirectoryNotEmptyException)
+                          DirectoryNotEmptyException
+                          FileVisitResult)
            java.lang.InterruptedException))

 (def ^:private delete-retry-millis 100)
@@ -47,3 +48,14 @@
     (catch FileSystemException e
       (log/error e))))

+(defn copy-directory!
+  "Copy a directory from `from` to `to` recursively"
+  [from to]
+  (let [copy (fn [path]
+               (nio/copy! path (nio/resolve-path to (nio/relativize from path)))
+               FileVisitResult/CONTINUE)]
+    (nio/walk-file-tree
+     from
+     (nio/naive-visitor
+      :pre-visit-directory copy
+      :visit-file copy))))


Update cache ns doc.

Update cache ns doc.

--- src/blocks/store/cache.clj
+++ src/blocks/store/cache.clj
@@ -1,8 +1,10 @@
 (ns blocks.store.cache
-  "Logical block store which is backed by two other stores, a _primary store_
-  and a _cache_. Blocks will be added to the cache on reads and writes. Blocks
-  will be removed from the cache based on usage to keep it below a certain total
-  size."
+  "Logical block storage backed by two other stores, a _primary store_ and a
+  _cache_. Blocks are added to the cache on reads and writes, and evicted with
+  a least-recently-used strategy to keep the cache under a certain total size.
+
+  Operations on this store will prefer to look up blocks in the cache, and fall
+  back to the primary store when not available."
   (:require
     [blocks.core :as block]
     [clojure.data.priority-map :refer [priority-map]]


Added unit test to check for ordering in relation to #188

--- test/onyx/peer/lifecycles_test.clj
+++ test/onyx/peer/lifecycles_test.clj
@@ -24,26 +24,26 @@
 (defn my-inc [{:keys [n] :as segment}]
   (assoc segment :n (inc n)))

-(def counter (atom 0))
+(def counter (atom []))

 (defn start-task? [event lifecycle]
-  (swap! counter inc)
+  (swap! counter (fn [counter] (conj counter :task-started)))
   true)

 (defn before-task [event lifecycle]
-  (swap! counter inc)
+  (swap! counter (fn [counter] (conj counter :task-before)))
   {})

 (defn after-task [event lifecycle]
-  (swap! counter inc)
+  (swap! counter (fn [counter] (conj counter :task-after)))
   {})

 (defn before-batch [event lifecycle]
-  (swap! counter inc)
+  (swap! counter (fn [counter] (conj counter :batch-before)))
   {})

 (defn after-batch [event lifecycle]
-  (swap! counter inc)
+  (swap! counter (fn [counter] (conj counter :batch-after)))
   {})

 (def catalog
@@ -127,11 +127,30 @@
   (fact (set (butlast results)) => expected)
   (fact (last results) => :done))

-;; Counter is inc'ed 14 times. 1 time on start up,
+;; Counter is conj'd 14 times. 1 time on start up,
 ;; 5 for each start/stop of a batch, 2 more times
 ;; for starting and stopping the lifecycle, and 1 more post-batch for
 ;; shutting down the task.
-(fact @counter => 14)
+(fact (count @counter) => 14)
+
+(def expected-order
+  [:task-before
+   :task-started
+   :batch-before
+   :batch-after ; 1
+   :batch-before
+   :batch-after ; 2
+   :batch-before
+   :batch-after ; 3
+   :batch-before
+   :batch-after ; 4
+   :batch-before
+   :batch-after ; 5
+   :batch-before
+   :batch-after
+   :task-after])
+
+(fact @counter => expected-order)

 (doseq [v-peer v-peers]
   (onyx.api/shutdown-peer v-peer))


Add the ability to pass the `nowrap` parameter to uncompress.

https://github.com/funcool/buddy-core/issues/37

--- src/buddy/util/deflate.clj
+++ src/buddy/util/deflate.clj
@@ -38,15 +38,22 @@
   "Given a compressed data as byte-array,
   uncompress it and return as an other
   byte array."
-  [^bytes input]
-  (let [buf (byte-array 1024)
-        os (ByteArrayOutputStream.)
-        opts (Inflater. true)]
-    (with-open [is (ByteArrayInputStream. input)
-                iis (InflaterInputStream. is opts)]
-      (loop []
-        (let [readed (.read iis buf)]
-          (when (pos? readed)
-            (.write os buf 0 readed)
-            (recur)))))
-    (.toByteArray os)))
+  ([^bytes input]
+    (uncompress input true))
+  ([^bytes input ^Boolean nowrap]
+   (let [buf  (byte-array 1024)
+         os   (ByteArrayOutputStream.)
+         opts (Inflater. nowrap)]
+     (try
+       (with-open [is  (ByteArrayInputStream. input)
+                   iis (InflaterInputStream. is opts)]
+         (loop []
+           (let [readed (.read iis buf)]
+             (when (pos? readed)
+               (.write os buf 0 readed)
+               (recur)))))
+       (.toByteArray os)
+       (catch java.util.zip.ZipException e
+         (if nowrap
+           (uncompress input false)
+           (throw e)))))))


Bump macrowbar version

Bump macrowbar version

--- build.boot
+++ build.boot
@@ -7,7 +7,7 @@
                     [org.clojure/clojurescript   "1.9.946"]

                     ;; utility
-                    [moxaj/macrowbar             "0.2.1"]
+                    [moxaj/macrowbar             "0.2.3"]

                     ;; testing
                     [org.clojure/test.check      "0.10.0-alpha1" :scope "test"]


Use boot-test.

Use boot-test.

--- build.boot
+++ build.boot
@@ -1,16 +1,19 @@
 (set-env!
   :dependencies   '[[org.clojure/clojure "1.6.0" :scope "provided"]
                     [org.jruby/jruby-complete "1.7.16.1"]
-                    [adzerk/bootlaces "0.1.5" :scope "test"]])
+                    [adzerk/bootlaces "0.1.5" :scope "test"]
+                    [adzerk/boot-test "1.0.3" :scope "test"]])

-(require '[adzerk.bootlaces :refer :all])
+(require
+  '[adzerk.bootlaces :refer :all]
+  '[adzerk.boot-test :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"})
+(set-env! :resource-paths #{"src" "resources" "test"})

 (task-options!
   pom  {:project 'clj.rb
@@ -19,20 +22,10 @@
         :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"}})
-
-(deftask run-tests
-  "Run tests"
-  []
-  (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))))
-    fileset))
+                  :url "http://www.apache.org/licenses/LICENSE-2.0"}}
+  test {:namespaces '[clj.rb-test]})

 (deftask build
   "Run tests; build and install the jar."
   []
-  (comp (run-tests) (build-jar)))
+  (comp (test) (build-jar)))


bootlaces

bootlaces

--- build.boot
+++ build.boot
@@ -1,4 +1,4 @@
-(def project 'cljs-exe/boot-template)
+(def project 'cljs-exe)
 (def version "0.1.0")

 (set-env! :resource-paths #{"resources" "src"}
@@ -6,6 +6,7 @@
           ;; :source-paths   #{"test"}
           :dependencies   '[[org.clojure/clojure "RELEASE"]
                             [seancorfield/boot-new "RELEASE"]
+                            [adzerk/bootlaces "0.1.13" :scope "test"]
                             [adzerk/boot-test "RELEASE" :scope "test"]])

 (task-options!
@@ -23,4 +24,7 @@
   (comp (pom) (jar) (install)))

 (require '[adzerk.boot-test :refer [test]]
-         '[boot.new :refer [new]])
+         '[boot.new :refer [new]]
+         '[adzerk.bootlaces :refer :all])
+
+(bootlaces! version)


Fix format-commands #2

Fix format-commands #2

--- build.boot
+++ build.boot
@@ -21,6 +21,7 @@

 (require '[clojure.java.io :as io]
          '[clojure.pprint :as pprint]
+         '[clojure.string :as string]

          '[boot.util :as util]
          '[adzerk.boot-test :as boot-test]
@@ -42,7 +43,7 @@
         (map (fn [command]
                (if windows?
                  (into ["cmd" "/c"] command)
-                 (into ["sh" "-c"]  (str "'" (apply str command) "'"))))
+                 (into ["sh" "-c"]  [(str "'" (string/join " " command) "'")])))
              c)
         (interleave c (repeat [(if windows? "&" ";")]))
         (butlast c)


generate version specific docs

generate version specific docs

--- build.boot
+++ build.boot
@@ -94,6 +94,7 @@
     (codox :name "Compassus"
       :version +version+
       :description "A routing library for Om Next."
+      :output-path (str "doc/" +version+)
       :source-uri "https://github.com/anmonteiro/compassus/blob/master/{filepath}#L{line}")))

 (deftask release-devcards []


Update very old dependencies

Update very old dependencies

--- build.boot
+++ build.boot
@@ -19,11 +19,11 @@

                  ;; App deps
                  [org.clojure/clojure         "1.7.0"]
-                 [org.clojure/clojurescript   "1.7.170"]
+                 [org.clojure/clojurescript   "1.7.228"]
                  [org.clojure/core.async      "0.2.374"]
-                 [reagent                     "0.5.0"]
+                 [reagent                     "0.5.1"]
                  [re-frame                    "0.5.0"]
-                 [replumb/replumb             "0.1.3-SNAPSHOT"]
+                 [replumb/replumb             "0.1.5-SNAPSHOT"]
                  [cljsjs/jqconsole            "2.13.1-0"]
                  [cljsjs/highlight            "8.4-0"]
                  [re-com                      "0.7.0-alpha2"]
@@ -32,7 +32,7 @@
                  [markdown-clj                "0.9.78"]
                  [hickory                     "0.5.4"]
                  [cljsjs/showdown             "0.4.0-1"]
-                 [org.clojure/tools.reader    "1.0.0-alpha1"]
+                 [org.clojure/tools.reader    "1.0.0-alpha3"]
                  [cljsjs/enquire              "2.1.2-0"]
                  [com.cemerick/piggieback     "0.2.1"]
                  [binaryage/devtools          "0.4.1"]


indenting

indenting

--- src/celestial/provider.clj
+++ src/celestial/provider.clj
@@ -46,7 +46,7 @@
   "specific model transformations"
   [res ts]
     (reduce
-      (fn [res [k v]] (update-in res [k] v )) res ts))
+      (fn [res [k v]] (update-in res [k] v)) res ts))

 (defn wait-for
   "A general wait for pred function"


fix color calculation

fix color calculation

--- src/chat/client/views.cljs
+++ src/chat/client/views.cljs
@@ -37,7 +37,7 @@
                        str
                        (.substring 33 36)
                        (js/parseInt 16)
-                       (->> (/ 4096)))]
+                       (/ 4096))]
     (str "hsl(" (* 360 normalized) ",50%,50%)")))

 (defn thread-tags-view [thread owner]


got basic motion working

got basic motion working

--- src/main/clojure/naojure/core.clj
+++ src/main/clojure/naojure/core.clj
@@ -708,7 +708,7 @@
                                             (limits joint-name))]
     (call-service robot :motion "angleInterpolationWithSpeed"
                   [joint-name
-                   (list (Float. pos-rad))
+                   (java.util.ArrayList. (list (Float. pos-rad)))
                    (Float. speed-fraction)])))

 (defn- do-joints
@@ -742,4 +742,4 @@
         channel (:channel options)
         joint-changes (only-joint-actions actions)
         joint-tasks (do-joints robot duration joint-changes)]
-    ))
+    joint-tasks))


Tweak spacing around images in topics.

Tweak spacing around images in topics.

--- src/oc/email/content.clj
+++ src/oc/email/content.clj
@@ -80,9 +80,10 @@
             (when title? (spacer 1))
             (when headline?
               [:p {:class "topic-headline"} headline])
-            (when image-url? (spacer 2))
+            (when image-url? (spacer 6))
             (when image-url?
               [:img {:src image-url}])
+            (when image-url? (spacer 4))
             (when body? (spacer 2))
             (when body? body)
             (spacer 10)]


Now a list of service names can be returned.

--- src/onix/persistence.clj
+++ src/onix/persistence.clj
@@ -26,11 +26,9 @@

 (defn list-applications
   []
-  (dynamo/lazy-scan applications-table {:conditions {} :attributes_to_get ["name"]} @dynamo-client)
-  ;; (dynamo/with-client
-  ;;   @dynamo-client
-  ;;   (dynamo/query applications-table {}))
-  )
+  {:applications
+   (map :name (dynamo/lazy-scan applications-table {:conditions {} :attributes_to_get ["name"]} @dynamo-client))}
+ )

 (defn dynamo-health-check
   "Checks that we can talk to Dynamo and get a description of one of our tables."
@@ -42,15 +40,3 @@
     true
     (catch AmazonServiceException e (warn e "AWS Dynamo service error") nil)
     (catch AmazonClientException e (warn e "AWS Dynamo client error") nil)))
-
-(dynamo/lazy-scan applications-table {:conditions {} :attributes_to_get ["name"]} @dynamo-client)
-
-
-;; (defn scan-dynamo
-;;   [entity-type table attribute]
-;;   (dynamo/lazy-scan table {:conditions {"entityType" (dynamo/create-condition :EQ entity-type)} :attributes_to_get [attribute]} @dynamo-client))
-
-
-;; (defn scan-entities
-;;   [entity-type]
-;;   (scan-dynamo entity-type (dynamo-entity-table) "entityId"))


Extract :id values from maps when converting to-id. Fixes #242.

--- src/overtone/sc/node.clj
+++ src/overtone/sc/node.clj
@@ -91,12 +91,15 @@

 (defn to-id
   "If object can be converted to an sc id, then return the sc id,
-   otherwise returns the object unchanged."
+   otherwise returns the object unchanged. Maps with :id keys will
+   convert to the associated value."
   [obj]
-    (try
+  (try
     (to-sc-id obj)
     (catch IllegalArgumentException e
-      obj)))
+      (if-let [id (:id obj)]
+        id
+        obj))))

 (defn idify
   "Attempts to convert all objs in col to a sc id. Maps objs to


Fix bug introduced in commit dd8b59d whereby a group wasn't considered to be a node, and therefore sending control messages to groups threw exceptions due to an apparent lack of 'liveness'.

--- src/overtone/sc/node.clj
+++ src/overtone/sc/node.clj
@@ -149,9 +149,12 @@
 ;; n_end event when a synth node is destroyed.

 (defn node?
-  "Returns true if obj is a synth node."
+  "Returns true if obj is a synth node i.e. a SynthNode or a
+   SynthGroup."
   [obj]
-  (= overtone.sc.node.SynthNode (type obj)))
+  (or
+   (= overtone.sc.node.SynthNode (type obj))
+   (= overtone.sc.node.SynthGroup (type obj))))

 (defn live-node?


nothing important

nothing important

--- src/Miscellaneous/make_src.clj
+++ src/Miscellaneous/make_src.clj
@@ -39,7 +39,7 @@

 (defn ->file [address-from address-to]
-  ((file-to address-to) (to-src address-from)))
+  ((file-to address-to) (to-srt address-from)))

 (defn ->file2 [address-from]
   (->file address-from (str address-from ".srt")))
@@ -50,14 +50,3 @@

 #_(->file2 "E:/mongoDB_courses/welcome")

-
-
-(def raw-json (slurp "E:/mongodb2_4/Bookstore.json"))
-
-(def distilled-json (apply str (string/split raw-json #"\n")))
-
-distilled-json
-
-((file-to "E:/mongodb2_4/Bookstore2.json") distilled-json)
-
-


Added remaining tests for common-fetcher module

--- test/emender_jenkins/common_fetcher_test.clj
+++ test/emender_jenkins/common_fetcher_test.clj
@@ -69,3 +69,18 @@
             (is (re-matches #"\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d" (:finished-on @status)))
             (is (>= (:last-duration @status) 0))))))

+(deftest test-run-fetcher
+    "Checking the function run-fetcher."
+    (testing "the function run-fetcher."
+        (with-redefs [run-fetcher-in-a-loop (fn [name sleep config func status] name)]
+            (= "Fetcher name" (run-fetcher "Fetcher name" 0 nil nil nil)))))
+
+(deftest test-run-fetcher-in-a-loop
+    "Checking the function run-fetcher-in-a-loop."
+    (testing "the function run-fetcher-in-a-loop."
+        (let [counter (atom 10)]
+        (with-redefs [run-fetcher-one-iteration (fn [name config func status]
+                                                    (swap! counter dec)
+                                                    (if (zero? @counter) (throw (RuntimeException. name))))]
+            (is (thrown-with-msg? RuntimeException #"Fetcher name" (run-fetcher-in-a-loop "Fetcher name" 0 nil nil nil)))))))
+


remove unnecessary markup

remove unnecessary markup

--- src/client/pages/play.cljs
+++ src/client/pages/play.cljs
@@ -39,10 +39,9 @@
       [:span.key-af1cf {:style "width:70px"} "Space"]]
     [:div.label-29ee4 "Hard Drop"]
     (if-not battle-mode?
-      [:div
-        [:div
-          [:span.key-af1cf {:style "font-family:arial"} "P"]]
-        [:div.label-29ee4 "Pause game"]])
+      (hiccups/html
+        [:div [:span.key-af1cf {:style "font-family:arial"} "P"]]
+        [:div.label-29ee4 "Pause game"]))
     [:div
       [:span.key-af1cf {:style "font-family:arial"} "M"]]
     [:div.label-29ee4 "Music on / off"]
@@ -63,12 +62,12 @@
     [:div#gameScreenLines.metric-b93a8]
     [:div.line-8975a]
     (if battle-mode?
-      [:div
+      (hiccups/html
         [:div.label-39b9c "Time Left"]
-        [:div#gameScreenTimeLeft.metric-b93a8]]
-      [:div
+        [:div#gameScreenTimeLeft.metric-b93a8])
+      (hiccups/html
         [:div.label-39b9c "Level"]
-        [:div#gameScreenLevel.metric-b93a8]])])
+        [:div#gameScreenLevel.metric-b93a8]))])

 (hiccups/defhtml game-html [battle-mode?]
   [:div.wrapper-08ed4


Login redirect cookie fix

Login redirect cookie fix

--- src/clj/salava/user/db.clj
+++ src/clj/salava/user/db.clj
@@ -435,8 +435,7 @@
         last-visited (last-visited ctx user-id)
         expires (+ (long (/ (System/currentTimeMillis) 1000)) (get-in ctx [:config :core :session :max-age]))]
     (-> ok-status
-        (assoc-in [:session :identity] {:id id :role role :private private :activated activated :last-visited last-visited :expires expires})
-        (assoc-in [:cookies "login_redirect"] {:value nil :max-age 600 :http-only true :path "/"}))))
+        (assoc-in [:session :identity] {:id id :role role :private private :activated activated :last-visited last-visited :expires expires}))))

 (defn finalize-login [ctx ok-res user-id pending-badge-id new-account]
   (save-pending-badge-and-email ctx user-id pending-badge-id new-account)


loosen up the parser

loosen up the parser

--- src/clj/tictag/tagtime.clj
+++ src/clj/tictag/tagtime.clj
@@ -19,11 +19,12 @@
               (str/replace #"\[[^\[\]]*\]" "")
               (str/split #" "))))

-(def formatter (f/formatter "yyyy.MM.dd HH:mm:ss E"))
+(def formatter (f/formatter t/utc "yyyy.MM.dd HH:mm:ss E" "yyyy-MM-dd HH:mm:ss E"))

 (defn parse-local-time [time-str]
   (when (= (count time-str) 23)
-    (f/parse formatter time-str)))
+    (try (f/parse formatter time-str)
+         (catch Exception e nil))))

 (defn sanity-check [ts tags]


Refine unused code

Refine unused code

--- src/cljam/fasta/reader.clj
+++ src/cljam/fasta/reader.clj
@@ -71,16 +71,6 @@
                      (map? s) (cons s (lazy-seq (read-fn* rdr name))))))]
     (read-fn rdr nil)))

-(def ^:private newline-character (char 10))
-(def ^:private return-character (char 13))
-
-(defn- newline*?
-  [c]
-  (or (= c newline-character)
-      (= c return-character)))
-
-(def newline? (memoize newline*?))
-
 (defn- read-sequence-with-offset
   [^FASTAReader rdr offset-start offset-end]
   (let [len (- offset-end offset-start)
@@ -131,6 +121,9 @@
          (.clear ~buffer)
          ba#)))

+(def ^:private gt-byte (byte \>))
+(def ^:private newline-byte (byte \newline))
+
 (defn- sequqntial-read*
   "Core function to read FASTA sequentially.
    Function f is called every time a single sequence finishes reading.
@@ -146,10 +139,10 @@
            (loop [i 0 name-line? false rname rname*]
              (if (< i bytes)
                (let [b (aget buf i)]
-                 (if (= b 62) ; \>
+                 (if (= b gt-byte)
                    (do (when-let [s (create-ba s-buf)] (f {:name rname :sequence s}))
                        (recur (inc i) true rname))
-                   (if (= b 10) ; \newline
+                   (if (= b newline-byte)
                      (if name-line?
                        (recur (inc i) false (create-ba n-buf))
                        (recur (inc i) name-line? rname))


rn implied-difference implied-deltas

rn implied-difference implied-deltas

--- src/cljc/commos/delta.cljc
+++ src/cljc/commos/delta.cljc
@@ -82,10 +82,10 @@
         :else
         [[:is [] [y]]]))

-(defn implied-difference
-  "Returns the implied difference in deltas so that no :is
-  replacements of maps or sets, or :ex dissociations of maps are
-  asserted."
+(defn implied-deltas
+  "Return deltas implied with (raw) delta so that no :is replacements
+  of whole maps or sets, or :ex dissociations of whole maps are
+  included."
   [val [op ks v :as delta]]
   (let [cur-v (get-in val ks)]
     (case op


RR: use app-state instead if empty-app-state fn for language cursor

--- src/cljs/hatti/shared.cljs
+++ src/cljs/hatti/shared.cljs
@@ -78,7 +78,7 @@
 ;; LANGUAGE

 (defn language-cursor []
-  (om/ref-cursor (:languages (om/root-cursor (empty-app-state)))))
+  (om/ref-cursor (:languages (om/root-cursor app-state))))

 (defn language-selector
    "A language selector and a following divider."


Basics of communication between client and server

--- src/cljs/skytwit/core.cljs
+++ src/cljs/skytwit/core.cljs
@@ -28,20 +28,57 @@
          (println (:?data (<! ch-chsk)))
          (recur))

+(defn handle-change
+  [e owner {:keys [text]}]
+  (om/set-state! owner :text (.. e -target -value)))
+
+(defn send-twitter-handle
+  [n]
+  (chsk-send! [:post/change {:name n}]))
+
+(defn input-field
+  [data owner]
+  (reify
+    om/IInitState
+    (init-state [_] {:text ""})
+    om/IRenderState
+    (render-state [this state]
+      (dom/div nil
+               (dom/h2 nil "Enter a twitter handle")
+               (dom/div nil
+                        (dom/input
+                          #js {:type "text" :ref "twitter-handle"
+                               :value (:text state)
+                               :onChange #(handle-change % owner state)})
+                        (dom/button #js {:onClick #(send-twitter-handle (:text state))}
+                                    "Change handle"))))))
+
+(defn statistics
+  [app owner]
+  (reify
+    om/IRender
+    (render [_]
+      (dom/pre nil (pr-str (->> (:tweets app)
+                                (mapcat :hashtags)
+                                frequencies))))))
+
+(defn refresh
+  [app owner]
+  (reify
+    om/IRender
+    (render [_]
+      (dom/button #js {:onClick #(chsk-send! [:get/update {}])}
+                  "Refresh data"))))
+
 (defn root-component [app owner]
   (reify
     om/IRender
     (render [_]
       (dom/div nil
                (dom/h1 nil (:user-name app))
-               (dom/pre nil (pr-str (->> (:tweets app)
-                                         (mapcat :hashtags)
-                                         frequencies)))
-               (dom/pre nil (pr-str app))
-               (dom/div #js {:onClick (fn []
-                                        (chsk-send! [:get/update {:msg "empty"}])
-                                        (js/alert "hello server"))}
-                        "click-me!")))))
+               (om/build input-field app)
+               (om/build statistics app)
+               (om/build refresh app)))))

 (om/root
  root-component


Add labels for terrain-effects table

Add labels for terrain-effects table

--- src/cljs/zetawar/data.cljs
+++ src/cljs/zetawar/data.cljs
@@ -64,6 +64,11 @@
     ;; Status information
     :hover-tile-location "Hovering over tile: "
     :none "none"
+    :movement-cost-label "Movement Cost"
+    :attack-bonus-label "Attack Bonus"
+    :armor-bonus-label "Armor Bonus"
+    :selected-label "Selected"
+    :targeted-label "Targeted"
     }})

 ;; TODO: remove redundant id keys (?)


Updated the API routes

Updated the API routes

--- src/clojars/routes/api.clj
+++ src/clojars/routes/api.clj
@@ -4,26 +4,37 @@
             [clojars.db :as db]
             [clojars.web.common :as common]
             [clojars.stats :as stats]
-            [cheshire.core :as json]))
+            [cheshire.core :as json]
+            [korma.core :refer [exec-raw]]))
+
+(defn get-artifact [group-id artifact-id]
+  (let [stats (stats/all)]
+    (some-> (db/find-jar group-id artifact-id)
+            (dissoc :id :created :promoted_at)
+            (assoc :recent_versions (db/recent-versions group-id artifact-id)
+                   :downloads (stats/download-count stats group-id artifact-id))
+            (update-in [:recent_versions] (fn [versions]
+                                            (map (fn [version]
+                                                   (assoc version :downloads (stats/download-count stats group-id artifact-id (:version version))))
+                                                 versions)))
+            json/generate-string)))

 (defroutes routes
   (context "/api" []
-    (GET ["/:group-id", :group-id #"[^/]+"] [group-id]
+    (GET ["/groups/:group-id", :group-id #"[^/]+"] [group-id]
       (let [stats (stats/all)]
         (-> (db/jars-by-groupname group-id)
             (->> (map (fn [jar]
-                        (assoc jar :downloads (stats/download-count stats group-id (:jar_name jar))))))
-            (json/generate-string))))
-    (GET ["/:group-id/:artifact-id", :group-id #"[^/]+", :artifact-id #"[^/]+"]
-      [group-id artifact-id]
-      (let [stats (stats/all)]
-        (some-> (db/find-jar group-id artifact-id)
-                (assoc :recent_versions (db/recent-versions group-id artifact-id)
-                       :downloads (stats/download-count stats group-id artifact-id))
-                (update-in [:recent_versions] (fn [versions]
-                                                (map (fn [version]
-                                                       (assoc version :downloads (stats/download-count stats group-id artifact-id (:version version))))
-                                                     versions)))
-                (json/generate-string))))
+                        (-> jar
+                            (dissoc :id :created :promoted_at)
+                            (assoc :downloads (stats/download-count stats group-id (:jar_name jar)))))))
+            json/generate-string)))
+    (GET ["/artifacts/:artifact-id", :artifact-id #"[^/]+"] [artifact-id]
+      (get-artifact artifact-id artifact-id))
+    (GET ["/artifacts/:group-id/:artifact-id", :group-id #"[^/]+", :artifact-id #"[^/]+"] [group-id artifact-id]
+      (get-artifact group-id artifact-id))
+    (GET "/users/:username" [username]
+      (-> {:groups (db/find-groupnames username)}
+          json/generate-string))
     (ANY "*" _
       (not-found nil))))


introduce session-go-to-url-or-destroy-session

--- src/shale/sessions.clj
+++ src/shale/sessions.clj
@@ -165,6 +165,13 @@
   Return nil or :webdriver-is-dead."
   (webdriver-go-to-url (resume-webdriver-from-id session-id) url))

+(defn session-go-to-url-or-destroy-session [session-id url]
+  "Asynchronously point a session to a url. Destroy the session if the
+  webdriver is dead. Return true if everything seems okay."
+  (let [okay (not (session-go-to-url session-id current-url))]
+    (when (not okay) (destroy-session session-id))
+    okay))
+
 (def ModifyArg
   "Modification to a session"
   (s/either
@@ -189,11 +196,8 @@
   (if (some #{session-id} (session-ids))
     (last
       (with-car*
-        (if (if current-url
-              (let [okay (not (session-go-to-url session-id current-url))]
-                (when (not okay) (destroy-session session-id))
-                okay)
-              true)
+        (if (or (not current-url)
+              (session-go-to-url-or-destroy-session session-id current-url))
             (let [sess-key (session-key session-id)
                   sess-tags-key (session-tags-key session-id)]
               (doall


Updated for new model namespace.

Updated for new model namespace.

--- src/simulacrum/api.clj
+++ src/simulacrum/api.clj
@@ -6,9 +6,9 @@
             [net.cgrand.enlive-html :as html]
             [incanter.core :as matrix]
             [incanter.stats :as stats]
-            [simulacrum.bigfive :as bigfive]
             [simulacrum.const :as const]
-            [simulacrum.ipip :as ipip]
             [simulacrum.math :as math]
+            [simulacrum.model.bigfive :as bigfive]
+            [simulacrum.model.ipip :as ipip]
             [simulacrum.util :as util]
             [simulacrum.version :as version]))


simplified video processing, removed stream saving

--- src/sormilla/video.clj
+++ src/sormilla/video.clj
@@ -24,7 +24,8 @@
   target)

 (defn read-fully [^InputStream in ^bytes buffer ^long offset ^long size]
-  (IOUtils/readFully in buffer offset size))
+  (IOUtils/readFully in buffer offset size)
+  buffer)

 (defn make-reader [^InputStream in]
   (fn []
@@ -34,11 +35,11 @@
         (read-fully in header 0 12)
         (let [signature    (bin/get-int header 0)
               header-size  (bin/get-short header 6)
-              payload-size (bin/get-int header 8)]
+              payload-size (bin/get-int header 8)
+              payload      (byte-array payload-size)]
           (when-not (= signature 0x45566150) (throw (java.io.IOException. (format "out of sync (0x%08X)" signature))))
           (read-fully in header 12 (- header-size 12))
-          (read-fully in payload 0 payload-size)
-          [[header header-size] [payload payload-size]])
+          (read-fully in payload 0 payload-size))
         (catch java.io.EOFException _
           nil)))))

@@ -54,22 +55,21 @@
     (if (neg? (.avcodec_open context codec)) (throw (Exception. "Could not open codec")))
     (.av_init_packet packet)

-    (fn ^BufferedImage [[^bytes buffer size]]
-      (set! (.size packet) size)
-      (set! (.data_base packet) (ba->ia buffer ibuffer size))
-      (set! (.data_offset packet) 0)
-
-      (.avcodec_decode_video2 context frame got-picture? packet)
-      (when (zero? (first got-picture?)) (throw (java.io.IOException. "Could not decode frame")))
-
-      (let [picture         (.displayPicture (.priv_data context))
-            width           (.imageWidth picture)
-            height          (.imageHeight picture)
-            picture-buffer  (int-array (* width height))
-            image           (BufferedImage. width height BufferedImage/TYPE_INT_RGB)]
-        (FrameUtils/YUV2RGB picture picture-buffer)
-        (.setRGB image 0 0 width height picture-buffer 0 width)
-        image))))
+    (fn ^BufferedImage [^bytes buffer]
+      (let [size (alength buffer)]
+        (set! (.size packet) size)
+        (set! (.data_base packet) (ba->ia buffer ibuffer size))
+        (set! (.data_offset packet) 0)
+        (.avcodec_decode_video2 context frame got-picture? packet)
+        (when (zero? (first got-picture?)) (throw (java.io.IOException. "Could not decode frame")))
+        (let [picture         (.displayPicture (.priv_data context))
+              width           (.imageWidth picture)
+              height          (.imageHeight picture)
+              picture-buffer  (int-array (* width height))
+              image           (BufferedImage. width height BufferedImage/TYPE_INT_RGB)]
+          (FrameUtils/YUV2RGB picture picture-buffer)
+          (.setRGB image 0 0 width height picture-buffer 0 width)
+          image)))))

 (def video-source (atom nil))

@@ -79,34 +79,28 @@
     (.setSoTimeout 2000)
     (.connect (InetSocketAddress. ^InetAddress @video-source 5555))))

-(defn save [^OutputStream out data]
-  (doseq [[buffer size] data]
-    (.write out buffer 0 size))
-  out)
-
 (def run (atom false))

-(defn video-streaming []
+(defn send-init-video [^Socket socket]
+  (doto (.getOutputStream socket)
+    (.write (byte-array (map bin/ubyte [1 0 0 0])))
+    (.flush)))
+
+(defn video-streaming-task []
   (try
     (while @run
       (let [socket      (open-socket)
-            out         (agent (io/output-stream (io/file (str "sormilla-" (.format (java.text.SimpleDateFormat. "yyyyMMdd-HHmmss") (java.util.Date.)) ".h264"))))
-            reader      (make-reader (BufferedInputStream. (.getInputStream socket)))
+            reader      (make-reader (-> socket .getInputStream BufferedInputStream.))
             decoder     (make-decoder)]
         (try
-          (doto (.getOutputStream socket)
-            (.write (byte-array (map bin/ubyte [1 0 0 0])))
-            (.flush))
+          (send-init-video socket)
           (while @run
-            (let [data (reader)]
-                (send-off out save data)
-                (swap! world assoc :image (decoder (second data)))))
+            (->> (reader) (decoder) (swap! world assoc :image)))
           (catch java.io.IOException e
             (println "I/O error:" e ": reconnecting...")
             (Thread/sleep 1000))
           (finally
-            (try (.close socket) (catch Exception _))
-            (try (.close ^OutputStream @out) (catch Exception _))))))
+            (try (.close socket) (catch Exception _))))))
     (catch Throwable e
       (println "exception while processing video stream" e)
       (.printStackTrace e))))
@@ -121,9 +115,9 @@
                (start! [this config]
                  (reset! run true)
                  (reset! video-source (if (:video-sim config)
-                                        (do (println "Using simulated video") (InetAddress/getByName nil))
-                                        (do (println "Real video") comm/drone-ip)))
-                 (task/submit :video video-streaming)
+                                        (InetAddress/getByName nil)
+                                        comm/drone-ip))
+                 (task/submit :video video-streaming-task)
                  config)
                (stop! [this]
                  (reset! run false)


allow_outbound all the things

allow_outbound all the things

--- src/terraboot/core.clj
+++ src/terraboot/core.clj
@@ -7,7 +7,7 @@
             [clojure.set :as set]))

 (def account-id "165664414043")
-(def default-sgs ["allow_ssh"])
+(def default-sgs ["allow_ssh" "allow_outbound"])

 (def ubuntu "ami-9b9c86f7")
 (def current-coreos-ami "ami-1807e377")


Show lunch and bistro times (even if they don't exist)

--- src/varjocafe/view.clj
+++ src/varjocafe/view.clj
@@ -22,11 +22,20 @@
                                           (html/substitute (food-line food)))
                  [:.menu] (html/after "\n        "))

+(def opening-times-category-name {:business "Aukioloajat"
+                                  :lounas   "Lounas"
+                                  :bistro   "Bistro"})
+
+(html/defsnippet opening-times-category "templates/layout.html" [:.restaurant-row.expanded :.opening-times :> html/any-node]
+                 [restaurant category]
+                 [:dt html/any-node] (html/replace-vars {:title (opening-times-category-name category)})
+                 [:dd] (html/content (->> (get-in restaurant [:information category :regular])
+                                          (format/opening-times-html))))
+
 (html/defsnippet opening-times "templates/layout.html" [:.restaurant-row.expanded :.opening-times]
                  [restaurant]
-                 [:dt html/any-node] (html/replace-vars {:title "Aukioloajat"})
-                 [:dd] (html/content (->> (get-in restaurant [:information :business :regular])
-                                          (format/opening-times-html))))
+                 [:.opening-times] (html/content (->> [:business :lounas :bistro]
+                                                      (map #(opening-times-category restaurant %)))))

 (html/defsnippet restaurant-row "templates/layout.html" [:.restaurant-row]
                  [restaurant dates]


remove temp meta tag for pinterest verification

--- src/pc/views/content.clj
+++ src/pc/views/content.clj
@@ -102,9 +102,6 @@
     [:link {:rel "stylesheet"       :href (pc.assets/asset-path "/css/app.css")}]
     [:link {:rel "stylesheet"       :href "https://fonts.googleapis.com/css?family=Roboto:500,900,100,300,700,400"}]

-    ;; temporary meta tag, to verify account on pinterest
-    [:meta {:name "p:domain_verify" :content "3382b742326a852747a8bbb04e8462e5"}]
-
     [:style "#om-app{min-height:100vh;background-size:10px 10px,10px 10px,100px 100px,100px 100px;background-color:rgba(51,51,51,1);background-image:linear-gradient(to bottom,rgba(85,85,85,.25)10%,rgba(85,85,85,0)10%),linear-gradient(to right,rgba(85,85,85,.25)10%,rgba(85,85,85,0)10%),linear-gradient(to bottom,rgba(85,85,85,.57)1%,rgba(85,85,85,0)1%),linear-gradient(to right,rgba(85,85,85,.57)1%,rgba(85,85,85,0)1%);}#om-app:active{cursor:wait;}"]

     (embed-json-in-head "window.Precursor"


Add exclamation point to train-model-file\!

--- project/analyze-data/src/analyze_data/train_model.clj
+++ project/analyze-data/src/analyze_data/train_model.clj
@@ -14,7 +14,7 @@
   :dataset    the dataset the model was trained on"
   (fn [model-type dataset] model-type))

-(defn train-model-file
+(defn train-model-file!
   "Like train-model, but accepts a file name for input and output.

   model-type: type of model to create


src/wlmmap/handler.clj (get-markers-toolserver): New function

* src/wlmmap/handler.clj (get-markers-toolserver): New function to
get the markers directly from the toolserver (need to be refactored.)

--- src/wlmmap/handler.clj
+++ src/wlmmap/handler.clj
@@ -124,6 +124,33 @@
 (def toolserver-url
   "http://toolserver.org/~erfgoed/api/api.php?action=search&format=json&limit=5000&props=lat|lon|name|registrant_url|id|image|lang|monument_article")

+(defremote get-markers-toolserver [bounds-string]
+  ;; FIXME Need to factor out the function below
+  (map #(when (and (not (nil? (:lat %)))
+                   (not (nil? (:lon %)))
+                   (not (or (nil? (:name %)) (= "" (:name %)))))
+          (let [reg (:registrant_url %)
+                id (:id %)
+                nam (cleanup-name (:name %))
+                imc (:image %)
+                img (codec/url-encode imc)
+                lng (:lang %)
+                emb (str "")
+                ilk (str "" emb "")
+                art (:monument_article %)
+                lnk "%s"
+                arl (format lnk lng (codec/url-encode art) art)
+                src (format "Source: %s" reg id)
+                all (str "
" nam "
"
+                         (when (not (= "" imc)) (str ilk "
"))
+                         (when (not (= "" art)) (str arl "
"))
+                         (when (not (= "" reg)) src))]
+            (list %2 (list (:lat %) (:lon %)) (= "" imc) all)))
+       (:monuments
+        ;; FIXME factor out the loooong string
+        (json/read-str (slurp (format "http://toolserver.org/~erfgoed/api/api.php?action=search&format=json&limit=5000&props=lat|lon|name|registrant_url|id|image|lang|monument_article&bbox=%s" bounds-string)) :key-fn keyword))
+       (range 100000)))
+
 (def db-options
   (atom
    (sort


Fix uneval not forcing nl in guide.

Fix uneval not forcing nl in guide.

--- src/zprint/zprint.cljc
+++ src/zprint/zprint.cljc
@@ -4824,6 +4824,7 @@
     ; remove it, or we're going to do a lot of nothing
     [(dissoc param-map :group-seq) previous-data out]
     (let [group-seq (if (and (empty? group-seq) zloc) nil group-seq)
+          uneval? (= (ztag zloc) :uneval)
           guided-newline? (= next-guide :newline)
           ; incoming-pairs is [pair-ind pair-result]
           do-pairs? (or (= next-guide :pair-end)
@@ -5116,6 +5117,9 @@
               ; Comments cause an overflow of the size, forcing the next
               ; thing onto a new line
               (or comment? comment-inline?) (inc width)
+	      ; Uneval stuff with a previous newline will force the next
+	      ; thing onto a new line
+	      (and uneval? previous-newline?) (inc width)
               ; If is multi-line, and we have more than one line, and
               ; we don't allow anything after a multi-line thing on
               ; the same line, then force the next thing onto a new line


gzip all assets

gzip all assets

--- src/pc/assets.clj
+++ src/pc/assets.clj
@@ -168,7 +168,8 @@
     (doseq [file (public-files)
             :when (not= \. (first (.getName file)))
             :let [key (str/replace-first (str file) "resources/public/" "")
-                  tag (md5 file)]]
+                  gzipped-bytes (gzip/gzip file)
+                  tag (byte-array->md5 gzipped-bytes)]]
       (let [existing (try+
                       (s3/get-object-metadata :bucket-name cdn-bucket :key key)
                       (catch AmazonS3Exception e
@@ -180,8 +181,11 @@
           (let [_ (log/infof "uploading %s to %s" (str file) key)
                 res (s3/put-object :bucket-name cdn-bucket
                                    :key key
-                                   :file file
+                                   :input-stream (java.io.ByteArrayInputStream. gzipped-bytes)
                                    :metadata {:content-type (mime-type-of file)
+                                              :content-md5 tag
+                                              :content-encoding "gzip"
+                                              :content-length (count gzipped-bytes)
                                               :cache-control "max-age=3155692"})]
             (log/infof "uploaded %s" res)
             (assert (= tag (:etag res)))
@@ -205,13 +209,16 @@
           assets (reduce (fn [acc path]
                            (let [file-path (str assets-directory path)
                                  md5 (md5 file-path)
+                                 gzipped-bytes (gzip/gzip file-path)
                                  ;; TODO: figure out a better way to handle leading slashes
                                  key (assetify (subs path 1) md5)]
                              (log/infof "pushing %s to %s" file-path key)
                              (s3/put-object :bucket-name cdn-bucket
                                             :key key
-                                            :input-stream (gzip/gzip file-path)
+                                            :input-stream (java.io.ByteArrayInputStream. gzipped-bytes)
                                             :metadata {:content-type (mime-type-of file-path)
+                                                       :content-length (count gzipped-bytes)
+                                                       :content-md5 (byte-array->md5 gzipped-bytes)
                                                        :content-encoding "gzip"
                                                        :cache-control "max-age=3155692"})
                              (assoc acc path {:s3-key key :s3-bucket cdn-bucket})))


first pass at multi player

first pass at multi player

--- src/tic_tac_toe/core.clj
+++ src/tic_tac_toe/core.clj
@@ -8,6 +8,8 @@
             [hiccup.form :as form]
             [hiccup.element :as element]
             [ring.util.response :as resp]
+            [ring.middleware.session :as session ]
+            [ring.util.response :as response]
 ))

 (def picture-map {:e "empty.png" :x "cross.png" :o "nought.png"})
@@ -149,7 +151,13 @@

 (defroutes app-routes
-  (GET "/" [] (get-board-atom))
+  (GET "/" {session :session} ;(get-board-atom)
+       (let [board (if (contains? session :board)
+                      (:board session)
+                      blank-board)]
+         (assoc (response/response (get-board board)) :session (assoc session :board board))))
+  (GET "/dump-session" {session :session} {:body (str "waaaaaa " session)
+                                           :session (assoc session :1 1)})
   (GET "/place-piece/:pos/:piece" [pos piece]
        (do
          (swap! board place-piece (keyword piece) (Integer/parseInt pos))
@@ -164,7 +172,8 @@

 (def app
   (-> app-routes
-      (handler/site)))
+      (handler/site)
+      (session/wrap-session)))

 (defn make-server
   ([]


fix bug (reported by Kurt) wherein non-default z axes were not updated

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

--- acqEngine/src/org/micromanager/acq_engine.clj
+++ acqEngine/src/org/micromanager/acq_engine.clj
@@ -401,10 +401,20 @@
               0))
          z-ref))))

+(defn update-z-positions [msp-index]
+  (let [msp (get-msp msp-index)]
+    (dotimes [i (.size msp)]
+      (let [stage-pos (.get msp i)
+            stage-name (.stageName stage-pos)]
+        (when (= 1 (.numAxes stage-pos))
+          (when (or (not (core isContinuousFocusEnabled))
+                    (core isContinuousFocusDrive stage-name))
+            (set-msp-z-position msp-index stage-name (get-z-stage-position stage-name))))))))
+
 (defn recall-z-reference [current-position]
   (let [z-drive (@state :default-z-drive)]
-    (when (and (or (not (core isContinuousFocusEnabled))
-                   (core isContinuousFocusDrive z-drive)))
+    (when (or (not (core isContinuousFocusEnabled))
+              (core isContinuousFocusDrive z-drive))
       (set-z-stage-position z-drive
         (or (get-msp-z-position current-position z-drive)
             (@state :reference-z))))))
@@ -414,7 +424,6 @@
     (when (and (or (not (core isContinuousFocusEnabled))
                    (core isContinuousFocusDrive z-drive)))
       (let [z (get-z-stage-position z-drive)]
-        (set-msp-z-position current-position z-drive z)
         (state-assoc! :reference-z z)))))

 ;; startup and shutdown
@@ -495,6 +504,7 @@
              (run-autofocus))
           #(when check-z-ref
              (store-z-reference current-position))
+          #(update-z-positions current-position)
           #(when z-drive
              (let [z (compute-z-position event)]
                (set-stage-position z-drive z)))


Minor changes. Took out run.

Minor changes. Took out run.

--- src/divergence/system.cljs
+++ src/divergence/system.cljs
@@ -128,20 +128,15 @@
                 [ax ay ar] (@e :acceleration)]]
     (when actions
       (when
-        (actions :left) (swap! e assoc-in [:acceleration] [-2 0 0]))
+        (actions :left) (swap! e assoc-in [:acceleration] [-3 0 0]))
       (when
-        (actions :right) (swap! e assoc-in [:acceleration] [2 0 0]))
+        (actions :right) (swap! e assoc-in [:acceleration] [3 0 0]))
       (when
         (actions :down) (swap! e assoc-in [:acceleration] [0 1 0]))
+      (when
+        (actions :up) (swap! e assoc-in [:acceleration] [0 -2 0]))
       (when (not-any? actions [:up :left :right :down])
-        (swap! e assoc-in [:acceleration] [0 0 0])))
-    (when
-        (and (actions :run) (actions :right)) (swap! e assoc-in [:acceleration] [4 0 0]))
-    (when
-        (and (actions :run) (actions :left)) (swap! e assoc-in [:acceleration] [-4 0 0]))
-    (when
-        (actions :up) (swap! e assoc-in [:acceleration] [0 -2 0]))
-    ))
+        (swap! e assoc-in [:acceleration] [0 0 0])))))

 (defn movement-caps [entities]
   (doseq [e entities]
@@ -150,8 +145,8 @@
            [ax ay ar] :acceleration
            } @e
           ]
-      (when (and (not (actions :run)) (> vx 6)) (swap! e assoc-in [:velocity] [6 vy vr]))
-      (when (and (not (actions :run)) (< vx -6)) (swap! e assoc-in [:velocity] [-6 vy vr]))
+      (when (and (not (actions :run)) (> vx 8)) (swap! e assoc-in [:velocity] [9 vy vr]))
+      (when (and (not (actions :run)) (< vx -8)) (swap! e assoc-in [:velocity] [-9 vy vr]))
       (when (and (< vy -4) (swap! e assoc-in [:velocity] [vx -4 vr])))
     ))
 );;Andrew


Take out head name

Take out head name

--- src/doctopus/db/schema.clj
+++ src/doctopus/db/schema.clj
@@ -38,7 +38,6 @@

 (def tentacle-schema
   [[:name "varchar(50)" "PRIMARY KEY"]
-;   [:head_name "varchar(50)"]
    [:output_root "varchar(50)"]
    [:html_commands "varchar(250)"]
    [:source_control "varchar(50)"]


Solved day 12

Solved day 12

--- src/adventofcode/solutions.clj
+++ src/adventofcode/solutions.clj
@@ -376,6 +376,31 @@
 ;simply:
 (reduce + (map #(s->int %) (re-seq #"\-?\d+" (slurp-day-input 12))))

+;part 2 a "bit" more involved :)
+(defn- move-on-balance-and-current
+  "a is balance and current position map, fb is function to apply against balance"
+  [a fb]
+  (-> a
+      (update :current inc)
+      (update :balance fb)))
+
+(defn- where-is-first-balanced
+  "Will find first occurence of particular char c which is balanced with it's counterpart ic"
+  [input c ic]
+  (reduce (fn [a x]
+            (condp = x                                       ;why not use "case"? Because case requires compile-time constants!!!
+              ic (move-on-balance-and-current a inc)
+              c (if (pos? (:balance a))
+                  (move-on-balance-and-current a dec)
+                  (reduced a))
+              (move-on-balance-and-current a identity)))
+          {:balance 0 :current 0}
+          input))
+
+(defn- where-jsobj-starts [s]
+  (- (count s) (:current (where-is-first-balanced (reverse s) \{ \}))))
+(defn- where-jsobj-ends [s]
+  (:current (where-is-first-balanced s \} \{)))

 (defn- rm-red-jsobj
   "Removes single JS object containing property with value 'red'"
@@ -384,17 +409,17 @@
     (when (>= lr 0)
       (let [llrs (subs input 0 lr)
             rlrs (subs input lr)
-            ob (.lastIndexOf llrs "{")
-            cb (.indexOf rlrs "}")]
-        (str (subs input 0 ob) (subs rlrs (inc cb)))))))
+            ob (where-jsobj-starts llrs)
+            cb (where-jsobj-ends rlrs)]
+        (str (subs input 0 (dec ob)) (subs rlrs (inc cb)))))))

 ;TODO: fix this, this is wrong, it is not taking into account that there can be objects
 ;prior to "red" valued property which breaks my conception
 (defn day12 [input]
   (reduce #(if %2
-            %2
-            (reduced (reduce
-                       +
-                       (map
-                         (fn [n] (s->int n)) (re-seq #"\-?\d+" %))))) (iterate rm-red-jsobj input)))
-
+                %2
+                (reduced (reduce
+                           +
+                           (map
+                             (fn [n] (s->int n)) (re-seq #"\-?\d+" %))))) (iterate rm-red-jsobj input)))
+


Day 9 completed

Day 9 completed

--- src/adventofcode/solutions.clj
+++ src/adventofcode/solutions.clj
@@ -105,13 +105,13 @@
               input))))

 ; day 6
-(defn- s2int [s] (Integer/parseInt s))
+(defn- s->int [s] (Integer/parseInt s))

 (def ^{:private true} day6-instruction-regex #"(\w+) (?<x0>\d+),(?<y0>\d+) through (?<x1>\d+),(?<y1>\d+)")

 (defn- day6-get-instruction [line]
   (let [[[_ action x0 y0 x1 y1]] (re-seq day6-instruction-regex line)]
-    [(keyword action) (s2int x0) (s2int y0) (s2int x1) (s2int y1)]))
+    [(keyword action) (s->int x0) (s->int y0) (s->int x1) (s->int y1)]))

 (def ^{:private true} actions-1 {:off    #(aset-int % %2 %3 0)
                                  :on     #(aset-int % %2 %3 1)
@@ -158,7 +158,7 @@

 (defn to-int [s]
   (when (and (not (st/blank? s)) (is-integer s))
-    (s2int s)))
+    (s->int s)))

 (defn day-7-get-instruction [line]
   (let [[_ _ _ lw oper rw target] (day7-instr-parts line)
@@ -267,16 +267,25 @@
       0
       input)))

-(defn day9 []
+(defn permutations [s]
+  (lazy-seq
+    (if (seq (rest s))
+      (apply concat (for [x s]
+                      (map #(cons x %) (permutations (remove #{x} s)))))
+      [s])))
+
+(defn day9
+  "Provide min/max as comp-f parameters for parts 1 and 2 respectively"
+  [comp-f]
   (let [input (day-input-line-seq 9)
-        distances (map #(let [[[_ from to dist]] (re-seq #"^(\w+) to (\w+) = (\d+)$" %)]
-                         [[from to] dist]) input)
-        places (reduce #(let [[[from to] _] %2]
-                         (conj % from to)) #{} distances)]
-    places))
-;TODO the idea is to generate cartesian product (resulting in veeeeery big set :( ) of locations
-;TODO and to go through them....
-
-;(defmacro cart-proddedup [set]
-;  (let [syms (map gensym set)
-;        `(for [~@(reduce #(conj % %2 'set) [])])]))+        distances (into {} (map #(let [[[_ from to dist]] (re-seq #"^(\w+) to (\w+) = (\d+)$" %)]
+                          [#{from to} (s->int dist)]) input))
+        places (reduce #(let [[endpoints _] %2]
+                         (conj % (first endpoints) (last endpoints))) #{} distances)
+        all-routes (permutations places)
+        route-len (fn [r] (reduce #(let [dist (distances %2)]
+                                    (+ dist %)) 0 (map set (partition 2 1 r))))]
+    (reduce #(comp-f % (route-len %2))
+            (route-len (first all-routes))
+            (rest all-routes))))
+


Logic for deciding when to spawn new villages

--- src/amindblowingworld/civs.clj
+++ src/amindblowingworld/civs.clj
@@ -149,19 +149,26 @@
   (fn []
     (let [s     (get-settlement id-settlement)
           event (rand-nth [:growing :shrinking :stable])]
-      (when (not (ghost-town? s))
+      (when (and s (not (ghost-town? s)))
         (when (= event :growing)
-          (let [perc (+ 1.0 (/ (rand) 4.0))
+          (let [perc (+ 1.0 (/ (rand) 5.0))
                 new-pop (int (* (.pop s) perc))]
             (update-settlement-pop id-settlement new-pop)))
         (when (= event :shrinking)
-          (let [perc (- 1.00 (/ (rand) 4.0))
+          (let [perc (- 1.00 (/ (rand) 8.0))
                 new-pop (int (* (.pop s) perc))]
             (update-settlement-pop id-settlement new-pop)))
         (let [s (get-settlement id-settlement)]
-          (when (and (< (.pop s) 50) (chance 0.35))
+          (when (and (< (.pop s) 70) (chance 0.35))
             (update-settlement-pop id-settlement 0)
-            (record-event "Village " (.name s) " is now a ghost town")))))))
+            (update-biome-map)
+            (record-event (str "Village " (.name s) " is now a ghost town") nil))
+          (when (and (> (.pop s) 500) (chance 0.1))
+            (println "Spawning a new village")
+            (update-biome-map)
+            ))))))
+
+(def fastness 1000)

 (defn- create-tribe-in-game [game]
   (let [id-tribe (.next-id game)
@@ -177,7 +184,7 @@
         game (assoc-in game [:tribes id-tribe] tribe)
         game (assoc-in game [:settlements id-settlement] settlement)]
       (run-randomly (update-tribe-fun id-tribe) 3000 10000)
-      (run-randomly (update-settlement-fun id-settlement) 3000 10000)
+      (run-randomly (update-settlement-fun id-settlement) (* fastness 3) (* fastness 10))
       (record-event (str "Creating tribe " name-tribe) pos)
       (record-event (str "Creating village " name-settlement) pos)
       (update-biome-map)