text input for music read exercise

text input for music read exercise

--- src/cljs/daveconservatoire/site/ui/exercises.cljs
+++ src/cljs/daveconservatoire/site/ui/exercises.cljs
@@ -16,7 +16,8 @@

 (s/def ::description string?)
 (s/def ::option (s/cat :value string? :label string?))
-(s/def ::options (s/+ (s/spec ::option)))
+(s/def ::options (s/or :text #{::option-type-text}
+                       :select (s/+ (s/spec ::option))))

 (s/def ::ex-props (s/keys :req [::options]))
 (s/def ::ex-answer (s/nilable string?))
@@ -110,7 +111,8 @@
   Object
   (render [this]
     (let [{:keys [::options ::ex-answer ::ex-total-questions
-                  ::streak-count] :as props} (om/props this)]
+                  ::streak-count] :as props} (om/props this)
+          [opt-type _] (s/conform ::options options)]
       (assert (s/valid? ::ex-props props) (s/explain-str ::ex-props props))
       (dom/div #js {:className "lesson-content"}
         (dom/div #js {:className "single-exercise visited-no-recolor"
@@ -136,20 +138,29 @@
                           (dom/div #js {:id "hintsarea"}))
                         (dom/div #js {:id "answer_area_wrap"}
                           (dom/div #js {:id "answer_area"}
-                            (dom/form #js {:id "answerform" :name "answerform"}
+                            (dom/form #js {:id "answerform" :name "answerform" :onSubmit #(do
+                                                                                (check-answer this)
+                                                                                (.preventDefault %))}
                               (dom/div #js {:className "info-box" :id "answercontent"}
                                 (dom/span #js {:className "info-box-header"}
                                   "Answer")
-                                (dom/div #js {:className "fancy-scrollbar"}
-                                  (dom/ul nil
-                                    (for [[value label] options]
-                                      (dom/li #js {:key value}
-                                        (dom/label nil
-                                          (dom/input #js {:type     "radio" :name "exercise-answer"
-                                                          :checked  (= ex-answer value)
-                                                          :value    value
-                                                          :onChange #(um/set-string! this ::ex-answer :event %)})
-                                          (dom/span #js {:className "value"} label))))))
+                                (dom/div #js {:className "fancy-scrollbar" :id "solutionarea"}
+                                  (case opt-type
+                                    :text
+                                    (dom/input #js {:type     "text"
+                                                    :value    (or ex-answer "")
+                                                    :onChange #(um/set-string! this ::ex-answer :event %)})
+
+                                    :select
+                                    (dom/ul nil
+                                      (for [[value label] options]
+                                        (dom/li #js {:key value}
+                                          (dom/label nil
+                                            (dom/input #js {:type     "radio" :name "exercise-answer"
+                                                            :checked  (= ex-answer value)
+                                                            :value    value
+                                                            :onChange #(um/set-string! this ::ex-answer :event %)})
+                                            (dom/span #js {:className "value"} label)))))))
                                 (dom/div #js {:className "answer-buttons"}
                                   (dom/div #js {:className "check-answer-wrapper"}
                                     (dom/input #js {:className "simple-button green" :type "button" :value "Check Answer"
@@ -184,10 +195,10 @@
     (new-round this
       (merge
         (uc/initial-state Exercise nil)
-        {::options     [["lower" "Lower"] ["higher" "Higher"]]
-         ::pitch       ["C3" ".." "B5"]
-         ::variation   24
-         ::parent      this}
+        {::options   [["lower" "Lower"] ["higher" "Higher"]]
+         ::pitch     ["C3" ".." "B5"]
+         ::variation 24
+         ::parent    this}
         props)))

   static om/Ident
@@ -214,10 +225,10 @@
     (new-round this
       (merge
         (uc/initial-state Exercise nil)
-        {::options     [["yes" "Yes"] ["no" "No"]]
-         ::pitch       ["C3" ".." "B5"]
-         ::variation   [3 5 6 7 8 9 12 15 16]
-         ::parent      this}
+        {::options   [["yes" "Yes"] ["no" "No"]]
+         ::pitch     ["C3" ".." "B5"]
+         ::variation [3 5 6 7 8 9 12 15 16]
+         ::parent    this}
         props)))

   static om/Ident
@@ -246,8 +257,8 @@
     (new-round this
       (merge
         (uc/initial-state Exercise nil)
-        {::options     [["C" "C"] ["D" "D"] ["E" "E"] ["F" "F"] ["G" "G"] ["A" "A"] ["B" "B"]]
-         ::parent      this}
+        {::options ::option-type-text
+         ::parent  this}
         props)))

   static om/Ident
@@ -266,7 +277,7 @@
       (assoc props
         ::read-note (inc pos)
         ::notes notes
-        ::correct-answer note)))
+        ::correct-answer (.toLowerCase note))))

   Object
   (render [this]
@@ -292,10 +303,10 @@
       (let [intervals (get props ::intervals [12 7 4 5 9 2 11])]
         (merge
           (uc/initial-state Exercise nil)
-          {::options     (mapv #(vector (str %) (INTERVAL-NAMES %)) intervals)
-           ::pitch       ["C3" ".." "B5"]
-           ::variation   intervals
-           ::parent      this}
+          {::options   (mapv #(vector (str %) (INTERVAL-NAMES %)) intervals)
+           ::pitch     ["C3" ".." "B5"]
+           ::variation intervals
+           ::parent    this}
           props))))

   static om/Ident


support chrome bullshit 2018

support chrome bullshit 2018

--- src/cljs/daveconservatoire/site/ui/exercises.cljs
+++ src/cljs/daveconservatoire/site/ui/exercises.cljs
@@ -192,6 +192,16 @@
                      (map-indexed #(-> [[id %] %2]) urls)))
         sound-req))

+(defn start-exercise-custom-sounds [this]
+  (go
+    (let [{::keys [custom-sounds-req]} (om/props this)
+          progress-chan (handle-progress (om/parent this) (async/chan 10))
+          sounds        (<! (audio/load-sound-library
+                              (flatten-request custom-sounds-req)
+                              progress-chan))]
+      (um/set-value! (om/parent this) ::custom-sounds sounds))
+    nil))
+
 (om/defui ^:once Exercise
   static uc/InitialAppState
   (initial-state [_ _] {::ex-answer              nil
@@ -200,6 +210,7 @@
                         ::hints-used             0
                         ::play-notes             play-notes
                         ::started?               false
+                        ::context-missing        false
                         ::custom-sounds-progress {:ui/progress-value 0
                                                   :ui/progress-total 1}
                         ::custom-sounds-req      nil})
@@ -211,15 +222,12 @@
   (componentDidMount [this]
     (let [{::keys [custom-sounds-req]} (om/props this)]
       (if custom-sounds-req
-        (go
-          (let [progress-chan (handle-progress (om/parent this) (async/chan 10))
-                sounds (<! (audio/load-sound-library
-                             (flatten-request custom-sounds-req)
-                             progress-chan))]
-            (um/set-value! (om/parent this) ::custom-sounds sounds))))))
+        (if @audio/*audio-context*
+          (start-exercise-custom-sounds this)
+          (um/set-value! (om/parent this) ::context-missing true)))))

   (render [this]
-    (let [{::keys [options ex-answer ex-total-questions streak-count notes hints
+    (let [{::keys [options ex-answer ex-total-questions streak-count notes hints context-missing
                    hints-used started? custom-sounds-req custom-sounds custom-sounds-progress]
            :as    props} (om/props this)
           state        (-> this om/get-reconciler om/app-state deref)
@@ -238,9 +246,22 @@
           (dom/div #js {:style #js {"textAlign" "center"}}
             (dom/h1 nil "Make sure you have your volume up, many of our exercises play sound!")
             (if (and custom-sounds-req (not custom-sounds))
-              (dom/div nil
-                (some-> custom-sounds-progress progress-bar)
-                (dom/div nil "Loading..."))
+              (if context-missing
+                (dom/div nil
+                  (dom/a #js {:className "btn btn-primary"
+                              :onClick   (fn [e]
+                                           (.preventDefault e)
+                                           (let [audio-ready (audio/upsert-sound-context)]
+                                             (go
+                                               (<! audio-ready)
+                                               (um/set-value! parent ::context-missing false)
+                                               (<! (start-exercise-custom-sounds this))
+                                               (um/set-value! parent ::started? true)
+                                               (js/setTimeout #(play-sound (om/props this)) 200))))}
+                    (dom/h1 nil "Start Exercise")))
+                (dom/div nil
+                  (some-> custom-sounds-progress progress-bar)
+                  (dom/div nil "Loading...")))
               (dom/a #js {:className "btn btn-primary"
                           :onClick   (fn [e]
                                        (.preventDefault e)


allow user to override default [:synsem :subcat]

--- src/babel/engine.clj
+++ src/babel/engine.clj
@@ -29,10 +29,14 @@
                                         do-enrich :do-enrich}]]
   (let [do-enrich (if do-enrich do-enrich true)
         spec (if (or (= false add-subcat)
-                     (fail? (unify spec {:synsem {:subcat '()}})))
+                     (fail? (unify spec {:synsem {:subcat '()}}))
+                     (not (:none (get-in spec [:synsem :subcat] :none))))
                spec
+
+               ;; else:
                (unify spec
                       {:synsem {:subcat '()}}))
+
         language-model (if (future? language-model)
                          @language-model
                          language-model)


(toks2): convert seqs to vectors

(toks2): convert seqs to vectors

--- src/babel/parse.cljc
+++ src/babel/parse.cljc
@@ -22,6 +22,8 @@
 (defn toks2 [tokens n]
   "group tokens together into every possible sequence of n or less tokens."
   (cond
+    (seq? tokens)
+    (toks2 (vec tokens) n)
     (< n 1) nil
     (= n 1) (vec (list tokens))
     (> n (count tokens)) (toks2 tokens (count tokens))


Make company description optional.

Make company description optional.

--- src/open_company/resources/common.clj
+++ src/open_company/resources/common.clj
@@ -105,7 +105,6 @@
 ;; TODO check for non-blank?
 (def Company
   (merge {:name schema/Str
-          :description schema/Str
           :slug Slug
           :public schema/Bool
           :currency schema/Str
@@ -114,6 +113,7 @@
           :categories (schema/pred #(clojure.set/subset? (set (map keyword %)) (set category-names)))
           :stakeholder-update {:title schema/Str
                                :sections [SectionName]}
+          (schema/optional-key :description) schema/Str
           (schema/optional-key :home-page) schema/Str
           (schema/optional-key :logo) schema/Str
           (schema/optional-key :logo-width) schema/Int


Switch to sha2-256 as default identifier.

--- src/blobble/core.clj
+++ src/blobble/core.clj
@@ -39,7 +39,7 @@
   "Constructs a multihash for the given content."
   [content]
   (when content
-    (multihash/sha1 content)))
+    (multihash/sha2-256 content)))

 (defn validate!


#59 fix request to magnificent

#59 fix request to magnificent

--- src/org/zalando/stups/friboo/auth.clj
+++ src/org/zalando/stups/friboo/auth.clj
@@ -1,5 +1,6 @@
 (ns org.zalando.stups.friboo.auth
   (:require [clj-http.client :as http]
+            [cheshire.core :as json]
             [org.zalando.stups.friboo.ring :as r]
             [org.zalando.stups.friboo.config :refer [require-config]]
             [org.zalando.stups.friboo.log :as log]
@@ -21,8 +22,8 @@
                         {:content-type     :json
                          :oauth-token      token
                          :throw-exceptions false
-                         :body             {:policy  policy
-                                            :payload {:team team}}})]
+                         :body             (json/encode {:policy  policy
+                                                         :payload {:team team}})})]
     (= 200 (:status auth-response))))

 (defn get-auth
@@ -33,9 +34,10 @@
       true
       (let [policy      (get-in request [:configuration :magnificent-policy] "relaxed-radical-agility")
             token       (get-in request [:tokeninfo "access_token"])
+            realm       (get-in request [:tokeninfo "realm"])
             user        (get-in request [:tokeninfo "uid"] "unknown user")
             has-access? (fetch-auth magnificent-url policy team token)]
-        (log/info (str "Access to team" team (if has-access? "granted" "denied") "to" user))
+        (log/info (str "Access " (if has-access? "granted" "denied") ": %s") {:team team :user user :realm realm})
         has-access?))))

 (defn require-auth


Add a location in app state to store invoices

--- frontend/state.cljs
+++ frontend/state.cljs
@@ -46,6 +46,7 @@
    :current-org-data {:plan nil
                       :projects nil
                       :users nil
+                      :invoices nil
                       :name nil}
    :instrumentation []})

@@ -120,6 +121,7 @@
 (def selected-containers-path (conj org-data-path :selected-containers))
 ;; Map of org login to boolean (selected or not selected)
 (def selected-piggyback-orgs-path (conj org-data-path :selected-piggyback-orgs))
+(def org-invoices-path (conj org-data-path :invoices))

 (def settings-path [:settings])


Bit-shifting casts

Bit-shifting casts

--- src/cljs/go/core.clj
+++ src/cljs/go/core.clj
@@ -530,13 +530,13 @@
   ([x y & more] `(bit-and-not (bit-and-not ~x ~y) ~@more)))

 (defmacro ^::ana/numeric bit-clear [x n]
-  (core/list 'js* "float64(int(~{}) &^ (1 << uint(~{})))" x n))
+  (core/list 'js* "float64(int(~{}) &^ (int(1) << uint(~{})))" x n))

 (defmacro ^::ana/numeric bit-flip [x n]
-  (core/list 'js* "float64(int(~{}) ^ (1 << uint(~{})))" x n))
+  (core/list 'js* "float64(int(~{}) ^ (int(1) << uint(~{})))" x n))

 (defmacro ^::ana/numeric bit-test [x n]
-  (core/list 'js* "float64((int(~{}) & (1 << uint(~{}))) != 0)" x n))
+  (core/list 'js* "float64((int(~{}) & (int(1) << uint(~{}))) != 0)" x n))

 (defmacro ^::ana/numeric bit-shift-left [x n]
   (core/list 'js* "float64(int(~{}) << uint(~{}))" x n))
@@ -551,7 +551,7 @@
   (core/list 'js* "float64(uint(~{}) >> uint(~{}))" x n))

 (defmacro ^::ana/numeric bit-set [x n]
-  (core/list 'js* "float64(int(~{}) | (1 << iint(~{})))" x n))
+  (core/list 'js* "float64(int(~{}) | (int(1) << uint(~{})))" x n))

 ;; internal
 (defmacro ^::ana/numeric mask [hash shift]
@@ -559,7 +559,7 @@

 ;; internal
 (defmacro ^::ana/numeric bitpos [hash shift]
-  (core/list 'js* "float64(1 << uint(~{}))" `(mask ~hash ~shift)))
+  (core/list 'js* "float64(int(1) << uint(~{}))" `(mask ~hash ~shift)))

 ;; internal
 (defmacro caching-hash [coll hash-fn hash-key]


minor cleanup

minor cleanup

--- core/project.clj
+++ core/project.clj
@@ -1,8 +1,12 @@
 ; i use this to uberjar up jcdc-pluginfactory, which is then used as a
-; project dependency for all my other scala plugins, so that scala is on their classpath.
+; project dependency for all my other plugins,
+; so that scala, clojure and all the jcdc.pluginfactory classes are available (on the classpath)
+; for all my plugins.
 (defproject jcdc.pluginfactory "0.1.0"
-  :resource-paths ["target/scala-2.10/classes/"]   ; puts plugin.xml in the jar.
-  :target-path    "target/"                        ; put the jar file in the target dir.
+  ; puts plugin.xml, and all jcdc.pluginfactory classes in the jar.
+  :resource-paths ["target/scala-2.10/classes/"]
+  ; put the jar file in the target dir.
+  :target-path    "target/"
   :dependencies   [
     [org.clojure/clojure          "1.4.0"]
     [org.scala-lang/scala-library "2.10.0-RC5"]


Extended entry templates to use previous/next links.

--- src/lambda_blog/templates/entries.clj
+++ src/lambda_blog/templates/entries.clj
@@ -3,33 +3,57 @@
   (:require [lambda-blog.templates.bits :refer [info-label row text-centered well]]
             [lambda-blog.templates.page :refer [page]]
             [lambda-blog.utils :refer [format-date pathcat]]
-            [s-html.tags :refer [a article div footer h1 header hr i nav p span time]]))
+            [s-html.tags :refer [a article div footer h1 header hr i li nav p span time ul]]))

-(defn entry-template [contents-template {:keys [path path-to-root tags timestamp title] :as ent}]
+(defn entry-title [{:keys [path path-to-root tags timestamp title]}]
+  (text-centered
+   (h1 (a {:href (pathcat path-to-root path)} title))
+   (p "Posted on " (time (format-date timestamp)))
+   (nav (map #(info-label
+               (a {:class :tag
+                   :href (pathcat path-to-root (:path %))}
+                  (:id %)))
+             (sort-by :id tags)))))
+
+(defn pager [{:keys [path-to-root]} {:keys [path title] :as link} class]
+  (div {:class [:col-xs-2 :col-sm-3]}
+       (when link
+         (nav
+          (ul {:class :pager}
+              (li {:class class}
+                  (a {:href (pathcat path-to-root path)}
+                     (when (= class :previous)
+                       (i {:class [:fa :fa-chevron-left]}))
+                     (span {:class [:title-short :hidden-xs]}
+                           title)
+                     (when (= class :next)
+                       (i {:class [:fa :fa-chevron-right]})))))))))
+
+(defn entry
+  [{:keys [contents next previous] :as ent}]
   (article
    (header
     (well
      (row
-      (text-centered
-       (h1 (a {:href (pathcat path-to-root path)} title))
-       (p "Posted on " (time (format-date timestamp)))
-       (nav (map #(info-label
-                   (a {:class :tag
-                       :href (pathcat path-to-root (:path %))}
-                      (:id %)))
-                 (sort-by :id tags)))))))
-   (contents-template ent)))
-
-(def entry-summary (partial entry-template
-                            (fn [{:keys [path path-to-root summary]}]
-                              [summary
-                               (p (a {:href (pathcat path-to-root path)}
-                                     "Continue reading "
-                                     (i {:class [:fa :fa-arrow-right]})))])))
-
-(def entry (partial entry-template :contents)) ;; TODO Add prev/next post.
+      (pager ent previous :previous)
+      (div {:class [:col-xs-8 :col-sm-6]}
+           (entry-title ent))
+      (pager ent next :next))))
+   contents))

 (def entry-page (partial page entry))
+
+(defn entry-summary [{:keys [path path-to-root summary tags] :as ent}]
+  (article
+   (-> ent
+       entry-title
+       row
+       well
+       header)
+   summary
+   (p (a {:href (pathcat path-to-root path)}
+         "Continue reading "
+         (i {:class [:fa :fa-arrow-right]})))))

 (defn filtered-entries [{:keys [path-to-root] :as ent} entries]
   (page


-warn

-warn

--- src-cljs/cljs_workcalendar/api.cljs
+++ src-cljs/cljs_workcalendar/api.cljs
@@ -1,13 +1,5 @@
 (ns cljs-workcalendar.api
   (:require [cljs-workcalendar.calendar-data :as data]))
-
-(defn createWorkCalendarService []
-  ;; create map from [y m d] -> day type (:holiday :workday)
-  (let [m (apply hash-map
-                 (mapcat (fn [[year month day type]]
-                           (vector [year month day] type))
-                         data/work-calendar))]
-    (WorkCalendar. m)))

 (defn- date2vec [date]
   (vector (.getFullYear date)
@@ -85,3 +77,11 @@
                  (take-while (fn [d] (<= (.getTime d)
                                          to))
                              (iterate (fn [d] (add-days d 1)) from))))))))
+
+(defn createWorkCalendarService []
+  ;; create map from [y m d] -> day type (:holiday :workday)
+  (let [m (apply hash-map
+                 (mapcat (fn [[year month day type]]
+                           (vector [year month day] type))
+                         data/work-calendar))]
+    (WorkCalendar. m)))


validation bugfix (really) whopsie

validation bugfix (really) whopsie

--- src/dartbot/core.clj
+++ src/dartbot/core.clj
@@ -224,6 +224,7 @@

 (defn valid? [world {:keys [command bid gid payload]}]
   (case command
+    "next" (or (contains? world gid) (contains? world (find-game bid world)))
     "throw" (contains? world (find-game bid world))
     "start" true
     "delete" true
@@ -269,7 +270,6 @@

 (defn end-game [world gid]
   (http/upload-game gid (get world gid))
-  (spit (str gid ".game") (get world gid))
   ;(delete-game gid world)
   world
   )
@@ -330,4 +330,4 @@
         (do (reset! world-atom (update-world @world-atom message)) (recur (read-line)))
         (recur (read-line))
         )
-      )))
+      )))


whitespace

whitespace

--- src/philly_show_checker/server/api/v1/session.clj
+++ src/philly_show_checker/server/api/v1/session.clj
@@ -22,7 +22,7 @@
     :session-data @*session*}))

 (k-dsl/api-get
- {:status  "OK"
+ {:status       "OK"
   :session-data @*session*})


Deal with artifact removal by Go (http://www.go.cd/documentation/user/current/configuration/delete_artifacts.html)

--- scripts/gosync.clj
+++ scripts/gosync.clj
@@ -159,13 +159,20 @@
   ;; Also works around broken Go domain setup
   (clojure.string/replace url #"https?://[^/]+/go" go-url))

-(defn xml-artifacts-for-job-run [{pipeline-name :pipelineName
-                                  pipeline-run :pipelineRun
-                                  stage-name :stageName
-                                  stage-run :stageRun
-                                  job-name :jobName}]
-  (let [artifacts-url (format "/files/%s/%s/%s/%s/%s.json" pipeline-name pipeline-run stage-name stage-run job-name)
-        file-tree (get-json artifacts-url)]
+(defn try-get-artifact-tree [{pipeline-name :pipelineName
+                              pipeline-run :pipelineRun
+                              stage-name :stageName
+                              stage-run :stageRun
+                              job-name :jobName}]
+  (let [artifacts-url (format "/files/%s/%s/%s/%s/%s.json" pipeline-name pipeline-run stage-name stage-run job-name)]
+    (try
+      (get-json artifacts-url)
+      (catch Exception e
+        (println "Unable to get artifact list, might have been deleted by Go")
+        {}))))
+
+(defn xml-artifacts-for-job-run [job-instance]
+  (let [file-tree (try-get-artifact-tree job-instance)]
     (map replace-host-part-for-basic-auth
          (mapcat filter-xml-files file-tree))))


core: last

core: last

--- core.clj
+++ core.clj
@@ -194,4 +194,11 @@
             (seq ret)))
         (list (asig fdecl))))))

-
+(def
+  ^{:arglists '([coll])
+    :doc "Return the last item in coll, in linear time"
+    :added "1.0"}
+  last (fn last [s]
+         (if (next s)
+           (recur (next s))
+           (first s))))


time is a parameter

time is a parameter

--- src/om_animation_playground/core.cljs
+++ src/om_animation_playground/core.cljs
@@ -16,8 +16,8 @@
   (swap! app-state update-in [:tick] inc))

 (defn init-app-loop
-  []
-  (.setInterval js/window #(app-loop-tick) 1000))
+  [time]
+  (.setInterval js/window #(app-loop-tick) time))

 (defn init!
   []
@@ -25,6 +25,6 @@
    app
    app-state
    {:target (. js/document (getElementById "my-app"))})
-  (init-app-loop))
+  (init-app-loop 300))

 (init!)


Add volume settings to start invocation

Add volume settings to start invocation

--- src/overtone_workspace/ambi_piano.clj
+++ src/overtone_workspace/ambi_piano.clj
@@ -33,6 +33,7 @@
   (do
     ;;(volume 0.6)
     ;;(fadein-master)
+    (volume 0)
     (fadein-master 0.6)
     ;;(fadein-master 0.0 0.6 1/64)
     (def metro (metronome 128))


Cosmetics

Cosmetics

--- test/clojure/clojurewerkz/cassaforte/cql_test.clj
+++ test/clojure/clojurewerkz/cassaforte/cql_test.clj
@@ -19,8 +19,6 @@

 (use-fixtures :each th/with-temporary-keyspace)
-
-

 (let [s (th/make-test-session)]

@@ -38,8 +36,7 @@
                                             :age  ?}))
           r        {:name "Alex" :city "Munich" :age (int 19)}]
       (client/execute s
-                      (client/bind prepared ["Alex" "Munich" (int 19)])
-                      )
+                      (client/bind prepared ["Alex" "Munich" (int 19)]))
       (is (= r (first (select s :users))))))

   (deftest test-update


Better test name

Better test name

--- test/clojurewerkz/cassaforte/collections_test.clj
+++ test/clojurewerkz/cassaforte/collections_test.clj
@@ -9,7 +9,7 @@
 (let [s (client/connect ["127.0.0.1"])]
   (use-fixtures :each (fn [f]
                         (th/with-temporary-keyspace s f)))
-  (deftest test-map-and-list-conversion
+  (deftest test-collection-conversion-on-load
     (let [t :users_collections]
       (create-table s t
                   (column-definitions


Have fred use FQ symbol in :arg-resolvers

--- spec/fred.clj
+++ spec/fred.clj
@@ -1,7 +1,7 @@
 (ns fred
   ;; Used a non-standard prefix for rook, to demonstrate that the eval occurs
   ;; in the fred namespace, not somewhere where there's a rook alias already.
-  {:arg-resolvers [(r/build-map-arg-resolver {:partner :barney})]}
+  {:arg-resolvers [(io.aviso.rook/build-map-arg-resolver {:partner :barney})]}
   (:require
     [clojure.core.async :refer [go]]
     [io.aviso.rook :as r]
@@ -16,4 +16,4 @@
         (c/to :get partner)
         c/send
         (c/then (response
-                  (utils/response {:message (format "%s says `%s'" partner (:message response))}))))))+                  (utils/response {:message (format "%s says `%s'" partner (:message response))}))))))


adds additional info for mismatch in bindings (#439)

--- waiter/src/waiter/correlation_id.clj
+++ waiter/src/waiter/correlation_id.clj
@@ -41,23 +41,28 @@
 (def default-correlation-id "UNKNOWN")
 (def ^:dynamic dynamic-correlation-id default-correlation-id)

-(defmacro with-correlation-id
-  "Executes the body with the specified value of correlation-id."
-  [correlation-id & body]
-  `(binding [dynamic-correlation-id ~correlation-id]
-     (let [start-thread-id# (.getId (Thread/currentThread))
-           result# (do ~@body)
-           end-thread-id# (.getId (Thread/currentThread))]
-       (when (not= start-thread-id# end-thread-id#)
-         (log/warn "with-correlation-id binding executed on different threads"
-                   {:correlation-id ~correlation-id
-                    :thread-ids {:end end-thread-id# :start start-thread-id#}}))
-       result#)))
-
 (defn get-correlation-id
   "Retrieve the value of the current correlation-id."
   []
   dynamic-correlation-id)
+
+(defmacro with-correlation-id
+  "Executes the body with the specified value of correlation-id."
+  [correlation-id & body]
+  `(let [correlation-id# ~correlation-id]
+     (binding [dynamic-correlation-id correlation-id#]
+       (let [start-thread# (Thread/currentThread)
+             result# (do ~@body)
+             end-thread# (Thread/currentThread)]
+         (when (not= (.getId start-thread#) (.getId end-thread#))
+           (log/warn "with-correlation-id binding executed on different threads"
+                     {:end {:correlation-id (get-correlation-id)
+                            :thread-id (.getId end-thread#)
+                            :thread-name (.getName end-thread#)}
+                      :start {:correlation-id correlation-id#
+                              :thread-id (.getId start-thread#)
+                              :thread-name (.getName start-thread#)}}))
+         result#))))

 (defmacro correlation-id->str


Not refering munge anymore

Not refering munge anymore

--- src/grimoire/doc.clj
+++ src/grimoire/doc.clj
@@ -1,5 +1,4 @@
 (ns grimoire.doc
-  (:refer-clojure :exclude [munge])
   (:require [clojure.java.io :as io]
             [clojure.string :as string]
             [clojure.repl] ;; gon crowbar into this...


GAWB-2658: Send proper payload when saving a workspace method config (#976)

* Send proper payload when saving a workspace method config

* populate initially

--- src/cljs/main/broadfcui/common/method/config_io.cljs
+++ src/cljs/main/broadfcui/common/method/config_io.cljs
@@ -22,15 +22,19 @@
 (react/defc IOTables
   {:start-editing
    (fn [{:keys [props state locals]}]
-     (swap! locals merge (:values props))
+     (swap! locals utils/deep-merge (:values props))
      (swap! state assoc :editing? true))
    :cancel-editing
    (fn [{:keys [state]}]
      (swap! state dissoc :editing?))
    :save
-   (fn [{:keys [state locals]}]
+   (fn [{:keys [props state locals]}]
      (swap! state dissoc :editing?)
-     @locals)
+     {:inputs (select-keys (:inputs @locals) (-> props :values :inputs keys))
+      :outputs (select-keys (:outputs @locals) (-> props :values :outputs keys))})
+   :component-will-mount
+   (fn [{:keys [props locals]}]
+     (swap! locals utils/deep-merge (:values props)))
    :render
    (fn [{:keys [props this]}]
      (let [id (gensym "io-table-")]
@@ -51,7 +55,7 @@
                                  (let [[task variable] (take-last 2 (string/split name "."))
                                        k-name (keyword name)
                                        error-message (get-in invalid-values [io-key k-name])
-                                       value (get-in values [io-key k-name])]
+                                       value (get-in @locals [io-key k-name])]
                                    (merge (dissoc item :inputType :outputType :optional)
                                           (utils/restructure task variable error-message value)
                                           {:type (some-> (or inputType outputType) process-type)
@@ -100,7 +104,8 @@
                                     [:div {:style (clip table-style/default-cell-left)}
                                      (if editing?
                                        [Autosuggest
-                                        {:initial-value value
+                                        {:key name
+                                         :initial-value value
                                          :data data
                                          :label name
                                          :placeholder (if optional? "Optional" "Select or enter")


Re-arrange widgets

Re-arrange widgets

--- ui-gallery/desktop/src-common/ui_gallery/core.clj
+++ ui-gallery/desktop/src-common/ui_gallery/core.clj
@@ -9,9 +9,7 @@
   (fn [screen entities]
     (update! screen :camera (orthographic) :renderer (stage))
     (let [ui-skin (skin "uiskin.json")]
-      (table [(check-box "I'm a check box" ui-skin)
-              :row
-              (dialog "I'm a dialog" ui-skin :text "This is my content")
+      (table [(dialog "I'm a dialog" ui-skin :text "This is my content")
               :row
               [(image "clojure.png")
                :width 100
@@ -23,6 +21,8 @@
                            "I am too"
                            "So am I"]
                           ui-skin)
+              :row
+              (check-box "I'm a check box" ui-skin)
               :row
               (label "I'm a label" ui-skin)
               :row


This doesn't change anything, it just reorders the functions to make refatoring them easier.

--- src/circle/backend/build/config.clj
+++ src/circle/backend/build/config.clj
@@ -60,12 +60,146 @@
    :schedule {:commit
               {:job :build}}})

+(defn parse-spec-actions [spec]
+  (->> spec
+       (#(select-keys % [:setup :dependencies :compile :test :extra]))
+       (map-vals (fn [lines]
+                   (->> lines
+                        (re-seq #".*")
+                        (vec)
+                        (remove empty?)
+                        (map parse-action))))))
+
 (defn spec-commands [spec]
   (->> spec
        ((juxt :setup :dependencies :compile :test :extra))
        (mapcat (fn [line]
                  (str/split (or line "") #"\r\n")))
        (remove empty?)))
+
+(defn validate-action-map [cmd]
+  (validate! [(is-map?)
+              (require-predicate (fn [cmd]
+                                   (= 1 (count cmd))))
+              (fn [cmd]
+                ((allow-keys [:environment :pwd] (format "only :environment and :pwd are allowed in action %s" cmd)) (-> cmd (first) (val))))] cmd))
+
+(defn parse-action-map
+  "Converts user command string into a bash action."
+  [cmd]
+  (validate-action-map cmd)
+  (let [body (-> cmd (first) (key))
+        body (apply-if (keyword? body) name body)
+        env (-> cmd (first) (val) :environment)
+        pwd (-> cmd (first) (val) :pwd)]
+    (bash body :environment env :pwd pwd)))
+
+(defn parse-action [cmd]
+  (cond
+   (string? cmd) (bash cmd)
+   (map? cmd) (parse-action-map cmd)))
+
+(defn validate-job [job]
+  (validate! [(require-keys [:template])] job))
+
+(defn parse-actions [job]
+  (doall (map parse-action (-> job :commands))))
+
+(defn set-spec [actions]
+  (map #(action/set-source % :spec) actions))
+
+(defn load-actions
+  "Finds job in config, loads approprate template and parses actions"
+  [job]
+  (let [template-name (-> job :template)
+        actions (set-spec (parse-actions job))]
+    (template/apply-template template-name actions)))
+
+(defn load-job [config job-name]
+  (throw-if-not (keyword? job-name) "job name must be a keyword")
+  (let [job (-> config :jobs job-name)]
+    (throw-if-not job "could not find job named %s" job-name)
+    (validate-job job)
+    job))
+
+(defn parse-notify [notifies]
+  (for [n notifies]
+    (if (re-find #"^:" n)
+      (keyword (.substring n 1))
+      n)))
+
+(defn keypair-name
+  "Infer the name of the keypair given the path to the private key"
+  [priv-key-path]
+  (let [priv-key-path (fs/basename priv-key-path)
+        idx (.lastIndexOf priv-key-path ".")]
+    (if (> idx 0)
+      (.substring priv-key-path 0 idx)
+      priv-key-path)))
+
+(defn load-keys
+  "Slurp the file paths and returns a map. Url is the canonical url for the repo. "
+  [node url]
+  (when (-> node :private-key)
+    (try
+      (let [pub-key-path (-> node :public-key)
+            priv-key-path (-> node :private-key)
+            pub-key (slurp (fs/join (git/default-repo-path url) pub-key-path))
+            priv-key (slurp (fs/join (git/default-repo-path url) priv-key-path))]
+        {:private-key priv-key
+         :public-key pub-key
+         :keypair-name (ec2/ensure-keypair (keypair-name priv-key-path) pub-key)})
+      (catch Exception e
+        (println "except" e)
+        (error e "error loading keys")))))
+
+(defn load-default-node [config]
+  circle.backend.build.nodes.rails/default-rails-node)
+
+(defn load-specific-node
+  "Load a named node out of the config file"
+  [config node-name url]
+  (let [node (-> config :nodes node-name)
+        node (merge node (load-keys node url))]
+    (throw-if-not node "node named %s not found in config" node-name)
+    node))
+
+(defn load-node [config job url]
+  (let [node-name (-> job :node (keyword))]
+    (if node-name
+      (load-specific-node config node-name url)
+      (load-default-node config))))
+
+(defn translate-email-recipient
+  "Translates an email recipient like :committer to an email address"
+  [github-json to]
+  (condp = to
+    :owner (-?> github-json :repository :owner :email (vector))
+    :committer (->> (-> github-json :commits)
+                    (map (fn [c]
+                           (-> c :author :email))))))
+
+(defn get-build-email-recipients
+  "Takes a seq of email notifiers, like :committer. returns email literals"
+  [notifies github-json]
+  (->> notifies
+       (mapcat #(translate-email-recipient github-json %))
+       (set)))
+
+(defn infer-project-name [url]
+  (-> url
+      (clj-url.core/parse)
+      :path
+      (str/split #"/")
+      (last)
+      (str/replace #"\.git$" "")))
+
+(defn minimal-project [url]
+  {:name (infer-project-name url)})
+
+(defn minimal-config [url]
+  {})
+

 (defn get-config-from-db [url]
   (let [project (project/get-by-url url)]
@@ -95,114 +229,7 @@
      (get-config-from-db url)
      (get-config-from-yml url))))

-(defn validate-action-map [cmd]
-  (validate! [(is-map?)
-              (require-predicate (fn [cmd]
-                                   (= 1 (count cmd))))
-              (fn [cmd]
-                ((allow-keys [:environment :pwd] (format "only :environment and :pwd are allowed in action %s" cmd)) (-> cmd (first) (val))))] cmd))
-
-(defn parse-action-map
-  "Converts user command string into a bash action."
-  [cmd]
-  (validate-action-map cmd)
-  (let [body (-> cmd (first) (key))
-        body (apply-if (keyword? body) name body)
-        env (-> cmd (first) (val) :environment)
-        pwd (-> cmd (first) (val) :pwd)]
-    (bash body :environment env :pwd pwd)))
-
-(defn parse-action [cmd]
-  (cond
-   (string? cmd) (bash cmd)
-   (map? cmd) (parse-action-map cmd)))
-
-(defn validate-job [job]
-  (validate! [(require-keys [:template])] job))
-
-(defn parse-actions [job]
-  (doall (map parse-action (-> job :commands))))
-
-(defn set-spec [actions]
-  (map #(action/set-source % :spec) actions))
-
-(defn load-actions
-  "Finds job in config, loads approprate template and parses actions"
-  [job]
-  (let [template-name (-> job :template)
-        actions (set-spec (parse-actions job))]
-    (template/apply-template template-name actions)))
-
-(defn load-job [config job-name]
-  (throw-if-not (keyword? job-name) "job name must be a keyword")
-  (let [job (-> config :jobs job-name)]
-    (throw-if-not job "could not find job named %s" job-name)
-    (validate-job job)
-    job))
-
-(defn parse-notify [notifies]
-  (for [n notifies]
-    (if (re-find #"^:" n)
-      (keyword (.substring n 1))
-      n)))
-
-(defn keypair-name
-  "Infer the name of the keypair given the path to the private key"
-  [priv-key-path]
-  (let [priv-key-path (fs/basename priv-key-path)
-        idx (.lastIndexOf priv-key-path ".")]
-    (if (> idx 0)
-      (.substring priv-key-path 0 idx)
-      priv-key-path)))
-
-(defn load-keys
-  "Slurp the file paths and returns a map. Url is the canonical url for the repo. "
-  [node url]
-  (when (-> node :private-key)
-    (try
-      (let [pub-key-path (-> node :public-key)
-            priv-key-path (-> node :private-key)
-            pub-key (slurp (fs/join (git/default-repo-path url) pub-key-path))
-            priv-key (slurp (fs/join (git/default-repo-path url) priv-key-path))]
-        {:private-key priv-key
-         :public-key pub-key
-         :keypair-name (ec2/ensure-keypair (keypair-name priv-key-path) pub-key)})
-      (catch Exception e
-        (println "except" e)
-        (error e "error loading keys")))))
-
-(defn load-default-node [config]
-  circle.backend.build.nodes.rails/default-rails-node)
-
-(defn load-specific-node
-  "Load a named node out of the config file"
-  [config node-name url]
-  (let [node (-> config :nodes node-name)
-        node (merge node (load-keys node url))]
-    (throw-if-not node "node named %s not found in config" node-name)
-    node))
-
-(defn load-node [config job url]
-  (let [node-name (-> job :node (keyword))]
-    (if node-name
-      (load-specific-node config node-name url)
-      (load-default-node config))))
-
-(defn translate-email-recipient
-  "Translates an email recipient like :committer to an email address"
-  [github-json to]
-  (condp = to
-    :owner (-?> github-json :repository :owner :email (vector))
-    :committer (->> (-> github-json :commits)
-                    (map (fn [c]
-                           (-> c :author :email))))))
-
-(defn get-build-email-recipients
-  "Takes a seq of email notifiers, like :committer. returns email literals"
-  [notifies github-json]
-  (->> notifies
-       (mapcat #(translate-email-recipient github-json %))
-       (set)))
+

 (defn add-project-info
   "Adds a bunch of relevant information from the project to the build
@@ -239,29 +266,6 @@
      (add-project-info project)
      (build/build))))

-(defn infer-project-name [url]
-  (-> url
-      (clj-url.core/parse)
-      :path
-      (str/split #"/")
-      (last)
-      (str/replace #"\.git$" "")))
-
-(defn minimal-project [url]
-  {:name (infer-project-name url)})
-
-(defn minimal-config [url]
-  {})
-
-(defn parse-spec-actions [spec]
-  (->> spec
-       (#(select-keys % [:setup :dependencies :compile :test :extra]))
-       (map-vals (fn [lines]
-                   (->> lines
-                        (re-seq #".*")
-                        (vec)
-                        (remove empty?)
-                        (map parse-action))))))

 (defn infer-build-from-url
   "Assumes url does not have a circle.yml. Examine the source tree, and return a build"


fix broken link

fix broken link

--- src/clj/clojuredocs/pages/intro.clj
+++ src/clj/clojuredocs/pages/intro.clj
@@ -164,7 +164,7 @@
       [:p
        "New to Clojure and not sure where to start? Here are a few good resources to get you off on the right foot:"]
       [:ul.getting-started-resources
-       [:li [:a {:href "http://thechangelog.com/rich-hickeys-greatest-hits/"} "Rich Hickey's Greatest Hits (videos)"]]
+       [:li [:a {:href "https://changelog.com/posts/rich-hickeys-greatest-hits/"} "Rich Hickey's Greatest Hits (videos)"]]
        [:li [:a {:href "http://www.braveclojure.com"} "Clojure for the Brave and True"]]
        [:li [:a {:href "http://aphyr.com/posts/301-clojure-from-the-ground-up-welcome"}
              "Clojure from the Ground Up"]]


Changed classify ns usage to reflect updated :as name

--- src/clj/forma/hadoop/jobs/forma.clj
+++ src/clj/forma/hadoop/jobs/forma.clj
@@ -9,7 +9,7 @@
             [forma.thrift :as thrift]
             [forma.hadoop.predicate :as p]
             [forma.trends.analysis :as a]
-            [forma.ops.classify :as log]
+            [forma.ops.classify :as classify]
             [forma.trends.filter :as f]
             [forma.utils :as u]
             [forma.source.humidtropics :as humid]
@@ -250,14 +250,15 @@
   (let [first-idx (date/datetime->period t-res est-start)]
     (<- [?s-res ?eco ?beta]
         (src ?s-res ?pd ?mod-h ?mod-v ?s ?l ?val ?neighbor-val ?eco ?hansen)
-        (log/logistic-beta-wrap [ridge-const convergence-thresh max-iterations]
-                                ?hansen ?val ?neighbor-val :> ?beta)
+        (classify/logistic-beta-wrap
+         [ridge-const convergence-thresh max-iterations]
+         ?hansen ?val ?neighbor-val :> ?beta)
         (:distinct false))))

 (defmapop [apply-betas [betas]]
   [eco val neighbor-val]
   (let [beta (((comp keyword str) eco) betas)]
-    (log/logistic-prob-wrap beta val neighbor-val)))
+    (classify/logistic-prob-wrap beta val neighbor-val)))

 (defbufferop consolidate-timeseries
   "Orders tuples by the second incoming field, inserting a supplied
@@ -284,7 +285,7 @@
   "query to end all queries: estimate the probabilities for each
   period after the training period."
   [{:keys [nodata]} beta-src dynamic-src static-src]
-  (let [betas (log/beta-dict beta-src)]
+  (let [betas (classify/beta-dict beta-src)]
     (<- [?s-res ?mod-h ?mod-v ?s ?l ?prob-series]
         (dynamic-src ?s-res ?pd ?mod-h ?mod-v ?s ?l ?val ?neighbor-val)
         (u/obj-contains-nodata? nodata ?val :> false)


Improve performance, fix time reporting

Improve performance, fix time reporting

--- src/cljs/asciinema_player/core.cljs
+++ src/cljs/asciinema_player/core.cljs
@@ -24,6 +24,9 @@
          :loop loop
          :speed speed}))

+(defn elapsed-time-since [then]
+  (/ (- (.getTime (js/Date.)) (.getTime then)) 1000))
+
 (defn apply-diff [state {:keys [lines cursor]}]
   (merge-with merge state {:lines lines :cursor cursor}))

@@ -38,6 +41,28 @@
       (close! ch))
     ch))

+(defn frames->chan [frames speed]
+  (let [ch (chan)
+        start (js/Date.)]
+    (go
+      (loop [frames frames
+             virtual-time 0
+             pending-diff {}]
+        (when-let [[delay diff] (first frames)]
+          (let [wall-time (* (elapsed-time-since start) speed)
+                new-virtual-time (+ virtual-time delay)
+                ahead (- new-virtual-time wall-time)]
+            (if (pos? ahead)
+              (do
+                (when-not (empty? pending-diff)
+                  (>! ch pending-diff))
+                (<! (timeout (/ (* 1000 ahead) speed)))
+                (>! ch diff)
+                (recur (rest frames) new-virtual-time {}))
+              (recur (rest frames) new-virtual-time (merge-with merge pending-diff diff))))))
+      (close! ch))
+    ch))
+
 (defn prev-diff [frames seconds]
   (loop [frames frames
          seconds seconds
@@ -56,12 +81,6 @@
           (cons [(- delay seconds) diff] (rest frames))))
       frames)))

-(defn elapsed-time-since [then]
-  (/ (- (.getTime (js/Date.)) (.getTime then)) 1000))
-
-(defn frames-at-speed [frames speed]
-  (map (fn [[delay diff]] [(/ delay speed) diff]) frames))
-
 (defn reset-blink [state]
   (assoc-in state [:cursor :on] true))

@@ -72,8 +91,8 @@
   (let [start (js/Date.)
         play-from (:play-from state)
         speed (:speed state)
-        frames (-> (:frames state) (next-frames play-from) (frames-at-speed speed))
-        diff-chan (coll->chan frames)
+        frames (-> (:frames state) (next-frames play-from))
+        diff-chan (frames->chan frames speed)
         timer-chan (coll->chan (repeat [0.3 true]))
         stop-playback-chan (chan)
         elapsed-time #(* (elapsed-time-since start) speed)


disable export for private users

disable export for private users

--- src/cljs/salava/badge/ui/modal.cljs
+++ src/cljs/salava/badge/ui/modal.cljs
@@ -7,7 +7,7 @@
             [salava.badge.ui.assertion :as a]
             [salava.badge.ui.settings :as se]
             [salava.core.ui.share :as s]
-            [salava.core.ui.helper :refer [path-for]]
+            [salava.core.ui.helper :refer [path-for private?]]
             [salava.core.time :refer [date-from-unix-time]]
             [salava.social.ui.follow :refer [follow-badge]]
             [salava.core.ui.error :as err]
@@ -212,7 +212,8 @@
   (let [invalid? (or (bh/badge-expired? (:expires_on @state)) (pos? (:revoked @state)))
         selected-language (cursor state [:content-language])
         data (content-setter @selected-language (:content @state))
-        disable-link (if invalid? "btn disabled")]
+        disable-link (if invalid? "btn disabled")
+        disable-export (if (or (private?) invalid?) "btn disabled")]
     [:div.col-md-9.badge-modal-navi
      [:ul {:class "nav nav-tabs wrap-grid"}
       [:li.nav-item{:class  (if (or (nil? (:tab-no @state))(= 1 (:tab-no @state))) "active")}
@@ -225,7 +226,7 @@
        [:a.nav-link {:class disable-link :href "#" :on-click #(show-settings-dialog (:id @state) state init-data "share")}
         [:div  [:i.nav-icon {:class "fa fa-share-alt fa-lg"}] (t :badge/Share)  ]]]
       [:li.nav-item {:class (if (= 4 (:tab-no @state)) "active")}
-       [:a.nav-link {:class disable-link :href "#" :on-click #(swap! state assoc :tab [se/download-tab-content (assoc data :assertion_url (:assertion_url @state)
+       [:a.nav-link {:class disable-export  :href "#" :on-click #(swap! state assoc :tab [se/download-tab-content (assoc data :assertion_url (:assertion_url @state)
                                                                                :obf_url (:obf_url @state)) state] :tab-no 4)}
         [:div  [:i.nav-icon {:class "fa fa-download fa-lg"}] (t :core/Download)  ]]]
       [:li.nav-item {:class (if (= 5 (:tab-no @state)) "active")}


Show url if no title for image

Show url if no title for image

--- src/cljs/surprise_kittens/core.cljs
+++ src/cljs/surprise_kittens/core.cljs
@@ -32,15 +32,15 @@
     (let [kitten (:kitten (om/props this))
           {:keys [link title]} kitten]
       (dom/div #js {:style #js {:textAlign "center"}}
-       (dom/h1 nil "Surprise! Kittens!")
-       (dom/img #js {:className "clickable rounded shadowed"
-                     :onClick (fn [e]
-                                (GET kitten-url
-                                  #(om/transact! this `[(kitten/change ~%)])))
-                     :src link})
-       (dom/a #js {:href link :title title}
-         (dom/h4 nil title))
-       (dom/small nil "Made with <3 for S.")))))
+        (dom/h1 nil "Surprise! Kittens!")
+        (dom/img #js {:className "clickable rounded shadowed"
+                      :onClick (fn [e]
+                                 (GET kitten-url
+                                   #(om/transact! this `[(kitten/change ~%)])))
+                      :src link})
+        (dom/a #js {:href link :title title}
+          (dom/h4 nil (or title link)))
+        (dom/small nil "Made with <3 for S.")))))

 (defmulti mutate om/dispatch)


Make main paredit-widget function default to enabled

--- src/clojure/paredit_widget/core.clj
+++ src/clojure/paredit_widget/core.clj
@@ -128,7 +128,7 @@

 (defn get-toggle-fn [w]
   (let [buffer (atom (paredit.parser/edit-buffer nil 0 -1 (s/value w)))
-        enable? (atom false)]
+        enable? (atom true)]
     (doto w
       (.addKeyListener (key-event-handler w buffer enable?))
       (.addInputMethodListener (input-method-event-handler w buffer enable?)))


Re-comment out genome_two_point_crossover

--- src/clojush/instructions/genome.clj
+++ src/clojush/instructions/genome.clj
@@ -563,7 +563,7 @@
                         :genome)))
       state)))

-(define-registered
+#_(define-registered
   genome_two_point_crossover
   ^{:stack-types [:genome]}
   (fn [state]


tweaks

tweaks

--- src/jsx_fun/core.clj
+++ src/jsx_fun/core.clj
@@ -201,9 +201,9 @@
       (.eval (io/reader (io/resource "META-INF/resources/webjars/lodash/3.10.1/lodash.js")))))

   (try
-    (let [cx (Context/enter)
-          _ (.setOptimizationLevel cx -1)
-          scope (.initStandardObjects cx)
+    (let [cx     (Context/enter)
+          _      (.setOptimizationLevel cx -1)
+          scope  (.initStandardObjects cx)
           source (slurp (io/resource "babel-core/browser.js"))]
       (.evaluateString cx scope "var global = {};" "shim.js" 1 nil)
       (.evaluateString cx scope source "babel.js" 1 nil))
@@ -236,6 +236,15 @@
         scope  (.initStandardObjects cx)
         source (slurp (io/resource "babel-core/browser.js"))]
     (.evaluateString cx scope
-      "null"
-      "<cmd>" 1 nil))
+      "Object.getOwnPropertySymbols"
+      "<cmd>" 1 nil))
+
+  (let [cx     (Context/enter)
+        _      (.setOptimizationLevel cx -1)
+        scope  (.initStandardObjects cx)
+        source (slurp (io/resource "babel-core/browser.js"))]
+    (.evaluateString cx scope
+      "Object.getOwnPropertyNames"
+      "<cmd>" 1 nil))
+
   )


Drones are now records.

Drones are now records.

--- src/com/lemondronor/turboshrimp.clj
+++ src/com/lemondronor/turboshrimp.clj
@@ -15,28 +15,49 @@
 (declare drone-init-navdata)

+(defrecord Drone
+    [name
+     host
+     at-port
+     counter
+     at-socket
+     navdata-agent
+     navdata-handler
+     navdata-socket
+     nav-data])
+
+
+(defn drone-ip [drone]
+   (.getHostName ^InetAddress (:host drone)))
+
+(defmethod print-method Drone [d ^java.io.Writer w]
+  (.write w (str "#<Drone "
+                 (drone-ip d)
+                 (if (drones (:name d))
+                   "[connected]"
+                   "[not connected]")
+                 ">")))
+
+
 (defn drone-initialize [& options]
   (let [{:keys [name hostname at-port]} options]
-    {:name (or name :default)
-     :host (InetAddress/getByName
-            (or hostname default-hostname))
-     :at-port (or at-port default-at-port)
-     :counter (atom 0)
-     :at-socket (DatagramSocket.)
-     :navdata-agent (agent {})
-     :navdata-handler (atom nil)
-     :navdata-socket (DatagramSocket.)
-     :nav-data (atom {})}))
-
+    (map->Drone
+     {:name (or name :default)
+      :host (InetAddress/getByName
+             (or hostname default-hostname))
+      :at-port (or at-port default-at-port)
+      :counter (atom 0)
+      :at-socket (DatagramSocket.)
+      :navdata-agent (agent {})
+      :navdata-handler (atom nil)
+      :navdata-socket (DatagramSocket.)
+      :nav-data (atom {})})))

 (defn connect [drone]
   (swap! drones assoc (:name drone) drone)
   (mdrone (:name drone) :flat-trim)
   drone)

-
-(defn drone-ip [drone-name]
-   (.getHostName ^InetAddress (:host (drone-name @drones))))

 (defn send-command [name ^String data]
   (let [^InetAddress host (:host (name @drones))


Fix error data on resolver error log

Fix error data on resolver error log

--- src/com/wsscode/pathom/connect.cljc
+++ src/com/wsscode/pathom/connect.cljc
@@ -1084,7 +1084,7 @@
 (defn reader3-run-resolver-node
   "Call a run graph node resolver and execute it."
   [{::keys   [indexes]
-    ::p/keys [async-parser? processing-sequence]
+    ::p/keys [async-parser?]
     :as      env}
    plan
    {::keys     [sym]
@@ -1118,11 +1118,11 @@
                                                         ::resolver-call-input e
                                                         ::resolver-response   r})
                            r)
-                         (catch #?(:clj Throwable :cljs :default) e
+                         (catch #?(:clj Throwable :cljs :default) err
                            (reader3-node-log! env node {::pt/event            ::node-resolver-error
                                                         ::resolver-call-input e
-                                                        ::resolver-error      e})
-                           (throw e))))]
+                                                        ::resolver-error      err})
+                           (throw err))))]
       (if async-parser?
         (go-promise
           (let [response (try
@@ -1131,11 +1131,11 @@
                                                           ::resolver-call-input e
                                                           ::resolver-response   r})
                              r)
-                           (catch #?(:clj Throwable :cljs :default) e
+                           (catch #?(:clj Throwable :cljs :default) err
                              (reader3-node-log! env node {::pt/event            ::node-resolver-error
                                                           ::resolver-call-input e
-                                                          ::resolver-error      e})
-                             (throw e)))]
+                                                          ::resolver-error      err})
+                             (throw err)))]
             (if (reader3-merge-resolver-response env sym response)
               (<?maybe (reader3-run-next-node env plan node)))))
         (if (reader3-merge-resolver-response env sym response)


Persist input once parsed. 30% speedup for 1 million entries locally.

--- src/laskuri/core.clj
+++ src/laskuri/core.clj
@@ -7,7 +7,8 @@
   (:require [clojure.java.io :as io])
   (:use [clojure.tools.logging :only (info error)])
   (:require [environ.core :refer [env]])
-  (:gen-class main true)) ;:gen-class :)
+  (:import [org.apache.spark.api.java JavaSparkContext StorageLevels])
+  (:gen-class main true))

 (defn format-kv
@@ -82,7 +83,9 @@
   (let [parsed-lines (get-parsed-lines ctx input-location redact)

         ; filter out lines that didn't resolve, leaving good DOIs
-        parsed-lines-ok (f/filter parsed-lines (f/fn [[date doi domain status]] (not= 0 (.length status))))
+        parsed-lines-ok (f/persist
+                          (f/filter parsed-lines (f/fn [[date doi domain status]] (not= 0 (.length status))))
+                          StorageLevels/DISK_ONLY)

         ; doi -> date
         doi-date (f/map parsed-lines-ok (f/fn [[date doi [subdomain domain tld] status]]
@@ -132,13 +135,15 @@

         ; date truncated to period
         ; date represents the beginning of the period (i.e. first second of the day, month or year).
-        parsed-lines-period (f/map parsed-lines-ok (f/fn [[date doi domain status]]
-                                                    [(condp = period
-                                                     :year (util/truncate-year date)
-                                                     :month (util/truncate-month date)
-                                                     :day (util/truncate-day date)
-                                                     nil date
-                                                     date) doi domain]))
+        parsed-lines-period (f/persist
+                              (f/map parsed-lines-ok (f/fn [[date doi domain status]]
+                                [(condp = period
+                                 :year (util/truncate-year date)
+                                 :month (util/truncate-month date)
+                                 :day (util/truncate-day date)
+                                 nil date
+                                 date) doi domain]))
+                              StorageLevels/DISK_ONLY)

         ; For the following, the period is included in the key because we're counting unique 'X per period'
         ; (e.g. '10.5555/12345678 per month').


reference typing coded (need tests ...)

reference typing coded (need tests ...)

--- src/latte/typing.clj
+++ src/latte/typing.clj
@@ -62,10 +62,11 @@
  (type-of {} [] :kind) => [:ko {:msg "Kind has not type" :term :kind}])

 (defn type-check? [def-env env term type]
+  ;; (println "type-check? term=" term "type=" type)
   (let [[status type'] (type-of def-env env term)]
     (if (= status :ok)
       (norm/delta-beta-eq? def-env type type')
-      (throw (ex-info "Cannot check type of term" {:term term})))))
+      (throw (ex-info "Cannot check type of term" {:term term :from type'})))))

 ;;{
 ;;
@@ -248,3 +249,46 @@
 ;;              ::> (prod [xM+1 tM+1] ... (prod [xN tN] t [e1/x1, e2/x2, ...eM/xM]) ...)
 ;;}

+(defn type-of-ref [def-env env name args]
+  (let [ddef (get def-env name)]
+    (cond
+      (nil? ddef) [:ko {:msg "No such definition." :def-name name}]
+      (> (count args) (:arity ddef))
+      [:ko {:msg "Too many arguments for definition." :term (list* name args) :arity ddef}]
+      :else
+      (loop [args args, params (:params ddef), sub {}]
+        ;; (println "args=" args "params=" params "sub=" sub)
+        (if (seq args)
+          (let [arg (first args)
+                ty (stx/subst (second (first params)) sub)]
+            ;; (println "arg=" arg "ty=" ty)
+            (if (not (type-check? def-env env arg ty))
+              [:ko {:msg "Wrong argument type"
+                    :term (list* name args)
+                    :arg arg
+                    :expected-type ty}]
+              (recur (rest args) (rest params) (assoc sub (ffirst params) arg))))
+          ;; all args have been checked
+          (loop [params (reverse params), res (:ret-type ddef)]
+            (if (seq params)
+              (recur (rest params) (list 'prod (first params) res))
+              ;; all params have been handled
+              [:ok (stx/subst res sub)])))))))
+
+(example
+ (type-of '{test {:params [[x :type] [y :type]]
+                  :ret-type :type
+                  :arity 2}}
+          '[[a :type] [b :type]]
+          '(test a b))
+ => [:ok :type])
+
+(example
+ (type-of '{test {:params [[x :type] [y :type]]
+                  :ret-type :type
+                  :arity 2}}
+          '[[bool :type] [a :type] [b bool]]
+          '(test a b))
+ => '[:ko {:msg "Wrong argument type", :term (test b), :arg b, :expected-type :type}])
+
+


Implemented tip by Laurent to suppress unwanted warning about uninitialized log4j.

--- ccw.support.examples/src/ccw/support/examples/labrepl/wizards/LabreplCreationOperation.clj
+++ ccw.support.examples/src/ccw/support/examples/labrepl/wizards/LabreplCreationOperation.clj
@@ -229,7 +229,7 @@
 													(let [console (wait-for-resource #(ClojureClient/findActiveReplConsole) "Console" *timeout* *step* (.newChild job-progress 30))]
 			                      (if console
 			                        (do
-				                        (EvaluateTextAction/evaluateText console "(labrepl/-main)")
+				                        (EvaluateTextAction/evaluateText console "(org.apache.log4j.BasicConfigurator/configure (org.apache.log4j.varia.NullAppender.)) (labrepl/-main)")
 													      (open-browser (.newChild job-progress 30)))
 			                        Status/CANCEL_STATUS)))))]
                   (.schedule repl-browser-job))))))))


Исправления

Исправления

--- radiolamp-6P3S/src/r6p3s/core.cljs
+++ radiolamp-6P3S/src/r6p3s/core.cljs
@@ -318,7 +318,7 @@
        (when (< 0 h) (str h " час. "))
        (when m  (str m " мин. ")) ;; Минуты отображаем всегда
        (when s  (str s " сек. "))
-       (when ms (str ms " милисек."))))
+       (when ms (str ms " мс"))))

 (defn the-time-has-passed-from-the-date-as-str [date]
   (let [[d h m] (the-time-has-passed-from-the-date date)]


just failed on openjdk-7

just failed on openjdk-7

--- dada-core/src/test/clojure/org/dada/core/test_clojure.clj
+++ dada-core/src/test/clojure/org/dada/core/test_clojure.clj
@@ -85,11 +85,11 @@
       (is (faster 1000000000 (.v r) (aget a 0))))))

 ;; no it's not autoboxing slowing down the int-array test - array access is slower than record access - by a factor of 10
-(if (not (ibm?))
-  (deftest record-vs-object-array-access
-    (let [^Value r (Value. 0)
-	  ^objects a (object-array [0])]
-      (is (faster 1000000000 (.v r) (aget a 0))))))
+;; (if (not (ibm?))
+;;   (deftest record-vs-object-array-access
+;;     (let [^Value r (Value. 0)
+;; 	  ^objects a (object-array [0])]
+;;       (is (faster 1000000000 (.v r) (aget a 0))))))

 (defrecord Foo (^int a))
 (defrecord Bar (^Integer a))


on-upsert working and notifiying "joined-model" for simple cases

--- dada2-core/src/test/clojure/org/dada2/test_join_model.clj
+++ dada2-core/src/test/clojure/org/dada2/test_join_model.clj
@@ -2,6 +2,7 @@
     (:use
      [clojure test]
      [clojure.tools logging]
+     [org.dada2 utils]
      [org.dada2 core]
      [org.dada2 test-core]
      [org.dada2 map-model]
@@ -46,22 +47,22 @@
    (fn [args] (apply join-fn v args))
    (permute [[]] (map (fn [index key] (index (key v))) rhs-indeces ks))))

-(defn- lhs-upsert [[old-index & rhs-indeces] ks v join-fn]
+(defn- lhs-upsert [[old-index & rhs-indeces] ks v join-fn joined-model]
   (let [new-index (mapv (fn [index key] (group index (key v) v)) old-index ks)
-	new-indeces (apply vector new-index rhs-indeces)]
-    (println "LHS JOINS: " (derive-joins v rhs-indeces ks join-fn)) ;TODO: what should we do with this ?
-    new-indeces))
+	new-indeces (apply vector new-index rhs-indeces)
+	joins (derive-joins v rhs-indeces ks join-fn)]
+    [new-indeces (fn [_] (on-upserts joined-model joins))]))

 ;;; TODO
 (defn- lhs-delete [old-indeces i ks v join-fn])
 (defn- lhs-upserts [old-indeces i ks vs join-fn])
 (defn- lhs-deletes [old-indeces i ks vs join-fn])

-(defn- lhs-view [indeces i keys join-fn]
+(defn- lhs-view [indeces i keys join-fn joined-model]
   (reify
    View
    ;; singleton changes
-   (on-upsert [_ upsertion] (swap! indeces lhs-upsert keys upsertion join-fn) nil)
+   (on-upsert [_ upsertion] ((swap*! indeces lhs-upsert keys upsertion join-fn joined-model) []) nil) ;TODO - pass in views to notifier
    (on-delete [_ deletion]  (swap! indeces lhs-delete keys deletion join-fn) nil)
    ;; batch changes
    (on-upserts [_ upsertions] (swap! indeces lhs-upserts keys upsertions join-fn) nil)
@@ -69,8 +70,7 @@

 ;; TODO: return a pair - first is notification fn, second is new-indeces - use swap*! to apply

-(defn- rhs-upsert [old-indeces i lhs-key rhs-ks v join-fn]
-  (println "rhs-upsert: " old-indeces i rhs-ks v join-fn)
+(defn- rhs-upsert [old-indeces i lhs-key rhs-ks v join-fn joined-model]
   (let [
 	old-index (nth old-indeces i)
 	key (lhs-key v)
@@ -84,8 +84,7 @@
 	rhs-indeces (rest new-indeces)
 	joins (mapcat (fn [lhs] (derive-joins lhs rhs-indeces rhs-ks join-fn)) lhses)
 	]
-    (println "RHS JOINS: " joins)
-    new-indeces
+    [new-indeces (fn [_] (on-upserts joined-model joins))]
     ))

 ;;; TODO
@@ -93,11 +92,11 @@
 (defn- rhs-upserts [old-indeces i ks vs join-fn])
 (defn- rhs-deletes [old-indeces i ks vs join-fn])

-(defn- rhs-view [indeces i key keys join-fn]
+(defn- rhs-view [indeces i key keys join-fn joined-model]
   (reify
    View
    ;; singleton changes
-   (on-upsert [_ upsertion] (swap! indeces rhs-upsert i key keys upsertion join-fn) nil)
+   (on-upsert [_ upsertion] ((swap*! indeces rhs-upsert i key keys upsertion join-fn joined-model) []) nil) ;TODO: pass in views to notifier
    (on-delete [_ deletion]  (swap! indeces rhs-delete i keys deletion join-fn) nil)
    ;; batch changes
    (on-upserts [_ upsertions] (swap! indeces rhs-upserts i keys upsertions join-fn) nil)
@@ -105,18 +104,18 @@

 ;;; attach lhs to all rhses such that any change to an rhs initiates an
 ;;; attempt to [re]join it to the lhs and vice versa.
-(defn- join-views [join-fn [lhs-model & lhs-keys] & rhses]
+(defn- join-views [join-fn [lhs-model lhs-keys joined-model] & rhses]
   (let [indeces (atom [(apply vector (repeat (count rhses) {}))])]
     ;; view lhs
     (log2 :info (str " lhs: " lhs-model ", " lhs-keys))
-    (attach lhs-model (lhs-view indeces 0 lhs-keys join-fn))
+    (attach lhs-model (lhs-view indeces 0 lhs-keys join-fn joined-model))
     ;; view rhses
     (doseq [[model key] rhses]
 	(let [i (count @indeces)]   ; figure out offset for this index
 	  (log2 :info (str " rhs: " model ", " i ", " key))
 	  (swap! indeces conj {})	; add index for this model
 	  ;; view rhs model
-	  (attach model (rhs-view indeces i key lhs-keys join-fn))))
+	  (attach model (rhs-view indeces i key lhs-keys join-fn joined-model))))
     indeces))

 (deftype JoinModel [^String name ^Atom state ^Atom views]
@@ -174,7 +173,8 @@
   (let [as (versioned-optimistic-map-model (str :as) :name :version >)
 	bs (versioned-optimistic-map-model (str :bs) :name :version >)
 	cs (versioned-optimistic-map-model (str :cs) :name :version >)
-	join (join-model "join-model" [[as :fk-b :fk-c][bs :b][cs :c]] join-abc)
+	joined-model (versioned-optimistic-map-model (str :joined) :name :version >)
+	join (join-model "join-model" [[as [:fk-b :fk-c] joined-model][bs :b][cs :c]] join-abc)
 	view (test-view "test")
 	a1 (->A :a1 0 :b :c)
 	a2 (->A :a2 0 :b :c)
@@ -183,6 +183,7 @@
 	c1 (->C :c1 0 :c "c1-data")
 	c2 (->C :c2 0 :c "c2-data")]
     (is (= [[{}{}]{}{}] (data join)))
+    (is (= {} (data joined-model)))

     (attach join view)
     (is (= nil (data view)))
@@ -190,27 +191,51 @@
     ;; initial data
     (on-upsert bs b1)
     (is (= [[{}{}]{:b [b1]} {}] (data join)))
+    (is (= {} (data joined-model)))

     (on-upsert cs c1)
     (is (= [[{}{}]{:b [b1]} {:c [c1]}] (data join)))
+    (is (= {} (data joined-model)))

     ;; join - lhs - a1
     (on-upsert as a1)
     (is (= [[{:b [a1]}{:c [a1]}]{:b [b1]} {:c [c1]}] (data join)))
+    (is (= {:a1-b1-c1 (->ABC :a1-b1-c1 0 "b1-data" "c1-data")} (data joined-model)))

     ;; join - new rhs - b2
     (on-upsert bs b2)
     (is (= [[{:b [a1]}{:c [a1]}]{:b [b1 b2]} {:c [c1]}] (data join)))
+    (is (= {
+	   :a1-b1-c1 (->ABC :a1-b1-c1 0 "b1-data" "c1-data")
+	   :a1-b2-c1 (->ABC :a1-b2-c1 0 "b2-data" "c1-data")}
+	   (data joined-model)))

     ;; join - new rhs - c2
     (on-upsert cs c2)
     (is (= [[{:b [a1]}{:c [a1]}]{:b [b1 b2]} {:c [c1 c2]}] (data join)))
-
+    (is (= {
+	   :a1-b1-c1 (->ABC :a1-b1-c1 0 "b1-data" "c1-data")
+	   :a1-b2-c1 (->ABC :a1-b2-c1 0 "b2-data" "c1-data")
+	   :a1-b1-c2 (->ABC :a1-b1-c2 0 "b1-data" "c2-data")
+	   :a1-b2-c2 (->ABC :a1-b2-c2 0 "b2-data" "c2-data")
+	   }
+	   (data joined-model)))
     ;; join - new lhs - a2
     (on-upsert as a2)
     (is (= [[{:b [a1 a2]}{:c [a1 a2]}]{:b [b1 b2]} {:c [c1 c2]}] (data join)))
-
+    (is (= {
+	   :a1-b1-c1 (->ABC :a1-b1-c1 0 "b1-data" "c1-data")
+	   :a1-b2-c1 (->ABC :a1-b2-c1 0 "b2-data" "c1-data")
+	   :a1-b1-c2 (->ABC :a1-b1-c2 0 "b1-data" "c2-data")
+	   :a1-b2-c2 (->ABC :a1-b2-c2 0 "b2-data" "c2-data")
+	   :a2-b1-c1 (->ABC :a2-b1-c1 0 "b1-data" "c1-data")
+	   :a2-b2-c1 (->ABC :a2-b2-c1 0 "b2-data" "c1-data")
+	   :a2-b1-c2 (->ABC :a2-b1-c2 0 "b1-data" "c2-data")
+	   :a2-b2-c2 (->ABC :a2-b2-c2 0 "b2-data" "c2-data")
+	   }
+	   (data joined-model)))
     ;; what about amend-in/out ?
     ;; what about delete ?

+    ;; check outgoing joins
     ))


Only return latest 20 items in the feed

Only return latest 20 items in the feed

--- newsfeed/src/newsfeed/api.clj
+++ newsfeed/src/newsfeed/api.clj
@@ -44,7 +44,7 @@

 (defn combine-feeds
   [feeds]
-  (reverse (sort-by get-sort-value (apply concat (map :entries feeds)))))
+  (take 20 (reverse (sort-by get-sort-value (apply concat (map :entries feeds))))))

 (defn process-feed
   [feed]


Trying to accept a fix in lein-cljsbuild, but failed

--- libs/axiom-cljs/project.clj
+++ libs/axiom-cljs/project.clj
@@ -3,7 +3,8 @@
   :url "https://github.com/brosenan/axiom"
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}
-  :aliases {"im" "classpath" ;; As a no-op
+  :aliases {"im" "classpath"
+            "im1" ["doo" "phantom" "test" "once"]
             "eim" ["monolith" "each" "im"]}
   :dependencies [[org.clojure/clojure "1.8.0"]
                  [org.clojure/clojurescript "1.9.671"]
@@ -11,7 +12,7 @@
                  [devcards "0.2.3"]
                  [org.clojure/core.async "0.3.442"]
                  [jarohen/chord "0.8.1"]]
-  :plugins [[lein-cljsbuild "1.1.4" :exclusions [[org.clojure/clojure]]]
+  :plugins [[lein-cljsbuild "1.1.7-SNAPSHOT" :exclusions [[org.clojure/clojure]]]
             [lein-figwheel "0.5.6"]
             [lein-doo "0.1.7"]]
   :clean-targets ^{:protect false} [:target-path "out" "resources/public/cljs"]


tidy up the logging a bit

tidy up the logging a bit

--- src/merlion/core.clj
+++ src/merlion/core.clj
@@ -9,7 +9,7 @@
             [clojure.test :as test :refer [deftest testing is]]
             [clojure.java.io :as io]
             [clojure.set :as set]
-            [taoensso.timbre :as log :refer [debug]]
+            [taoensso.timbre :as log :refer [debug info]]
             [clojure.core.async :as async
              :refer [<! <!! go chan >! close! alts!]]))

@@ -140,8 +140,11 @@
         (is (ready-for? (poll-channels [[ssh :read]] 1357) ssh :read))))))

 (defn accept-connection [socket]
-  (let [s1 (log/spy (.accept socket))]
+  (let [s1 (.accept socket)]
     (when s1
+      (when (log/may-log? :debug)
+        ;; no need to getRemoteAddress if we don't have debug logging
+        (log/debug (str "accepted connection from " (.getRemoteAddress s1))))
       (doto s1
         (.configureBlocking false)))))

@@ -209,8 +212,7 @@
             ;; if we have no serversocket and no open channels, it's
             ;; byebye time
             (empty? (.keys selector))
-            (do (debug "backend stopped")
-                nil)
+            nil

             ;; Zeroth, close the corresponding down/upstream for any up/downstream
             ;; on which we received eof while reading
@@ -270,13 +272,14 @@
             ))))))

+
 (defn backend-chan
   [host port listener]
-  (debug ["backend chan for " host port])
+  (info (str "started backend for " host ":" port))
   (let [ch (chan)]
     (future
       (backend listener host port ch)
-      (debug ["backend thread quit" host port]))
+      (info (str "backend " host  ":" port " quit")))
     ch))

 (defn parse-address [a]
@@ -287,7 +290,7 @@
   (let [existing (keys backends)
         wanted (map #(vector % listener) (keys (:backends config)))
         unwanted (set/difference (set existing) (set wanted))]
-    (debug ["unwanted " unwanted])
+    (log/spy :trace unwanted)
     (run! #(async/put! % :quit) (map #(:chan (get backends %)) unwanted))
     (reduce (fn [m [n v]]
               (let [a (parse-address (:listen-address v))]
@@ -310,15 +313,19 @@
   (.. listener socket getLocalPort))

 (defn update-listener [listener config]
-  (if-let [req-addr (log/spy (get-in config [:config :listen-address]))]
+  (when-let [l (keyword (get-in config [:config :log-level]))]
+    (when-not (= l (:level log/*config*))
+      (log/info (str "Setting log level to " l))
+      (log/set-level! (keyword l))))
+  (if-let [req-addr (log/spy :trace (get-in config [:config :listen-address]))]
     (let [req-port (:port (parse-address req-addr))
           old-port (and listener (get-port listener))]
       (if (and listener
                (= old-port req-port))
-        (log/spy listener)
+        (log/spy :trace listener)
         (let [new-l (ServerSocketChannel/open)]
           (and listener (.close listener))
-          (doto (log/spy new-l)
+          (doto (log/spy :trace new-l)
             (.configureBlocking false)
             (.bind (InetSocketAddress. req-port))))))
     nil))
@@ -346,10 +353,7 @@

 (defn healthy-backends [timestamp backends]
   (let [h (filter (partial seen-since? timestamp) (vals backends))]
-    (if (seq h)
-      (debug ["backends " (map :name h)])
-      (debug ["no healthy backends "]))
-    h))
+    (log/spy :trace h)))

 (defn run-server [prefix]
   (let [config-ch (combined-config-watcher prefix)
@@ -368,12 +372,13 @@
                          val))

                 (= ch shutdown)
-                (do (debug "quit") (.close listener))
+                (do (info "server quit") (.close listener))

                 :else
                 (recur backends listener config)))))
     shutdown))

 (defn -main [prefix]
+  (log/set-level! :debug)
   (run-server prefix)
   (while true (Thread/sleep 5000)))


tweak message handling

tweak message handling

--- src/bolt/core.cljs
+++ src/bolt/core.cljs
@@ -74,11 +74,10 @@
     (if url
       ;; TODO: url encode args
       (let [redirect-url (build-url url (:args cmd))]
-        (prn js/console redirect-url)
+        (om/update! app assoc :message "Redirecting ...")
         (set! (.-location js/window) redirect-url))
-      (do
-        (om/update! app assoc :error (str "No command found for " (:name cmd)))
-        nil))))
+      (om/update! app assoc :error (str "No command found for " (:name cmd))))
+    nil))

 (defn bolt-app [app owner]
   (reify
@@ -101,8 +100,11 @@
                (when (:error app)
                  (dom/div
                    #js {:className "alert alert-danger"}
-                   nil
                    (:error app)))
+               (when (:message app)
+                 (dom/div
+                   #js {:className "alert alert-success"}
+                   (:message app)))
                (om/build search-form app {:opts {:chan (om/get-state owner :chan)}})
                (when (:search-result app)
                  (handle-search-result app))))))


revert boot-cljs-test to work on Windows CI

--- build.boot
+++ build.boot
@@ -9,7 +9,7 @@
                  [com.cognitect/transit-clj   "0.8.293"        :scope "test"]
                  [com.cemerick/piggieback     "0.2.1"          :scope "test"]
                  [adzerk/boot-cljs            "1.7.228-2"      :scope "test"]
-                 [crisptrutski/boot-cljs-test "0.3.0-SNAPSHOT" :scope "test"]
+                 [crisptrutski/boot-cljs-test "0.2.2"          :scope "test"]
                  [org.clojure/tools.nrepl     "0.2.12"         :scope "test"]
                  [weasel                      "0.7.0"          :scope "test"]])

@@ -46,7 +46,7 @@
                 (nil? exit?) not)]
     (comp
       (testing)
-      (if windows? (add-node-modules) identity)
+      (add-node-modules)
       (test-cljs
         :js-env :node
         :namespaces #{'lumo.js-deps-tests 'lumo.repl-tests}


put config map in var, fix dev task, add libs task

--- build.boot
+++ build.boot
@@ -10,6 +10,7 @@
                 "maven-central" "http://mvnrepository.com"
                 "central" "http://repo1.maven.org/maven2/"}
  :dependencies   '[[org.clojure/clojure "1.8.0" :scope "provided"]
+                   [boot/core "2.5.2" :scope "provided"]
                    [migae/boot-gae "0.1.0-SNAPSHOT" :scope "test"]
                    [miraj/boot-miraj "0.1.0-SNAPSHOT" :scope "test"]
                    [miraj/html "5.1.0-SNAPSHOT"]
@@ -29,112 +30,110 @@
                    [ring/ring-servlet "1.4.0"]
                    [ring/ring-defaults "0.1.5"]
                    [ns-tracker/ns-tracker "0.3.0"]
-                   ]
+                   ])

- ;; web.xml doco: http://docs.oracle.com/cd/E13222_01/wls/docs81/webapp/web_xml.html
- :gae {;; :build-dir "build/exploded-app"
-       ;; :sdk-root  "~/.gradle/appengine-sdk"
-       :list-tasks true
-       ;; :verbose true
-       :aot #{'migae.servlets}
-       :app-id (clojure.string/replace +project+ #"/" ".")
-       :module "foo"
-       :version (clojure.string/lower-case (clojure.string/replace +version+ #"\." "-"))
-       :display-name {:name "hello app"}
-       :descr {:text "description of this web app, for web.xml etc."}
-       :appengine {:thread-safe true
-                   ;; :public-root "/static"
-                   :system-properties {:props [{:name "myapp.maximum-message-length" :value "140"}
-                                               {:name "myapp.notify-every-n-signups" :value "1000"}
-                                               {:name"myapp.notify-url"
-                                                :value "http://www.example.com/supnotfy"}]}
-                   ;; :env-vars [{:name "FOO" :value "BAR"}]
-                   :logging {:jul {:name "java.util.logging.config.file"
-                                   :value "WEB-INF/logging.properties"}}
-                             ;; #_{:log4j {:name "java.util.logging.config.file"
-                             ;;          :value "WEB-INF/classes/log4j.properties"}}}
-                   :sessions true
-                   :ssl true
-                   :async-session-persistence {:enabled "true" :queue-name "myqueue"}
-                   :inbound-services [{:service :mail} {:service :warmup}]
-                   ;;mime: http://www.opensource.apple.com/source/JBoss/JBoss-739/jakarta-tomcat-LE-jdk14/conf/web.xml
-                   :mime-mappings [{:ext "abs" :type "audio/x-mpeg"}
-                                   {:ext "gz"  :type "application/x-gzip"}
-                                   {:ext "htm" :type "text/html"}
-                                   {:ext "html" :type "text/html"}
-                                   {:ext "svg" :type "image/svg+xml"}
-                                   {:ext "txt" :type "text/plain"}
-                                   {:ext "xml" :type "text/xml"}
-                                   {:ext "xsl" :type "text/xsl"}
-                                   {:ext "zip" :type "application/zip"}]
-                   :precompilation true
-                   :scaling {:basic {:max-instances 11 :idle-timeout "10m"
-                                     :instance-class "B2"}
-                             :manual {:instances 5
-                                     :instance-class "B2"}
-                             :automatic {:instance-class "F2"
-                                         :idle-instances {:min 5
-                                                          ;; ‘automatic’ is the default value.
-                                                          :max "automatic"}
-                                         :pending-latency {:min "30ms" :max "automatic"}
-                                         :concurrent-requests {:max 50}}}
-                   ;; :resource-files {:include [{:path "**.xml"
-                   ;;                            :expiration "4d h5"
-                   ;;                            :http-header {:name "Access-Control-Allow-Origin"
-                   ;;                                          :value "http://example.org"}}]
-                   ;;                  :exclude [{:path "feed/**.xml"}]}
-                   ;; :static-files {:include {:path "foo/**.png"
-                   ;;                          :expiration "4d h5"
-                   ;;                          :http-header {:name "Access-Control-Allow-Origin"
-                   ;;                                        :value "http://example.org"}}
-                   ;;                :exclude {:path "bar/**.zip"}}
-                   }
-       :welcome {:file "index.html"}
-       :errors [{:code 404 :url "/404.html"}] ;; use :code, or:type, e.g 'java.lang.String
-       :servlet-ns 'migae.servlets
-       :servlets [{:ns 'migae.echo  ;; = servlet-class
-                   ;; :jsp - alternative to :ns, for using java servlet pages
-                   :name "echo-servlet"
-                   :display {:name "Awesome Echo Servlet"}
-                   :desc {:text "blah blah"}
-                   :url "/echo/*"
-                   :params [{:name "greeting" :val "Hello"}]
-                   :load-on-startup {:order 3}}
+(def gae
+  ;; web.xml doco: http://docs.oracle.com/cd/E13222_01/wls/docs81/webapp/web_xml.html
+  {;; :build-dir "build/exploded-app"
+   ;; :sdk-root  "~/.gradle/appengine-sdk"
+   :list-tasks true
+   ;; :verbose true
+   :aot #{'migae.servlets}
+   :app-id (clojure.string/replace +project+ #"/" ".")
+   :module "foo"
+   :version (clojure.string/lower-case (clojure.string/replace +version+ #"\." "-"))
+   :display-name {:name "hello app"}
+   :descr {:text "description of this web app, for web.xml etc."}
+   :appengine {:thread-safe true
+               ;; :public-root "/static"
+               :system-properties {:props [{:name "myapp.maximum-message-length" :value "140"}
+                                           {:name "myapp.notify-every-n-signups" :value "1000"}
+                                           {:name"myapp.notify-url"
+                                            :value "http://www.example.com/supnotfy"}]}
+               ;; :env-vars [{:name "FOO" :value "BAR"}]
+               :logging {:jul {:name "java.util.logging.config.file"
+                               :value "WEB-INF/logging.properties"}}
+               ;; #_{:log4j {:name "java.util.logging.config.file"
+               ;;          :value "WEB-INF/classes/log4j.properties"}}}
+               :sessions true
+               :ssl true
+               :async-session-persistence {:enabled "true" :queue-name "myqueue"}
+               :inbound-services [{:service :mail} {:service :warmup}]
+               ;;mime: http://www.opensource.apple.com/source/JBoss/JBoss-739/jakarta-tomcat-LE-jdk14/conf/web.xml
+               :mime-mappings [{:ext "abs" :type "audio/x-mpeg"}
+                               {:ext "gz"  :type "application/x-gzip"}
+                               {:ext "htm" :type "text/html"}
+                               {:ext "html" :type "text/html"}
+                               {:ext "svg" :type "image/svg+xml"}
+                               {:ext "txt" :type "text/plain"}
+                               {:ext "xml" :type "text/xml"}
+                               {:ext "xsl" :type "text/xsl"}
+                               {:ext "zip" :type "application/zip"}]
+               :precompilation true
+               :scaling {:basic {:max-instances 11 :idle-timeout "10m"
+                                 :instance-class "B2"}
+                         :manual {:instances 5
+                                  :instance-class "B2"}
+                         :automatic {:instance-class "F2"
+                                     :idle-instances {:min 5
+                                                      ;; ‘automatic’ is the default value.
+                                                      :max "automatic"}
+                                     :pending-latency {:min "30ms" :max "automatic"}
+                                     :concurrent-requests {:max 50}}}
+               ;; :resource-files {:include [{:path "**.xml"
+               ;;                            :expiration "4d h5"
+               ;;                            :http-header {:name "Access-Control-Allow-Origin"
+               ;;                                          :value "http://example.org"}}]
+               ;;                  :exclude [{:path "feed/**.xml"}]}
+               ;; :static-files {:include {:path "foo/**.png"
+               ;;                          :expiration "4d h5"
+               ;;                          :http-header {:name "Access-Control-Allow-Origin"
+               ;;                                        :value "http://example.org"}}
+               ;;                :exclude {:path "bar/**.zip"}}
+               }
+   :welcome {:file "index.html"}
+   :errors [{:code 404 :url "/404.html"}] ;; use :code, or:type, e.g 'java.lang.String
+   :servlet-ns 'migae.servlets
+   :servlets [{:ns 'migae.echo  ;; = servlet-class
+               ;; :jsp - alternative to :ns, for using java servlet pages
+               :name "echo-servlet"
+               :display {:name "Awesome Echo Servlet"}
+               :desc {:text "blah blah"}
+               :url "/echo/*"
+               :params [{:name "greeting" :val "Hello"}]
+               :load-on-startup {:order 3}}

-                  {:ns 'migae.math      ;; REQUIRED
-                   :name "math-servlet"  ;; REQUIRED
-                   :url "/math/*"      ;; REQUIRED
-                   :params [{:name "op" :val "+"}
-                            {:name "arg1" :val 3}
-                            {:name "arg2" :val 2}]}]
-       :appstats {:admin-console {:url "/appstats" :name "Appstats"}
-                  :name "appstats"
-                  :desc {:text "Google Appstats Service"}
-                  :url "/admin/appstats/*"
-                  :security-role "admin"
-                  :filter {:display {:name "Google Appstats"}
-                           :desc {:text "Google Appstats Filter"}
-                           :url "/*"
-                           :params [{:name "logMessage"
-                                     :val "Appstats available: /appstats/details?time={ID}"}
-                                    {:name "calculateRpcCosts"
-                                     :val true}]}
-                  :servlet {:display {:name "Google Appstats"}}}
-       :filters [{:ns 'migae.reloader   ; REQUIRED
-                  :name "reloader"      ; REQUIRED
-                  :display {:name "Clojure reload filter"} ; OPTIONAL
-                  :url "/*"            ; REQUIRED
-                  :desc {:text "clojure reload filter"}}]
-       :security [{:resource {:name "foo" :desc {:text "Foo resource security"}
-                              :url "/foo/*"}
-                  :role "admin"}]})
-
-(def gae)
-
-(println "GAE ns: " (var gae))
+              {:ns 'migae.math      ;; REQUIRED
+               :name "math-servlet"  ;; REQUIRED
+               :url "/math/*"      ;; REQUIRED
+               :params [{:name "op" :val "+"}
+                        {:name "arg1" :val 3}
+                        {:name "arg2" :val 2}]}]
+   :appstats {:admin-console {:url "/appstats" :name "Appstats"}
+              :name "appstats"
+              :desc {:text "Google Appstats Service"}
+              :url "/admin/appstats/*"
+              :security-role "admin"
+              :filter {:display {:name "Google Appstats"}
+                       :desc {:text "Google Appstats Filter"}
+                       :url "/*"
+                       :params [{:name "logMessage"
+                                 :val "Appstats available: /appstats/details?time={ID}"}
+                                {:name "calculateRpcCosts"
+                                 :val true}]}
+              :servlet {:display {:name "Google Appstats"}}}
+   :filters [{:ns 'migae.reloader   ; REQUIRED
+              :name "reloader"      ; REQUIRED
+              :display {:name "Clojure reload filter"} ; OPTIONAL
+              :url "/*"            ; REQUIRED
+              :desc {:text "clojure reload filter"}}]
+   :security [{:resource {:name "foo" :desc {:text "Foo resource security"}
+                          :url "/foo/*"}
+               :role "admin"}]})

 (require '[migae.boot-gae :as gae]
-         '[boot-miraj :as mrj])
+         '[boot-miraj :as mrj]
+         '[boot.task.built-in :as builtin])

 (task-options!
  mrj/config {:root "build/exploded-app"
@@ -145,14 +144,26 @@
        :description "Example code, boot, miraj, GAE"
        :license     {"EPL" "http://www.eclipse.org/legal/epl-v10.html"}})

+(deftask libs
+  "" []
+  (comp
+   (builtin/uber :as-jars true)
+   (builtin/sift :include #{#"jar$"} :move {#"(.*jar$)" "WEB-INF/lib/$1"})
+   (builtin/target :dir #{"build"} :no-clean true)))
+
 (deftask dev
   "run all the boot-gae tasks"
   []
-  (comp (gae/deps)
-        (gae/aot)
-        (gae/clj-cp)
-        (gae/assets)
-        (gae/config-servlets)
-        (gae/config-xml)
-        (gae/config-logging)
-        (gae/run)))
+  (comp (gae/assets :type :html)
+        (gae/assets :type :css)
+        (gae/assets :type :js)
+        (gae/assets :type :ico)
+        (gae/assets :type :clj :odir "WEB-INF/classes")
+        (gae/logging)
+        (gae/config)
+        (builtin/target :dir #{"build"})
+        (gae/servlets) ;; :namespace 'migae.servlets)  ;; :dir "WEB-INF/classes")
+        (builtin/sift :include #{#"class$"}
+                      :move {#"(.*class$)" "WEB-INF/classes/$1"})
+        (builtin/target :dir #{"build"} :no-clean true)
+        #_(gae/run)))


Update pom [skip ci]

Update pom [skip ci]

--- build.boot
+++ build.boot
@@ -44,8 +44,7 @@
        :version     +version+
        :description "mikron is a schema-based serialization library for Clojure and ClojureScript"
        :url         "http://github.com/moxaj/mikron"
-       :license     {:name "Eclipse Public License"
-                     :url  "http://www.eclipse.org/legal/epl-v10.html"}})
+       :license     {"Eclipse Public License" "http://www.eclipse.org/legal/epl-v10.html"}})

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