Added coordinate-system to granule atom format.

--- src/cmr/search/results_handlers/atom_results_handler.clj
+++ src/cmr/search/results_handlers/atom_results_handler.clj
@@ -29,6 +29,7 @@
    "browsable"
    "day-night"
    "cloud-cover"
+   "coordinate-system"
    "ords-info"
    "ords"])

@@ -51,6 +52,7 @@
           [browsable] :browsable
           [day-night] :day-night
           [cloud-cover] :cloud-cover
+          [coordinate-system] :coordinate-system
           ords-info :ords-info
           ords :ords} :fields} elastic-result
         start-date (when start-date (str/replace (str start-date) #"\+0000" "Z"))
@@ -73,6 +75,7 @@
      :browse-flag browsable
      :day-night day-night
      :cloud-cover (str cloud-cover)
+     :coordinate-system coordinate-system
      :shapes (srl/ords-info->shapes ords-info ords)}))

 (def ATOM_HEADER_ATTRIBUTES
@@ -122,9 +125,9 @@
 (defn- atom-reference->xml-element
   "Converts a search result atom reference into an XML element"
   [reference]
-  (let [{:keys [id title updated dataset-id producer-gran-id
-                size original-format data-center start-date end-date atom-links
-                online-access-flag browse-flag day-night cloud-cover shapes]} reference]
+  (let [{:keys [id title updated dataset-id producer-gran-id size original-format
+                data-center start-date end-date atom-links online-access-flag browse-flag
+                day-night cloud-cover coordinate-system shapes]} reference]
     (x/element :entry {}
                (x/element :id {} id)
                (x/element :title {:type "text"} title)
@@ -141,6 +144,7 @@
                (x/element :echo:browseFlag {} browse-flag)
                (when day-night (x/element :echo:dayNightFlag {} day-night))
                (when cloud-cover (x/element :echo:cloudCover {} cloud-cover))
+               (when coordinate-system (x/element :echo:coordinateSystem {} coordinate-system))
                (map atom-spatial/shape->xml-element shapes))))

 (defn- append-links


Fixed typo in the core module

Fixed typo in the core module

--- src/emender_jenkins/core.clj
+++ src/emender_jenkins/core.clj
@@ -30,7 +30,7 @@
     "Definitions of all command line options that are  currenty supported."
     ;; an option with a required argument
     [["-h"   "--help"                       "show help"                                                    :id :help]
-     ["-p"   "--port   PORT"                "port number on which Stage Dashboard should accepts requests" :id :port]
+     ["-p"   "--port   PORT"                "port number on which Emender Jenkins should accepts requests" :id :port]
      ["-j"   "--jenkins-url url"            "url to Jenkins, for example: http://10.20.30.40:8080/"        :id :jenkins-url]
      ["-t"   "--test-jobs-suffix suffix"    "test jobs suffix, for example 'test'"                         :id :test-jobs-suffix]
      ["-f"   "--fetch-only"                 "just start job fetcher once, then stop processing"            :id :fetch-only]
@@ -201,7 +201,7 @@
             (start-server configuration (get-port port) openshift-port openshift-ip))))

 (defn -main
-    "Entry point to the Emender service server."
+    "Entry point to the Emender-Jenkins service server."
     [& args]
     (let [all-options         (cli/parse-opts args cli-options)
           options             (all-options :options)


Revert "Prevent a comment from being considered an expression."

This reverts commit 10f2c7066c1ad5a2d3d2d0a7960abc995b108261.

--- src/enoki_lang_clj/core.cljs
+++ src/enoki_lang_clj/core.cljs
@@ -20,6 +20,7 @@
                | ASSIGNMENT
                | BLOCK
                | JSBLOCK
+               | COMMENT
                | RANGE

     EXPRESSIONS = {EXPRESSION <WS>?}


Transform keys returned by create!

Transform keys returned by create!

--- src/time_tracker/timers/db.clj
+++ src/time_tracker/timers/db.clj
@@ -43,9 +43,10 @@
 (defn create!
   "Creates and returns a timer if authorized."
   [connection project-id google-id]
-  (create-timer-query<! {:google_id  google-id
-                         :project_id project-id}
-                        {:connection connection}))
+  (-> (create-timer-query<! {:google_id  google-id
+                             :project_id project-id}
+                            {:connection connection})
+      (transform-timer-map)))

 (defn update-duration!
   "Set the elapsed duration of the timer."


Ideas

Ideas

--- src/clj/algorithms_clj/ancestors.clj
+++ src/clj/algorithms_clj/ancestors.clj
@@ -34,6 +34,7 @@
     [parent 'Jessy 'Mike]
     [parent 'Jessy 'Nicola]

+    [parent 'Mike 'Herb]
     [parent 'Alice 'Herb]
     [parent 'Alice 'Lisa]
     ))
@@ -69,6 +70,7 @@
   (fresh [z]
     ;; TODO - CUT: one child is enough but it keeps exploring and reporting the same couple
     ;; defna does not work - defnu cut at the first finding, for all siblings!
+    ;; The notion to express is "there exists" instead of "for all": HOW?
     (father x z) (mother y z)
     ))


Remove unneeded require

Remove unneeded require

--- src/cljs/rhapsody/lib/web_audio.cljs
+++ src/cljs/rhapsody/lib/web_audio.cljs
@@ -3,8 +3,7 @@
             [leipzig.melody :as melody]
             [cljs-bach.synthesis :as synth]
             [web-audio.constant-source-node]
-            [audio-loader.audio-loader]
-            [sample-player.sample-player]))
+            [audio-loader.audio-loader]))

 ;; Enable the ConstantSourceNode polyfill.
 (.polyfill js/ConstantSourceNode)


Fixed divide-by-zero error on empty vectors

--- src/clojush/instructions/vectors.clj
+++ src/clojush/instructions/vectors.clj
@@ -360,13 +360,18 @@
             (empty? (:integer state))
             (and (= lit-type :integer) (empty? (rest (:integer state)))))
       state
-      (let [item (if (= lit-type :integer)
+      (let [vect (top-item type state)
+            item (if (= lit-type :integer)
                    (stack-ref :integer 1 state)
                    (top-item lit-type state))
-            index (mod (top-item :integer state) (count (top-item type state)))
-            result (assoc (top-item type state)
-                          index
-                          item)]
+            index (if (empty? vect)
+                    0
+                    (mod (top-item :integer state) (count vect)))
+            result (if (empty? vect)
+                     vect
+                     (assoc vect
+                            index
+                            item))]
         (push-item result
                    type
                    (pop-item lit-type (pop-item :integer (pop-item type state))))))))


Fix typo

Fix typo

--- src/clj/conference_rating/handler.clj
+++ src/clj/conference_rating/handler.clj
@@ -75,11 +75,11 @@
     (escape-html x)
     x))

