Modify behaviour of File->Parse to always define path on the Parse it creates.

--- src/incise/parsers/html.clj
+++ src/incise/parsers/html.clj
@@ -12,20 +12,25 @@
             [clojure.java.io :refer [file reader]])
   (:import [java.io File]))

+(defn meta-and-content->Parse [parse-meta content]
+  (let [meta-with-defaults (merge {:extension "/index.html"
+                                   :content content} parse-meta)]
+    (map->Parse
+      (assoc meta-with-defaults
+             :path (help/meta->path meta-with-defaults)))))
+
 (defn File->Parse
   [content-fn ^File file]
   (let [file-str (slurp file)
         parse-meta (edn/read-string file-str)
         content (content-fn (second (s/split file-str #"\}" 2)))
-        parse-data (merge {:extension "/index.html"
-                           :content content} parse-meta)
-        parse-from-file (map->Parse parse-data)]
+        parse-from-file (meta-and-content->Parse parse-meta content)]
     (record-parse (.getCanonicalPath file) parse-from-file)
     parse-from-file))

 (defn write-Parse
   [^incise.parsers.core.Parse parse-data]
-  (let [out-file (file (conf/get :out-dir) (help/Parse->path parse-data))]
+  (let [out-file (file (conf/get :out-dir) (:path parse-data))]
     (-> out-file
         (.getParentFile)
         (.mkdirs))


lein2 placeholder support in tests file

lein2 placeholder support in tests file

--- src/leiningen/fore_prob.clj
+++ src/leiningen/fore_prob.clj
@@ -81,9 +81,12 @@
   "return the content of the main tests file of the current project, stripped
    out of any 'replace-me' placeholder test"
   [project]
-  (cs/replace
+  (->
     (slurp (tests-path project))
-    #"(?m)^\(deftest replace-me[^)]+\)+$" ""))
+    ;; lein1
+    (cs/replace #"(?m)^\(deftest replace-me[^)]+\)+$" "")
+    ;; lein2
+    (cs/replace #"(?m)^\(deftest a-test\s+\(testing \"FIXME[^)]+\)+$" "")))

 (defn- get-src
   "return the content of the main source file of the current project"
@@ -137,11 +140,17 @@

 (def fore-url "http://4clojure.com/api/problem/")

-(defn get-prob
-  "Return a problem map from its number using 4clojure API"
+(defn- prob-url
+  "return an API URL for a problem number. This doesn’t check that the URL is
+   valid"
   [n]
-  (let [req (http/get (str fore-url n) {:as :json
-                                        :throw-exceptions false})]
+  (str fore-url n))
+
+(defn- get-prob
+  "return a problem map from its number using 4clojure API"
+  [n]
+  (let [req (http/get (prob-url n) {:as :json
+                                    :throw-exceptions false})]
     (if (= (req :status) 200)
       ;; we don't need scores here and it's polluting debug logs
       (dissoc (req :body) :scores))))


show edit name tooltip even if not editable

--- src-cljs/frontend/components/aside.cljs
+++ src-cljs/frontend/components/aside.cljs
@@ -120,7 +120,7 @@
           [:section.aside-people
            (let [show-mouse? (get-in app [:subscribers client-id :show-mouse?])]
              [:a.people-you {:key client-id
-                  :data-bottom (when (and can-edit? (not change-username-learned?)) "Click to edit")
+                  :data-bottom (when-not change-username-learned? "Click to edit")
                   :role "button"
                   :on-click #(if can-edit?
                                (om/set-state! owner :editing-name? true)


added special messaging for our exit code 65 failures

--- src-cljs/frontend/components/build.cljs
+++ src-cljs/frontend/components/build.cljs
@@ -27,33 +27,43 @@
             [om.core :as om :include-macros true])
     (:require-macros [frontend.utils :refer [html defrender]]))

-(defn infrastructure-fail-message [owner]
-  (if-not (enterprise?)
-    [:div
-     "Looks like we had a bug in our infrastructure, or that of our providers (generally "
-     [:a {:href "https://status.github.com/"} "GitHub"]
-     " or "
-     [:a {:href "https://status.aws.amazon.com/"} "AWS"]
-     ") We should have automatically retried this build. We've been alerted of"
-     " the issue and are almost certainly looking into it, please "
-     (common/contact-us-inner owner)
-     " if you're interested in the cause of the problem."]
-
+(defn infrastructure-fail-message [owner fail-reason]
+  (if (enterprise?)
     [:div
      "Looks like you may have encountered a bug in the build infrastructure. "
      "Your build should have been automatically retried.  If the problem persists, please "
      (common/contact-us-inner owner)
-     ", so CircleCI can investigate."]))
-
+     ", so CircleCI can investigate."]
+
+    (cond
+      (= fail-reason "exit-code-65-bug")
+      [:div "This build failed as an \"Exit Code 65\" bug. "
+       "You will not be charged for this build and it will be retried up to 3 times."
+       "To follow progress regarding the root cause of this error, please follow "
+       [:a {:href "https://discuss.circleci.com/t/xcode-exit-code-65/4284/9"
+            :target "_blank"}
+        "this Discuss post."]]
+
+      :else
+      [:div
+       "Looks like we had a bug in our infrastructure, or that of our providers (generally "
+       [:a {:href "https://status.github.com/"} "GitHub"]
+       " or "
+       [:a {:href "https://status.aws.amazon.com/"} "AWS"]
+       ") We should have automatically retried this build. We've been alerted of"
+       " the issue and are almost certainly looking into it, please "
+       (common/contact-us-inner owner)
+       " if you're interested in the cause of the problem."])))

 (defn report-error [{:keys [build show-premium-content?]} owner]
   (let [build-id (build-model/id build)
-        build-url (:build_url build)]
+        build-url (:build_url build)
+        fail-reason (:fail_reason build)]
     (when (:failed build)
       [:div.alert.alert-danger.iconified
        [:div [:img.alert-icon {:src (common/icon-path "Info-Error")}]]
        (if (:infrastructure_fail build)
-         (infrastructure-fail-message owner)
+         (infrastructure-fail-message owner fail-reason)
          [:div.alert-wrap
           "If you continue to get stuck, we suggest checking out our "
           [:a (open-ext {:href "https://circleci.com/docs/troubleshooting/"})


Moved to form style display.

Moved to form style display.

--- src-cljs/kixi/hecuba/tabs/profiles.cljs
+++ src-cljs/kixi/hecuba/tabs/profiles.cljs
@@ -13,6 +13,35 @@
         first
         :profiles))

+(defn handle-change [owner key e]
+  (let [value (.-value (.-target e))]
+    (om/set-state! owner [:profile_data key] value)))
+
+(defn text-control [data state owner key label]
+  [:div.form-group
+   [:label.control-label {:for (name key)} label]
+   (if (:editing state)
+     [:div
+      [:input {:defaultValue (get data key "")
+               :class "form-control"
+               :on-change #(handle-change owner key %1)
+               :type "text"
+               :id (name key)}]]
+     [:p {:class "form-control-static col-md-10"} (get data key "")])])
+
+(defn text-area-control [data state owner key title]
+  (let [text (get data key)]
+    (if (:editing state)
+      [:div
+       [:div.form-group
+        [:label.control-label  title]
+        [:form {:role "form"}
+         [:textarea.form-control {:on-change #(handle-change owner key %1) :rows 2} text]]]]
+      (if (and text (re-find #"\w" text))
+        [:div [:h3 title]
+         [:p text]]
+        [:div {:class "hidden"} [:p {:class "form-control-static col-md-10"} text]]))))
+
 (defn format-time-inst [t format]
   (if (nil? t)
     "Undated"
@@ -54,13 +83,13 @@
             [:div {:class (profile-column-width)}
              (bs/panel
               "Occupancy"
-              [:dl
-               [:dt "Occupancy Under 18"] [:dd (display profile_data :occupancy_under_18)]
-               [:dt "Occupancy 18 To 60"] [:dd (display profile_data :occupancy_18_to_60)]
-               [:dt "Occupancy Over 60"] [:dd (display profile_data :occupancy_over_60)]
-               [:dt "Occupant Change"] [:dd (display profile_data :occupant_change)]])]))]))))
-
-(defn measurements-row [profiles ownwer]
+              [:div
+               (text-control profile_data state owner :occupancy_under_18 "Occupancy Under 18")
+               (text-control profile_data state owner :occupancy_18_to_60 "Occupancy 18 To 60")
+               (text-control profile_data state owner :occupancy_over_60 "Occupancy Over 60")
+               (text-control profile_data state owner :occupant_change "Occupant Change")])]))]))))
+
+(defn measurements-row [profiles owner]
   (reify
     om/IRenderState
     (render-state [_ state]
@@ -71,19 +100,19 @@
             [:div {:class (profile-column-width)}
              (bs/panel
               "Measurements"
-              [:dl
-               [:dt "Footprint (internal groundfloor area (m2)"] [:dd (display profile_data :footprint)]
-               [:dt "External Perimeter (m)"] [:dd (display profile_data :external_perimeter)]
-               [:dt "Gross Internal Area (m2)"] [:dd (display profile_data :gross_internal_area)]
-               [:dt "Number Of Storeys"] [:dd (display profile_data :number_of_storeys)]
-               [:dt "Total Volume (m3)"] [:dd (display profile_data :total_volume)]
-               [:dt "Total Rooms"] [:dd (display profile_data :total_rooms)]
-               [:dt "Total Bedrooms"] [:dd (display profile_data :bedroom_count)]
-               [:dt "Habitable Rooms"] [:dd (display profile_data :habitable_rooms)]
-               [:dt "Inadequate Heating?"] [:dd (display profile_data :inadequate_heating)]
-               [:dt "Heated Habitable Rooms"] [:dd (display profile_data :heated_habitable_rooms)]])]))]))))
-
-(defn energy-row [profiles ownwer]
+              [:div
+               (text-control profile_data state owner :footprint "Footprint (internal groundfloor area (m2)")
+               (text-control profile_data state owner :external_perimeter "External Perimeter (m)")
+               (text-control profile_data state owner :gross_internal_area "Gross Internal Area (m2)")
+               (text-control profile_data state owner :number_of_storeys "Number Of Storeys")
+               (text-control profile_data state owner :total_volume "Total Volume (m3)")
+               (text-control profile_data state owner :total_rooms "Total Rooms")
+               (text-control profile_data state owner :bedroom_count "Total Bedrooms")
+               (text-control profile_data state owner :habitable_rooms "Habitable Rooms")
+               (text-control profile_data state owner :inadequate_heating "Inadequate Heating?")
+               (text-control profile_data state owner :heated_habitable_rooms "Heated Habitable Rooms")])]))]))))
+
+(defn energy-row [profiles owner]
   (reify
     om/IRenderState
     (render-state [_ state]
@@ -94,20 +123,33 @@
             [:div {:class (profile-column-width)}
              (bs/panel
               "Energy"
-              [:dl
-               [:dt "DER (kgCO2/m2/yr)"] [:dd (display profile_data :der)]
-               [:dt "TER (kgCO2/m2/yr)"] [:dd (display profile_data :ter)]
-               [:dt "Total Primary Energy Requirement"] [:dd (display profile_data :primary_energy_requirement)]
-               [:dt "Space Heating Requirement"] [:dd (display profile_data :space_heating_requirement)]
-               [:dt "Annual Space Heating Requirement"] [:dd (display profile_data :annual_space_heating_requirement)]
-               ;; hot water?
-               [:dt "Renewable Contribution Heat"] [:dd (display profile_data :renewable_contribution_heat)]
-               [:dt "Renewable Contribution Elec"] [:dd (display profile_data :renewable_contribution_elec)]
-
-               [:dt "Electricity Meter Type"] [:dd (display profile_data :electricity_meter_type)]
-               [:dt "Linked to Mains Gas Supply"] [:dd (display profile_data :mains_gas)]
-               [:dt "Electricity Storage Present"] [:dd (display profile_data :electricity_storage_present)]
-               [:dt "Heat Storage Present"] [:dd (display profile_data :heat_storage_present)]])]))]))))
+              [:div
+               (text-control profile_data state owner :der "DER (kgCO2/m2/yr)")
+               (text-control profile_data state owner :ter "TER (kgCO2/m2/yr)")
+               (text-control profile_data state owner :primary_energy_requirement "Total Primary Energy Requirement")
+               (text-control profile_data state owner :space_heating_requirement "Space Heating Requirement")
+               (text-control profile_data state owner :annual_space_heating_requirement "Annual Space Heating Requirement")
+               (text-control profile_data state owner :renewable_contribution_heat "Renewable Contribution Heat")
+               (text-control profile_data state owner :renewable_contribution_elec "Renewable Contribution Elec")
+               (text-control profile_data state owner :electricity_meter_type "Electricity Meter Type")
+               (text-control profile_data state owner :mains_gas "Linked to Mains Gas Supply")
+               (text-control profile_data state owner :electricity_storage_present "Electricity Storage Present")
+               (text-control profile_data state owner :heat_storage_present "Heat Storage Present")])]))]))))
+
+(defn efficiency-row [profiles ownwer]
+  (reify
+    om/IRenderState
+    (render-state [_ state]
+      (html
+       [:div.col-md-12
+        (for [profile profiles]
+          (let [profile_data (:profile_data profile)]
+            [:div {:class (profile-column-width)}
+             (bs/panel
+              "Energy"
+              [:div
+
+               ])]))]))))

 (defn profile-rows [profiles owner]
@@ -116,11 +158,12 @@
     (render-state [_ state]
       (html
        [:div.col-md-12
-        (om/build header-row profiles)
-        (om/build occupancy-row profiles)
-        (om/build measurements-row profiles)
-        (om/build energy-row profiles)
-        ;; (om/build efficiency profiles)
+        [:form {:role "form"}
+         (om/build header-row profiles)
+         (om/build occupancy-row profiles)
+         (om/build measurements-row profiles)
+         (om/build energy-row profiles)
+         (om/build efficiency-row profiles)]
         ;; (om/build flats profiles)
         ;; (om/build firepalces profiles)
         ;; (om/build glazing profiles)


More fixes for carmine in stormspec

More fixes for carmine in stormspec

--- src/polismath/stormspec.clj
+++ src/polismath/stormspec.clj
@@ -48,9 +48,9 @@
 (defspout poll-spout ["type" "zid" "batch"] {:prepare true :params [type poll-fn timestamp-key poll-interval]}
   [conf context collector]
   (let [last-timestamp (atom 0)]
-    (if (= poll-fn :sim-poll)
-      (log/info "Starting sim poller!")
-      (start-sim-poller!))
+    ;(if (= poll-fn :sim-poll)
+      ;(log/info "Starting sim poller!")
+      ;(start-sim-poller!))
     (spout
       (nextTuple []
         (log/info "Polling" type ">" @last-timestamp)
@@ -116,6 +116,7 @@
      ;["-s" "--sim"]
      ["-r" "--recompute"]]
     ;sim/cli-options
+    []
     ))


Assert that Last-Modified is set

Assert that Last-Modified is set

--- test/cljc/reitit/ring_test.cljc
+++ test/cljc/reitit/ring_test.cljc
@@ -286,9 +286,11 @@
          (testing "different file-types"
            (let [response (app {:uri "/files/hello.json", :request-method :get})]
              (is (= "application/json" (get-in response [:headers "Content-Type"])))
+             (is (get-in response [:headers "Last-Modified"]))
              (is (= "{\"hello\": \"file\"}" (slurp (:body response)))))
            (let [response (app {:uri "/files/hello.xml", :request-method :get})]
              (is (= "text/xml" (get-in response [:headers "Content-Type"])))
+             (is (get-in response [:headers "Last-Modified"]))
              (is (= "<xml><hello>file</hello></xml>\n" (slurp (:body response))))))

          (testing "not found"
@@ -301,4 +303,5 @@
                  raise ::not-called]
              (app {:uri "/files/hello.xml", :request-method :get} respond raise)
              (is (= "text/xml" (get-in @result [:headers "Content-Type"])))
+             (is (get-in @result [:headers "Last-Modified"]))
              (is (= "<xml><hello>file</hello></xml>\n" (slurp (:body @result))))))))))