-(defn- sanatize [m]
+(defn- sanitize [m]
   (walk/postwalk escape-string m))

 (s/defn add-conference [conference :- schemas/Conference db]
-  (let [add-result (db/add-conference (sanatize conference) db)
+  (let [add-result (db/add-conference (sanitize conference) db)
         id         (:_id add-result)]
     (created (str "/api/conferences/" id) add-result)))

@@ -95,7 +95,7 @@
 (def parse-rating (coerce/coercer schemas/Rating coerce/json-coercion-matcher))

 (defn add-rating [conference-id request db]
-  (let [complete (assoc (sanatize (:body request))
+  (let [complete (assoc (sanitize (:body request))
                    :conference-id conference-id
                    :user (user-identity request))
         rating (parse-rating complete)
@@ -137,7 +137,7 @@
     (GET "/" [] (home-page api-key))))

 (defn update-conference [id conference db]
-  (let [update-result (db/update-conference-by-id id (sanatize conference) db)]
+  (let [update-result (db/update-conference-by-id id (sanitize conference) db)]
     (utf-json-response update-result)))

 (defn add-attendance [conference-id request db]


Fixing LR search issue found in CI.

Fixing LR search issue found in CI.

--- src/cmr/spatial/lr_binary_search.clj
+++ src/cmr/spatial/lr_binary_search.clj
@@ -130,10 +130,20 @@
 ;; ring. It returns the midpoints of those intersections.
 (defmethod ring->lr-search-points :default
   [ring]
-  (let [{:keys [mbr contains-north-pole contains-south-pole]} ring
+  (let [{:keys [mbr]} ring
         vert-arc (mbr->vert-dividing-arc mbr)
-        intersections (distinct
-                        (arc-ring-intersection-points vert-arc ring))]
+        intersections (arc-ring-intersection-points vert-arc ring)
+
+        ;; Handle cases where the ring mbr is the width of the entire world
+        intersections (if (and (= -180.0 (:west mbr))
+                               (= 180.0 (:east mbr)))
+                        ;; The vertical arc above will be on the prime meridian. Try the antimeridian as well.
+                        (distinct
+                          (concat intersections
+                                  (arc-ring-intersection-points
+                                    (mbr->vert-dividing-arc (assoc mbr :west 179.0 :east -179.0))
+                                    ring)))
+                        (distinct intersections))]

     ;; Between at least 2 of the points there will be a midpoint in the ring.
     ;; Create a list of test points from midpoints of all combinations of points.


Added more endpoints (local-only).

Added more endpoints (local-only).

--- src/cljc/cmr/client/common/const.cljc
+++ src/cljc/cmr/client/common/const.cljc
@@ -27,7 +27,13 @@
      :local ":3002"}
    :search
     {:service "/search"
-     :local ":3003"}})
+     :local ":3003"}
+   ;; Local-only endpoints
+   :bootstrap {:local ":3006"}
+   :cubby {:local ":3007"}
+   :index-set {:local ":3005"}
+   :indexer {:local ":3004"}
+   :metadata-db {:local ":3001"}})

 (def default-environment-type
   "Default deployment type for the CMR client."


Popover on mouse over/out

Popover on mouse over/out

--- src/cljs/cljs_browser_repl/views.cljs
+++ src/cljs/cljs_browser_repl/views.cljs
@@ -159,17 +159,37 @@
   [symbol]
   (get-in api/cljs-api-edn [:symbols symbol]))

+(defn symbol-popover
+  "A popover's body in which details of the given symbol will be shown."
+  [showing? sym-doc-map]
+  (let [{name :name desc :description} sym-doc-map]
+   [popover-content-wrapper
+    :showing? showing?
+    :position :below-center
+    :width "300"
+    :backdrop-opacity 0.4
+    :title name
+    :body [(fn []
+             [:span desc])]]))
+
 (defn build-symbol-ui
   "Builds the UI for a single symbol. Will be either a link with popup or
   a simple `<span>`."
   [symbol]
   (if-let [symbol (get-symbol-doc-map (str symbol))]
-    [hyperlink-href                     ; add popup
-     :label (:name symbol)
-     :class "api-panel-symbol"
-     :style {:display "inline-flex"}
-     :href ""                         ; add url to documentation
-     :target "_blank"]
+    (let [showing? (reagent/atom false)]
+      [popover-anchor-wrapper
+       :showing? showing?
+       :position :below-center
+       :anchor [hyperlink-href
+                :label (:name symbol)
+                :attr {:on-mouse-over #(reset! showing? true)
+                       :on-mouse-out  #(reset! showing? false)}
+                :class "api-panel-symbol"
+                :style {:display "inline-flex"}
+                :href "" ; add url to documentation
+                :target "_blank"]
+       :popover [symbol-popover showing? symbol]])
     [:span.api-panel-symbol (str symbol)]))

 (defn build-topics-ui


some stuff. url functions

some stuff. url functions

--- src/cljs/omnext_routing_one/core.cljs
+++ src/cljs/omnext_routing_one/core.cljs
@@ -1,13 +1,16 @@
 (ns omnext-routing-one.core
   (:require [goog.dom :as gdom]
             [om.next :as om :refer-macros [defui]]
-            [om.dom :as dom]))
+            [om.dom :as dom]
+            [clojure.string :as string]
+            ))

 (enable-console-print!)

 ;; URL helper functions

 (defn parse-url-hash [h]
+  "#/foo/bar/?a=b&c=d -> {:path [\"foo\" \"bar\"], :params {:a \"b\", :c \"d\"}}"
   (let [
       h (subs h 2)
       [path params] (string/split h #"\u003f")
@@ -21,9 +24,41 @@
                                  ])
                     #(string/split % "=")) (string/split params "&")))
       ]
-  {:path path
-   :params params}
-  )
+    {:path path
+     :params params}
+    )
+  )
+
+(defn path-and-params-to-hash
+  "Opposite for function from above. Expects keys of `params` to be keywords"
+  ([path]
+   (path-and-params-to-hash nil)
+   )
+  ([path params]
+    (apply str "#/" (string/join "/" path) "/"
+         (when params
+           (cons
+             "?"
+            (string/join "&" (map (fn [[k v]]
+                                    (str
+                                      (-> k name js/encodeURIComponent)
+                                      "="
+                                      (-> v js/encodeURIComponent)
+                                      )
+                                    ) params))
+            )
+           )
+         )
+   )
+  )
+
+;; Tab functions
+
+(defn get-tab-by-parsed-url [tabs {:keys [path params]}]
+  "Tabs format is defined in `tabs` below. See `parse-url-hash` for second param"
+  (first (filter
+           #(= (:url-path %) path)
+           tabs))
   )

@@ -32,7 +67,7 @@
 (defui CountriesTab
   static om/IQueryParams
   (params [_]
-          ; ...
+          {:page 1}
           )

   static om/IQuery
@@ -66,7 +101,16 @@
   (render [this]
           (apply dom/ul nil
                  (map (fn [country]
-                        (dom/li nil country)
+                        (dom/li nil
+                                (:name country)
+                                (dom/span
+                                  #js {:style #js {:fontWeight "bold"
+                                                   :marginLeft "5px"}}
+                                  "("
+                                  (:code country)
+                                  ")"
+                                  )
+                                )
                         )
                       )
                  )
@@ -87,8 +131,8 @@
   Object
   (render [this]
           (apply dom/ul nil
-                 (map (fn [country]
-                        (dom/li nil country)
+                 (map (fn [ocean]
+                        (dom/li nil ocean)
                         )
                       )
                  )
@@ -120,26 +164,68 @@
 ;; Processing the initial URL

 (def initial-url
-  js/window.location.hash)
-
-(
+  (parse-url-hash
+    js/window.location.hash
+    )
+  )
+
+(def initial-tab
+  (get-tab-by-parsed-url tabs initial-url)
+  )
+
+(def initial-component
+  (:component initial-tab)
+  )
+
+(def initial-query-for-root
+  (when initial-component
+    (om/query initial-component)
+    )
+  )
+
+(def initial-params-for-root
+  (when initial-component
+    (om/params initial-component)
+    )
+  )

 ;; Components

 (defui RootView
   static om/IQueryParams
   (params [_]
-    )
-
-  static om/IQuery
-  (query [_]
-    )
-
-  Object
-  (render [this]
-    (dom/div #js {:className "container"}
-             "Hello, world!"
-             )
+          initial-params-for-root ; here and below, we're passing (pre-computed) value
+                                  ; and not doing function calls
+    )
+
+  static om/IQuery
+  (query [_]
+         initial-query-for-root
+    )
+
+  Object
+  (render [this]
+          (let []
+            (dom/div #js {:className "container"}
+                     ;; Tabs (navigation)
+                        (apply dom/ul
+                        #js
+                        {:className "nav nav-tabs", :role "tablist"}
+                        (map (fn [tab]
+                        (dom/li
+                          #js
+                          {:className "active", :role "presentation"}
+                          (dom/a
+                          #js
+                          {:shape "rect",
+                            :href "#home",
+                            :aria-controls "home",
+                            :role "tab",
+                            :data-toggle "tab"}
+                          (:title tab))))
+                             tabs))
+                    )
+            )
           )
   )

@@ -149,6 +235,10 @@

 (defmethod readf :default
   [{:keys [state] :as env} k params]
+  (if-let [v (get @state k)]
+    {:value k}
+    {:value nil}
+    )
   )

 (defmulti mutatef om/dispatch)


Simplified arg parsing.

Simplified arg parsing.

--- tagcount/src/tagcount/core.clj
+++ tagcount/src/tagcount/core.clj
@@ -105,5 +105,5 @@
       (info "Started worker" i "with uuid" uuid))))

 (defn -main [& args]
-  (let [workers ((fnil #(Integer/parseInt %) "1") (first args))]
+  (let [workers (Integer/parseInt (or (first args) "1"))]
     (start-workers workers)))


removed [] error

removed [] error

--- main/src/dda/pallet/dda_managed_vm/infra/credential_management.clj
+++ main/src/dda/pallet/dda_managed_vm/infra/credential_management.clj
@@ -100,7 +100,7 @@
                                                                    :path-to-repo "/.password-store"})
          passwordstorestomount (apply str (for [repo credential-store] (selmer/render-file "gopass_mount.yml.templ" {:repo-name (:repo-name repo)
                                                                                :user-name user-name})))]
-     (actions/directory
+     (actions/directory
       (str user-home "/.password-store")
       :owner user-name
       :group user-name)
@@ -134,7 +134,7 @@
      (logging/info (str facility "-configure user: configure-gopass")))
     (actions/exec-script script)
     (create-gopass-autocompletion-file user-name user-home)
-    (when (some? credential-store)
+    (if (not (empty? credential-store))
       (if (= (count credential-store) 1)
         (single-gopass-setup user-name user-home (:repo-name (first credential-store)))
         (multi-gopass-setup user-name user-home credential-store)))))


Removing msg from vis on atake.

Removing msg from vis on atake.

--- src/cbfg/core.cljs
+++ src/cbfg/core.cljs
@@ -69,8 +69,9 @@
              (swap! vis #(assoc-in % [:actxs actx :wait-chs ch] :take))
              (vis-add-ch vis ch)))
     :end (fn [vis actx args]
-           (let [[ch result] args]
-             (swap! vis #(dissoc-in % [:actxs actx :wait-chs ch]))))}
+           (let [[ch msg] args]
+             (swap! vis #(dissoc-in % [:actxs actx :wait-chs ch]))
+             (swap! vis #(dissoc-in % [:chs ch :msgs msg]))))}
    "aput"
    {:beg (fn [vis actx args]
            (let [[ch msg] args]


Passing delta to vis-svg-actxs.

Passing delta to vis-svg-actxs.

--- src/cbfg/core.cljs
+++ src/cbfg/core.cljs
@@ -175,7 +175,7 @@
        [])
      "</div>"]))

-(defn vis-svg-actxs [vis positions]
+(defn vis-svg-actxs [vis positions delta]
   ["<defs>"
    "<marker id='triangle'"
    " viewBox='0 0 10 10' refX='0' refY='5'"
@@ -190,7 +190,8 @@
                 actx-position (+ 0.5 (get positions actx-id))
                 wait-chs (:wait-chs actx-info)
                 chs (:chs vis)
-                line-height 21]
+                line-height 21
+                stroke-width 1]
             (map (fn [kv]
                    (let [[ch wait-kind] kv
                          ch-info (get chs ch)
@@ -199,10 +200,12 @@
                      (if (= :put wait-kind)
                        ["<line x1='500' y1='" (* actx-position line-height)
                         "' x2='600' y2='" (* ch-position line-height)
-                        "' stroke='green' stroke-width='1' marker-end='url(#triangle)'/>"]
+                        "' stroke='green' stroke-width='" stroke-width
+                        "' marker-end='url(#triangle)'/>"]
                        ["<line x1='600' y1='" (* ch-position line-height)
                         "' x2='500' y2='" (* actx-position line-height)
-                        "' stroke='red' stroke-width='1' marker-end='url(#triangle)'/>"])))
+                        "' stroke='red' stroke-width='" stroke-width
+                        "' marker-end='url(#triangle)'/>"])))
                  wait-chs)))
         (:actxs vis))])

@@ -243,17 +246,17 @@
       (let [[actx event] (<! event-ch)
             [verb step & args] event
             vis-event-handler (get (get vis-event-handlers verb) step)
-            positions (atom {})]
-        (vis-event-handler vis actx args)
-        (let [actx-ch-ch-infos (group-by #(:first-taker-actx (second %)) (:chs @vis))]
-          (set-el-innerHTML "vis-html"
-                            (apply str (flatten (vis-html-actx @vis @root-actx positions
-                                                               actx-ch-ch-infos))))
-          (set-el-innerHTML "vis-svg"
-                            (apply str (flatten (vis-svg-actxs @vis @positions))))
-          (set-el-innerHTML "event"
-                            (str num-events ": " (last actx) " " verb " " step " " args))))
-      (recur (inc num-events)))
+            positions (atom {})
+            delta (vis-event-handler vis actx args)
+            actx-ch-ch-infos (group-by #(:first-taker-actx (second %)) (:chs @vis))]
+        (set-el-innerHTML "vis-html"
+                          (apply str (flatten (vis-html-actx @vis @root-actx positions
+                                                             actx-ch-ch-infos))))
+        (set-el-innerHTML "vis-svg"
+                          (apply str (flatten (vis-svg-actxs @vis @positions delta))))
+        (set-el-innerHTML "event"
+                          (str num-events ": " (last actx) " " verb " " step " " args))
+        (recur (inc num-events))))
     (ago w-actx w
          (reset! root-actx w-actx)
          (let [in (achan-buf w-actx 100)


More obvious var name.

More obvious var name.

--- src/cbfg/lane.cljs
+++ src/cbfg/lane.cljs
@@ -29,5 +29,5 @@
                   (let [lane-ch (make-lane-fn lane-pump (:lane m) out-ch)]
                     (aput lane-pump lane-ch m)
                     (recur (assoc lane-chs (:lane m) lane-ch)))))
-              (doseq [[n lane-ch] lane-chs] ; Close all lane-chs and exit.
+              (doseq [[lane-name lane-ch] lane-chs] ; Close lane-chs & exit.
                 (aclose lane-pump lane-ch)))))


fixing destroy call

fixing destroy call

--- test/celestial/integration/capistrano.clj
+++ test/celestial/integration/capistrano.clj
@@ -14,13 +14,13 @@
 (fact "basic deploy" :integration :capistrano
    (p/add-type redis-type)
    (let [id (p/add-system redis-prox-spec)
-         cap (rconstruct redis-actions {:action :deploy :target "192.168.5.100"})]
+         cap (rconstruct redis-actions {:action :deploy :target "192.168.5.200"})]
      (reload redis-prox-spec)
      (.setup cap)
      (exists? (:dst cap)) => truthy
      (.run cap)
      (.cleanup cap)
-     (destroy id redis-prox-spec)
+     (destroy (assoc redis-prox-spec :system-id id))
      (exists? (:dst cap))  => falsey
      (p/system-exists? id)  => falsey
      ))


Add test for 26d07be0 (batch processing fixes for parallel-reader)

--- test/com/wsscode/pathom/connect_test.cljc
+++ test/com/wsscode/pathom/connect_test.cljc
@@ -3651,4 +3651,44 @@
                                                    :c 2}))]
                                ::p/env       {::pp/external-wait-ignore-timeout 200}}
                   '[{:>/bla [:b :c]}])
-                #:>{:bla {:c 2, :b 1}}))))))
+                #:>{:bla {:c 2, :b 1}})))
+
+       (testing "fix concurrency-related caching issues for items repeated across batches"
+         (let [things (into (sorted-map) (map #(do [% (char (+ (int \a) %))])
+                                              (range 26)))
+               to-thing-list (fn [ids]
+                               {:list-of-things (map #(do {:thing-id %}) ids)})
+               thing-list-resolver
+               (pc/resolver 'thing-list-batches
+                            {::pc/output [:thing-batches]}
+                            (fn [env _]
+                              (go {:thing-batches
+                                   (take 100
+                                         (cycle [(to-thing-list (take 20 (keys things)))
+                                                 (to-thing-list (drop 6 (keys things)))
+                                                 (to-thing-list (drop 20 (keys things)))]))})))
+               thing-value-resolver
+               (pc/resolver 'thing-value
+                            {::pc/input #{:thing-id}
+                             ::pc/output [:thing-value]
+                             ::pc/batch? true}
+                            (fn [env input]
+                              (let [c (async/chan)]
+                                (future
+                                  (Thread/sleep 1500)
+                                  (async/put! c
+                                              (if (sequential? input)
+                                                (mapv (fn [v] {:thing-value (get things (:thing-id v))})
+                                                      input)
+                                                {:thing-value (get things (:thing-id input))})))
+                                c)))
+               ;; run the test multiple times to increase the likelihood of the issue occurring
+               results (pmap (fn [_]
+                               (quick-parser {::pc/register [thing-list-resolver thing-value-resolver]}
+                                             '[{:thing-batches [{:list-of-things [:thing-value]}]}]))
+                             (range 5))]
+           (is (empty? (for [{:keys [thing-batches]} results
+                             {:keys [list-of-things]} thing-batches
+                             {:keys [thing-value]} list-of-things
+                             :when (= thing-value ::p/not-found)]
+                         thing-value))))))))


Fix 4-2 words.

Fix 4-2 words.

--- test/workshop/jobs/challenge_4_2_test.clj
+++ test/workshop/jobs/challenge_4_2_test.clj
@@ -7,7 +7,8 @@

 ;; Logging is great and all, but we've now opened to the door
 ;; to something much more interesting - maintaining state.
-;; In this challenge, you're going to create an atom in
+;; In this challenge, you're going to reference an atom defined
+;; in the corresponding source file and use it in
 ;; the :before-task-start lifecycle hook.
 ;; After each batch is processed, find the maximum value
 ;; that we saw in the :identity task. After the task is finished,


Increasing default session timeout

Increasing default session timeout

--- src/cylon/core.clj
+++ src/cylon/core.clj
@@ -403,7 +403,8 @@
     :password-store (new-password-file (:password-file opts))
     :http-session-store (new-atom-backed-session-store
                          (or (:session-timeout-in-seconds opts)
-                             10))}))
+                             (* 60 60) ; one hour by default
+                             ))}))

 ;; Now that we have a protection system, we want the ability to create
 ;; bidi routes components that can be protected by simply declaring a dependency upon the protection system component.