Number layers correctly in tests

Number layers correctly in tests

--- test/cljs/fatlip/core_test.cljs
+++ test/cljs/fatlip/core_test.cljs
@@ -24,19 +24,19 @@
     (is (= (count (-> graph :layers (get 0) :nodes))
            (count (-> ordered-graph :layers (get 0) :nodes))
            3)
-        "Number of nodes in layer 1")
+        "Number of nodes in layer 0")
     (is (= (count (-> graph :layers (get 1) :nodes))
            (count (-> ordered-graph :layers (get 1) :nodes))
            6)
-        "Number of nodes in layer 2")
+        "Number of nodes in layer 1")
     (is (= (count (-> graph :layers (get 2) :nodes))
            (count (-> ordered-graph :layers (get 2) :nodes))
            3)
-        "Number of nodes in layer 3")
+        "Number of nodes in layer 2")
     (is (= (count (-> graph :layers (get 3) :nodes))
            (count (-> ordered-graph :layers (get 3) :nodes))
            1)
-        "Number of nodes in layer 4")
+        "Number of nodes in layer 3")
     (is (= (count (:p graph)) 2) "Number of p nodes")
     (is (= (count (:q graph)) 2) "Number of q nodes")
     (is (= (count (:r graph)) 2) "Number of r nodes")


Fixed first line format and parsing.

Fixed first line format and parsing.

--- nav-obj-splitter.clj
+++ nav-obj-splitter.clj
@@ -19,7 +19,8 @@
     (= type "Page") 8))

 (defn parse-first-line [line]
-  (let [matches (re-find (re-pattern #"^(.+) (\d+) (.+)") line)
+  (let [first-line-format #"^OBJECT (.+) (\d+) (.+)"
+        matches (re-find (re-pattern first-line-format) line)
         type (nth matches 1)
         id (nth matches 2)
         name (nth matches 3)]
@@ -36,3 +37,4 @@
 (parse-first-line "Table 100 Test Table")
 (def objmeta (parse-first-line "Table 100 Test Table"))
 (make-single-file-name objmeta)
+(parse-first-line "OBJECT Table 70902 Test Table (48)")


Added documentation to functions. New namespace.

--- nav-obj-splitter.clj
+++ nav-obj-splitter.clj
@@ -1,8 +1,10 @@
-(ns nav.big-object-text-file.split
+(ns nav.source.split
   (:use [clojure.test]
         [clojure.string :only [join]]))

-(defn type-id [type]
+(defn type-id
+  "Returns the NAV specific type id for the object type."
+  [type]
   (cond
     (= type "Table") 1
     (= type "Form") 2
@@ -13,7 +15,9 @@
     (= type "MenuSuite") 7
     (= type "Page") 8))

-(defn parse-first-line [line]
+(defn parse-first-line
+  "Parses meta data from the first line of the object source file."
+  [line]
   (let [first-line-format #"^OBJECT (.+) (\d+) (.+)"
         matches (re-find (re-pattern first-line-format) line)
         type (nth matches 1)
@@ -21,7 +25,9 @@
         name (nth matches 3)]
     {:type-id (type-id type) :type type :id id :name name}))

-(defn make-single-file-name [object-metadata]
+(defn make-single-file-name
+  "Returns a file name built from object meta data."
+  [object-metadata]
   (let [type-id (:type-id object-metadata)
         type (:type object-metadata)
         id (:id object-metadata)


Remove date time test.

Remove date time test.

--- test/incognito/transit_test.clj
+++ test/incognito/transit_test.clj
@@ -21,26 +21,6 @@
                                                          (atom {'incognito.transit_test.Bar
                                                                 (fn [foo] (assoc foo :c "banana"))}))}})]
                  (transit/write writer bar)
-                 (let [bais (ByteArrayInputStream. (.toByteArray baos))
-                       reader (transit/reader bais :json
-                                              {:handlers {"incognito"
-                                                          (incognito-read-handler (atom {}))}})]
-                   (transit/read reader)))))))))
-
-#_(defrecord DateTime [ts])
-
-#_(deftest incognito-roundtrip-date-time-test
-  (testing "Test incognito date-time transport."
-    (let [now (t/now)]
-      (is (= #incognito.base.IncognitoTaggedLiteral{:tag 'org.joda.time.DateTime,
-                                                    :value "2017-04-17T13:11:29.977Z"}
-             (with-open [baos (ByteArrayOutputStream.)]
-               (let [writer (transit/writer baos :json
-                                            {:handlers {org.joda.time.DateTime
-                                                        (incognito-write-handler
-                                                         (atom {'org.joda.time.DateTime
-                                                                (fn [r] (->DateTime (str r)))}))}})]
-                 (transit/write writer now)
                  (let [bais (ByteArrayInputStream. (.toByteArray baos))
                        reader (transit/reader bais :json
                                               {:handlers {"incognito"


Removed bogus dtd references from tests

Removed bogus dtd references from tests

--- test/notv_backend/core_test.clj
+++ test/notv_backend/core_test.clj
@@ -4,13 +4,13 @@

 (def trivial-xml
   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
-   <!DOCTYPE tv SYSTEM \"xmltv.dtd\">
+   <!DOCTYPE tv>
    <tv source-info-url=\"multiple\" source-data-url=\"multiple\" generator-info-name=\"XMLTV\" generator-info-url=\"http://xmltv.org/\">
    </tv>")

 (def non-trivial-xml
   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
-   <!DOCTYPE tv SYSTEM \"xmltv.dtd\">
+   <!DOCTYPE tv>
    <tv source-info-url=\"multiple\" source-data-url=\"multiple\" generator-info-name=\"XMLTV\" generator-info-url=\"http://xmltv.org/\">
      <channel id=\"channel-1\">
        <display-name lang=\"fi\">CHANNEL-1</display-name>


[lein] Add lein-ancient

[lein] Add lein-ancient

For finding outdated dependencies.

--- lein/.lein/profiles.clj
+++ lein/.lein/profiles.clj
@@ -1,2 +1,3 @@
 {:user {:plugins [[nightlight/lein-nightlight "1.6.3"]
-                  [lein-auto "0.1.3"]]}}
+                  [lein-auto "0.1.3"]
+                  [lein-ancient "0.6.10"]]}}


s/medium/(medium)/

s/medium/(medium)/

--- src/babel/english.cljc
+++ src/babel/english.cljc
@@ -21,8 +21,8 @@
                            ;;temporary
                            copy]]))

-(def lexicon (:lexicon medium))
-(def grammar (:grammar-map medium))
+(def lexicon (:lexicon (medium)))
+(def grammar (:grammar-map (medium)))

 (defn fo-ps [expr]
   (parse/fo-ps expr fo))


Setting up the route for post formats to server

--- pp-server/src/pp_server/core/handler.clj
+++ pp-server/src/pp_server/core/handler.clj
@@ -3,8 +3,11 @@
             [compojure.route :as route]
             [ring.middleware.defaults :refer [wrap-defaults site-defaults]]))

+;; TODO: eventually abstract the route to take a type
+;; this will help use a map of functions to the type.
 (defroutes app-routes
-  (GET "/" [] "Hello World")
+  (POST "/format/:type" request
+    request) ;; TODO: just echos request currently
   (route/not-found "Not Found"))

 (def app


Added more tests. Also nicer ones.

Added more tests. Also nicer ones.

--- test/staircase/test/handler.clj
+++ test/staircase/test/handler.clj
@@ -1,53 +1,84 @@
 (ns staircase.test.handler
-  (:require [staircase.protocols])
-  (:import staircase.protocols.Resource)
+  (:require [cheshire.core :as json]
+            [com.stuartsierra.component :as component])
   (:use clojure.test
+        staircase.protocols
         ring.mock.request
         staircase.handler))

-(defrecord MockResource [existance things updated]
-  staircase.protocols.Resource
+(defrecord MockResource [existance things]
+  Resource

   (exists? [_ id] existance)
   (get-all [_] things)
   (get-one [_ id] (first (filter #(= (str (:id %1)) (str id)) things)))
-  (update [_ id doc] updated)
+  (update [this id doc] (merge (get-one this id) doc))
   (delete [_ id])
   (create [_ doc] (doc "id")))

-(def histories (MockResource. true (map #(hash-map :id %1 :data "mock") (range 3)) {:updated true}))
-(def steps (MockResource. true [] nil))
+(defn json-request [meth path & [payload]]
+  (let [req (-> (request meth path)
+                (header "Accept" "application/json"))]
+    (if payload
+      (-> req (body (json/generate-string payload)) (content-type "application/json"))
+      req)))

-(def app (-> (new-router) (assoc :histories histories) (assoc :steps steps) (.start) :handler))
+(defn data-is [resp expected]
+  (is (= (json/parse-string (:body resp) true) expected)))

-(defn json-request [meth path]
-  (-> (request meth path) (header "Accept" "application/json") (content-type "application/json")))
+(deftest test-empty-app
+  (let [histories (MockResource. false [])
+        steps (MockResource. false [])
+        app (-> (new-router) (assoc :histories histories :steps steps) (component/start) :handler)]

-(deftest test-app
-  (testing "main route"
-    (let [response (app (request :get "/"))]
-      (is (= (:status response) 200))
-      (is (= (:body response) "Hello World"))))
+    (testing "GET /histories/1"
+      (let [req (json-request :get "/histories/1")
+            response (app req)]
+        (is (= (:status response) 404))))

-  (testing "GET /histories"
-    (let [req (json-request :get "/histories")
-          response (app req)]
-      (is (= (:status response) 200))
-      (is (= (:body response) "[{\"data\":\"mock\",\"id\":0},{\"data\":\"mock\",\"id\":1},{\"data\":\"mock\",\"id\":2}]"))))
+    (testing "GET /histories"
+      (let [req (json-request :get "/histories")
+            response (app req)]
+        (is (= (:status response) 200))
+        (data-is response [])))))

-  (testing "POST /histories"
-    (let [req (-> (json-request :post "/histories")
-                  (body "{\"id\": 1}"))
-          response (app req)]
-      (is (= (:status response) 200))
-      (is (= (:body response) "{\"data\":\"mock\",\"id\":1}"))))
+(deftest test-app-with-stuff
+  (let [histories (MockResource. true (map #(hash-map :id %1 :data "mock") (range 3)))
+        steps (MockResource. true [])
+        app (-> (new-router) (assoc :histories histories :steps steps) (component/start) :handler)]

-  (testing "GET /histories/1"
-    (let [req (-> (json-request :get "/histories/1"))
-          response (app req)]
-      (is (= (:status response) 200))
-      (is (= (:body response) "{\"data\":\"mock\",\"id\":1}"))))
-
-  (testing "not-found route"
-    (let [response (app (request :get "/invalid"))]
-      (is (= (:status response) 404)))))
+    (testing "main route"
+      (let [response (app (request :get "/"))]
+        (is (= (:status response) 200))
+        (is (= (:body response) "Hello World"))))
+
+    (testing "GET /histories"
+      (let [req (json-request :get "/histories")
+            response (app req)]
+        (is (= (:status response) 200))
+        (data-is response [{:data "mock" :id 0} {:data "mock" :id 1} {:data "mock" :id 2}])))
+
+    (testing "POST /histories"
+      (let [req (json-request :post "/histories" {:id 1})
+            response (app req)]
+        (is (= (:status response) 200))
+        (data-is response {:data "mock" :id 1})))
+
+    (testing "GET /histories/1"
+      (let [req (json-request :get "/histories/1")
+            response (app req)]
+        (is (= (:status response) 200))
+        (data-is response {:data "mock" :id 1})))
+
+    (testing "PUT /histories/1"
+      (let [response (app (json-request :put "/histories/1" {:updated true}))]
+        (is (= (:status response) 200))
+        (data-is response {:data "mock" :id 1 :updated true})))
+
+    (testing "DELETE /histories/id"
+      (let [response (app (request :delete "/histories/1"))]
+        (is (= (:status response) 204))))
+
+    (testing "not-found route"
+      (let [response (app (request :get "/invalid"))]
+        (is (= (:status response) 404))))))


Rename ns appropriately

Rename ns appropriately

--- src/squelch/audio_node.cljs
+++ src/squelch/audio_node.cljs
@@ -1,4 +1,4 @@
-(ns squelch.audio-context)
+(ns squelch.audio-node)

 ; -----------
 ; Properties:


remove log not needed

remove log not needed

--- src/webapp/client/init.cljs
+++ src/webapp/client/init.cljs
@@ -381,7 +381,7 @@
 (js/setInterval
  my-timer 5000)

-(log "Submitted")
+;(log "Submitted")


First attempt at item-get operation.

First attempt at item-get operation.

--- src/cbfg/world/t2.cljs
+++ src/cbfg/world/t2.cljs
@@ -17,7 +17,12 @@
     [coll-state (assoc m :status :ok :value coll-state)]

     "item-get"
-    [coll-state (assoc m :status :not-implemented-yet)]
+    (do (act item-get actx
+             (aput item-get (:kvs-mgr-ch coll-state)
+                   (assoc m :op :multi-get
+                          :kvs-ident (:kvs-ident coll-state)
+                          :keys [(:key m)])))
+        [coll-state nil])

     "item-set"
     [coll-state (assoc m :status :not-implemented-yet)]
@@ -32,20 +37,21 @@
 ; somewhat like "dot files" in a filesystem.

 (defn make-coll [actx rev path kvs-mgr-ch]
-  (let [coll-ch (achan actx)]
+  (let [coll-ch (achan actx)
+        coll-res {:rev rev
+                  :path path
+                  :coll-ch coll-ch
+                  :kvs-mgr-ch kvs-mgr-ch}]
     (act coll-init actx
          (let [res (areq coll-init kvs-mgr-ch {:op :kvs-open :name [path rev]})]
            (if (= (:status res) :ok)
              (state-loop actx [:coll path rev] coll-handler
-                         {:kvs-ident (:kvs-ident res)}
+                         (assoc coll-res :kvs-ident (:kvs-ident res))
                          :req-ch coll-ch)
              (do (println "make-coll kvs-open failed" res)
                  ; TODO: Should also consume any reqs that raced onto coll-ch.
                  (aclose coll-init coll-ch)))))
-    {:rev rev
-     :path path
-     :coll-ch coll-ch
-     :kvs-mgr-ch kvs-mgr-ch}))
+    coll-res))

 ; --------------------------------------------

@@ -167,7 +173,7 @@
     "lane-state"
     [lane-state (assoc m :status :ok :value lane-state)]

-    ["coll-state" "item-get" "item-set" "item-del"]
+    ("coll-state" "item-get" "item-set" "item-del")
     (if-let [coll-ch (get-in lane-state [:cur-coll :coll-ch])]
       (do (msg-put actx (fn [_] coll-ch) (merge m lane-state))
           [lane-state nil])


support for prompt to trash an installed card

--- src/clj/game/cards.clj
+++ src/clj/game/cards.clj
@@ -9,6 +9,11 @@
                      :msg (msg "trash " (:title target))
                      :choices {:req #(and (:installed %) (= (:type %) "Hardware"))}
                      :effect (effect (trash target {:cause :subroutine}))})
+
+(def trash-installed {:prompt "Choose an installed card to trash" :label "Trash an installed card"
+                      :msg (msg "trash " (:title target))
+                      :choices {:req #(and (:installed %) (= (:side %) "Runner"))}
+                      :effect (effect (trash target {:cause :subroutine}))})

 (load "cards-agendas")
 (load "cards-assets")
@@ -24,4 +29,4 @@

 (def cards (merge cards-agendas cards-assets cards-events cards-hardware cards-ice cards-icebreakers cards-identities
                   cards-operations cards-programs cards-resources cards-upgrades))
-                  +


strip namespace from env keywords

strip namespace from env keywords

--- src/clj/shale/core.clj
+++ src/clj/shale/core.clj
@@ -47,7 +47,7 @@
               port 6379
               db 0}} redis-conf
         host (if (and host (keyword? host) (namespace host) (= "env" (namespace host)))
-               (get env/env host)
+               (get env/env (keyword (name host)))
                host)]
     (when (not host)
       (logging/infof "env: %s" env/env))


Cleanup & (def max-cnt 100)

Cleanup & (def max-cnt 100)

--- src/clj/ufo/parser.clj
+++ src/clj/ufo/parser.clj
@@ -117,20 +117,18 @@
     ;; (slurp file) $
     (exp-parser $)))

+(def max-cnt 100) ;; category-theory.org has about 48 [e "..."]
+
 (def parse
   (fn [ss]
     (loop [s ss
            acc []
            cnt 0]
-      (if (or (empty? s) (> cnt 4))
+      (if (> cnt max-cnt)
         (do
-          (if (> cnt 4) (println "(> cnt 4)"))
+          (println "Stopping at (>" cnt "max-cnt)")
           acc)
-        (let [result (exp-parser s)
-              [txt-exp rest] result]
-          ;; (println "s:       " s)
-          ;; (println "txt-exp: " txt-exp)
-          ;; (println "rest:    " rest)
-          ;; (println "(into acc txt-exp)" (into acc txt-exp))
-          ;; (println "---------------")
-          (recur rest (into acc txt-exp) (inc cnt)))))))
+        (if (empty? s)
+          acc
+          (let [[txt-exp rest] (exp-parser s)]
+            (recur rest (into acc txt-exp) (inc cnt))))))))


Remove extraneous imports

Remove extraneous imports

--- src/clj_http/core2.clj
+++ src/clj_http/core2.clj
@@ -5,9 +5,7 @@
             [clj-http.multipart :as mp]
             [clj-http.util :refer [opt]]
             [clojure.pprint])
-  (:import (java.io ByteArrayOutputStream File FilterInputStream InputStream)
-           (java.net URI)
-           (javax.net.ssl SSLContext)
+  (:import (java.io FilterInputStream InputStream)
            (org.apache.http HttpHost)
            (org.apache.http.client.methods HttpGet)
            (org.apache.http.client.protocol HttpClientContext)


Refine postgres.filter/sql-str spec

Refine postgres.filter/sql-str spec

- in raster vis we don't have columns associated

--- backend/specs/akvo/lumen/specs/postgres.clj
+++ backend/specs/akvo/lumen/specs/postgres.clj
@@ -35,7 +35,7 @@

 (s/fdef postgres.filter/sql-str
   :args (s/cat
-	 :columns (s/coll-of ::db.dsv/column :distinct true)
+	 :columns (s/nilable (s/coll-of ::db.dsv/column :distinct true))
 	 :filters (s/nilable ::postgres.filter/filters))
   :ret string?)


add missing require in the pedestal example

--- examples/pedestal/src/example/server.clj
+++ examples/pedestal/src/example/server.clj
@@ -2,6 +2,7 @@
   (:require [io.pedestal.http]
             [clojure.core.async :as a]
             [reitit.interceptor.pedestal :as pedestal]
+            muuntaja.interceptor
             [reitit.http :as http]
             [reitit.ring :as ring]))


pagination based on ranking

pagination based on ranking

--- src/crawler/corpus.clj
+++ src/crawler/corpus.clj
@@ -140,13 +140,49 @@
         action-and-pagination (distinct
                                (map
                                 (fn [[u x]]
-                                  [(-> x :path rest) (-> x :path first)])
+                                  (let [src-url (:src-url x)
+                                        src-bod (:body
+                                                 (a-corpus src-url))]
+                                    [[(if (nil? x)
+                                        nil
+                                        (-> x :path rest))
+                                      (-> x :path first)]
+                                     (similarity-cosine-char-freq (:body x)
+                                                                  src-bod)]))
                                 pagination-candidates))

         dest-page-test (fn [src-data dest-data]
                          (similar? (-> src-data second :body)
-                                   (-> dest-data second :body)))]
-    {:paging-actions (into {} action-and-pagination)
+                                   (-> dest-data second :body)))
+
+        paging-actions (reduce
+                        (fn [acc [[src-axn pg-axn] n]]
+                          (cond (not
+                                 ((:similarities acc)
+                                  [src-axn pg-axn]))
+                                (merge
+                                 acc
+                                 {:similarities (merge (:similarities acc)
+                                                       {[src-axn pg-axn] n})
+                                  :actions (merge (:actions acc)
+                                                  {src-axn pg-axn})})
+
+                                (< ((:similarities acc)
+                                    [src-axn pg-axn]))
+                                (merge
+                                 acc
+                                 {:similarities (merge (:similarities acc)
+                                                       {[src-axn pg-axn] n})
+                                  :actions (merge
+                                            (:actions acc)
+                                            {src-axn pg-axn})})
+
+                                :else
+                                acc))
+                        {:similarities {}
+                         :actions {}}
+                        action-and-pagination)]
+    {:paging-actions (:actions paging-actions)

      :refine  (into
                {}
@@ -177,7 +213,7 @@
                                            src-url
                                            dest-page-test))
                           grouped-by-source)))))]))
-                action-and-pagination))}))
+                (:actions paging-actions)))}))

 (defn refine-action-seq
   "Estimates the yield of a path from root to leaf"


gravatar + mobile actions

gravatar + mobile actions

--- src/cljs/swarmpit/component/header.cljs
+++ src/cljs/swarmpit/component/header.cljs
@@ -7,7 +7,10 @@
             [swarmpit.component.state :as state]
             [swarmpit.url :refer [dispatch!]]
             [rum.core :as rum]
-            [sablono.core :refer-macros [html]]))
+            [sablono.core :refer-macros [html]]
+            [clojure.string :as string]
+            [goog.crypt :as crypt])
+  (:import [goog.crypt Md5]))

 (enable-console-print!)