Rescale the layout before drawing it the first time

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

--- src/conexp/contrib/draw/lattices.clj
+++ src/conexp/contrib/draw/lattices.clj
@@ -339,7 +339,9 @@
   (defn make-lattice-editor
     "Creates a lattice editor with initial layout."
     [frame layout]
-    (let [^JPanel main-panel (JPanel. (BorderLayout.)),
+    (let [layout (scale-layout [0 0] [100 100] layout),
+
+          ^JPanel main-panel (JPanel. (BorderLayout.)),

           scn (draw-on-scene layout),
           ^Canvas canvas (get-canvas-from-scene scn),


Adjust main.

Adjust main.

--- src/dsbdp/main.clj
+++ src/dsbdp/main.clj
@@ -32,9 +32,9 @@
                      "out:" (long (/ (delta-cntr :out (.value out-cntr)) 1000)) "k;"))
         out-fn (fn [_ _]
                  (.inc out-cntr))
-        in-data 1
+        in-data 20
         pipeline (create-local-processing-pipeline
-                   (create-hashmap-inc-put-proc-fns 6)
+                   (create-factorial-proc-fns 1)
                    out-fn)
         in-fn (get-in-fn pipeline)
         in-loop (ProcessingLoop.


First working version with async-pipeline.

--- src/dsbdp/main.clj
+++ src/dsbdp/main.clj
@@ -193,19 +193,18 @@
                                (fn []
                                  (in-fn in-data)
                                  (.inc in-cntr)))
+          direct-proc-fn (create-direct-proc-fn scenario)
           in-loop (ProcessingLoop.
                     "DataGenerationLoop"
                     (cond
                       (.endsWith scenario "-direct")
-                        (let [proc-fn (create-direct-proc-fn scenario)]
-                          (fn []
-                            (proc-fn in-data)
+                        (fn []
+                          (direct-proc-fn in-data)
+                          (.inc out-cntr))
+                      (.endsWith scenario "-pmap")
+                        (fn []
+                          (doseq [data (pmap direct-proc-fn (repeat in-data))]
                             (.inc out-cntr)))
-                      (.endsWith scenario "-pmap")
-                        (let [proc-fn (create-direct-proc-fn scenario)]
-                          (fn []
-                            (doseq [data (pmap proc-fn (repeat in-data))]
-                              (.inc out-cntr))))
                       (.endsWith scenario "-async-pipeline")
                         (if
                           (and
@@ -226,6 +225,31 @@
                         (> batch-size 0)) (create-batched-in-fn (get-in-fn pipeline))
                       (not (nil? in-data)) (create-flood-in-fn (get-in-fn pipeline))
                       :default (fn [] (.inc out-cntr))))
+          async-out-count-loop (if
+                                 (and
+                                   (.endsWith scenario "-async-pipeline")
+                                   (not (nil? in-data)))
+                                 (ProcessingLoop.
+                                   "AsyncOutputCountLoop"
+                                   (fn []
+                                     (while true
+                                       (do
+                                         (async/<!! out-chan)
+                                         (.inc out-cntr))))))
+          async-pipeline (if
+                           (and
+                             (.endsWith scenario "-async-pipeline")
+                             (not (nil? in-data)))
+                           (async/pipeline
+                             8
+                             out-chan
+                             (fn [rf]
+                               (fn ([] (rf))
+                               ([result] (rf result))
+                               ([result data]
+                                 (let [ret (direct-proc-fn data)]
+                                   (rf result (if (nil? ret) 1 ret))))))
+                             in-chan))
           self-adaptivity-cfg (options :self-adaptivity-cfg)
           self-adaptivity-controller (if (not (nil? self-adaptivity-cfg))
                                        (create-self-adaptivity-controller
@@ -255,10 +279,17 @@
       (println "Starting experiment...")
       (.setName (Thread/currentThread) "Main")
       (.start in-loop)
-      (run-repeat (executor) (fn []
-                               (stats-fn)
-                               (thread-info-fn) (println)
-                               )
-                  1000)
-      (run-once (executor) (fn [] (System/exit 0)) 120000))))
-
+      (if
+        (not (nil? async-out-count-loop))
+        (.start async-out-count-loop))
+      (run-repeat
+        (executor)
+        (fn []
+          (stats-fn)
+          (thread-info-fn) (println)
+          )
+        1000)
+      (run-once
+        (executor)
+        (fn [] (System/exit 0)) 120000))))
+


Do a thing

Do a thing

--- src/icecap/handlers/http.clj
+++ src/icecap/handlers/http.clj
@@ -8,13 +8,20 @@
             [taoensso.timbre :refer [info spy]])
   (:import [java.net URI]))