@@ -35,74 +38,180 @@
                    :marginRight 36}
      :hide        {:display "none"}}))

-(rum/defc appbar < rum/reactive [title]
-  (let [{:keys [opened anchorEl]} (state/react state/layout-cursor)]
+(defn- user-gravatar-hash [email]
+  (let [md5 (Md5.)]
+    (when (some? email)
+      (do
+        (.update md5 (string/trim email))
+        (crypt/byteArrayToHex (.digest md5))))))
+
+(defn- user-avatar []
+  (comp/avatar
+    {:className "Swarmpit-appbar-avatar"
+     :src       (str "https://www.gravatar.com/avatar/"
+                     (user-gravatar-hash (storage/email))
+                     "?d=https://raw.githubusercontent.com/swarmpit/swarmpit/issues/159/resources/public/img/user.png")}))
+
+(defn- user-menu [anchorEl]
+  (html
+    [:div
+     (comp/icon-button
+       {:aria-owns     (when anchorEl "Swarmpit-appbar-user-menu")
+        :aria-haspopup "true"
+        :onClick       (fn [e]
+                         (state/update-value [:anchorEl] (.-currentTarget e) state/layout-cursor))
+        :color         "inherit"} (user-avatar))
+     (comp/menu
+       {:id              "Swarmpit-appbar-user-menu"
+        :key             "Swarmpit-appbar-user-menu"
+        :anchorEl        anchorEl
+        :anchorOrigin    {:vertical   "top"
+                          :horizontal "right"}
+        :transformOrigin {:vertical   "top"
+                          :horizontal "right"}
+        :open            (some? anchorEl)
+        :onClose         #(state/update-value [:anchorEl] nil state/layout-cursor)}
+       (comp/menu-item
+         {:key       "Swarmpit-appbar-user-menu-logged-info"
+          :className "Swarmpit-appbar-user-menu-logged-info"
+          :disabled  true} (html [:div
+                                  [:span "Signed in as"]
+                                  [:br]
+                                  [:span.Swarmpit-appbar-user-menu-logged-user (storage/user)]]))
+       (comp/divider)
+       (comp/menu-item
+         {:key     "Swarmpit-appbar-user-menu-api-token"
+          :onClick (fn []
+                     (dispatch!
+                       (routes/path-for-frontend :api-access)))} "API access")
+       (comp/menu-item
+         {:key     "Swarmpit-appbar-user-menu-settings"
+          :onClick (fn []
+                     (dispatch!
+                       (routes/path-for-frontend :password)))} "Change password")
+       (comp/menu-item
+         {:key     "Swarmpit-appbar-user-menu-logout"
+          :onClick (fn []
+                     (storage/remove "token")
+                     (eventsource/close!)
+                     (dispatch!
+                       (routes/path-for-frontend :login)))} "Log out"))]))
+
+(defn- search-input [placeholder on-change-fn]
+  (html
+    [:div.Swarmpit-appbar-search
+     [:div.Swarmpit-appbar-search-icon icon/search]
+     (comp/input
+       {:placeholder      placeholder
+        :onChange         on-change-fn
+        :classes          {:root  "Swarmpit-appbar-search-root"
+                           :input "Swarmpit-appbar-search-input"}
+        :id               "Swarmpit-appbar-search-filter"
+        :disableUnderline true})]))
+
+(defn- mobile-actions-menu
+  [actions mobileMoreAnchorEl]
+  (comp/menu
+    {:anchorEl        mobileMoreAnchorEl
+     :anchorOrigin    {:vertical   "top"
+                       :horizontal "right"}
+     :transformOrigin {:vertical   "top"
+                       :horizontal "right"}
+     :open            (some? mobileMoreAnchorEl)
+     :onClose         #(state/update-value [:mobileMoreAnchorEl] nil state/layout-cursor)}
+    (->> actions
+         (map #(comp/menu-item
+                 {}
+                 (:button %)
+                 (html [:p (:name %)]))))))
+
+(rum/defc appbar < rum/reactive [{:keys [title search actions]}]
+  (let [{:keys [opened anchorEl mobileMoreAnchorEl]} (state/react state/layout-cursor)]
     (comp/mui
-      (comp/app-bar
-        {:position  "absolute"
-         :key       "Swarmpit-appbar"
-         :color     "primary"
-         :className (if opened
-                      "Swarmpit-appbar Swarmpit-appbar-shift"
-                      "Swarmpit-appbar")}
-        (comp/toolbar
-          {:disableGutters (not opened)}
-          (comp/icon-button
-            {:key        "Swarmpit-appbar-menu-btn"
-             :color      "inherit"
-             :aria-label "Open drawer"
-             :onClick    #(state/update-value [:opened] true state/layout-cursor)
-             :className  (if opened
-                           "Swarmpit-appbar-menu-btn hide"
-                           "Swarmpit-appbar-menu-btn")}
-            icon/menu)
-          (comp/typography
-            {:key       "Swarmpit-appbar-title"
-             :className "Swarmpit-appbar-title"
-             :variant   "title"
-             :color     "inherit"
-             :noWrap    true}
-            title)
-          (html
-            [:div
+      (html
+        [:div
+         (comp/app-bar
+           {:position  "absolute"
+            :key       "Swarmpit-appbar"
+            :color     "primary"
+            :className (if opened
+                         "Swarmpit-appbar Swarmpit-appbar-shift"
+                         "Swarmpit-appbar")}
+           (comp/toolbar
+             {:disableGutters (not opened)}
              (comp/icon-button
-               {:aria-owns     (when anchorEl "Swarmpit-appbar-user-menu")
-                :aria-haspopup "true"
-                :onClick       (fn [e]
-                                 (state/update-value [:anchorEl] (.-currentTarget e) state/layout-cursor))
-                :color         "inherit"} icon/account-circle)
-             (comp/menu
-               {:id              "Swarmpit-appbar-user-menu"
-                :key             "Swarmpit-appbar-user-menu"
-                :anchorEl        anchorEl
-                :anchorOrigin    {:vertical   "top"
-                                  :horizontal "right"}
-                :transformOrigin {:vertical   "top"
-                                  :horizontal "right"}
-                :open            (some? anchorEl)
-                :onClose         #(state/update-value [:anchorEl] nil state/layout-cursor)}
-               (comp/menu-item
-                 {:key       "Swarmpit-appbar-user-menu-logged-info"
-                  :className "Swarmpit-appbar-user-menu-logged-info"
-                  :disabled  true} (html [:div
-                                          [:span "Signed in as"]
-                                          [:br]
-                                          [:span.Swarmpit-appbar-user-menu-logged-user (storage/user)]]))
-               (comp/divider)
-               (comp/menu-item
-                 {:key     "Swarmpit-appbar-user-menu-api-token"
-                  :onClick (fn []
-                             (dispatch!
-                               (routes/path-for-frontend :api-access)))} "API access")
-               (comp/menu-item
-                 {:key     "Swarmpit-appbar-user-menu-settings"
-                  :onClick (fn []
-                             (dispatch!
-                               (routes/path-for-frontend :password)))} "Change password")
-               (comp/menu-item
-                 {:key     "Swarmpit-appbar-user-menu-logout"
-                  :onClick (fn []
-                             (storage/remove "token")
-                             (eventsource/close!)
-                             (dispatch!
-                               (routes/path-for-frontend :login)))} "Log out"))]))))))+               {:key        "Swarmpit-appbar-menu-btn"
+                :color      "inherit"
+                :aria-label "Open drawer"
+                :onClick    #(state/update-value [:opened] true state/layout-cursor)
+                :className  (if opened
+                              "Swarmpit-appbar-menu-btn hide"
+                              "Swarmpit-appbar-menu-btn")}
+               icon/menu)
+             (comp/typography
+               {:key       "Swarmpit-appbar-title"
+                :className "Swarmpit-appbar-title"
+                :variant   "title"
+                :color     "inherit"
+                :noWrap    true}
+               title)
+             (when search
+               (search-input (:placeholder search)
+                             (:on-change search)))
+             (html
+               [:div.grow])
+             (html
+               [:div.Swarmpit-appbar-section-desktop
+                (->> actions
+                     (map :button))])
+             (html
+               [:div.Swarmpit-appbar-section-mobile
+                (comp/icon-button
+                  {:aria-haspopup "true"
+                   :onClick       (fn [e]
+                                    (state/update-value [:mobileMoreAnchorEl] (.-currentTarget e) state/layout-cursor))
+                   :color         "inherit"} icon/more)])
+             (html
+               [:div
+                (comp/icon-button
+                  {:aria-owns     (when anchorEl "Swarmpit-appbar-user-menu")
+                   :aria-haspopup "true"
+                   :onClick       (fn [e]
+                                    (state/update-value [:anchorEl] (.-currentTarget e) state/layout-cursor))
+                   :color         "inherit"} (user-avatar))
+                (comp/menu
+                  {:id              "Swarmpit-appbar-user-menu"
+                   :key             "Swarmpit-appbar-user-menu"
+                   :anchorEl        anchorEl
+                   :anchorOrigin    {:vertical   "top"
+                                     :horizontal "right"}
+                   :transformOrigin {:vertical   "top"
+                                     :horizontal "right"}
+                   :open            (some? anchorEl)
+                   :onClose         #(state/update-value [:anchorEl] nil state/layout-cursor)}
+                  (comp/menu-item
+                    {:key       "Swarmpit-appbar-user-menu-logged-info"
+                     :className "Swarmpit-appbar-user-menu-logged-info"
+                     :disabled  true} (html [:div
+                                             [:span "Signed in as"]
+                                             [:br]
+                                             [:span.Swarmpit-appbar-user-menu-logged-user (storage/user)]]))
+                  (comp/divider)
+                  (comp/menu-item
+                    {:key     "Swarmpit-appbar-user-menu-api-token"
+                     :onClick (fn []
+                                (dispatch!
+                                  (routes/path-for-frontend :api-access)))} "API access")
+                  (comp/menu-item
+                    {:key     "Swarmpit-appbar-user-menu-settings"
+                     :onClick (fn []
+                                (dispatch!
+                                  (routes/path-for-frontend :password)))} "Change password")
+                  (comp/menu-item
+                    {:key     "Swarmpit-appbar-user-menu-logout"
+                     :onClick (fn []
+                                (storage/remove "token")
+                                (eventsource/close!)
+                                (dispatch!
+                                  (routes/path-for-frontend :login)))} "Log out"))])))
+         (mobile-actions-menu actions mobileMoreAnchorEl)]))))


remove go and back to >git status

remove go and back to >git status

--- clj-tcp/src/clj_tcp/client.clj
+++ clj-tcp/src/clj_tcp/client.clj
@@ -68,9 +68,7 @@
       ;(prn "channel read 0")
       ;(info "channelRead0")
       (let [d (if (instance? ByteBuf in) (buffer->bytes in) in)]
-         (try
-           (go (>! read-ch d))
-           (catch java.lang.AssertionError e (>!! read-ch d)))))
+         (>!! read-ch d)))
     (exceptionCaught [^ChannelHandlerContext ctx cause]
       (error "Client-handler exception caught " cause)
       (error cause (>!! internal-error-ch [cause ctx]) )
@@ -178,7 +176,7 @@
                                       read-group (NioEventLoopGroup.)
                                       reconnect-count (AtomicInteger. (int 0))
                                       closed (AtomicBoolean. false)
-                                      read-ch (chan 100) internal-error-ch (chan 100) error-ch (chan 100) write-ch (chan 100)}}]
+                                      read-ch (chan 1000) internal-error-ch (chan 100) error-ch (chan 100) write-ch (chan 1000)}}]
   "Start a Client instance with read-ch, write-ch and internal-error-ch"
   (try
   (let [g (if group group (NioEventLoopGroup.))


better output, use Integer/parseInt, remember about max points

--- src/hackerrank/compare_the_triplets.clj
+++ src/hackerrank/compare_the_triplets.clj
@@ -6,26 +6,27 @@
 ; https://www.hackerrank.com/challenges/compare-the-triplets

+(def max-points 100)
 (def alice (atom 0))
 (def bob (atom 0))

 ;; https://clojuredocs.org/clojure.core/swap!
 ;; https://clojuredocs.org/clojure.core/cond
 (defn score [a b]
-  (cond (= (compare a b) 1) (swap! alice inc)
-        (= (compare a b) -1) (swap! bob inc)))
+  (cond (and (> (compare a b) 0) (< @alice max-points)) (swap! alice inc)
+        (and (< (compare a b) 0) (< @bob max-points)) (swap! bob inc)))

 (let [a0_temp "5 6 7" ; (read-line)
       a0_t (split a0_temp #"\s+")
-      a0 (parseInt (a0_t 0))
-      a1 (parseInt (a0_t 1))
-      a2 (parseInt (a0_t 2))
+      a0 (Integer/parseInt (a0_t 0))
+      a1 (Integer/parseInt (a0_t 1))
+      a2 (Integer/parseInt (a0_t 2))

       b0_temp "3 6 10" ;(read-line)
       b0_t (split b0_temp #"\s+")
-      b0 (parseInt (b0_t 0))
-      b1 (parseInt (b0_t 1))
-      b2 (parseInt (b0_t 2))]
+      b0 (Integer/parseInt (b0_t 0))
+      b1 (Integer/parseInt (b0_t 1))
+      b2 (Integer/parseInt (b0_t 2))]

   ;; https://clojuredocs.org/clojure.string/join
   (println (join " " [a0 a1 a2]))
@@ -35,5 +36,5 @@
   (score a1 b1)
   (score a2 b2)

-  (println @alice " " @bob)
+  (println @alice @bob)
 )


Minor refactor

Minor refactor

--- src/main/cljc/mikron/compiler/core.cljc
+++ src/main/cljc/mikron/compiler/core.cljc
@@ -18,28 +18,25 @@
   (let [{:keys [schema processor-types] :as global-options}
         (util/enforce-spec ::core-specs/compile-schema-args args)

-        all-processor-types
-        (->> processor.common/processor (methods) (keys) (set))
+        processor-types
+        (cond-> (->> processor.common/processor (methods) (keys) (set))
+          (some? processor-types) (set/intersection processor-types))

-        processor-types
-        (if-not (some? processor-types)
-          all-processor-types
-          (set/intersection processor-types all-processor-types))
-
-        custom-schemas
-        (schema/custom-schemas schema)
+        custom-processors
+        (->> (for [processor-type processor-types
+                   custom-schema  (schema/custom-schemas schema)]
+               [[processor-type custom-schema]
+                (processor.common/processor-name processor-type custom-schema)])
+             (into {}))

         global-options
         (-> global-options
-            (assoc :custom-processors (->> (for [processor-type processor-types
-                                                 custom-schema  custom-schemas]
-                                             [[processor-type custom-schema]
-                                              (processor.common/processor-name processor-type custom-schema)])
-                                           (into {})))
+            (assoc :custom-processors custom-processors)
             (update :diff-paths schema/expand-paths schema)
             (update :interp-paths schema/expand-paths schema))]
     {:processors     (->> processor-types
                           (map (fn [processor-type]
-                                 [processor-type `(fn ~(processor.common/processor processor-type global-options))]))
+                                 [processor-type
+                                  `(fn ~(processor.common/processor processor-type global-options))]))
                           (into {}))
      :global-options global-options}))


Prevent using invalid names

Prevent using invalid names

--- template/src/leiningen/new/play_clj.clj
+++ template/src/leiningen/new/play_clj.clj
@@ -1,10 +1,13 @@
 (ns leiningen.new.play-clj
   (:require [clojure.java.io :as io]
+            [leiningen.core.main :as main]
             [leiningen.droid.new :as droid-new]
             [leiningen.new.templates :as t]))

 (defn play-clj
   [name & [package-name]]
+  (when (contains? #{"game" "main-screen"} name)
+    (main/abort "Choose a more creative name than that, silly!"))
   (let [render (t/renderer "play-clj")
         lein-droid-render (droid-new/renderer "templates")
         desktop-class-name "desktop-launcher"


add noop in bake for defile, fixes compile errors when called in project.clj

--- bake/bake/core.clj
+++ bake/bake/core.clj
@@ -18,6 +18,9 @@
     `(alter-var-root #'*context* merge-in {'~name '~opts})))

 (defmacro deftask "Just ignore deftask calls in bake."
+  [name & body])
+
+(defmacro defile "Same as deftask above"
   [name & body])

 (defn quit []


added innitial zeitgeist checks to assess the diveristy and construction of the starting population

--- ws/Hybrid_Windows4.clj
+++ ws/Hybrid_Windows4.clj
@@ -58,7 +58,7 @@
 mathKernelSz
 ;; @@
 ;; =>
-;;; {"type":"html","content":""c:/program files/wolfram research/mathematica/10.0/mathkernel.exe"","value":"\"c:/program files/wolfram research/mathematica/10.0/mathkernel.exe\""}
+;;; {"type":"html","content":""/Applications/Mathematica.app/Contents/MacOS/MathKernel"","value":"\"/Applications/Mathematica.app/Contents/MacOS/MathKernel\""}
 ;; <=

 ;; **
@@ -97,7 +97,7 @@
 ;; <=

 ;; @@
-(def prob_inheritance 0.75) ;;to do with crossover  ;probability that terms are directly inherited from parent to child.
+(def prob_inheritance 0.8) ;;to do with crossover  ;probability that terms are directly inherited from parent to child.

 (def mutate_pref1 0.8)
 (def mutate_pref2 0.8)
@@ -138,9 +138,9 @@

     (if (or (< spmax sp) (= new-gene (vec (replicate length 0)) ))

-      (assoc (vec (repeat length 0)) (rand-int length) 1)
+      ;(assoc (vec (repeat length 0)) (rand-int length) 1)

-      ;(new-poly-term max_pow spmax length)
+      (new-poly-term max_pow spmax length)
       ;[0 1];;cant have this or else it will crash the mathematica
       new-gene
       )
@@ -153,8 +153,6 @@
 ;; <=

 ;; @@
-
-
 (defn create-genotype

   "creates a new individual of length between 1 and max_length decided at random.
@@ -185,10 +183,6 @@
 ;; =>
 ;;; {"type":"html","content":"#'goliath/distribute-parent","value":"#'goliath/distribute-parent"}
 ;; <=
-
-;; **
-;;;
-;; **

 ;; **
 ;;; ##Cross-over and mutate functions
@@ -352,11 +346,64 @@

 ;; @@
 (def initial-zeitgeist (evolution/make-zeitgeist (random-initial-population 100 poly_length power power_sum term_length)))
-
 ;; @@
 ;; =>
 ;;; {"type":"html","content":"#'goliath/initial-zeitgeist","value":"#'goliath/initial-zeitgeist"}
 ;; <=
+
+;; **
+;;; ## Innitial Zeitgeist Checks
+;;;
+;;; A few checks to assess the 'health' and diversity of the innitial zeitgiest population.
+;;;
+;;; Considered extremely privitol in generating valid solutions, to start with a healthy population of individuals.
+;;;
+;;;
+;;; **Number frequency**
+;;; - The frequency the a given number appears within a genotype in a population.
+;; **
+
+;; @@
+; take all poly terms from all individiuals and flatten them into one lazy sequence, perform a frequency count of the numbers present in this sequence containing all recurring numbers.
+
+
+(sort (frequencies (flatten (map :genotype (:rabble initial-zeitgeist)))))
+
+;Graphical plot of above.
+
+(plot/list-plot (mapv second (sort (frequencies (flatten (map :genotype (:rabble initial-zeitgeist)))))) :colour 'red')
+
+;total
+
+(count (flatten (map :genotype (:rabble initial-zeitgeist))))
+
+;; @@
+;; =>
+;;; {"type":"html","content":"1844","value":"1844"}
+;; <=
+
+;; **
+;;; **Length of Genotypes**
+;;;
+;;; Lengths of generated polynomils within the innitial populaiton
+;;;
+;;;
+;; **
+
+;; @@
+;;e.g   [[1 2 4 5] [1 2 3 4]]  length = 2
+
+(def l_o_g (sort (frequencies (mapv count (map :genotype (:rabble initial-zeitgeist))))))
+
+(plot/list-plot l_o_g :plot-range [:all [0  (apply max (map second l_o_g))]])
+;; @@
+;; =>
+;;; {"type":"vega","content":{"axes":[{"scale":"x","type":"x"},{"scale":"y","type":"y"}],"scales":[{"name":"x","type":"linear","range":"width","zero":false,"domain":{"data":"88d0014f-c79d-41f5-bb86-1e5f263bf8c5","field":"data.x"}},{"name":"y","type":"linear","range":"height","nice":true,"zero":false,"domain":[0,16]}],"marks":[{"type":"symbol","from":{"data":"88d0014f-c79d-41f5-bb86-1e5f263bf8c5"},"properties":{"enter":{"x":{"scale":"x","field":"data.x"},"y":{"scale":"y","field":"data.y"},"fill":{"value":"steelblue"},"fillOpacity":{"value":1}},"update":{"shape":"circle","size":{"value":70},"stroke":{"value":"transparent"}},"hover":{"size":{"value":210},"stroke":{"value":"white"}}}}],"data":[{"name":"88d0014f-c79d-41f5-bb86-1e5f263bf8c5","values":[{"x":1,"y":14},{"x":2,"y":11},{"x":3,"y":12},{"x":4,"y":16},{"x":5,"y":11},{"x":6,"y":10},{"x":7,"y":6},{"x":8,"y":12},{"x":9,"y":8}]}],"width":400,"height":247.2187957763672,"padding":{"bottom":20,"top":10,"right":10,"left":50}},"value":"#gorilla_repl.vega.VegaView{:content {:axes [{:scale \"x\", :type \"x\"} {:scale \"y\", :type \"y\"}], :scales [{:name \"x\", :type \"linear\", :range \"width\", :zero false, :domain {:data \"88d0014f-c79d-41f5-bb86-1e5f263bf8c5\", :field \"data.x\"}} {:name \"y\", :type \"linear\", :range \"height\", :nice true, :zero false, :domain [0 16]}], :marks [{:type \"symbol\", :from {:data \"88d0014f-c79d-41f5-bb86-1e5f263bf8c5\"}, :properties {:enter {:x {:scale \"x\", :field \"data.x\"}, :y {:scale \"y\", :field \"data.y\"}, :fill {:value \"steelblue\"}, :fillOpacity {:value 1}}, :update {:shape \"circle\", :size {:value 70}, :stroke {:value \"transparent\"}}, :hover {:size {:value 210}, :stroke {:value \"white\"}}}}], :data [{:name \"88d0014f-c79d-41f5-bb86-1e5f263bf8c5\", :values ({:x 1, :y 14} {:x 2, :y 11} {:x 3, :y 12} {:x 4, :y 16} {:x 5, :y 11} {:x 6, :y 10} {:x 7, :y 6} {:x 8, :y 12} {:x 9, :y 8})}], :width 400, :height 247.2188, :padding {:bottom 20, :top 10, :right 10, :left 50}}}"}
+;; <=
+
+;; **
+;;; ** Sum of powers in a gene**
+;; **

 ;; @@
 ;;this function uses discrete differential to find speeds


remove the old versions of icon and svg-icon

--- src-cljs/frontend/components/common.cljs
+++ src-cljs/frontend/components/common.cljs
@@ -158,19 +158,6 @@

 (defn svg-icon [icon-name & [{:keys [path-props svg-props]}]]
   (let [template (get icon-templates icon-name)]
-    (html
-     [:svg (merge {:viewBox "0 0 100 100" :class "iconpile"} svg-props)
-      (for [path (:paths template)]
-        (html [:path (merge {:class (name path) :d (get icon-paths path) :key (name path)} path-props)]))])))
-
-(defn icon [icon-name & [{:keys [path-props svg-props]}]]
-  (html
-   [:i {:class (str "icon-" (name icon-name))}
-    (svg-icon icon-name {:path-props path-props
-                         :svg-props svg-props})]))
-
-(defn svg-icon [icon-name & [{:keys [path-props svg-props]}]]
-  (let [template (get icon-templates icon-name)]
     (apply dom/svg (clj->js (merge {:viewBox "0 0 100 100" :className "iconpile"} svg-props))
            (for [path (:paths template)]
              (dom/path (clj->js (merge {:className (name path) :d (get icon-paths path) :key (name path)} path-props)))))))


sound plays!

sound plays!

--- src/frontend/core.cljs
+++ src/frontend/core.cljs
@@ -2,6 +2,7 @@

 (defonce room-id (.getAttribute (. js/document (getElementById "roomid")) "data"))
 (defonce socket (js/io))
+(defonce current-sound-id "current-song")
 (defonce app-state (atom {:signed-in? false
                           :messages []
                           :message-received? false
@@ -10,7 +11,9 @@
                           :music-info []
                           :music-files {}
                           :data-downloaded 0
-                          :download-progress nil}))
+                          :download-progress nil
+                          :current-track-id nil
+                          :current-sound nil}))

 (enable-console-print!)

@@ -45,6 +48,19 @@
         (fn []
           (println "Upload successful!"))))))
 ; end stuff that should be cleaned up with react....
+
+(defn play-track [track-id]
+  (let [reader (new js/FileReader)
+        song-blob (get (:music-files @app-state) track-id)]
+    (.readAsDataURL reader song-blob)
+    (set! (.-onloadend reader)
+      (fn []
+        (swap! app-state assoc :current-sound
+          (.createSound js/soundManager #js {:id current-sound-id
+                                             :type "audio/mpeg"
+                                             :url (.-result reader)
+                                             :autoLoad true}))
+        (.play (:current-sound @app-state))))))

 (.on socket "connect" #(.emit socket "join-room" room-id))
 (.on socket "sign-in-success"
@@ -89,8 +105,17 @@
         (swap! app-state assoc :music-files
           (merge (:music-files @app-state)
                  {track-id
-                  (new js/Blob #js [(get (:music-files @app-state) track-id) data-chunk])}))))
+                  (new js/Blob #js [(get (:music-files @app-state) track-id) data-chunk]
+                               #js {:type "audio/mpeg"})}))))
     (.on stream "end"
       (fn []
         (println "Download complete!")
-        (swap! app-state assoc :download-progress nil)))))
+        (swap! app-state assoc :download-progress nil)
+
+        (if (= (:current-track-id @app-state) track-id)
+          (play-track track-id))))))
+
+(.on socket "track-change"
+  (fn [track-id]
+    (swap! app-state assoc :current-track-id track-id)
+    (.emit socket "file-download-request" track-id)))


Split alter-meta! application in deftesttask, fixes #435

After a	tireless Sunday, with Micha we realized that alter-meta! in deftesttask needs to be applied
after the def takes place. This was triggering the dreaded "deftask ... was overridden".

--- boot/core/src/boot/test.clj
+++ boot/core/src/boot/test.clj
@@ -108,7 +108,6 @@
   deftask or comp. Another way to say it is that a boot middleware
   should be passed here."
   [task]
-  ;; TODO - deftesttask
   (pod/add-shutdown-hook! #(done! pod/data))
   (.await (get pod/data "start-latch"))
   (try
@@ -154,12 +153,12 @@
       (testing \"whatever\"
         (is true \"Whatever must be true\"))))

-  When *load-tests* is false, deftesttask is ignored."
+  When clojure.test/*load-tests* is false, deftesttask is ignored."
   [& forms]
   (when test/*load-tests*
     (let [new-forms (-> forms
                         (boot.test/update-body #(cons 'boot.test/test-task (list %))))]
-      `(alter-meta! (core/deftask ~@new-forms) assoc ::test-task ::test-me))))
+      `(do (core/deftask ~@new-forms) (alter-meta! (var ~(first new-forms)) assoc ::test-task ::test-me)))))

 ;;;;;;;;;;;;;;;;;;
 ;;  Test Vars   ;;


Moved a bracket- dropdown was ending in the wrong spot.

--- src-cljs/frontend/components/project_settings.cljs
+++ src-cljs/frontend/components/project_settings.cljs
@@ -1882,7 +1882,7 @@
             [:option {:value "us-west-1"} "us-west-1"]  ;; US West (N. California)
             [:option {:value "us-west-2"} "us-west-2"]  ;; US West (Oregon)
             [:option {:value "ca-central-1"} "ca-central-1"]  ;; Canada (Central)
-            [:option {:value "ap-south-1"} "ap-south-1"]] ;; Asia Pacific (Mumbai)
+            [:option {:value "ap-south-1"} "ap-south-1"] ;; Asia Pacific (Mumbai)
             [:option {:value "sa-east-1"} "sa-east-1"]  ;; South America (São Paulo)
             [:option {:value "eu-west-1"} "eu-west-1"]  ;; EU (Ireland)
             [:option {:value "eu-west-2"} "eu-west-2"]  ;; EU (London)
@@ -1891,7 +1891,7 @@
             [:option {:value "ap-northeast-2"} "ap-northeast-2"]  ;; Asia Pacific (Seoul)
             [:option {:value "ap-southeast-1"} "ap-southeast-1"]  ;; Asia Pacific (Singapore)
             [:option {:value "ap-southeast-2"} "ap-southeast-2"]  ;; Asia Pacific (Sydney)
-            [:option {:value "cn-north-1"} "cn-north-1"]  ;; China (Beijing)
+            [:option {:value "cn-north-1"} "cn-north-1"]]  ;; China (Beijing)

            [:div.input-with-help
             [:input#application-root


removed temp code

removed temp code

--- integration/dda/pallet/dda_managed_vm/app/instantiate_existing.clj
+++ integration/dda/pallet/dda_managed_vm/app/instantiate_existing.clj
@@ -24,9 +24,6 @@
     [dda.config.commons.user-env :as user-env]
     [dda.pallet.dda-managed-vm.app :as app]
     [dda.pallet.dda-managed-vm.app.external-config :as ext-config]))
-
-(defn hallo []
- (println (ext-config/provisioning-ip)))

 (def ssh-pub-key
   (user-env/read-ssh-pub-key-to-config))


Add support for React Devtools via :displayName for the Om-wrapped inputs (OmInput, OmTextarea). Also add OmOption.

--- src/sablono/interpreter.cljx
+++ src/sablono/interpreter.cljx
@@ -8,10 +8,11 @@
 ;; Taken from om, to hack around form elements.

 #+cljs
-(defn wrap-form-element [ctor]
+(defn wrap-form-element [ctor react-name]
   (js/React.createClass
    #js
-   {:getInitialState
+   {:displayName react-name
+    :getInitialState
     (fn []
       (this-as this #js {:value (aget (.-props this) "value")}))
     :onChange
@@ -36,10 +37,13 @@
                    :children (aget (.-props this) "children")}))))}))

 #+cljs
-(def input (wrap-form-element js/React.DOM.input))
+(def input (wrap-form-element js/React.DOM.input "OmInput"))

 #+cljs
-(def textarea (wrap-form-element js/React.DOM.textarea))
+(def textarea (wrap-form-element js/React.DOM.textarea "OmTextarea"))
+
+#+cljs
+(def option (wrap-form-element js/React.DOM.option "OmOption"))

 #+cljs
 (defn dom-fn [tag]


Add subnav

Add subnav

--- src-cljs/frontend/components/header.cljs
+++ src-cljs/frontend/components/header.cljs
@@ -192,7 +192,7 @@
                                        :on-click #(raise! owner [:track-external-link-clicked {:path (auth-url) :event "Auth GitHub" :properties {:source "header sign-in" :url js/window.location.pathname}}])
                                        :title "Sign in with Github"}
                   "Sign in"]]]))]]
-          (when (contains? #{:about :contact} nav-point)
+          (when (contains? #{:about :team :contact} nav-point)
             [:div.navbar.navbar-default.navbar-static-top.subnav
              [:div.container-fluid
               [:ul.nav.navbar-nav


Add inc test for template foo.

Add inc test for template foo.

--- test/dsbdp/test/processing_fn_utils.clj
+++ test/dsbdp/test/processing_fn_utils.clj
@@ -28,3 +28,15 @@
     (is (= 1 ((nth proc-fns 1) nil nil)))
     (is (= 3 ((last proc-fns) nil nil)))))

+(deftest create-proc-fn-vec-from-template-with-ret-val-test
+  (let [proc-fns (create-proc-fn-vec-from-template '(fn [i _] (inc i)) '(fn [_ o] (inc o)) 4)]
+    (is (= 4 (count proc-fns)))
+    (is (= 1 ((first proc-fns) 0 nil)))
+    (is (= 1 ((nth proc-fns 1) nil 0)))
+    (is (= 1 ((last proc-fns) nil 0)))
+    (is (= 4 (->>
+               ((proc-fns 0) 0 nil)
+               ((proc-fns 1) nil)
+               ((proc-fns 2) nil)
+               ((proc-fns 3) nil))))))
+


don't break arrows

don't break arrows

--- src-cljs/frontend/components/app.cljs
+++ src-cljs/frontend/components/app.cljs
@@ -94,7 +94,8 @@
                                                      [:client-id]
                                                      [:cust-data]
                                                      [:document/id]
-                                                     [:keyboard]])
+                                                     [:keyboard]
+                                                     [:keyboard-shortcuts]])
                        {:react-key "canvas"})

              (om/build chat/chat (select-in app [state/chat-opened-path


don't use concat over str

don't use concat over str

--- src-cljs/frontend/components/app.cljs
+++ src-cljs/frontend/components/app.cljs
@@ -41,9 +41,8 @@

         (if-let [nav-point (:navigation-point app)]
           (html
-           [:div#app.app {:class (concat
-                                   (when (overlay-visible? app) ["state-menu"])
-                                   (when (:show-landing? app) ["state-outer"]))}
+           [:div#app.app {:class (str (when (overlay-visible? app) " state-menu ")
+                                      (when (:show-landing? app) " state-outer "))}
             (when (:show-landing? app)
               (om/build outer/outer (select-in app [[:show-landing?]
                                                     [:document/id]


kill truncate and tell viewer list when chats open

--- src-cljs/frontend/components/hud.cljs
+++ src-cljs/frontend/components/hud.cljs
@@ -132,15 +132,17 @@
     om/IRenderState
     (render-state [_ {:keys [editing-name? new-name]}]
         (let [{:keys [cast! db]} (om/get-shared owner)
+              chat-opened? (get-in app state/chat-opened-path)
               client-id (:client-id app)
               viewers-count (count (remove (comp :hide-in-list? last) (:subscribers app)))
               can-edit? (not (empty? (:cust app)))
-              viewers-truncated? (< 4 viewers-count)
               show-viewers? (and (not (overlay-visible? app))
                                  (get app :show-viewers? (< 1 viewers-count 6)))]
           (html
-            [:div.viewers.hud-item
-             {:class (when viewers-truncated? ["truncated"])}
+            [:div.viewers
+             {:class (concat
+                       (when chat-opened? ["chat-open"])
+                       [(str "atleast" viewers-count)])}
              (when show-viewers?
                [:div.viewers-list
                 [:div.viewers-list-frame


change title when mic is on

change title when mic is on

--- src-cljs/frontend/components/hud.cljs
+++ src-cljs/frontend/components/hud.cljs
@@ -271,7 +271,9 @@
                    (when config/subdomain
                      [:a.viewer-toggle {:on-click #(cast! :recording-toggled)
                                         :role "button"
-                                        :title "Share your audio with everyone in the doc"}
+                                        :title (if (:recording sub)
+                                                 "Turn off your mic"
+                                                 "Share your audio with everyone in the doc")}
                       (common/icon (if (:recording sub) :mic-off :mic))])]]])
               (for [[id {:keys [show-mouse? color cust-name hide-in-list? stream-url] :as sub}] (dissoc (get-in app [:subscribers :info]) client-id)
                     :when (not hide-in-list?)


Initializes pool->fenzo atom earlier (#1424)

--- scheduler/src/cook/kubernetes/compute_cluster.clj
+++ scheduler/src/cook/kubernetes/compute_cluster.clj
@@ -206,8 +206,15 @@
     ; so we launch within a future so that our caller can continue initializing other clusters.
     (future
       (try
+        (log/info "Initializing Kubernetes compute cluster" name)
+
+        ; We need to reset! the pool->fenzo atom before initializing the
+        ; watches, because otherwise, we will start to see and handle events
+        ; for pods, but we won't be able to update the corresponding Fenzo
+        ; instance (e.g. unassigning a completed task from its host)
+        (reset! pool->fenzo-atom pool->fenzo)
+
         ; Initialize the pod watch path.
-        (log/info "Initializing Kubernetes compute cluster" name)
         (let [conn cook.datomic/conn
               cook-pod-callback (make-cook-pod-watch-callback this)]
           ; We set cook expected state first because initialize-pod-watch sets (and invokes callbacks on and reacts to) the
@@ -221,8 +228,6 @@

         ; Initialize the node watch path.
         (api/initialize-node-watch api-client name current-nodes-atom)
-
-        (reset! pool->fenzo-atom pool->fenzo)
         (catch Throwable e
           (log/error e "Failed to bring up compute cluster" name)
           (throw e))))


Try to make restart-pred-fn test more reliable

--- test/onyx/peer/restart_pred_fn_test.clj
+++ test/onyx/peer/restart_pred_fn_test.clj
@@ -2,7 +2,8 @@
   (:require [clojure.core.async :refer [chan >!! <!! close! sliding-buffer]]
             [midje.sweet :refer :all]
             [onyx.plugin.core-async :refer [take-segments!]]
-            [onyx.test-helper :refer [load-config]]
+            [onyx.extensions :as extensions]
+            [onyx.test-helper :refer [load-config playback-log get-counts]]
             [onyx.api]))

 (def id (java.util.UUID/randomUUID))
@@ -22,7 +23,6 @@
 (def batch-size 20)

 (defn my-inc [{:keys [n] :as segment}]
-  (Thread/sleep 20)
   (assoc segment :n (inc n)))

 (defn restartable? [e]
@@ -76,6 +76,9 @@
 (def check-restarted-calls
   {:lifecycle/before-task-start (fn [_ _ ]
                                   (swap! startup-counter inc)
+                                  (when (= 2 @startup-counter)
+                                    (>!! in-chan :done)
+                                    (close! in-chan))
                                   {})
    :lifecycle/before-batch (fn [_ _]
                              (when (= (swap! batch-counter inc) 2)
@@ -97,10 +100,7 @@
 (doseq [n (range n-messages)]
   (>!! in-chan {:n n}))

-(>!! in-chan :done)
-(close! in-chan)
-
-(def v-peers (onyx.api/start-peers 4 peer-group))
+(def v-peers (onyx.api/start-peers 3 peer-group))

 (onyx.api/submit-job
  peer-config
@@ -111,7 +111,7 @@

 (def results (take-segments! out-chan))

-(fact @startup-counter => 3)
+(fact @startup-counter => 2)

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


Update core.clj

Update core.clj

--- src/jarkeeper/core.clj
+++ src/jarkeeper/core.clj
@@ -15,7 +15,6 @@
             [jarkeeper.views.json :as project-json]
             [ancient-clj.core :as anc])
   (:import (java.io PushbackReader)))
-

 (defn- starting-num? [string]


Add docstring to the available-zone-ids fn

Without the docs, it wasn't clear if it returned a set or a seq, and if the contents were strings or ZoneId objects, making inspection (or usage) of the code required

--- src/java_time/zone.clj
+++ src/java_time/zone.clj
@@ -81,7 +81,9 @@
   :implicit-arities [1 2]
   ([] (jt.clock/make (fn [^Clock c] (.getZone c)))))

-(defn available-zone-ids []
+(defn available-zone-ids
+  "Returns a set of string identifiers for all available ZoneIds."
+  []
   (ZoneId/getAvailableZoneIds))

 ;; offset date/time


make a function public #29

make a function public #29

--- src/tamaki/template/page.clj
+++ src/tamaki/template/page.clj
@@ -44,7 +44,7 @@
   ([] (compile-mds (:page-dir (config/read-config)))))

-(defn- load-postmd [path]
+(defn load-postmd [path]
   (letfn [(extract-date-from-filename [filename] (-> (re-seq #"^\d{4}-\d{1,2}-\d{1,2}" filename) first))
           (build-link [filename] (string/replace filename
                                                  #"(\d{4})-(\d{1,2})-(\d{1,2})-(.+)\.(md|markdown)$"


Added exclusions support in project files.  Useful for libraries that have extra dependencies unnecessary for runtime.  (Looking at you, log4j)

--- src/leiningen/deps.clj
+++ src/leiningen/deps.clj
@@ -3,17 +3,25 @@
   (:require [lancet])
   (:use [leiningen.pom :only [default-repos]]
         [clojure.contrib.java-utils :only [file]])
-  (:import [org.apache.maven.model Dependency]
+  (:import [org.apache.maven.model Dependency Exclusion]
            [org.apache.maven.artifact.ant DependenciesTask RemoteRepository]
            [org.apache.tools.ant.util FlatFileNameMapper]))

 ;; TODO: unify with pom.clj

-(defn make-dependency [[dep version]]
-  (doto (Dependency.)
-    (.setGroupId (or (namespace dep) (name dep)))
-    (.setArtifactId (name dep))
-    (.setVersion version)))
+(defn make-exclusion [excl]
+  (doto (Exclusion.)
+    (.setGroupId (or (namespace excl) (name excl)))
+    (.setArtifactId (name excl))))
+
+(defn make-dependency [[dep version & exclusions]]
+  (let [es (map make-exclusion (when (= (first exclusions) :exclusions)
+                                 (second exclusions)))]
+    (doto (Dependency.)
+            (.setGroupId (or (namespace dep) (name dep)))
+            (.setArtifactId (name dep))
+            (.setVersion version)
+            (.setExclusions es))))

 (defn make-repository [[id url]]
   (doto (RemoteRepository.)


Add working shabam build/read/write.

Add working shabam build/read/write.

The db value now contains two values - :shabam and :pldb. The :shabam
is a bitmapped ancestry lookup for shas. The :pldb value used to be
the db value.

--- src/leiningen/voom.clj
+++ src/leiningen/voom.clj
@@ -1153,39 +1153,67 @@
       [proj-name (:version proj) has-snaps?])
     [nil nil nil]))

+(defn add-commit-facts
+  [pldb gitdir commit]
+  (-> pldb
+      (pldb/db-fact r-commit (:sha commit) (:ctime commit)
+                    (count (:parents commit)) (:parents commit))
+      (->/for [parent (:parents commit)]
+        (pldb/db-fact r-commit-parent (:sha commit) parent))
+      (->/for [[path file-sha] (:paths commit)]
+        (->/when-let [[_ dir] (re-matches #"(.*)(^|/)project.clj" path)]
+          (->/apply pldb/db-fact
+                    r-proj (:sha commit) dir (proj-fact-tail gitdir file-sha))))
+      (->/for [dir-path (set (mapcat sub-paths (keys (:paths commit))))]
+        (pldb/db-fact r-commit-path (:sha commit) dir-path))))
+
+(defn build-shabam
+  [{:keys [shabam pldb]} tips]
+  (loop [shabam shabam, stack (vec tips)]
+    (if-let [frame (peek stack)]
+      (if (vector? frame)
+        ;; parents all added themselves
+        (recur
+         (apply shabam-add shabam frame)
+         (pop stack))
+        ;; no parents checked yet
+        (if (shabam-contains? shabam frame)
+          (recur shabam (pop stack)) ;; I'm in db. Done.
+          (let [parents (seq
+                         (q pldb [par]
+                            (r-commit-parent frame par)))]
+            (recur shabam
+                   (-> stack
+                       (conj (into [frame] parents)) ;; to add myself later
+                       (into parents)))))) ;; have parents check themselves
+      {:shabam shabam :pldb pldb})))
+
 (defn add-git-facts
   [db gitdir]
   (-> db
     (->/let [old-branches (into {} (map (comp vec next)
-                                        (vdb/get-facts db r-branch)))
+                                        (vdb/get-facts (:pldb db) r-branch)))
              new-branches (zipmap
                            (origin-branches gitdir)
                            (map sha/mk (origin-branches gitdir :sha? true)))]
       (->/when (not= old-branches new-branches)
         (->/let [repo (-> (remotes gitdir) :origin :fetch)]
-          (vary-meta assoc ::dirty true)

           ;; Update branchs
           (->/for [[name sha] old-branches]
-            (pldb/db-retraction r-branch repo name sha))
+            (update-in [:pldb] pldb/db-retraction r-branch repo name sha))
           (->/for [[name sha] new-branches]
-            (pldb/db-fact r-branch repo name sha))
+            (update-in [:pldb] pldb/db-fact r-branch repo name sha))

           ;; Add commits
           (->/for [commit (exported-commits
                            gitdir (vals new-branches) (vals old-branches))]
-            (pldb/db-fact r-commit (:sha commit) (:ctime commit)
-                          (count (:parents commit)) (:parents commit))
-            (->/for [parent (:parents commit)]
-              (pldb/db-fact r-commit-parent (:sha commit) parent))
-            (->/for [[path file-sha] (:paths commit)]
-              (->/when-let [[_ dir] (re-matches #"(.*)(^|/)project.clj" path)]
-                (->/apply pldb/db-fact r-proj (:sha commit) dir
-                          (proj-fact-tail gitdir file-sha))))
-            (->/for [dir-path (set (mapcat sub-paths (keys (:paths commit))))]
-              (pldb/db-fact r-commit-path (:sha commit) dir-path))))))))
-
-(def voomdb-header "voom-db-3")
+            (->/assoc :pldb (add-commit-facts gitdir commit)))
+
+          (build-shabam (vals new-branches))
+          (vary-meta assoc ::dirty true))))))
+
+(def voomdb-header "voom-db-4")

 (defn ^File git-db-file
   [gitdir]
@@ -1194,19 +1222,22 @@
 (defn read-git-db
   [gitdir]
   (let [file (git-db-file gitdir)
-        [header & reldata] (-> file
+        [header & [shabam & reldata]] (-> file
                                io/input-stream
                                java.util.zip.GZIPInputStream.
                                (fress/read :handlers sha/read-handlers))]
     (if (= header voomdb-header)
-      (vdb/from-reldata
-       [r-branch r-commit r-commit-parent r-commit-path r-proj]
-       reldata)
+      {:shabam shabam
+       :pldb
+       , (vdb/from-reldata
+          [r-branch r-commit r-commit-parent r-commit-path r-proj]
+          reldata)}
       (do
         (println "Existing voomdb file for" (str gitdir)
                  "has wrong header" header "needed:"
                  voomdb-header)
-        pldb/empty-db))))
+        {:shabam (shabam-new)
+         :pldb pldb/empty-db}))))

 (defn write-git-db
   [db gitdir]
@@ -1217,14 +1248,15 @@
                                 :handlers sha/write-handlers))]
     (fress/begin-open-list w)
     (fress/write-object w voomdb-header)
-    (doseq [item (vdb/to-reldata db)]
+    (fress/write-object w (:shabam db))
+    (doseq [item (vdb/to-reldata (:pldb db))]
       (fress/write-object w item))))

 (defn updated-git-db
   [gitdir]
   (let [db (-> (if (.exists (git-db-file gitdir))
                  (read-git-db gitdir)
-                 pldb/empty-db)
+                 {:shabam (shabam-new) :pldb pldb/empty-db})
                (add-git-facts gitdir))]
     (when (::dirty (meta db))
       (write-git-db db gitdir))
@@ -1344,7 +1376,9 @@
   (def xdb3 (vdb/from-reldata [r-tree] (fress/read (fress/write (vdb/to-reldata xdb1)))))
   (pldb/with-db xdb3 (l/run* [a] (r-tree a :b :c :d)))

-  (time (def db (add-git-facts pldb/empty-db (io/file voom-repos "lein-voom"))))
+  (time (def db (add-git-facts {:shabam (shabam-new)
+                                :pldb pldb/empty-db}
+                               (io/file voom-repos "lein-voom"))))
   (time (def db (updated-git-db (io/file voom-repos "lein-voom"))))
   (time (def db2 (updated-git-db (io/file voom-repos "lonocore"))))
   )


Give better error when no project matches in 'box-remove.

--- src/leiningen/voom.clj
+++ src/leiningen/voom.clj
@@ -693,11 +693,12 @@
   [proj & args]
   (doseq [a args
           :let [prjs (resolve-short-proj a (all-boxes))]]
-    (if (= 1 (count prjs))
-      (let [box-root (find-box)
-            link (adj-path box-root (first prjs))
-            repo (adj-path box-root task-dir (first prjs))]
-        (safe-delete-repo repo link))
+    (case (count prjs)
+      0 (println "Project directory not found for:" a)
+      1 (let [box-root (find-box)
+              link (adj-path box-root (first prjs))
+              repo (adj-path box-root task-dir (first prjs))]
+          (safe-delete-repo repo link))
       (do
         (print (str "Cannot remove '" a "', multiple matches:"))
         (doseq [p prjs]


(maint) Add JRubyPuppetService as a dependency of RequestHandlerService

The very first thing the RequestHandlerService does in the init is get
the JRubyPuppetService, so this commit adds it as an explicit
dependency.

--- src/clj/puppetlabs/services/request_handler/request_handler_service.clj
+++ src/clj/puppetlabs/services/request_handler/request_handler_service.clj
@@ -8,7 +8,8 @@
 (tk/defservice request-handler-service
   handler/RequestHandlerService
   [[:PuppetServerConfigService get-config]
-   [:VersionedCodeService current-code-id]]
+   [:VersionedCodeService current-code-id]
+   [:JRubyPuppetService]]
   (init [this context]
     (let [jruby-service (tk-services/get-service this :JRubyPuppetService)
           config (get-config)]


Make input and output argument mandatory

--- src/mdr2/pipeline1.clj
+++ src/mdr2/pipeline1.clj
@@ -47,7 +47,8 @@

 (defn audio-encoder
   "Invoke the audio encoder script."
-  [{:keys [input output bitrate] :as args}]
-  (apply sh "daisy-pipeline"
-         (str install-path "/modify_improve/dtb/DTBAudioEncoder.taskScript")
-         (map (fn [[k v]] (format "--%s=%s" (name k) v)) args)))
+  [input output & {:keys [bitrate stereo freq] :as opts}]
+  (let [args (merge opts {:input input :output output})]
+    (apply sh "daisy-pipeline"
+           (str install-path "/modify_improve/dtb/DTBAudioEncoder.taskScript")
+           (map (fn [[k v]] (format "--%s=%s" (name k) v)) args))))


namespace

namespace

--- src/clojure/zensols/nlparse/stanford.clj
+++ src/clojure/zensols/nlparse/stanford.clj
@@ -8,7 +8,7 @@
            (edu.stanford.nlp.process CoreLabelTokenFactory)
            (edu.stanford.nlp.ling CoreLabel))
   (:require [zensols.actioncli.dynamic :refer (dyn-init-var) :as dyn]
-            [zensols.actioncli.resource :refer (resource-path)]))
+            [zensols.actioncli.resource :refer (resource-path) :as res]))

 (defn- initialize
   "Initialize model resource locations.


Prevent creation of already existing job via triggers

--- src/cider_ci/builder/jobs/trigger.clj
+++ src/cider_ci/builder/jobs/trigger.clj
@@ -49,6 +49,13 @@
     (some (fn [[_ trigger]]
             (trigger-fulfilled? tree-id job trigger)) triggers)))

+(defn job-does-not-exist-yet [job-config]
+  (->> [(str "SELECT true AS exists_yet FROM jobs "
+             "WHERE tree_id = ? AND key = ? ")
+        (:tree_id job-config) (:key job-config)]
+       (jdbc/query (rdbms/get-ds))
+       first :exists_yet not))
+

 ;##############################################################################

@@ -64,6 +71,7 @@
            (filter #(some-trigger-fulfilled? tree-id %))
            (map #(assoc % :tree_id tree-id))
            (filter jobs.dependencies/fulfilled?)
+           (filter job-does-not-exist-yet)
            (map jobs/create)
            doall)))
   tree-id)


make assemble task use earxml, target

make assemble task use earxml, target

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

--- src/migae/boot_gae.clj
+++ src/migae/boot_gae.clj
@@ -393,7 +393,7 @@
                            (boot/add-source edn-tmp)
                            boot/commit!))))))

-(declare filters install-sdk libs logging reloader servlets target webxml)
+(declare earxml filters install-sdk libs logging reloader servlets target webxml)

 (boot/deftask assemble
   "assemble a service-based app (ear)"
@@ -414,19 +414,23 @@
         checkout-vec (-> (boot/get-env) :checkouts)
         cos (map #(assoc (apply hash-map %) :coords [(first %) (second %)]) checkout-vec)
         ]
-    (boot/with-pre-wrap [fileset]
-      (doseq [co cos]
-        (let [mod (if (:default co) "default" (if-let [mod (:module co)] mod "default"))]
-          (let [corec (get checkouts (first (:coords co)))
-                co-dir (:dir corec)
-                jar-path (.getPath (:jar corec))
-                out-dir (doto (io/file tmpdir mod) io/make-parents)]
-            ;; (println "co-dir: " co-dir)
-            ;; (println "out-dir: " out-dir)
-            (fs/copy-dir co-dir out-dir))))
-      (-> fileset
-          (boot/add-asset tmpdir :exclude #{(re-pattern (str "/META-INF/.*"))})
-          (boot/commit!)))))
+    (comp
+     (earxml)
+     (boot/with-pre-wrap [fileset]
+       (doseq [co cos]
+         (let [mod (if (:default co) "default" (if-let [mod (:module co)] mod "default"))]
+           (let [corec (get checkouts (first (:coords co)))
+                 co-dir (:dir corec)
+                 jar-path (.getPath (:jar corec))
+                 out-dir (doto (io/file tmpdir mod) io/make-parents)]
+             ;; (println "co-dir: " co-dir)
+             ;; (println "out-dir: " out-dir)
+             (fs/copy-dir co-dir out-dir))))
+       (-> fileset
+           (boot/add-asset tmpdir :exclude #{(re-pattern (str "/META-INF/.*"))})
+           (boot/commit!)))
+     (target)
+     )))

 (boot/deftask build
   "assemble, configure, and build app"
@@ -929,7 +933,6 @@
   ;;(let [mod (str (-> (boot/get-env) :gae :module :name))]
   (comp (builtin/watch)
         (builtin/notify :audible true)
-        ;;(builtin/sift :move {#"(.*\.clj$)" (str (if mod (str mod "/")) classes-dir "/$1")})
         (builtin/sift :move {#"(.*\.clj$)" (str classes-dir "/$1")})
         (if service
           (target :no-clean true :service service :monitor true)


import pipe

import pipe

--- src/cljc/commos/delta/compscribe.cljc
+++ src/cljc/commos/delta/compscribe.cljc
@@ -4,11 +4,13 @@
                                                 <! >!
                                                 put!
                                                 alts!
+                                                pipe
                                                 go go-loop]]
                :cljs [cljs.core.async :refer [chan close!
                                               <! >!
                                               put!
-                                              alts!]])
+                                              alts!
+                                              pipe]])
             [clojure.walk :refer [prewalk postwalk]]
             [commos.shared.core :refer [flatten-keys]])
   #?(:cljs (:require-macros [cljs.core.async.macros :refer [go-loop go]])))


admin menu section hidden for user

admin menu section hidden for user

--- src/cljs/swarmpit/component/menu.cljs
+++ src/cljs/swarmpit/component/menu.cljs
@@ -2,6 +2,7 @@
   (:require [material.component :as comp]
             [material.icon :as icon]
             [swarmpit.component.state :as state]
+            [swarmpit.storage :as storage]
             [clojure.string :as string]
             [rum.core :as rum]))

@@ -62,8 +63,10 @@
    {:name "Nodes"
     :icon icon/nodes}
    {:name "Networks"
-    :icon icon/networks}
-   {:name "SETTINGS"}
+    :icon icon/networks}])
+
+(def admin-menu
+  [{:name "SETTINGS"}
    {:name "Dockerhub"
     :icon icon/dockerhub}
    {:name "Registries"
@@ -130,4 +133,6 @@
                     selected (string/includes? domain name)]
                 (if (some? icon)
                   (drawer-item name icon opened selected)
-                  (drawer-category name opened)))) menu))))))+                  (drawer-category name opened)))) (if (storage/admin?)
+                                                     (concat menu admin-menu)
+                                                     menu)))))))


Add defscreen devcards to demonstrate route generation and matching

--- src/docs/workflo/macros/docs/screen.cljs
+++ src/docs/workflo/macros/docs/screen.cljs
@@ -1,8 +1,10 @@
 (ns workflo.macros.docs.screen
-  (:require [cljs.pprint :refer [pprint]]
+  (:require [bidi.bidi :as bidi]
+            [cljs.pprint :refer [pprint]]
             [devcards.core :refer-macros [defcard defcard-doc dom-node]]
             [workflo.macros.screen :as screen
              :refer-macros [defscreen]]
+            [workflo.macros.screen.bidi :as screen-bidi]
             [workflo.macros.view :as view
              :refer-macros [defview]]))

@@ -15,6 +17,9 @@
 (defview UserProfile
   (render))

+(defview UserSettings
+  (render))
+
 (defscreen users
   (url "users")
   (navigation
@@ -23,11 +28,18 @@
    {:content user-list}))

 (defscreen user
-  (url "user/:user-id")
+  (url "users/:user-id")
   (navigation
    (title "User"))
   (layout
    {:content user-profile}))
+
+(defscreen user-settings
+  (url "users/:user-id/settings")
+  (navigation
+   (title "User Settings"))
+  (layout
+   {:content user-settings}))

 (defcard
   "## Registered screens
@@ -46,9 +58,60 @@
       (title \"User\"))
      (layout
       {:content user-profile}))
+
+   (defscreen user-settings
+     (url \"users/:user-id/settings\")
+     (navigation
+      (title \"User Settings\"))
+     (layout
+      {:content user-settings}))
    ```"
   (screen/registered-screens))

 (defcard
   "## Resolved `users` screen"
   (screen/resolve-screen 'users))
+
+(defcard
+  "## Routes
+
+  ```
+  (workflo.macros.screen.bidi/routes)
+  ```"
+  (screen-bidi/routes))
+
+(defcard
+  "## Routing for users
+
+   ```
+   [(bidi/path-for <routes> 'users)
+    (bidi/match-route <routes> \"/users\")
+    (workflo.macros.screen.bidi/match \"/users\")]
+   ```"
+  [(bidi/path-for (screen-bidi/routes) 'users)
+   (bidi/match-route (screen-bidi/routes) "/users")
+   (screen-bidi/match "/users")])
+
+(defcard
+  "## Routing for a user
+
+   ```
+   [(bidi/path-for <routes> 'user :user-id 5)
+    (bidi/match-route <routes> \"/users/10\")
+    (workflo.macros.screen.bidi/match \"/users/10\")]
+   ```"
+  [(bidi/path-for (screen-bidi/routes) 'user :user-id 5)
+   (bidi/match-route (screen-bidi/routes) "/users/10")
+   (screen-bidi/match "/users/10")])
+
+(defcard
+  "## Routing for a user's settings
+
+   ```
+   [(bidi/path-for <routes> 'user-settings :user-id 5)
+    (bidi/match-route <routes> \"/users/15/settings\")
+    (workflo.macros.screen.bidi/match \"/users/15/settings\")]
+   ```"
+  [(bidi/path-for (screen-bidi/routes) 'user-settings :user-id 5)
+   (bidi/match-route (screen-bidi/routes) "/users/15/settings")
+   (screen-bidi/match "/users/15/settings")])


Improve handling of publisher channel

Improve handling of publisher channel

--- src/photon/streams.clj
+++ src/photon/streams.clj
@@ -13,6 +13,7 @@
                      pub sub alts!]])
   (:import (java.net ServerSocket)
            (java.io DataOutput)))
+
 ;; TODO: Do something about the conflict between keywords and strings
 ;;       for the keys (e.g. stream-name)

@@ -66,7 +67,8 @@
   (dosync
     (if-let [p (:publication @state)]
       p
-      (let [c (chan (sliding-buffer 4096))
+      (let [sb (sliding-buffer 1)
+            c (chan sb)
             new-p {:channel c :p (pub c :stream-name)}]
         (dosync
             (alter state
@@ -75,6 +77,7 @@
                            (conj (:all-channels old-state) c)]
                        (merge old-state
                               {:publication new-p
+                               :pub-buffer sb
                                :all-channels new-channels})))))
         new-p))))

@@ -365,7 +368,7 @@
 (defmethod stream->ch "hot-cold" [a-stream params]
   (log/info "Initialising hot-cold stream with params" (pr-str params))
   (let [date (extract-date params)
-        ch (chan (buffer 1))
+        ch (chan 1024)
         _ (log/info "Getting stream-name and data")
         stream-name (get params :stream-name "__all__")
         _ (log/info "Finished getting stream-name and data")]
@@ -394,14 +397,14 @@
     ch))

 (defmethod stream->ch "hot" [a-stream params]
-  (let [ch (chan 1)
+  (let [ch (chan 1024)
         stream-name (get params :stream-name "__all__")]
     (if (= stream-name "__all__")
       (tap (:mult-channel (:global-channel a-stream)) ch)
       (sub (:p (publisher a-stream)) stream-name ch))
     ch))

-(defrecord AsyncStreamState [projections publication active-streams
+(defrecord AsyncStreamState [projections publication pub-buffer active-streams
                              virtual-streams all-channels])

 (defn pipeline [num fn ch]
@@ -441,6 +444,7 @@
             initial-state (map->AsyncStreamState
                            {:projections {}
                             :publication nil
+                            :pub-buffer nil
                             :active-streams {}
                             :virtual-streams {}
                             :all-channels #{}})


add dependency to core project, will need it later on to send metrics, status, etc.

--- components/quartzite/project.clj
+++ components/quartzite/project.clj
@@ -2,5 +2,6 @@
             :plugins [[lein-modules "0.3.11"]]
             :modules {:parent "../.."}
             :description "A quartzite component"
-            :dependencies [[clojurewerkz/quartzite "2.0.0"]
+            :dependencies [[gorillalabs.tesla/core :version]
+                           [clojurewerkz/quartzite "2.0.0"]
                            ])