+
+(defn scheme
+  "Get the scheme of a URL."
+  [^String url]
+  (.getScheme (URI. url)))
+
 (defn valid-scheme?
   "Checks if the given URL has a valid scheme."
   [^String url]
-  (#{"http" "https"} (.getScheme (URI. url))))
+  (#{"http" "https"} (scheme url)))

 (defstep :http
-  {:url sc/URI
+  {:url (s/both sc/URI
+                (s/pred valid-scheme? 'valid-scheme?))
    :method (s/enum :GET :POST :DELETE :PUT :PATCH :HEAD)}
   [step]
   (let [req (spy (request step))]


Fix whitespace issue.

Fix whitespace issue.

--- src/ipython_clojure/core.clj
+++ src/ipython_clojure/core.clj
@@ -216,7 +216,7 @@
                                   :status "ok"
                                   :started (now)} session-id signer (:idents message))
             ;; Send stdout
-            (send-message iopub-socket "stream" {:name "stdout",:text output}
+            (send-message iopub-socket "stream" {:name "stdout" :text output}
                           parent-header {} session-id signer)
             ;; Send results
             (send-message iopub-socket "execute_result"


adding domainname and hosts file setup to set-host

--- src/aws/provider.clj
+++ src/aws/provider.clj
@@ -75,9 +75,12 @@
       (s/partial-system (spec :system-id) {:machine {:ssh-host ec2-host :ip (pubdns-to-ip ec2-host)}}))))

 (defn set-hostname [spec endpoint instance-id user]
-  "Uses a generic method of setting hostname in Linux"
-  (let [hostname (get-in spec [:machine :hostname]) remote {:host (pub-dns endpoint instance-id) :user user}]
-    (execute (<< "echo kernel.hostname = ~{hostname} | sudo tee -a /etc/sysctl.conf") remote )
+  "Uses a generic method of setting hostname in Linux, not that in ec2 both Centos and Ubuntu use sudo!"
+  (let [{:keys [hostname domain]} (spec :machine)
+        remote {:host (pub-dns endpoint instance-id) :user user}]
+    (execute (<< "echo kernel.hostname=~{hostname} | sudo tee -a /etc/sysctl.conf") remote )
+    (execute (<< "echo kernel.domainname=\"~{hostname}.~{domain}\" | sudo tee -a /etc/sysctl.conf") remote )
+    (execute (<< "echo 127.0.1.1 ~{hostname}.~{domain} ~{hostname} | sudo tee -a /etc/hosts") remote )
     (execute "sudo sysctl -e -p" remote)
     (with-ctx ec2/create-tags [(instance-desc endpoint instance-id :id)] {:Name hostname})
     ))


improve comments

improve comments

--- src/babel/parse.cljc
+++ src/babel/parse.cljc
@@ -217,14 +217,14 @@
        (line-seq reader)))

 (defn parse
-  "return a list of all possible parse trees for a string or a sequence of tokens.
+  "Return a list of all possible parse trees for a string or a sequence of tokens.
    If the input is a string, then use a language-independent tokenizer
   to turn the string into a sequence of tokens.  In the latter case,
   the tokens are assumed to be produced by splitting a string in some
   language-dependent way. If parse-with-truncate is false, then at
   each step of parsing the input, the entire tree will be preserved
   rather than just the immediate parents of the root node. Preserving
-  the entire tree costs about 20% time than truncating it."
+  the entire tree costs about 20% more time than truncating it."
   ([input model & {:keys [parse-with-truncate original-input]}]
    (let [parse-with-truncate
          (cond (= parse-with-truncate false)


add :from-language when generating source expression

--- src/babel/reader.clj
+++ src/babel/reader.clj
@@ -104,7 +104,10 @@
            :tense (dag_unify.core/get-in target-expression [:synsem :sem :tense])
            :sem (dag_unify.core/get-in target-expression [:synsem :sem])
            :subj (dag_unify.core/get-in target-expression [:synsem :sem :subj :pred])
-           :source (if source-expression ((:morph @((get models source-language))) source-expression))}]
+           :source (if source-expression
+                     ((:morph @((get models source-language)))
+                      source-expression
+                      :from-language target-language-str))}]
       (if (:source pairing)
         (str (:target pairing) " => " (:source pairing))
         (str " FAILED: " (dissoc pairing :source)))


Update MP3 encoder to operate on JS arrays/data

--- src/main/audio_utils/mp3_encoder.cljs
+++ src/main/audio_utils/mp3_encoder.cljs
@@ -1,5 +1,6 @@
 (ns audio-utils.mp3-encoder
   (:require [cljsjs.lamejs]
+            [audio-utils.util :as u]
             [audio-utils.worker :as w]))

 (defrecord MP3Encoder [bit-rate sample-rate next]
@@ -11,14 +12,14 @@
     (reset! next nil))

   (process-audio [this data]
-    (let [int-data (mapv (fn [samples]
-                           (into-array (map #(* 32768 %) samples)))
-                         data)
-          encoder  (js/lamejs.Mp3Encoder. (count data) sample-rate
+    (let [int-data (u/amap (fn [samples]
+                             (u/amap #(* 32768 %) samples))
+                           data)
+          encoder  (js/lamejs.Mp3Encoder. (u/acount data) sample-rate
                                           bit-rate)
           encoded  #js []]
       (doto encoded
-        (.push (apply (aget encoder "encodeBuffer") int-data))
+        (.push (apply (.-encodeBuffer encoder) int-data))
         (.push (.flush encoder)))
       (some-> @next (w/process-audio encoded)))))


Remove extraneous quote

Remove extraneous quote

--- src/lt/plugins/kukui/db.cljs
+++ src/lt/plugins/kukui/db.cljs
@@ -71,7 +71,6 @@
                             (lines ?e ?file ?first ?last)]

    ;; just entities
-   '
    'ent-by-tag-and-type  '[:find ?e
                            :in $ % ?input-tag ?ent-type
                            :where (tagged-with ?e ?input-tag) [?e :type ?ent-type]]


Gameover Screen + spacebar to restart.

Gameover Screen + spacebar to restart.

--- src/canvas/main.cljs
+++ src/canvas/main.cljs
@@ -12,6 +12,7 @@

 (def SCALE-W 800)
 (def SCALE-H 450)
+(def WIN_SCORE 5)

 (def PLAYER_1_COLOR "dodgerblue")
 (def PLAYER_2_COLOR "peru")
@@ -64,6 +65,7 @@
 (defrecord GameBackground [])
 (defrecord GameNet [])
 (defrecord GameStartScreen [])
+(defrecord GameOverScreen [])
 (defrecord Paddle [x y width height vy color])
 (defrecord Ball [x y radius vx vy fill-color oob?])
 (defrecord Score [score x y font color align])
@@ -127,6 +129,19 @@
     (.fillText ctx "[ Escape ] to quit." (/ SCALE-W 2) 430)
     (.restore ctx)))

+(extend-type GameOverScreen
+  IDrawable
+  (draw! [_ ctx]
+    (.save ctx)
+    (aset ctx "textAlign" "center")
+    (aset ctx "font" "60px Helvetica")
+    (aset ctx "fillStyle" "peru")
+    (.fillText ctx "GAME OVER" (/ SCALE-W 2) 200)
+    (aset ctx "font" "20px Helvetica")
+    (aset ctx "fillStyle" "dodgerblue")
+    (.fillText ctx "Press the spacebar." (/ SCALE-W 2) 300)
+    (.restore ctx)))
+
 (extend-type Score
   IDrawable
   (draw! [{:keys [score x y font color align]} ctx]
@@ -202,6 +217,7 @@
   {:background (GameBackground.)
    :net        (GameNet.)
    :game-start (GameStartScreen.)
+   :game-over  (GameOverScreen.)
    :score-1    (Score. 0 (- (/ SCALE-W 2) 75) 60 SCORE_FONT SCORE_COLOR "right")
    :score-2    (Score. 0 (+ (/ SCALE-W 2) 75) 60 SCORE_FONT SCORE_COLOR "left")
    :paddle-1   (Paddle. 20 (- SCALE-H 120) 20 100 10 PLAYER_1_COLOR)
@@ -226,9 +242,12 @@
   (draw! (:background @state) ctx)
   ;;
   ;; While playing and game-over
-  (when (contains? #{:playing :gameover} (:mode @state))
+  (when (contains? #{:playing :game-over} (:mode @state))
     (draw! (:score-2 @state) ctx)
     (draw! (:score-1 @state) ctx))
+  ;;
+  (when (contains? #{:game-over} (:mode @state))
+    (draw! (:game-over @state) ctx))
   ;;
   (when (contains? #{:game-start} (:mode @state))
     (draw! (:game-start @state) ctx))
@@ -274,13 +293,19 @@
           {score2 :score} score-2
           p1? (> x SCALE-W)
           p2? (< x 0)
-          s1 (assoc score-1 :score (if p1? (inc score1) score1))
-          s2 (assoc score-2 :score (if p2? (inc score2) score2))
+          score1 (if p1? (inc score1) score1)
+          score2 (if p2? (inc score2) score2)
+          s1 (assoc score-1 :score score1)
+          s2 (assoc score-2 :score score2)
+          mode (if (or (>= score1 WIN_SCORE)
+                       (>= score2 WIN_SCORE))
+                 :game-over
+                 (:mode state))
           ball (cond
                  p2? (assoc ball :x (- SCALE-W 25) :y (/ SCALE-H 2))
                  p1? (assoc ball :x 25 :y (/ SCALE-H 2))
                  :else ball)]
-      (assoc state :score-1 s1 :score-2 s2 :ball ball))))
+      (assoc state :score-1 s1 :score-2 s2 :ball ball :mode mode))))

 (defn animate-loop!
   [state ctx]
@@ -324,8 +349,9 @@
                         (assoc % :mode :game-start)))

         (= :space event)
-        (swap! state #(if (= (:mode %) :game-start)
-                        (merge % objects {:mode :playing})
+        (swap! state #(case (:mode %)
+                        :game-start (merge % objects {:mode :playing})
+                        :game-over (assoc % :mode :game-start)
                         (assoc % :pause? (not (:pause? %)))))

         :else


Add a shutdown hook that prints all live threads, which is useful in a production environment

--- src/cfpb/qu/main.clj
+++ src/cfpb/qu/main.clj
@@ -23,7 +23,8 @@
     [reload :as reload]
     [stacktrace :as dev-stacktrace]]
    [ring.util.response :as response]
-   [taoensso.timbre :as log]))
+   [taoensso.timbre :as log])
+  (:import [java.lang.management.ManagementFactory]))

 (defn- wrap-cors
   [handler]
@@ -64,6 +65,15 @@
         worker (qc/create-worker cache)]
     (qc/start-worker worker)))

+(defn add-shutdown-hook
+  "Add a shutdown hook that prints all live threads"
+  []
+  (let [mx-bean (java.lang.management.ManagementFactory/getThreadMXBean)
+        stack (.dumpAllThreads mx-bean true true)]
+    (.addShutdownHook (Runtime/getRuntime) (Thread. (fn [] (areduce stack i ret nil (println (aget stack i))))))))
+
+
+
 (defn -main
   [& args]
   (ensure-mongo-connection)
@@ -83,6 +93,7 @@
     (log/info "Starting server on" (str (:ip options) ":" (:port options)))
     (when (:dev env)
       (log/info "Dev mode enabled" (:dev env)))
+    (add-shutdown-hook)
     (start-cache-worker)
     (run-server handler options)))


Fix argument order in json-response

Fix argument order in json-response

--- src/cfpb/qu/util.clj
+++ src/cfpb/qu/util.clj
@@ -8,8 +8,8 @@
 (defn json-response
   "Wraps the response in the json content type and generates JSON from the content"
   [content]
-  (content-type "application/json; charset=utf-8"
-                (json/generate-string content)))
+  (content-type {:body (json/generate-string content)}
+                "application/json; charset=utf-8"))

 (defn request-protocol
   [request]


separate try-spawn-piece and spawn-piece functions

--- src/client/core.cljs
+++ src/client/core.cljs
@@ -59,17 +59,21 @@
   []
   (js/console.log "game over"))

-(defn spawn-piece!
+(defn spawn-piece!
   "Spawns a random piece at the starting position."
+  [piece]
+    (swap! state assoc :piece piece
+                       :position start-position))
+
+(defn try-spawn-piece!
+  "Checks if new piece can be written to starting position."
   []
   (let [piece (get-rand-piece)
         [x y] start-position
         board (:board @state)]
     (if (piece-fits? piece x y board)
-      (swap! state assoc :piece (get-rand-piece)
-                     :position start-position)
-      (game-over))
-  ))
+      (spawn-piece! piece)
+      (game-over))))

 (defn collapse-rows!
   "Collapse all filled rows."
@@ -113,8 +117,8 @@
     ; If collapse routine returns a channel...
     ; then wait for it before spawning a new piece.
     (if-let [collapse-anim (go-go-collapse!)]
-      (go (<! collapse-anim) (spawn-piece!))
-      (spawn-piece!))))
+      (go (<! collapse-anim) (try-spawn-piece!))
+      (try-spawn-piece!))))

 (defn go-go-gravity!
   "Starts the gravity routine."
@@ -209,7 +213,7 @@

 (defn init []
   (size-canvas!)
-  (spawn-piece!)
+  (try-spawn-piece!)
   (add-key-events)
   (go-go-gravity!)


Refactor sort-by-second to DRY it

Refactor sort-by-second to DRY it

--- src/kmg/domain.clj
+++ src/kmg/domain.clj
@@ -25,9 +25,9 @@
 ;; (every-first #{["user2"] ["user1"]})

 (defn sort-by-second
-  ([coll] (sort #(- (compare (last %1) (last %2))) coll))
+  ([coll] (sort-by-second - coll))
   ([order coll] (sort #(order (compare (last %1) (last %2))) coll)))
-;; (sort-by-second - [[1 200] [3 400] [2 300]])
+;; (sort-by-second + [[1 200] [3 400] [2 300]])

 (defn recommendations-completed-by-user-dataset [db user]
   (d/q '[:find ?id ?timestamp


fixed idf score function

fixed idf score function

--- src/help_me_im_dumb/query_engine.clj
+++ src/help_me_im_dumb/query_engine.clj
@@ -25,15 +25,7 @@
   [term]
   (/
     (float index/TOTAL-DOCS)
-    (float (if (index/DICTIONARY (read-string term)) (index/DICTIONARY (read-string term)) 1))
-    ))
-
-(index/initialize-index)
-(index/DICTIONARY "run")
-(idf-score "run")
-
-(index/DICTIONARY "water")
-(idf-score "water")
+    (float (read-string (index/DICTIONARY term)))))

 (defn tf-score
   "given 1 doc and 1 term find term freq"
@@ -41,8 +33,6 @@
   (count
     (re-seq(re-pattern term)
             (get (index/docid->doc docid) :title))))
-
-

 (defn tfidf-scores
   [docids term]


Rename host,user to &host,&user in deftask

--- src/control/core.clj
+++ src/control/core.clj
@@ -225,7 +225,7 @@
                              (if (list? item)
                                (let [cmd (first item)]
                                  (if (cmd system-functions)
-                                   (list* cmd  'host 'user 'cluster (rest item))
+                                   (list* cmd  '&host '&user 'cluster (rest item))
                                    item))
                                item))
                            body)]


rc/convert/core.clj: cleaning

rc/convert/core.clj: cleaning

--- src/convert/core.clj
+++ src/convert/core.clj
@@ -2,12 +2,9 @@
   (:require
    [clojure.xml :as xml]
    [convert.allfiles :as files]
-   ;[convert.fewfiles :as files]
+   ;; [convert.fewfiles :as files]
    )
   (:gen-class :main true))
-
-(defn x-main [fname]
-  (println (str "Processing: " fname)))

 (defn convert [fname]
   (let [my-data


remove 'be called': should derive this via a passive lexical transformation

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -184,29 +184,6 @@
                                     :1plur "are born"
                                     :2plur "are born"
                                     :3plur "are born"}}}
-
-   "be called" {:synsem {:cat :verb
-                         :sem {:pred :be-called}}
-                :english {:future "be called"
-                          :participle "being called"
-                          :conditional "be called"
-                          :imperfect {:1sing "was being called"
-                                      :2sing "were being called"
-                                      :3sing "was being called"
-                                      :1plur "were being called"
-                                      :2plur "were being called"
-                                      :3plur "were being called"}
-                          :past {:english "was called"
-                                 :2sing "were called"
-                                 :2plur "were called"
-                                 :3plur "were called"}
-                          :present {:1sing "am called"
-                                    :2sing "are called"
-                                    :3sing "is called"
-                                    :1plur "are called"
-                                    :2plur "are called"
-                                    :3plur "are called"}}}
-
    "be missed" {:synsem {:cat :verb
                          :sem {:pred :mancare}}
                 :english {:future "be missed"


Wire up group name

Wire up group name

--- src/braid/ui/views/header.cljs
+++ src/braid/ui/views/header.cljs
@@ -106,11 +106,16 @@
           [:img.avatar {:style {:background-color (id->color @user-id)}
                         :src @user-avatar-url}]]))))

+(defn group-name-view []
+  (let [group (subscribe [:active-group])]
+    (fn []
+      [:div.group-name (@group :name)])))
+
 (defn header-view []
   [:div.header

     [:div.left
-      [:div.group-name "Braid"]
+      [group-name-view]
       [inbox-page-button-view]
       [recent-page-button-view]
       [search-bar-view]]


Return exception in callback in more cases

--- src/pdok/featured_to_extracts/api.clj
+++ src/pdok/featured_to_extracts/api.clj
@@ -81,7 +81,7 @@
             [entry nil]))
         [tmp nil]))
     (catch Exception e
-      [nil (:cause e)])))
+      [nil e])))

 (defn process* [worker-id stats callback-chan request]
   (log/info "Processing extract: " request)
@@ -92,11 +92,11 @@
         zipped? (if (nil? (:format request)) true (= (:format request) "zip"))
         [file err] (download-file (:changeLog request) zipped?)]
     (if-not file
-      (do
+      (let [msg (if err (str err) "Something went wrong downloading")
+            error-stats (merge request {:status "error" :msg msg})]
+        (log/warn msg error-stats)
         (swap! stats assoc-in [:processing worker-id] nil)
-        (stats-on-callback callback-chan request
-                           (assoc request :error
-                                          (if err err "Something went wrong downloading"))))
+        (stats-on-callback callback-chan request error-stats))
       (try
         (with-open [in (io/input-stream file)]
           (let [_ (log/info "Processing file:" (:changeLog request))
@@ -105,7 +105,7 @@
             (swap! stats assoc-in [:processing worker-id] nil)
             (stats-on-callback callback-chan request run-stats)))
         (catch Exception e
-          (let [error-stats (assoc request :error (str e))]
+          (let [error-stats (merge request {:status "error" :msg (str e)})]
             (log/warn e error-stats)
             (swap! stats assoc-in [:processing worker-id] nil)
             (stats-on-callback callback-chan request error-stats)))


Clojure's prototype for the whole algorithm

--- clojure-agents/src/clojure_agents/core.clj
+++ clojure-agents/src/clojure_agents/core.clj
@@ -2,20 +2,55 @@
    (:require [clj-http.client :as http-client])
    (:require [clojure.data.json :as json]))

+(def graph (agent {}))
+(def graph-builder (agent {:edges-assembled 0 :data {}}))
+(def edges-amount (agent 0))
+
+(defn- build-graph [_ builder]
+  (let [flattened-map
+        (map (fn [entry] (flatten (cons [(entry 0)] (entry 1)))) (builder :data))]
+    (assoc {} :adjacencies flattened-map :vertices (count (builder :data)))))
+
+(defn- on-graph-built [key ref old graph]
+  (do
+    (prn (format "Vertices: %d" (graph :vertices)))
+    (prn (format "Edges: %d" (count (graph :adjacencies))))))
+
+(defn- put-on-builder
+  [builder partial-edges]
+  (let [partial-map
+        (reduce #(assoc-in %1 [(:i %2) (:j %2)] (:weight %2)) {} partial-edges)]
+    (assoc builder
+           :edges-assembled (+ (builder :edges-assembled) (count partial-edges))
+           :data ((merge-with merge (builder :data) partial-map)))))
+
+(defn- on-builder-updated [key ref old builder]
+  (if (= @edges-amount (:edges-assembled builder))
+    (send graph build-graph builder)))
+
+
 (defn- get-edges
-  [offset limit]
+  [_ offset limit]
   (json/read-str
     (:body (http-client/get (format "http://localhost:8080/api/graph?offset=%d&limit=%d"
                                     offset limit)))
     :key-fn keyword))

+(defn- assemble-graph
+  [assembled partial-edges]
+  (merge-with merge assembled partial-edges))
+
+(defn- on-edges-received
+  [key ref old edges]
+  (send graph-builder put-on-builder edges))
+
 (defn- get-graph
   [offsets]
-  (letfn [(collect-into-builder [builder edges]
-            (reduce #(assoc-in %1 [(:i %2) (:j %2)] (:weight %2)) {} edges))]
-          (reduce collect-into-builder
-            {}
-            (map #(get-edges % 1000) offsets))))
+  (doseq [offset offsets]
+    (let [edges (agent [])]
+      (do
+        (add-watch edges :edges-watcher on-edges-received)
+        (send-off edges get-edges offset 1000)))))

 (defn- edges-amount-watcher
   [key ref old edges-amount]
@@ -24,11 +59,12 @@
          (let [batches-amount
                (+ (quot edges-amount 1000) (Integer/signum (mod edges-amount 1000)))]
            (range batches-amount))))
-  (println (get-graph offsets)))
+  (get-graph offsets))

 (defn main
   []
-  (def edges-amount (agent 0))
+  (add-watch graph :on-graph-built on-graph-built)
+  (add-watch graph-builder :on-builder-updated on-builder-updated)
   (add-watch edges-amount :edges-amount-watcher edges-amount-watcher)
   (send-off edges-amount
             (fn [_] (Integer/parseInt


Link to original source files

Link to original source files

--- modules/reitit-core/src/reitit/impl.cljc
+++ modules/reitit-core/src/reitit/impl.cljc
@@ -1,15 +1,3 @@
-; Copyright 2013 Relevance, Inc.
-; Copyright 2014-2016 Cognitect, Inc.
-
-; The use and distribution terms for this software are covered by the
-; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0)
-; which can be found in the file epl-v10.html at the root of this distribution.
-;
-; By using this software in any fashion, you are agreeing to be bound by
-; the terms of this license.
-;
-; You must not remove this notice, or any other, from this software.
-
 (ns ^:no-doc reitit.impl
   #?(:cljs (:require-macros [reitit.impl]))
   (:require [clojure.string :as str]
@@ -30,6 +18,10 @@
         coll))
     coll
     coll))
+
+;;
+;; https://github.com/pedestal/pedestal/blob/master/route/src/io/pedestal/http/route/prefix_tree.clj
+;;

 (defn wild? [s]
   (contains? #{\: \*} (first (str s))))


Fix reflection warnings

Fix reflection warnings

--- modules/reitit-core/src/reitit/trie.cljc
+++ modules/reitit-core/src/reitit/trie.cljc
@@ -61,8 +61,8 @@
         (case (get s to)
           \{ (let [to' (or (str/index-of s "}" to) (ex/fail! (str "Unclosed brackets: " (pr-str s))))]
                (if (= \* (get s (inc to)))
-                 (recur (concat ss (-static from to) (-catch-all (inc to) to')) (inc to') (inc to'))
-                 (recur (concat ss (-static from to) (-wild to to')) (inc to') (inc to'))))
+                 (recur (concat ss (-static from to) (-catch-all (inc to) to')) (long (inc to')) (long (inc to')))
+                 (recur (concat ss (-static from to) (-wild to to')) (long (inc to')) (long (inc to')))))
           \: (let [to' (or (str/index-of s "/" to) (count s))]
                (if (= 1 (- to' to))
                  (recur ss from (inc to))


Fix sort-order being wrong for capitalized symbols

Referred symbols with capital letters would appear earlier in the :refer
vector

--- src/refactor_nrepl/ns/constructor.clj
+++ src/refactor_nrepl/ns/constructor.clj
@@ -54,15 +54,16 @@
       (merge-libspecs libspecs))))

 (defn- get-sort-name [dep]
-  (if (sequential? dep)
-    (let [name (-> dep first name)
-          ;; penalize prefix forms so [foo.bar :as bar]
-          ;; comes before [foo.bar [qux :as qux] [quux ..]]
-          suffix (if (and (> (count dep) 1) (sequential? (second dep)))
-                   " ["
-                   "")]
-      (str name suffix))
-    (name dep)))
+  (str/lower-case
+   (if (sequential? dep)
+     (let [name (-> dep first name)
+           ;; penalize prefix forms so [foo.bar :as bar]
+           ;; comes before [foo.bar [qux :as qux] [quux ..]]
+           suffix (if (and (> (count dep) 1) (sequential? (second dep)))
+                    " ["
+                    "")]
+       (str name suffix))
+     (name dep))))

 (defn- dependency-comparator
   "Lexicographical comparison of dependency vectors based on the name
@@ -124,19 +125,19 @@
   [libspecs]
   (vec
    (for [libspec libspecs]
-         (create-libspec (update-in libspec [:ns] #(-> % suffix symbol))))))
+     (create-libspec (update-in libspec [:ns] #(-> % suffix symbol))))))

 (defn- create-libspec-vectors-with-prefix
   [libspecs]
   (vec
    (for [libspec libspecs]
-         (create-libspec libspec))))
+     (create-libspec libspec))))

 (defn- create-prefixed-libspec-vector
   [libspecs]
   (vec
    (for [{:keys [ns] :as libspec} libspecs]
-         (create-libspec (assoc libspec :ns (ns-suffix ns))))))
+     (create-libspec (assoc libspec :ns (ns-suffix ns))))))

 (defn- create-prefixed-libspec-vectors
   [[libspec & more :as libspecs]]


Fix head-response for nil responses

Fix head-response for nil responses

head-response made a {:body nil} response out of a regular nil response, which would be interpreted as an empty 200 response.

--- ring-core/src/ring/middleware/head.clj
+++ ring-core/src/ring/middleware/head.clj
@@ -11,7 +11,7 @@
 (defn head-response
   "Returns a nil body if original request was a HEAD."
   [response request]
-  (if (= :head (:request-method request))
+  (if (and response (= :head (:request-method request)))
     (assoc response :body nil)
     response))

@@ -23,4 +23,4 @@
     (-> request
         head-request
         handler
-        (head-response request))))+        (head-response request))))


Added find-all

Added find-all

--- src/pundit/api.clj
+++ src/pundit/api.clj
@@ -110,6 +110,11 @@
   (first
     (load-query klass *auth* (assoc q :limit 1))))

+(defn find-all
+  "Shorthand function to eagerly retrieve ALL hits of a query."
+  [klass & {:as q}]
+  (seq (load-query klass *auth* q)))
+
 (defn- remote-count* [klass q]
   (->> (merge q {:count 1 :limit 0})
        (GET ["classes" klass] *auth*)


lint fix

lint fix

--- src/metabase/driver/sync.clj
+++ src/metabase/driver/sync.clj
@@ -458,17 +458,17 @@
         (insert-or-update-active-field! field-def (existing-field-name->field (:name field-def)) table)))))

-(defn- determine-fk-type
-  "Determine whether a FK is `:1t1`, or `:Mt1`.
-   Do this by getting the count and distinct counts of source `Field`.
-
-   *  If count and distinct count are equal, we have a one-to-one foreign key relationship.
-   *  If count is > distinct count, we have a many-to-one foreign key relationship."
-  [field]
-  (let [field-count          (queries/field-count field)
-        field-distinct-count (queries/field-distinct-count field)]
-    (if (= field-count field-distinct-count) :1t1
-                                             :Mt1)))
+;(defn- determine-fk-type
+;  "Determine whether a FK is `:1t1`, or `:Mt1`.
+;   Do this by getting the count and distinct counts of source `Field`.
+;
+;   *  If count and distinct count are equal, we have a one-to-one foreign key relationship.
+;   *  If count is > distinct count, we have a many-to-one foreign key relationship."
+;  [field]
+;  (let [field-count          (queries/field-count field)
+;        field-distinct-count (queries/field-distinct-count field)]
+;    (if (= field-count field-distinct-count) :1t1
+;                                             :Mt1)))

 (defn- sync-table-fks! [driver table]
   (when (contains? (driver/features driver) :foreign-keys)


Added requirement for clojure.string in namespace declaration

Added functions to parse mplayer responses in slave mode to clojure maps.

      + mplayer-key->keyword creates proper keywords out of mplayer
      response keys; this was stolen wholesale from Clojurep
      Programming

       + mplayer-pairs->map creates a complete map from a set of
       mplayer responses

Added functions to control the mplayer slave via the FIFO
      + step-player
      + next-player
      + prev-player

Completed functions to get metadata from running mplayer
      + get-player-track-info: artist/title/album/genre/year/track/comment
      + get-player-progress: percent_pos/time_pos/time_length

--- src/moodseer_clj/process.clj
+++ src/moodseer_clj/process.clj
@@ -1,5 +1,6 @@
 (ns moodseer-clj.process
-  (:use [clojure.java.shell :only [sh]]))
+  (:use [clojure.java.shell :only [sh]])
+  (:require [clojure.string :as str]))

 ;; (sh "bash" "-c" "mplayer -playlist /tmp/gort.m3u -shuffle -quiet -slave -input file=/tmp/MYCMD  1>/tmp/mplayer-out.log 2>&1 & \n echo $!")
 ;; (sh "bash" "-c" "echo 'get_meta_artist\nget_meta_title\nget_meta_album\nget_meta_genre\nget_meta_year\nget_meta_track\nget_meta_comment' > /tmp/MYCMD")
@@ -9,6 +10,22 @@

 (def player-cmd (str "/usr/bin/mplayer -quiet -slave -input file=" fifo-path " -idle -nocache -nortc"))

+
+(defn mplayer-key->keyword [s]
+  (->>
+   (str/replace s #"(ANS_META_|ANS_)" "")
+   str/lower-case
+   keyword
+   ))
+
+(defn mplayer-pairs->map [& [pairs]]
+  (let [pairs (str/replace pairs "=\n" "=nil")] ;; egregious work-around for last value null
+  (->>
+   (clojure.string/split pairs #"[=\n]")
+   (map str/trim)
+   (map-indexed (fn [i x] (if (odd? i) x (mplayer-key->keyword x))))
+   (apply hash-map)
+   )))

 (defn mkfifo []
   (let [fifo-path "/tmp/MYCMD"]
@@ -25,6 +42,30 @@
 (defn pause-player []
   (sh "bash" "-c" (str "echo 'pause' > " fifo-path) ))

+(defn step-player
+  ([] (step-player 1))
+  ([step]
+     (sh "bash" "-c" (str "echo 'pt_step " step "' > " fifo-path))))
+
+(defn next-player []
+  (step-player 1))
+
+(defn prev-player []
+  (step-player -1))
+
 (defn quit-player []
   (sh "bash" "-c" (str "echo 'quit' > " fifo-path) ))

+(defn get-player-track-info []
+  (let [x (sh "bash" "-c" "echo 'get_meta_artist\nget_meta_title\nget_meta_album\nget_meta_genre\nget_meta_year\nget_meta_track\nget_meta_comment' > /tmp/MYCMD")
+        _ (Thread/sleep 200)
+        y (:out (sh "bash" "-c" "tail -7 /tmp/mplayer-out.log | egrep '^ANS_META' | sed \"s,',,g\""))
+        ]
+    y))
+
+(defn get-player-progress []
+  (let [x (sh "bash" "-c" "echo 'get_percent_pos\nget_time_pos\nget_time_length' > /tmp/MYCMD")
+        _ (Thread/sleep 200)
+        y (:out (sh "bash" "-c" "tail -3 /tmp/mplayer-out.log | egrep '^ANS_' | sed \"s,',,g\""))
+        ]
+    y))


Add Path Morph

Add Path Morph

--- src-cljs/cljs_workspace/om_morph.cljs
+++ src-cljs/cljs_workspace/om_morph.cljs
@@ -145,6 +145,40 @@
                   ; :onKeyDown #(when (.-metaKey %) (save-input % owner app))} (dom/span #js {
                     :ref "myInput"} (get-in app [:morph :TextString])))

+(defn to-svg-attr [elements]
+  (let [car (first elements)
+        cdr (rest elements)]
+    (str "M" (car :x) "," (car :y) " "
+      (reduce str (map #(str "L" (% :x) "," (% :y) " ") cdr)))))
+
+(defn render-path-node [app owner]
+  (let [vertices (get-in app [:shape :PathElements])
+        ulx (apply min (map #(% :x) vertices))
+        uly (apply min (map #(% :y) vertices))
+        lrx (apply max (map #(% :x) vertices))
+        lry (apply max (map #(% :y) vertices))
+        half-stroke (/ (get-in app [:shape :StrokeWidth]) 2)
+        w (Math/abs (- ulx lrx))
+        h (Math/abs (- uly lry))]
+  (dom/svg #js { :style #js {:position "absolute"
+                             :width (+ w (* 2 half-stroke))
+                             :height (+ h (* 2 half-stroke))
+                             :fill "none"
+                             :viewBox [(unchecked-negate half-stroke)
+                                       (unchecked-negate half-stroke)
+                                       (+ w half-stroke) (+ h half-stroke)] }}
+    (dom/path #js {:strokeWidth (get-in app [:shape :StrokeWidth])
+                   :stroke (get-in app [:shape :Fill])
+                   :d (to-svg-attr vertices)}))))
+
+(defmethod shape "Path" [app owner]
+  (let [style (extract-style (:shape app))]
+      (dom/div #js {:style (dict->js style) :className "Morph Path"}
+        ; we render a svg sub-tag into which we place a
+        ; <path> that covers the given PathElements
+        (render-path-node app owner)
+        (render-submorphs app))))
+
 (defmethod shape "Ellipse" [app owner]
   (let [style (extract-style (:shape app))]
     ;; we apply some customizations to the style, to make the shape elliptical


initialize app state from parsed projects

--- src-cljs/cljsbuild_ui/pages/main.cljs
+++ src-cljs/cljsbuild_ui/pages/main.cljs
@@ -12,10 +12,56 @@
 ;; App State
 ;;------------------------------------------------------------------------------

-(def state (atom {
+(def initial-project-build-state
+  "Initial state for a new build in a project"
+  {;; tool state
+   :active? true
+   :compile-time 0
+   :last-compile-time nil
+   :error nil
+   :state :done
+   :warnings []
+
+   ;; from project.clj
+   :id nil
+   :source-paths []
+   :compiler {}})
+
+(def initial-project-state
+  "Initial state for a new project"
+  {;; tool state
+   :compile-menu-showing? false
+   :auto-compile? true
+   :state :idle
+
+   ;; from project.clj
+   :name ""
+   :filename ""
+   :version ""
+   :license {}
+   :dependencies []
+   :plugins []
+
+   ;; from project.clj, but with extra tool state
+   ;; (see initial-project-build-state)
+   :builds []})
+
+(def initial-app-state
+  {:projects {:order []}})
+
+(def state (atom initial-app-state))
+
+(defn get-ordered-projects
+  "Given a project map containing a list of keys in :order, return a vector of their ordered values."
+  [project-map]
+  (let [proj-keys (-> project-map :order)]
+    (mapv #(get project-map %) proj-keys)))
+
+(def test-app-state
+  "A test app-state for quick-testing page rendering."
+  {
   :projects {
     "/home/oakmac/t3tr0s/project.clj" {
-    ;;"C:\\t3tr0s\\project.clj" {
       :compile-menu-showing? false
       :auto-compile? true
       :name "t3tr0s"
@@ -152,7 +198,7 @@
    the last compile."
   []
   (let [n (now)
-        prj-keys (keys (:projects @state))]
+        prj-keys (-> @state :projects :order)]
     (doall
       (map
         (fn [prj-key]
@@ -322,7 +368,7 @@
     (map
       (fn [prj-key]
         (swap! state assoc-in [:projects prj-key :compile-menu-showing?] false))
-      (-> @state :projects keys))))
+      (-> @state :projects :order))))

 (defn- click-compile-btn [prj-key]
   (let [prj (get-in @state [:projects prj-key])
@@ -522,26 +568,27 @@
                  (not (zero? (:warnings bld))))
         (map warning-row (:warnings bld)))]))

-(quiescent/defcomponent Project [[prj-key prj]]
-  (sablono/html
-    [:div.project-1b83a
-      [:div.wrapper-714e4
+(quiescent/defcomponent Project [prj]
+  (let [prj-key (:filename prj)]
+    (sablono/html
+      [:div.project-1b83a
+       [:div.wrapper-714e4
         [:div.left-ba9e7
-          (:name prj)
-          (when (= (:state prj) :idle)
-            [:span.edit-c0ba4 "edit"])]
+         (:name prj)
+         (when (= (:state prj) :idle)
+           [:span.edit-c0ba4 "edit"])]
         [:div.right-f5656
-          (case (:state prj)
-            :auto (auto-state prj-key)
-            :cleaning (cleaning-state prj-key)
-            :idle (idle-state prj-key prj)
-            :once (once-state prj-key)
-            "*unknown project state*")]]
-      [:table.tbl-bdf39
+         (case (:state prj)
+           :auto (auto-state prj-key)
+           :cleaning (cleaning-state prj-key)
+           :idle (idle-state prj-key prj)
+           :once (once-state prj-key)
+           "*unknown project state*")]]
+       [:table.tbl-bdf39
         (bld-tbl-hdr)
         (map-indexed
           #(BuildRow (assoc %2 :idx %1 :prj-key prj-key))
-          (:builds prj))]]))
+          (:builds prj))]])))

 (quiescent/defcomponent AppRoot [app-state]
   (sablono/html
@@ -553,7 +600,7 @@
           [:span.link-3d3ad [:i.fa.fa-plus] "Add project"]
           [:span.link-3d3ad [:i.fa.fa-gear] "Settings"]]
         [:div.clr-737fa]]
-      (map Project (:projects app-state))]))
+      (map Project (get-ordered-projects (:projects app-state)))]))

 ;;------------------------------------------------------------------------------
 ;; State Change and Rendering
@@ -590,8 +637,39 @@
     ;; TODO: we may not even use this
     (reset! events-added? true)))

+(defn attach-state-to-build
+  "Attach state to project-build map, and prune out unused keys"
+  [build]
+  (let [keep-keys [:id
+                   :source-paths
+                   :compiler]]
+    (-> initial-project-build-state
+        (merge (select-keys build keep-keys)))))
+
+(defn attach-state-to-proj
+  "Attach state to project map, and prune out unused keys"
+  [project]
+  (let [keep-keys [:filename
+                   :name
+                   :version
+                   :license
+                   :dependencies
+                   :plugins]
+        builds (->> project :cljsbuild :builds (mapv attach-state-to-build))]
+    (-> initial-project-state
+        (merge (select-keys project keep-keys))
+        (assoc :builds builds))))
+
+(defn init-projs!
+  [projects]
+  (js/console.log (pr-str projects))
+  (let [projects2 (map attach-state-to-proj projects)
+        filenames (mapv :filename projects2)
+        project-map (assoc (zipmap filenames projects2)
+                           :order filenames)]
+    (swap! state assoc :projects project-map)))
+
 (defn init! [projs]
-  (js/console.log (pr-str projs))
-  (add-events!)
-  ;; trigger the initial render
-  (swap! state identity))
+  (init-projs! projs)
+  (js/console.log (pr-str @state))
+  (add-events!))


[PDOK-4086] added config/date-formatter parameter + gml-to-featured.runner/todate function for reading datetime string and parsing those to a 'default' (ISO) format

--- src/gml_to_featured/runner.clj
+++ src/gml_to_featured/runner.clj
@@ -6,14 +6,18 @@
             [clojure.tools.cli :refer [parse-opts]]
             [clojure.string :as string]
             [clojure.tools.logging :as log]
-            [clojure.zip :as z])
+            [clojure.zip :as z]
+            [clj-time.format :as f])
   (:gen-class)
   (:import (javax.xml.stream.events XMLEvent)))

 (def ^:dynamic *sequence-selector* identity)
 (def ^:dynamic *feature-selector* identity)
 (def ^:dynamic *feature-identifier* identity)
+(def ^:dynamic *date-formatter* identity)
 (def ^:dynamic *translators* {})
+
+(def default-datetime-formatter (f/formatters :date-hour-minute-second-ms))

 (def unknown nil)

@@ -100,6 +104,12 @@
   (defn parse-multi-tag [mappings]
     (eval (code/multi mappings)))

+  (defn todate [datestring]
+    (if datestring
+      (f/unparse
+        default-datetime-formatter
+        (f/parse *date-formatter* datestring))))
+
  (def fns {'first clojure.core/first})

  (defn upgrade-comp [function-vector]
@@ -133,6 +143,10 @@
           feature-identifier (if feature-identifier
                              (apply comp feature-identifier)
                              identity)
+          date-formatter (:config/date-formatter config)
+          date-formatter (if date-formatter
+                           (f/formatter date-formatter)
+                           (f/formatters :date-hour-minute-second-ms))
           feature-selector (:config/feature-selector config)
           feature-selector (if feature-selector
                                (apply comp feature-selector)
@@ -141,6 +155,7 @@
       (binding [*translators* translators
                 *sequence-selector* sequence-selector
                 *feature-identifier* feature-identifier
+                *date-formatter* date-formatter
                 *feature-selector* feature-selector]
         (process reader writer dataset validity))))


Implement code to render a list of things.

--- basic/om-tut/src/om_tut/core.cljs
+++ basic/om-tut/src/om_tut/core.cljs
@@ -13,7 +13,7 @@
 (om/root
  (fn [data owner]
    (om/component
-    (apply dom/ul nil
+    (apply dom/ul #js {:className "animals"}
            (map (fn [text] (dom/li nil text)) (:list data)))))
  app-state
  {:target (. js/document (getElementById "app0"))})


(PDB-3065) Stop memoizing resource identity hashes

Because the memoization is based on count, not overall pool size, it
could consume arbitrary RAM, and was responsible for overruning a 32GB
JVM in the field.

cf. (PDB-3059)

--- src/puppetlabs/puppetdb/scf/hash.clj
+++ src/puppetlabs/puppetdb/scf/hash.clj
@@ -46,10 +46,6 @@
   {:post [(string? %)]}
   (generic-identity-hash [type title parameters]))

-;; Size of the cache is based on the number of unique resources in a
-;; "medium" site persona
-(def memoized-resource-identity-hash* (kitchensink/bounded-memoize resource-identity-hash* 40000))
-
 (defn resource-identity-hash
   "Compute a hash for a given resource that will uniquely identify it
   _for storage deduplication only_.
@@ -60,7 +56,7 @@
   [{:keys [type title parameters] :as resource}]
   {:pre  [(map? resource)]
    :post [(string? %)]}
-  (memoized-resource-identity-hash* type title parameters))
+  (resource-identity-hash* type title parameters))

 (defn catalog-resource-identity-format
   "Narrow `resource` to only contain the needed key/values for computing the hash of


Version 0.3.3

Version 0.3.3

--- metlog-vault/project.clj
+++ metlog-vault/project.clj
@@ -1,4 +1,4 @@
-(defproject metlog-vault "0.3.3-SNAPSHOT"
+(defproject metlog-vault "0.3.3"
   :description "Repository for long term storage of series data."

   :license {:name "Eclipse Public License"


Rename function

Rename function

--- src/tenor/core.clj
+++ src/tenor/core.clj
@@ -10,5 +10,5 @@

 (defn play-chord-with-instrument [instrument chord]
   (doseq [note chord]
-    (play-note instrument note)))
+    (play-note-with-instrument instrument note)))


Add SC-MAX-FLOAT-VAL - the maximum whole number that can be represented  with scsynth's floats due to precision constraints: 2**24.

--- src/overtone/sc/defaults.clj
+++ src/overtone/sc/defaults.clj
@@ -76,3 +76,5 @@
                             "/Applications/SuperCollider/plugins"
                             "/Applications/SuperCollider.app/Contents/Resources/plugins"
                             "/Applications/SuperCollider/SuperCollider.app/Contents/Resources/plugins"]}})
+
+(def SC-MAX-FLOAT-VAL (Math/pow 2 24))


Tidy up spacing

Tidy up spacing

--- src/overtone/sc/defaults.clj
+++ src/overtone/sc/defaults.clj
@@ -84,8 +84,8 @@
    :max-nodes        {:default 1024  :flag "-n" :desc "Max number of executing nodes allowed in the server"}
    :max-sdefs        {:default 1024  :flag "-d" :desc "Max number of synthdefs allowed"}
    :rt-mem-size      {:default 8192  :flag "-m" :desc "Real time memory size"}
-   :max-w-buffers    {:default 64    :flag "-w" :desc"Number of wire buffers"}
-   :num-rand-seeds   {:default 64    :flag "-r" :desc"Number of random seeds"}
+   :max-w-buffers    {:default 64    :flag "-w" :desc "Number of wire buffers"}
+   :num-rand-seeds   {:default 64    :flag "-r" :desc "Number of random seeds"}
    :load-sdefs?      {:default 1     :flag "-D" :desc "Load synthdefs on boot? 0 or 1"}
    :rendezvous?      {:default 1     :flag "-R" :desc "Publish to rendezvous? 0 or 1"}
    :max-logins       {:default 64    :flag "-l" :desc "Maximum number of named return addresses stored - also maximum number of txp connections accepted."}


Faster, maybe

Faster, maybe

--- src/fatlip/plot.cljs
+++ src/fatlip/plot.cljs
@@ -27,7 +27,7 @@
   Reversible
   (rev [this]
     (assoc this
-           :classes (vec (reverse (map #(vec (rseq %)) classes)))
+           :classes (vec (rseq (mapv #(vec (rseq %)) classes)))
            :succs preds
            :preds succs
            :block-succs block-preds


adds revoke-permission funciton

adds revoke-permission funciton

--- src/pc/models/permission.clj
+++ src/pc/models/permission.clj
@@ -48,6 +48,13 @@
                    :needs-email :email/permission-granted
                    :permission/granter-ref (:db/id granter)
                    :permission/doc-cust (UUID. (:db/id doc) (:db/id cust))}])))
+
+(defn revoke-permission [permission annotations]
+  (let [txid (d/tempid :db.part/tx)
+        temp-id (d/tempid :db.part/user)]
+    @(d/transact (pcd/conn)
+                 [(assoc annotations :db/id txid)
+                  (web-peer/retract-entity (:db/id permission))])))

 (defn grant-team-permit [team granter cust permit annotations]
   (let [txid (d/tempid :db.part/tx)


support subproperties

support subproperties

--- src/pc/views/blog/common.clj
+++ src/pc/views/blog/common.clj
@@ -1,5 +1,6 @@
 (ns pc.views.blog.common
   (:require [cheshire.core :as json]
+            [clojure.string :as str]
             [pc.views.common :refer (cdn-path)])
   (:import [java.util UUID]))

@@ -43,7 +44,13 @@
           var nodes = document.getElementsByClassName(classMap[key]);
           for (var i = 0; i < nodes.length; i++) {
             var node = nodes[i];
-            node[node.getAttribute('data-attr')] = fields[key];
+            var field = fields[key];
+            if (subprop = node.getAttribute('data-subprop')) {
+              for (k of subprop.split(',')) {
+                field = field[k];
+              }
+            }
+            node[node.getAttribute('data-attr')] = field;
           }
         }
       }
@@ -58,9 +65,14 @@
     (json/encode class-map) username)])

 (defn dribbble-attrs [class-map prop attr & {:as extra-attrs}]
-  (merge extra-attrs
-         {:class (str (:class extra-attrs) " " (get class-map prop))
-          :data-attr attr}))
+  (let [class-prop (if (string? prop)
+                     prop
+                     (first prop))]
+    (merge extra-attrs
+           {:class (str (:class extra-attrs) " " (get class-map class-prop))
+            :data-attr attr}
+           (when (coll? prop)
+             {:data-subprop (str/join "," (rest prop))}))))

 ; (defn dribbble-card [username]
 ;   (let [props ["comments_received_count" "bio" "shots_count" "can_upload_shot" "followings_count"
@@ -113,7 +125,7 @@
        [:a.dribbble-name profile-link
         [:strong (dribbble-attrs class-map "name" "innerText")]]]
       [:div.dribbble-link
-       [:a.dribbble-site (dribbble-attrs class-map "links" "href")
+       [:a.dribbble-site (dribbble-attrs class-map ["links" "web"] "href")
         ; [:span "unfold.co"]
-        [:span (dribbble-attrs class-map "links" "innerText")]]]]
+        [:span (dribbble-attrs class-map ["links" "web"] "innerText")]]]]
      (demo-with-blank-canvas (cdn-path "/blog/private-docs-early-access/grant-access.gif") "Grant someone access with their email address.")]))


Removed test to stdout

Removed test to stdout

--- test/forma/hadoop/jobs/forma_test.clj
+++ test/forma/hadoop/jobs/forma_test.clj
@@ -18,16 +18,6 @@
    :vcf-limit 25
    :long-block 15
    :window 5})
-
-(comment
-  (defn run-dynamic
-  "Test function that displays the output of the dynamic tap."
-  []
-  (?- (stdout)
-      (-> (analyze-trends some-map
-                       (hfs-seqfile "/Users/sritchie/Desktop/ndviseries1000/")
-                       (hfs-seqfile "/Users/sritchie/Desktop/ndviseries1000/"))
-          (c/first-n 10)))))

 ;; FORMA, broken down into pieces. We're going to have sixteen sample
 ;; timeseries, to test the business with the neighbors.


First cut of parsing incoming messages.

First cut of parsing incoming messages.

--- src/appengine_magic/services/mail.clj
+++ src/appengine_magic/services/mail.clj
@@ -1,5 +1,6 @@
 (ns appengine-magic.services.mail
   (:refer-clojure :exclude (send))
+  (:use [appengine-magic.utils :only [record]])
   (:import [com.google.appengine.api.mail MailServiceFactory
             MailService$Message MailService$Attachment]))

@@ -14,16 +15,17 @@

 (defrecord MailMessage [from to subject text-body html-body
-                        reply-to cc bcc attachments])
+                        sent-date received-date
+                        reply-to cc bcc attachments message-id])

 (defn make-attachment [filename data]
   (MailService$Attachment. filename data))

-(defn make-mail-message [& {:keys [from to subject text-body html-body
-                                   reply-to cc bcc attachments]
-                            :or {text-body "", html-body "", cc [], bcc [], attachments []}}]
+(defn make-message [& {:keys [from to subject text-body html-body
+                              reply-to cc bcc attachments]
+                       :or {text-body "", html-body "", cc [], bcc [], attachments []}}]
   ;; normalize and error-check
   (let [from (if-not (nil? from)
                  from
@@ -41,7 +43,11 @@
                     (throw (IllegalArgumentException. ":subject argument required")))
         cc (if (not (or (nil? cc) (sequential? cc))) [cc] cc)
         bcc (if (not (or (nil? bcc) (sequential? bcc))) [bcc] bcc)]
-    (MailMessage. from to subject text-body html-body reply-to cc bcc attachments)))
+    (record MailMessage
+            :from from :to to :subject subject
+            :text-body text-body :html-body html-body
+            :reply-to reply-to :cc cc :bcc bcc
+            :attachments attachments)))

 (defn- make-mail-service-message [^MailMessage msg]
@@ -63,3 +69,19 @@

 (defn send-to-admins [^MailMessage msg]
   (.sendToAdmins (get-mail-service) (make-mail-service-message msg)))
+
+
+(defn parse-message [request]
+  (let [session (javax.mail.Session/getDefaultInstance (java.util.Properties.) nil)
+        raw-msg (javax.mail.internet.MimeMessage. session (.getInputStream (:request request)))
+        from (first (map #(.toString %) (.getFrom raw-msg)))
+        subject (.getSubject raw-msg)
+        sent-date (.getSentDate raw-msg)
+        received-date (.getReceivedDate raw-msg)
+        to (map #(.toString %) (.getRecipients raw-msg javax.mail.Message$RecipientType/TO))
+        cc (map #(.toString %) (.getRecipients raw-msg javax.mail.Message$RecipientType/CC))
+        reply-to (first (map #(.toString %) (.getReplyTo raw-msg)))
+        message-id (.getMessageID raw-msg)]
+    (record MailMessage
+            :from from :to to :subject subject
+            :reply-to reply-to :cc cc)))


Fix creating directory instead of file.

Fix creating directory instead of file.

--- src/leiningen/new/vdom_app.clj
+++ src/leiningen/new/vdom_app.clj
@@ -17,4 +17,4 @@
       "resources/public/js"
       ["resources/public/js/vdom.js" (render "resources/public/js/vdom.js" data)]
       "resources/public/css"
-      "resources/public/css/{{path}}.css" (render "resources/public/css/styles.css" data))))
+      ["resources/public/css/{{path}}.css" (render "resources/public/css/styles.css" data)])))


Whitespace

Whitespace

--- src/grimoire/api.clj
+++ src/grimoire/api.clj
@@ -17,7 +17,6 @@

   {:arglists '[[config]]}
   dispatch)
-

 (defmulti list-artifacts
   "Returns a sequence of Thing[:artifact] representing all Maven
@@ -51,7 +50,6 @@
   "Returns a sequence of things representing itself at earlier or equal versions."

   dispatch)
-

 (defmulti read-notes
   "Returns a sequence of pairs [version note-text] for all notes on


docstring

docstring

--- src/cljc/commos/delta/compscribe.cljc
+++ src/cljc/commos/delta/compscribe.cljc
@@ -264,26 +264,29 @@

 (defn compscribe
   "Asynchronously subscribes via subs-fn and unsubs-fn at one or more
-  endpoints, combines received deltas so that they can be added to one
-  combined value and puts them onto target-ch.
+  endpoints, transforms received deltas so that they can be added to
+  one combined value and puts them onto target-ch.

   Specify used endpoints and their desired nesting in spec so:

   [endpoint (spec-map | spec)?]

-  root-endpoint may be any value recognized by subs-fn.
+  endpoint may be any value recognized by subs-fn.

   spec-map is a map {(key (spec-map | spec))+}

-  Deltas are composed according to the following rules:
-
-  1. If the id at key is not a collection, it is replaced with the
-  deltas streamed from endpoint.
-
-  2. If the id at key is a collection, it is replaced with deltas that
-  add to a map {(id streamed-val)+} from endpoint.
-
-  subs-fn is invoked with an endpoint and an id as arguments. It must
+  Deltas are transformed according to the following rules:
+
+  1. If the value at key is not a set, deltas are subscribed at the
+  endpoint of the associated spec (or nested spec-map) with the value
+  as id and are transformed to assert at key.
+
+  2. If the value at key is a set, deltas are subscribed at the
+  endpoint of the associated spec (or nested spec-map) with its values
+  as ids and are transformed to assert a map {(id streamed-val)+} at
+  key.
+
+  subs-fn is invoked with an endpoint and and id as arguments. It must
   return a unique core.async channel from which deltas can be taken.

   unsubs-fn may be invoked with the channel returned from subs-fn. It


Korma's SQLite database map no longer has :db key

Between 0.4.0 and 0.4.1, Korma dissoc's the :db from the options passed
to korma.db/sqlite3. The value is placed on the :subname key.

--- src/vip/data_processor/db/sqlite.clj
+++ src/vip/data_processor/db/sqlite.clj
@@ -34,7 +34,7 @@

 (defn attach-sqlite-db [{:keys [import-id spec-version] :as ctx}]
   (let [db (temp-db import-id spec-version)
-        db-file (get-in db [:db :db])]
+        db-file (get-in db [:db :subname])]
     (-> ctx
         (merge db)
         (update :to-be-cleaned conj db-file))))


Updated `virtual-node?` comment with more context.

--- src/vdom/core.cljs
+++ src/vdom/core.cljs
@@ -27,8 +27,12 @@
 (declare svg-tree)

 (defn virtual-node? [arg]
-  ;; use javascript notion of true/false,
-  ;; otherwise, this will return true for "" and cause issues
+  ;; Use javascript notion of true/false.
+  ;; `js/VDOM.isVirtualNode` doesn't just return true/false, but will
+  ;; return any js falsey argument passed in unchanged (eg. "").
+  ;; This causes `js/VDOM.isVirtualNode` to be false in js
+  ;; and true in cljs for any value that is falsey in js and
+  ;; true in cljs (eg. "", 0, -0, NaN, 0n).
   (js/Boolean (js/VDOM.isVirtualNode arg)))

 (defn html-tree [arg]


Restructuring some tests

Restructuring some tests

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

--- src/conexp/tests/fca/implications.clj
+++ src/conexp/tests/fca/implications.clj
@@ -181,21 +181,23 @@
     (is (sound-implication-set? ctx irr-subset))
     (is (complete-implication-set? ctx irr-subset))))

+(defvar stem-base-test-contexts [contexts/test-ctx-01,
+                                 contexts/test-ctx-04
+                                 contexts/test-ctx-07,
+                                 contexts/test-ctx-08])
+
 (deftest test-stem-base
   (is (= 1 (count (stem-base (one-context #{1 2 3 4 5})))))
-  (are [ctx] (let [sb (stem-base ctx)]
-               (is (minimal-implication-set? sb))
-               (is (sound-implication-set? ctx sb))
-               (is (complete-implication-set? ctx sb))
-               (is (let [premises (map premise sb)]
-                     (forall [X premises]
-                       (forall [Y premises]
-                         (=> (proper-subset? Y X)
-                             (proper-subset? (adprime ctx Y) X)))))))
-    contexts/test-ctx-01,
-    contexts/test-ctx-04
-    contexts/test-ctx-07,
-    contexts/test-ctx-08))
+  (doseq [ctx stem-base-test-contexts]
+    (let [sb (stem-base ctx)]
+      (is (minimal-implication-set? sb))
+      (is (sound-implication-set? ctx sb))
+      (is (complete-implication-set? ctx sb))
+      (is (let [premises (map premise sb)]
+            (forall [X premises]
+              (forall [Y premises]
+                (=> (proper-subset? Y X)
+                    (proper-subset? (adprime ctx Y) X)))))))))

 (deftest test-stem-base-with-background-knowledge
   ;; make sure implications with empty premise are handled correctly
@@ -212,10 +214,7 @@
              (impl 1 2 4 ==> 0 3)}))))

 (deftest test-stem-base-with-minimal-support-constraints
-  (with-testing-data [ctx [contexts/test-ctx-01,
-                           contexts/test-ctx-04
-                           contexts/test-ctx-07,
-                           contexts/test-ctx-08]
+  (with-testing-data [ctx stem-base-test-contexts
                       mis [0 1/5 1/3 1/2 4/5 1]]
     (= (set (filter #(<= mis (support % ctx))
                     (canonical-base ctx)))
@@ -242,9 +241,9 @@
                            contexts/test-ctx-04,
                            contexts/test-ctx-07,
                            contexts/test-ctx-08]]
-    (is (forall [P (subsets (attributes ctx))]
-          (<=> (proper-premise? ctx P)
-               (not (empty? (proper-conclusion ctx P))))))))
+    (forall [P (subsets (attributes ctx))]
+      (<=> (proper-premise? ctx P)
+           (not (empty? (proper-conclusion ctx P)))))))

 (deftest test-proper-premises-for-attributes
   (with-testing-data [ctx (random-contexts 10 20),
@@ -282,18 +281,12 @@
      #{(make-implication #{1} #{2 3 4})}))

 (deftest test-canonical-base-from-clop
-  (are [ctx] (and (= (canonical-base ctx)
-                     (canonical-base-from-clop (attributes ctx) #(adprime ctx %))))
-    contexts/test-ctx-01,
-    contexts/test-ctx-04
-    contexts/test-ctx-07,
-    contexts/test-ctx-08))
+  (with-testing-data [ctx stem-base-test-contexts]
+    (and (= (canonical-base ctx)
+            (canonical-base-from-clop (attributes ctx) #(adprime ctx %))))))

 (deftest test-intersect-implicational-theories
-  (with-testing-data [ctx [contexts/test-ctx-01
-                           contexts/test-ctx-04
-                           contexts/test-ctx-07
-                           contexts/test-ctx-08]
+  (with-testing-data [ctx stem-base-test-contexts,
                       n   (range 1 (count (objects ctx)))]
     (= (canonical-base ctx)
        (apply intersect-implicational-theories (attributes ctx)


update chat height when it gets multiple lines of text

--- src-cljs/frontend/components/chat.cljs
+++ src-cljs/frontend/components/chat.cljs
@@ -95,16 +95,17 @@
 (defn input [app owner]
   (reify
     om/IDisplayName (display-name [_] "Chat Input")
-    om/IInitState (init-state [_] {:chat-body (atom "")})
+    om/IInitState (init-state [_] {:chat-body (atom "")
+                                   :chat-height 64})
     om/IRenderState
-    (render-state [_ {:keys [chat-body]}]
+    (render-state [_ {:keys [chat-body chat-height]}]
       (let [{:keys [cast!]} (om/get-shared owner)
             chat-opened? (get-in app state/chat-opened-path)
             chat-submit-learned? (get-in app state/chat-submit-learned-path)
             submit-chat (fn [e]
                           (cast! :chat-submitted {:chat-body @(om/get-state owner :chat-body)})
                           (reset! (om/get-state owner :chat-body) "")
-                          (om/refresh! owner)
+                          (om/set-state! owner :chat-height 64)
                           (utils/stop-event e))]
         (html
           [:form.chat-box {:on-submit submit-chat
@@ -119,11 +120,14 @@
                                   :disabled (if (or (not chat-opened?)
                                                     (:show-landing? app)) true false)
                                   :id "chat-input"
-                                  :style {:height "64px"}
+                                  :style {:height chat-height}
                                   :required true
                                   :value @(om/get-state owner :chat-body)
-                                  :on-change #(reset! (om/get-state owner :chat-body)
-                                                      (.. % -target -value))}]
+                                  :on-change #(let [node (.-target %)]
+                                                (reset! (om/get-state owner :chat-body)
+                                                        (.-value node))
+                                                (when (not= (.-scrollHeight node) (.-clientHeight node))
+                                                  (om/set-state! owner :chat-height (max 64 (.-scrollHeight node)))))}]
            (if chat-submit-learned?
              [:div.chat-placeholder {:data-before "Chat."}]
              [:div.chat-teach-enter {:data-step-1 "Click here."


checkpoint

checkpoint

--- src-cljs/app/main.cljs
+++ src-cljs/app/main.cljs
@@ -2,14 +2,13 @@
   (:require-macros [hiccups.core :as hiccups])
   (:require
     [hiccups.runtime :as hiccupsrt])
-  (:use [jayq.core :only [$ document-ready html on attr]]))
+  (:use [jayq.core :only [$ document-ready html on attr prop text]]))

 ;;------------------------------------------------------------------------------
 ;; Atoms
 ;;------------------------------------------------------------------------------

-(def snapshot-list (atom nil))
-(def snapshot-index (atom nil)) ; can this be derived from current time, quickly?
+(def snapshots (atom nil))
 (def selected-time (atom nil))
 (def url-update-timout (atom nil)) ; This probably doesn't need to be atom, maybe be clojure feature that handles this

@@ -71,15 +70,28 @@
 (defn set-minutes! [new-mins]
   (swap! selected-time doto (.setMinutes new-mins)))

-(defn sync-time-with-snapshot! []
-  (swap! selected-time #(js/Date. (:time @snapshot-index))))
+(defn use-index-time! [index]
+  (swap! selected-time #(-> (@snapshot-list index) :time Date.)))

 ;;------------------------------------------------------------------------------
 ;; Watchers
 ;;------------------------------------------------------------------------------

-(defn on-snapshot-index-change [_ _ _ new-index]
-  (let [snapshot (@snapshot-list new-index)
+(defn )
+
+; TODO: Find closest index
+(defn on-selected-time-change [_ _ _ new-time]
+  (let [hour (.getHours new-time)
+        meridian (if (> 11 hour) "PM" "AM")
+        hour (if (> 12 hour) (- hour 12) hour)]
+    (val ($ "#hour") (pad hour))
+    (val ($ "#minute") (pad (.getMinutes new-time)))
+    (val ($ "#meridian") meridian)
+    (.datepicker ($ "#datepicker") "update" new-time))
+    )
+; CONTINUE HERE - REWORKING snapshots, selected-time atom
+
+  (let [snapshot (@snapshots new-index)
         time (Date. (:time snapshot))
         image (:image snapshot)
         time-display (str (.toDateString time) " " (.toLocaleTimeString time))]
@@ -88,76 +100,67 @@
     (prop ($ "#earlier") "disabled" (= (inc new-index) (count @snapshot-list)))
     (prop ($ "#later") "disabled" (zero? new-index))))

-(add-watch snapshot-index :_ on-snapshot-index-change)
-
-(defn on-selected-time-change [_ _ _ new-time]
-  (let [hour (.getHours new-time)
-        meridian (if (> 11 hour) "PM" "AM")
-        hour (if (> 12 hour) (- hour 12) hour)]
-    (val ($ "#hour") (pad hour))
-    (val ($ "#minute") (pad (.getMinutes new-time)))
-    (val ($ "#meridian") meridian)
-    (.datepicker ($ "#datepicker") "update" new-time)))
-
 (add-watch timestamp :_ on-selected-time-change)

 ;;------------------------------------------------------------------------------
 ;; Events
 ;;------------------------------------------------------------------------------

-(defn on-popstate! [])
-
-(defn on-datetime-change! []
-  ); todo
-
-(defn on-keydown! [e]
+(defn on-popstate [e]
+  (if (.-state e)
+    (swap! selected-time #(.-time e))))
+
+(defn on-datetime-change []
+  (let [date (.datepicker ($ "#datepicker") "getDate")
+        new-time (doto date
+                    (.setMinutes (.getMinutes @selected-time))
+                    (.setHours (.getHours @selected-time)))]
+    (swap! selected-time #(new-time))))
+
+(defn on-keydown [e]
   (let [key (.-which e)]
     (cond
-      (= key 37) (click-earlier!)
-      (= key 39) (click-later!))))
-
-(defn click-toggle-meridian! []
+      (= key 37) (click-earlier)
+      (= key 39) (click-later))))
+
+(defn click-toggle-meridian []
   (let [hours (+ (get-hours) 12)
         hours (if (>= 24 ) (- 24 hours) hours)]
     (set-hours! hours)))

-(defn click-decrement-hour! []
+(defn click-decrement-hour []
   (set-hours! (dec (get-hours))))

-(defn click-increment-hour! []
+(defn click-increment-hour []
   (set-hours! (inc (get-hours))))

-(defn click-decrement-Minute! []
+(defn click-decrement-Minute []
   (set-minutes! (dec (get-minutes))))

-(defn click-increment-minute! []
+(defn click-increment-minute []
   (set-minutes! (inc (get-minutes)))))

-(defn click-later! []
+(defn click-later []
   (if (pos? @snapshot-index)
-    (do
-      (swap! snapshot-index dec)
-      (sync-time-with-snapshot!))))
-
-(defn click-earlier! []
-  (if (>= @snapshot-index (count @snapshot-list))
-    (do
-      (swap! snapshot-index inc)
-      (sync-time-with-snapshot!))))
+    (use-index-time! (dec @snapshot-index))))
+
+(defn click-earlier []
+  (if (>= @snapshot-index (count @snapshot-list)
+    (use-index-time! (inc @snapshot-index)))))

 (defn add-events []
-  (aset js/window "onpopstate" on-popstate!)
-  (on ($ "datepicker") "changeDate" on-datetime-change!)
-  (on ($ js/document) "keydown" on-keydown!)
+  (aset js/window "onpopstate" on-popstate)
+  (on ($ "datepicker") "changeDate" on-datetime-change)
+  (on ($ js/document) "keydown" on-keydown)

   (-> ($ "body")
-    (on "click" ".toggle-meridian" click-toggle-meridian!)
-    (on "click" ".decrement-hour" click-decremen-hour!)
-    (on "click" ".increment-hour" click-increment-hour!)
-    (on "click" ".decrement-minute" click-decrement-Minute!)
-    (on "click" ".increment-minute" click-increment-minute!)
-    (on "click" "#later" click-later!)
-    (on "click" "#earlier" click-earlier!)))
+    (on "click" ".toggle-meridian" click-toggle-meridian)
+    (on "click" ".decrement-hour" click-decremen-hour)
+    (on "click" ".increment-hour" click-increment-hour)
+    (on "click" ".decrement-minute" click-decrement-Minute)
+    (on "click" ".increment-minute" click-increment-minute)
+    (on "click" "#later" click-later)
+    (on "click" "#earlier" click-earlier)))

 ;;------------------------------------------------------------------------------
 ;; App Init
@@ -172,7 +175,7 @@
         "endDate" end-date))))

 (defn init-timepicker []
-  )
+  (html ($ "timepickerContainer") (build-timepicker)))

 (defn init-snapshot-list []
   (swap! snapshot-list (fn []