seems to be working

seems to be working

--- src/bracketolojy/tournament.clj
+++ src/bracketolojy/tournament.clj
@@ -116,19 +116,23 @@
 (defn update-matchup [pick-pts-fn upset-pts-fn node]
   (let [round (get-in node [:data :round])
         pick-pts (pick-pts-fn round)
-        upset-pts (upset-pts-fn round)]
-    (->> (combo/cartesian-product (get-in node [:upper :data :teams]) (get-in node [:lower :data :teams])) ;all head to head games
-         (map (partial apply weighted-pairing-log5))        ;calculate win % per game
-         (mapcat (partial apply weighted-pairing-pts pick-pts upset-pts)) ;calculate expected pts per game
-         (reduce                                            ;aggregate game results together
-           #(let [name (:name %2)]
-             (if (contains? %1 name)
-               (-> (update-in %1 [name :weight] + (:weight %2))
-                   (update-in [name :avg-pts] + (:avg-pts %2)))
-               (assoc %1 name %2)))
-           {})
-         vals                                               ;get the aggregation
-         (assoc-in node [:data :teams]))))
+        upset-pts (upset-pts-fn round)
+        upper (get-in node [:upper :data :teams])
+        lower (get-in node [:lower :data :teams])]
+    (if (and lower upper)
+      (->> (combo/cartesian-product upper lower)
+           (map (partial apply weighted-pairing-log5))      ;calculate win % per game
+           (mapcat (partial apply weighted-pairing-pts pick-pts upset-pts)) ;calculate expected pts per game
+           (reduce                                          ;aggregate game results together
+             #(let [name (:name %2)]
+               (if (contains? %1 name)
+                 (-> (update-in %1 [name :weight] + (:weight %2))
+                     (update-in [name :avg-pts] + (:avg-pts %2)))
+                 (assoc %1 name %2)))
+             {})
+           vals                                             ;get the aggregation
+           (assoc-in node [:data :teams]))
+      node)))

 (defn compute-matchup [pick-pts-fn upset-pts-fn loc]
   (if (zip/end? loc)
@@ -144,18 +148,8 @@
          children
          make-node)
        bzip/post-order-first
-       (compute-matchup pick-pts-fn upset-pts-fn)))
-
-(defn tournament-probabilities
-  "Computes the probability of the various outcomes of a tournament.  Calculates the first round, then
-  uses the results from that to calculate the second round, ad infinitum until all rounds are calculated.
-  The first argument is an associative structure that gives the points per a correct pick for each round.
-  The second argument is an associative structure that gives the points per an upset pick for each round.
-  The third and final argument is the tournament bracket."
-  [pick-scoring upset-scoring tournament-bracket]
-  (walk/postwalk
-    (partial compute-matchup pick-scoring upset-scoring)
-    tournament-bracket))
+       (compute-matchup pick-pts-fn upset-pts-fn)
+       zip/root))

 (defn- update-child-expected-value
   "Update the expected value of each team in the field using parent-team-map.  The expected value for each team in the
@@ -213,7 +207,4 @@
        (#(let [tree %]
           (round-info (max-round tree) tree)))
        (matchup-info pick-scoring upset-scoring)
-       (tournament-probabilities
-         pick-scoring
-         upset-scoring)
        compute-expected-value))


Remove unnecessary pad between composer and body messages

--- src/braid/ui/styles/thread.cljs
+++ src/braid/ui/styles/thread.cljs
@@ -133,7 +133,6 @@
    {:flex-shrink 0
     :paddgin-bottom pad
     :padding-left (m/+ pad (rem 2))
-    :padding-top pad
     :padding-right pad
     :margin-bottom pad}


make pom a separate task

make pom a separate task

--- src/cake/tasks/dependencies.clj
+++ src/cake/tasks/dependencies.clj
@@ -125,16 +125,19 @@
     (ant Delete {:dir "lib"})
     (ant Move {:file "build/lib" :tofile "lib" :verbose true}))
   (invoke clean {})
-  (make-pom)
   (bake-restart))

 (defn stale-deps? [deps-str deps-file]
   (or (not (.exists deps-file)) (not= deps-str (slurp deps-file))))

-(deftask deps "Fetch dependencies and create pom.xml. Use 'cake deps force' to refetch."
+(deftask pom "Generate pom.xml from project.clj."
+  (make-pom))
+
+(deftask deps #{pom}
+  "Fetch dependencies and dev-dependencies. Use 'cake deps force' to refetch."
   (let [deps-str  (prn-str (into (sorted-map) (select-keys *project* [:dependencies :dev-dependencies])))
         deps-file (file "lib" "deps.clj")]
-    (if (or (stale-deps? deps-str deps-file) (not (.exists (file "pom.xml"))) (= ["force"] (:deps *opts*)))
+    (if (or (stale-deps? deps-str deps-file) (= ["force"] (:deps *opts*)))
       (do (fetch-deps)
           (spit deps-file deps-str))
       (when (= ["force"] (:compile *opts*))


logging on stop function of component type improved

--- src/clj/hellhound/component.clj
+++ src/clj/hellhound/component.clj
@@ -67,8 +67,14 @@
   (stop! [component]
     (let [stop-fn (::stop-fn component)]
       (if (started? component)
-        (assoc (stop-fn component) ::started? false)
-        component)))
+        (do
+          (log/debug (format "Stopping '%s' component ..."
+                             (get-name component)))
+          (assoc (stop-fn component) ::started? false))
+        (do
+          (log/debug (format "Skipping '%s' already stopped..."
+                             (get-name component)))
+          component))))

   (started? [component]
     (or (::started? component) false))


Make viewport cells query even faster

Make viewport cells query even faster

--- src/cljc/robinson/viewport.cljc
+++ src/cljc/robinson/viewport.cljc
@@ -354,21 +354,25 @@
             ;_ (println "r-y" r-y)
             ;_ (println "r-yrest" r-yrest)
             ;_ (println "r-xrest" r-xrest)
-            conj-cells (fn [cells place min-x min-y max-x max-y x-range y-range]
-                         (reduce (fn [cells [line sy]]
-                                   (reduce (fn [cells [cell sx]]
-                                             (conj! cells
-                                                    [cell sx sy (+ sx v-x) (+ sy v-y)]))
-                                           cells
-                                           (map vector (subvec line min-x max-x)
-                                                       x-range)))
-                                 cells
-                                 (map vector
-                                      (try
-                                        (subvec place min-y max-y)
-                                        (catch Exception e
-                                          (log/error "place count" (count place) "min-y" min-y "max-y" max-y)))
-                                      y-range)))
+            conj-cells (fn [result place min-x min-y max-x max-y x-range y-range]
+                         (let [lines (mapv vector (subvec place min-y max-y) y-range)]
+                           (loop [result result
+                                  linesy (first lines)
+                                  rest-lines (next lines)]
+                             (if-let [[line sy] linesy]
+                               (recur
+                                 (let [cells (mapv vector (subvec line min-x max-x) x-range)]
+                                   (loop [result result
+                                          cellsx (first cells)
+                                          rest-cells (next cells)]
+                                     (if-let [[cell sx] cellsx]
+                                       (recur (conj! result [cell sx sy (+ sx v-x) (+ sy v-y)])
+                                              (first rest-cells)
+                                              (next rest-cells))
+                                       result)))
+                                 (first rest-lines)
+                                 (next rest-lines))
+                               result))))
             cells (-> (transient [])
                         (conj-cells ul-cells start-x start-y v-width v-height r-x     r-y)
                         (conj-cells ur-cells 0       start-y start-x v-height r-xrest r-y)


Handling collision with walls and tail

Handling collision with walls and tail

--- src/cljs/battlesnake/snake.cljs
+++ src/cljs/battlesnake/snake.cljs
@@ -6,6 +6,12 @@
            38 [0 -1] ; up
            39 [1 0]  ; right
            40 [0 1]}); down
+
+(def width 500)
+(def height 500)
+(def block-size 10)
+(def grid-width (/ width block-size))
+(def grid-height (/ height block-size))

 (def edibles (atom []))

@@ -38,15 +44,33 @@
 (defn- add-points [& points]
   (vec (apply map + points)))

+(defn- crash? [loc {body :body}]
+  (js/console.log (str "loc: " loc))
+  (js/console.log (str "body" body))
+  (js/console.log (str "y < height? " (last loc) " < " grid-height))
+  (or
+   (some #(= % loc) body)
+   (let [[x y] loc]
+     (or
+      (< x 0)
+      (>= x grid-width)
+      (< y 0)
+      (>= y grid-height)))))
+
 (defn- move-snake []
   (let [h (first (:body @snake))
         dir (:dir @snake)
         nh (add-points h dir)]
-    (if-let [e (seq (filter #(= nh (:location %)) @edibles))]
+    (if (crash? nh @snake)
       (do
-        (swap! edibles #(filter (fn [x] (not= nh (:location x))) @edibles))
-        (swap! snake assoc :body (cons nh (:body @snake))))
-      (swap! snake assoc :body (cons nh (butlast (:body @snake)))))))
+        (js/alert "Game over!")
+        (reset! snake (create-snake))
+        (reset! edibles []))
+      (if-let [e (seq (filter #(= nh (:location %)) @edibles))]
+        (do
+          (swap! edibles #(filter (fn [x] (not= nh (:location x))) @edibles))
+          (swap! snake assoc :body (cons nh (:body @snake))))
+        (swap! snake assoc :body (cons nh (butlast (:body @snake))))))))

 (defn handle-input [e]
   (when-let [dir (dirs (js/parseInt (aget e "keyCode")))]


Stream now shows a sequence of items as the arrive

--- src/cljs/hacker_agent/core.cljs
+++ src/cljs/hacker_agent/core.cljs
@@ -20,19 +20,21 @@
               (base/stories-binder
                (base/item-cache-fn app-state [:cache]))))

+(defn stream-binder [f]
+  (fn [data path msg]
+    (let [[event key val] msg
+          child-path (conj path key)
+          add-change-fn #(do
+                           (f val)
+                           (swap! data assoc-in child-path val))]
+      (case event
+        :value (add-change-fn)
+        (.log js/console (clj->js [event key val]))))))
+
 (defonce new-synced
   (base/bind! app-state [:stream] base/max-item
-              (fn [data path msg]
-                (let [[event key val] msg
-                      child-path (conj path key)
-                      add-change-fn #(do
-                                       (swap! data assoc-in child-path val)
-                                       (base/bind! data (conj path :item)
-                                                   (base/id->fbref val)
-                                                   base/story-binder))]
-                  (case event
-                    :value (add-change-fn)
-                    (.log js/console (clj->js [event key val])))))))
+              (stream-binder
+               (base/item-cache-fn app-state [:stream :items]))))

 ;; ------------------------
 ;; Components
@@ -183,6 +185,17 @@
       (r/wrap (get @items entry)
               swap! items assoc entry)])])

+(defn stream [items]
+  [:ul
+   (for [[id entry] (reverse @items)]
+     ^{:key id}
+     (when-not (:deleted entry)
+       [:li
+        (case (:type entry)
+          "story" [story (r/wrap entry swap! assoc items id)]
+          "comment" [comment (r/wrap entry swap! assoc items id) true]
+          [:p "Cannot render item"])]))])
+
 ;; -------------------------
 ;; Views
 (defmulti page #(:render-view (deref %)))
@@ -205,11 +218,8 @@
       [:p "Cannot render item"])))

 (defmethod page :stream [state]
-  (when-let [entry (get-in @state [:stream :item])]
-    (case (:type entry)
-      "story" [story (r/wrap entry swap! state assoc :current-item)]
-      "comment" [comment (r/wrap entry swap! state assoc :current-item)]
-      [:p "Cannot render item"])))
+  (when-let [entries (get-in @state [:stream :items])]
+    [stream (r/wrap entries swap! assoc-in state [:stream :items])]))

 (defn main-page [state]
   [:div.main


subscription to messages working

subscription to messages working

--- src/cljs/minimal_chat/core.cljs
+++ src/cljs/minimal_chat/core.cljs
@@ -29,20 +29,6 @@
    :messages []
    :username (str "Guest" (rand-int 100))})

-(defonce fb-messages (atom nil))
-(defonce messages (reagent/atom []))
-
-;; -- Firebase helpers ------
-
-(defn bind-to-ratom [ratom ref & [korks]]
-  (let [ch (ma/listen-to< ref korks :value)]
-    (go-loop [[key val] (<! ch)]
-      (reset! ratom val)
-      (recur (<! ch)))))
-
-(defn firebase-swap! [fb-ref f & args]
-  (apply m/swap! fb-ref f args))
-
 ;; -- Helpers ---------------

 (defn- random-four-characters []
@@ -50,11 +36,6 @@
        (take 4)
        (str/join)
        (str/upper-case)))
-
-(defn join-room [id]
-  (let [fb-item (m/get-in fb-root [(str/lower-case id) :messages])]
-    (reset! fb-messages fb-item)
-    (bind-to-ratom messages fb-item)))

 ;; -- Subscriptions ---------

@@ -86,9 +67,20 @@
     (assoc db :username value)))

 (register-handler
+  :room-update
+  (fn [db [_ v]]
+    (assoc db :messages v)))
+
+(register-handler
   :join-chat-room
   (fn [db [_ room-id]]
-    (join-room room-id)
+    ;; listen to chat room on firebase
+    (let [id          (-> room-id (str/lower-case) (keyword))
+          fb-messages (m/get-in fb-root [id :messages])]
+      (m/listen-to fb-messages :value
+                     (fn [[_ v]] (println v) (dispatch [:room-update v]))))
+
+    ;; update current room id
     (assoc db :chat-room room-id)))

 (register-handler
@@ -123,11 +115,12 @@
      [:button {:type "submit"} "Send"]]))

 (defn show-messages []
-  [:div#messages
-   (for [[[k v] index] (map vector (take-last 30 @messages) (range))]
-     ^{:key (str "message-" index)}
-     (let [{:keys [username message]} v]
-       [:div [:span.username username] ": " [:span.message message]]))])
+  (let [messages (subscribe [:chat-room-messages])]
+    [:div#messages
+     (for [[[k v] index] (map vector @messages (range))]
+       (let [{:keys [username message]} v]
+         ^{:key (str "message-" index)}
+         [:div [:span.username username] ": " [:span.message message]]))]))

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


add link home

add link home

--- frontend/components/common.cljs
+++ frontend/components/common.cljs
@@ -169,7 +169,8 @@
 (defn nav [owner]
   (html
    [:nav.outer-nav
-    [:a.logo-circleci {:on-click #(raise! owner [:home-scroll-logo-clicked])}
+    [:a.logo-circleci {:on-click #(raise! owner [:home-scroll-logo-clicked])
+                       :href "/home"}
      [:figure (circle-logo)]]
     [:a {:href "/about"} "About"]
     [:a {:href "/pricing"} "Pricing"]


Added typography header to style.cljs

Added typography header to style.cljs

--- src/css-guide/styles/style.cljs
+++ src/css-guide/styles/style.cljs
@@ -471,6 +471,11 @@
   ```")

 ;; Typography Examples
+
+(def typography-header
+  "# Typography
+
+  ##### Source Sans Pro is the font family that Stylekit uses by default")

 (defview typography-font-scale
   "#### Font Scale"
@@ -669,6 +674,7 @@
                          :examples [syntax]}
                         {:id       :typography
                          :title    "Typography"
+                         :documentation typography-header
                          :examples [typography-font-scale typography-no-bullet typography-no-bullets
                                     typography-ellipsis typography-break-word  docs-typography-customize]}
                         {:id       :visibility


disable center piece

disable center piece

--- src/chessground/drag.cljs
+++ src/chessground/drag.cljs
@@ -53,7 +53,7 @@
     piece
     :onMount (fn [node]
                (-> (new js/Draggabilly node (clj->js {:distance 10}))
-                   (.on "dragStart" (fn [_ _ pointer] (center-piece pointer)))
+                   ; (.on "dragStart" (fn [_ _ pointer] (center-piece pointer)))
                    (.on "dragStart" #(push! (:move-start channels) key))
                    (.on "dragStart" (fn [_ _ pointer] (highlight-square (jq/parent ($ (get-target pointer))))))
                    (.on "dragMove" on-move)


different markup location

different markup location

--- src/clj/slice/handler.clj
+++ src/clj/slice/handler.clj
@@ -15,11 +15,12 @@
   (GET "/state" [] (slurp "state.edn"))
   (POST "/state" {:keys [body params]}
         (let [new-state (-> body slurp edn/read-string)]
-          (spit "document.html"
+          (spit "resources/public/document.html"
                 (hiccup/html5
+                 (hiccup/include-css "default.css")
                  (hiccup/include-css "document.css")
                  (:html new-state)))
-          (spit "document.css" (:css new-state))
+          (spit "resources/public/document.css" (:css new-state))
           (spit "state.edn" (dissoc new-state :html :css))
           "saved"))


Extract automaton-specific render/event code to a separate protocol.

--- src/cljs/beatha/core.cljs
+++ src/cljs/beatha/core.cljs
@@ -9,8 +9,7 @@

 (def app-state (atom {:grid {:width 10 :height 10 :cells {}}
                       :display {:width 600 :height 600}
-                      :started false
-                      :result :none}))
+                      :started false}))

 (defn cell-view
@@ -122,129 +121,165 @@
           "Reset display"))))))

+(defprotocol CellularAutomatonAppCustomization
+  (automaton-output-handler [this data owner o]
+    "Handles messages posted by the cellular automaton.")
+  (automaton-output-view [this]
+    "Generates Om component that renders any changes produced by
+    the handler.")
+  (automaton-output-reset [this data owner]
+    "Resets changes produced by the handler."))
+
 (defn gen-app-view
-  [automaton-spec]
-  (fn [data owner]
-    (reify
-      om/IInitState
-      (init-state [_]
-        {:change-grid-dimensions (chan)
-         :change-display-dimensions (chan)
-         :cell-state-changed (chan)
-         :started (chan)
-         :output-info-channel (chan)})
-      om/IWillMount
-      (will-mount [_]
-        (let [grid-c (om/get-state owner :change-grid-dimensions)
-              display-c (om/get-state owner :change-display-dimensions)
-              cell-state-c (om/get-state owner :cell-state-changed)
-              started-c (om/get-state owner :started)
-              output-info-c (om/get-state owner :output-info-channel)]
-          (go (while true
-                (alt!
-                  grid-c
-                  ([[width height]]
-                     (om/transact! data (fn [d] (assoc d :result :none)))
-                     (om/transact!
-                      data :grid
-                      (fn [grid]
-                        (assoc grid :width width :height height :cells {}))))
-
-                  display-c
-                  ([[width height]]
-                     (om/transact!
-                      data :display
-                      (fn [display]
-                        (assoc display :width width :height height))))
-
-                  cell-state-c
-                  ([[x y]]
-                     (om/transact!
-                      data [:grid :cells]
-                      (fn [grid]
-                        (let [cell (get grid [x y]
-                                        (a/default-cell automaton-spec))
-                              state (:state cell)
-                              cell (assoc cell
-                                     :state
-                                     (a/next-initial-state automaton-spec
-                                                           state))]
-                          (assoc grid [x y] cell)))))
-
-                  started-c
-                  ([started]
-                     (om/update! data :started started)
-                     (if started
-                       (om/set-state!
-                        owner :update-loop-id
-                        (js/setInterval
-                         (fn []
-                           (om/transact! data :grid
-                                         (partial a/next-grid automaton-spec))
-                           (a/fill-output-info-channel
-                            automaton-spec (:grid @data) output-info-c))
-                         (or (om/get-state owner :animation-step) 1000)))
-                       (when-let [id (om/get-state owner :update-loop-id)]
-                         (js/clearTimeout id))))
-
-                  output-info-c
-                  ([{:keys [s f]}]
-                     (when (or (> s 0) (> f 0))
-                       (om/transact!
-                        data
-                        (fn [d] (assoc d :result
-                                      (if (> s 0) :success :failure))))
-                       (put! started-c false))))))))
-      om/IRenderState
-      (render-state [_ state]
-        (dom/div
-         #js {:className "container-liquid"}
-         (dom/div
-          #js {:className "row"}
-          (dom/div
-           #js {:className "col-sm-2"}
-           (let [started (:started data)]
+  ([automaton-spec]
+     (gen-app-view automaton-spec
+                   (reify
+                     CellularAutomatonAppCustomization
+                     (automaton-output-handler [_ _ _ _])
+                     (automaton-output-view [_]
+                       (fn [data owner]
+                         (reify om/IRender (render [_] (dom/span nil "")))))
+                     (automaton-output-reset [_ _ _]))))
+  ([automaton-spec customization]
+     (fn [data owner]
+       (reify
+         om/IInitState
+         (init-state [_]
+           {:change-grid-dimensions (chan)
+            :change-display-dimensions (chan)
+            :cell-state-changed (chan)
+            :started (chan)
+            :output-info-channel (chan)})
+         om/IWillMount
+         (will-mount [_]
+           (let [grid-c (om/get-state owner :change-grid-dimensions)
+                 display-c (om/get-state owner :change-display-dimensions)
+                 cell-state-c (om/get-state owner :cell-state-changed)
+                 started-c (om/get-state owner :started)
+                 output-info-c (om/get-state owner :output-info-channel)]
+             (go (while true
+                   (alt!
+                     grid-c
+                     ([[width height]]
+                        (automaton-output-reset customization data owner)
+                        (om/transact!
+                         data :grid
+                         (fn [grid]
+                           (assoc grid
+                             :width width :height height :cells {}))))
+
+                     display-c
+                     ([[width height]]
+                        (om/transact!
+                         data :display
+                         (fn [display]
+                           (assoc display :width width :height height))))
+
+                     cell-state-c
+                     ([[x y]]
+                        (om/transact!
+                         data [:grid :cells]
+                         (fn [grid]
+                           (let [cell (get grid [x y]
+                                           (a/default-cell automaton-spec))
+                                 state (:state cell)
+                                 cell (assoc cell
+                                        :state
+                                        (a/next-initial-state automaton-spec
+                                                              state))]
+                             (assoc grid [x y] cell)))))
+
+                     started-c
+                     ([started]
+                        (om/update! data :started started)
+                        (if started
+                          (om/set-state!
+                           owner :update-loop-id
+                           (js/setInterval
+                            (fn []
+                              (om/transact!
+                               data :grid
+                               (partial a/next-grid automaton-spec))
+                              (a/fill-output-info-channel
+                               automaton-spec (:grid @data) output-info-c))
+                            (or (om/get-state owner :animation-step) 1000)))
+                          (when-let [id (om/get-state owner :update-loop-id)]
+                            (js/clearTimeout id))))
+
+                     output-info-c
+                     ([o] (automaton-output-handler
+                           customization data owner o)))))))
+         om/IRenderState
+         (render-state [_ state]
+           (dom/div
+            #js {:className "container-liquid"}
+            (dom/div
+             #js {:className "row"}
              (dom/div
-              #js {:className "row"}
-              (dom/button
-               #js {:type "button"
-                    :className "btn btn-primary btn-lg btn-block"
-                    :onClick #(put! (:started state) (not started))}
-               (if-not started "Start" "Stop"))))
-           (dom/div
-            #js {:className "row"}
-            (om/build grid-config-view
-                      data
-                      {:init-state
-                       (merge state
-                              {:width (get-in data [:grid :width])
-                               :height (get-in data [:grid :height])})}))
-           (dom/div
-            #js {:className "row"}
-            (om/build display-config-view
-                      data
-                      {:init-state
-                       (merge state
-                              {:width (get-in data [:display :width])
-                               :height (get-in data [:display :height])})})))
-          (dom/div #js {:className "col-sm-10"}
-                   (when (#{:success :failure} (:result data))
-                     (dom/div #js {:className "row"}
-                              (dom/label nil
-                                         "Result: "
-                                         (if (= :success (:result data))
-                                           "word is parsed"
-                                           "word is not parsed"))))
-                   (dom/div #js {:slassName "row"})
-                   (om/build grid-view
-                             data
-                             {:init-state
-                              (assoc state
-                                :default-cell
-                                (a/default-cell automaton-spec))}))))))))
-
-
-(om/root (gen-app-view a/unrestricted-language-parser)
-         app-state
-         {:target (. js/document (getElementById "app"))
-          :init-state {:animation-step 750}})
+              #js {:className "col-sm-2"}
+              (let [started (:started data)]
+                (dom/div
+                 #js {:className "row"}
+                 (dom/button
+                  #js {:type "button"
+                       :className "btn btn-primary btn-lg btn-block"
+                       :onClick #(put! (:started state) (not started))}
+                  (if-not started "Start" "Stop"))))
+              (dom/div
+               #js {:className "row"}
+               (om/build grid-config-view
+                         data
+                         {:init-state
+                          (merge state
+                                 {:width (get-in data [:grid :width])
+                                  :height (get-in data [:grid :height])})}))
+              (dom/div
+               #js {:className "row"}
+               (om/build display-config-view
+                         data
+                         {:init-state
+                          (assoc state
+                            :width (get-in data [:display :width])
+                            :height (get-in data [:display :height]))}))
+              (dom/div #js {:className "row"}
+                       (om/build (automaton-output-view customization) data)))
+             (dom/div #js {:className "col-sm-10"}
+                      (dom/div #js {:className "row"})
+                      (om/build grid-view
+                                data
+                                {:init-state
+                                 (assoc state
+                                   :default-cell
+                                   (a/default-cell automaton-spec))})))))))))
+
+
+(def unrestricted-language-parser-customization
+  (reify
+    CellularAutomatonAppCustomization
+    (automaton-output-handler [_ data owner {:keys [s f]}]
+      (when (or (> s 0) (> f 0))
+        (om/transact!
+         data (fn [d] (assoc d :result (if (> s 0) :success :failure))))
+        (put! (om/get-state owner :started) false)))
+    (automaton-output-view [_]
+      (fn [data _]
+        (reify
+          om/IRender
+          (render [_]
+            (dom/div #js {:className "row"
+                          :hidden (not (#{:success :failure} (:result data)))}
+                     (dom/h2 nil
+                             "Result: "
+                             (if (= :success (:result data))
+                               "word is parsed"
+                               "word is not parsed")))))))
+    (automaton-output-reset [_ data _]
+      (om/transact! data (fn [d] (assoc d :result :none))))))
+
+
+(om/root
+ (gen-app-view
+  a/unrestricted-language-parser unrestricted-language-parser-customization)
+ app-state
+ {:target (. js/document (getElementById "app"))
+  :init-state {:animation-step 750}})


Removed async stuff and use requestAnimationFrame

--- src/cljs/drawer/core.cljs
+++ src/cljs/drawer/core.cljs
@@ -21,8 +21,9 @@
           :active-tab "info-tab"
           :active-dropdown :none}
    :canvas {:width 0 :height 0
-            :view {:pos [0 0 0 0]
-                   :fov 250}}
+            :center [0 0]
+            :v-dist 0
+            :h-dist 0}
    :objects {}
    :pending-object {:name "" :object {}}})

@@ -37,7 +38,6 @@
   [state]
   (util/store-locally "state" state))

-
 (defn- init-watches
   "Initializers any state-atom watchers."
   [state]
@@ -45,16 +45,8 @@
              (let [canvas (.getElementById js/document "canvas")
                    context (.getContext canvas "2d")]
                (fn [_ _ _ new]
-                 (canvas/redraw-canvas new canvas context)))))
-
-(defn- app
-  "Update the state of the program
-  everytime it recieves a change
-  from one of the channels."
-  [state channels]
-  (go (while true
-        (swap! state
-               ((alts! channels :priority true) 0)))))
+                 (util/request-anim-frame
+                  #(canvas/redraw-canvas new canvas context))))))

 (defn- construct-actor
   "Contstructs an 'action-function'
@@ -67,32 +59,21 @@
       ([] (swap! state add-action))
       ([action] (swap! state (comp action add-action))))))

-(defn- construct-actor-async
-  "Constructs an 'action-function' for
-  given channel, that puts
-  (apply comp action add-fns)
-  on the channel, which then get's
-  applied to the state by 'app' asynchronously."
-  [channel & add-fns]
-  (let [add-action (apply comp add-fns)]
-    (fn
-      ([] (put! channel add-action))
-      ([action] (put! channel (comp action add-action))))))
-
 (defn ^:export init
   "Initializes the program."
   []
   (let [state (r/atom (fetch-state))
         cnvch (chan)
         usr-ac (construct-actor state)
-        cnv-ac (construct-actor-async cnvch canvas/get-canvas-update)]
-    (app state [cnvch])
+        cnv-ac (construct-actor state canvas/get-canvas-update)]
     (gui/init-gui state usr-ac)
     (init-watches state)
     (go (while true
           (<! (timeout fps))
           (cnv-ac)))
     (set! (.-onunload js/window) #(save-state @state))
-    (set! (.-onresize js/window) #(cnv-ac (canvas/get-canvas-info)))
-    (usr-ac api/addInitScenario))
-  ((.-onresize js/window)))
+    (set! (.-onresize js/window) #((cnv-ac canvas/set-canvas-info)
+                                   (go (<! (timeout 100))
+                                       (canvas/translate-canvas! (@state :canvas)))))
+    ((.-onresize js/window))
+    (usr-ac api/addInitScenario)))


Add entities map to state

Add entities map to state

--- src/cljs/gtfve/state.cljs
+++ src/cljs/gtfve/state.cljs
@@ -14,6 +14,7 @@
                         :last-query ""
                         :loading? false}}}
    :data {:stops-search-results []
+          :entitites {}
           :changes []
           :stops {}
           :stop-times []


Don't forget to disconnect old websockets

--- src/cljs/herder/core.cljs
+++ src/cljs/herder/core.cljs
@@ -72,6 +72,8 @@
         (js/console.log "something else" type)))))

 (defn ^:export mount-root []
+  (if (-> @channel-sockets nil? not)
+    (swap! channel-sockets component/stop))
   (reset! channel-sockets (new-channel-socket-client parse-ws "/chsk"))
   (swap! channel-sockets component/start)
   (.log js/console (pr-str @state))


Refactor courses db to use scraped edn format

--- src/cljs/kulive/core.cljs
+++ src/cljs/kulive/core.cljs
@@ -6,7 +6,7 @@
             [goog.events :as events]
             [goog.history.EventType :as EventType]
             [cljsjs.react :as react]
-            [clojure.string :as s])
+            [clojure.string :as string])
   (:require-macros [reagent.ratom  :refer [reaction]])
   (:import goog.History))

@@ -22,25 +22,33 @@
  (fn [db]
    (reaction (:courses @db))))

+#_[{:name "Beginner CSS" :number "CSS101" :time "Mon(2) Wed(2)"
+    :credits "3" :type "Elective" :prof "Prof. A"}
+   {:name "Intermediate CSS" :number "CSS201" :time "Tue(5) Thu(5)"
+    :credits "3" :type "Elective" :prof "Prof. B"}
+   {:name "Advanced Javascript" :number "JS406" :time "Mon(6) Wed(6)"
+    :credits "3" :type "Major" :prof "Prof. C"}
+   {:name "ClojureScript" :number "CLJS303" :time "Fri(1,2)"
+    :credits "3" :type "Major" :prof "Prof. D"}
+   {:name "Clojure" :number "CLJ505" :time "Tue(3,4) Thu(3,4)"
+    :credits "3" :type "Major" :prof "Prof. D"}
+   {:name "How to Train Your Dragon" :number "DR505" :prof "Prof. E"
+    :time "Tue(7) Thu(7)" :credits "3" :type "Elective"}]
+
 #_(def db
     (clojure.edn/read-string (slurp "resources/db/db2015-1R.edn")))
+
+(def dummy-data {"DISS352-00" {:kr {:professor "이지수", :r false, :number "DISS352-00", :name " 국제법특강I(영강)", :w false, :l true, :classification "전공선택 ", :credit-hours "3(  3)", :schedule ["화(1) 국제관322" "\n목(1) 국제관322"], :x true, :campus "안암", :href "http://infodepot.korea.ac.kr/lecture1/lecsubjectPlanView.jsp?year=2015&term=1R&grad_cd=0136&col_cd=3928&dept_cd=3931&cour_cd=DISS352&cour_cls=00&cour_nm=국제법특강I(영강)"}, :en {:professor nil, :schedule ["Tue(1) 138-322" "\nThu(1) 138-322"], :r false, :number "DISS352-00", :name "SPECIAL TOPICS IN INTERNATIONAL LAW I(English)", :w false, :l true, :classification "Major Elective", :credit-hours "3(  3)", :x true, :href "http://infodepot.korea.ac.kr/lecture1/lecsubjectPlanViewEng.jsp?year=2015&term=1R&grad_cd=0136&col_cd=3928&dept_cd=3931&cour_cd=DISS352&cour_cls=00&cour_nm=SPECIAL TOPICS IN INTERNATIONAL LAW I(English)"}},
+                 "EDBA231-02" {:kr {:professor "박철", :r true, :number "EDBA231-02", :name " 마케팅원론", :w false, :l true, :classification "전공필수 ", :credit-hours "3(  3)", :schedule ["월(9) 33-221" "\n목(1-2) 33-325"], :x true, :campus "세종", :href "http://infodepot.korea.ac.kr/lecture1/lecsubjectPlanView.jsp?year=2015&term=1R&grad_cd=0136&col_cd=0293&dept_cd=4633&cour_cd=EDBA231&cour_cls=02&cour_nm=마케팅원론"}, :en {:professor "Cheol Park", :r true, :number "EDBA231-02", :name "PRINCIPLES OF MARKETING", :w false, :l true, :classification "Major Required", :credit-hours "3(  3)", :schedule ["Mon(9) 33-221" "\nThu(1-2) 33-325"], :x true, :href "http://infodepot.korea.ac.kr/lecture1/lecsubjectPlanViewEng.jsp?year=2015&term=1R&grad_cd=0136&col_cd=0293&dept_cd=4633&cour_cd=EDBA231&cour_cls=02&cour_nm=PRINCIPLES OF MARKETING"}},
+                 "KFBT253-00" {:kr {:professor "김영준", :r true, :number "KFBT253-00", :name " 세포생물학", :w false, :l false, :classification "기본전공선택 ", :credit-hours "3(  3)", :schedule ["수(3-4) 7-217" "\n목(4) 9-615A"], :x false, :campus "세종", :href "http://infodepot.korea.ac.kr/lecture1/lecsubjectPlanView.jsp?year=2015&term=1R&grad_cd=0136&col_cd=4460&dept_cd=4554&cour_cd=KFBT253&cour_cls=00&cour_nm=세포생물학"}, :en {:professor "Young Jun Kim", :r true, :number "KFBT253-00", :name "CELL BIOLOGY", :w false, :l false, :classification "Basic Major", :credit-hours "3(  3)", :schedule ["Wed(3-4) 7-217" "\nThu(4) 9-615A"], :x false, :href "http://infodepot.korea.ac.kr/lecture1/lecsubjectPlanViewEng.jsp?year=2015&term=1R&grad_cd=0136&col_cd=4460&dept_cd=4554&cour_cd=KFBT253&cour_cls=00&cour_nm=CELL BIOLOGY"}},
+                 "BUSS207-03" {:kr {:professor "김우찬", :r false, :number "BUSS207-03", :name " 재무관리(영강)", :w false, :l true, :classification "전공필수 ", :credit-hours "3(  3)", :schedule ["화(1) 현차관B204" "\n목(1) 현차관B204"], :x false, :campus "안암", :href "http://infodepot.korea.ac.kr/lecture1/lecsubjectPlanView.jsp?year=2015&term=1R&grad_cd=0136&col_cd=0140&dept_cd=0142&cour_cd=BUSS207&cour_cls=03&cour_nm=재무관리(영강)"}, :en {:professor "Kim, Woochan", :r false, :number "BUSS207-03", :name "FINANCIAL MANAGEMENT(English)", :w false, :l true, :classification "Major Required", :credit-hours "3(  3)", :schedule ["Tue(1) 151-B204" "\nThu(1) 151-B204"], :x false, :href "http://infodepot.korea.ac.kr/lecture1/lecsubjectPlanViewEng.jsp?year=2015&term=1R&grad_cd=0136&col_cd=0140&dept_cd=0142&cour_cd=BUSS207&cour_cls=03&cour_nm=FINANCIAL MANAGEMENT(English)"}},
+                 "CHEM300-01" {:kr {:professor "이광렬", :r true, :number "CHEM300-01", :name " 전공심화연구I", :w false, :l false, :classification "전공선택 ", :credit-hours "3(  6)", :schedule [], :x true, :campus "안암", :href "http://infodepot.korea.ac.kr/lecture1/lecsubjectPlanView.jsp?year=2015&term=1R&grad_cd=0136&col_cd=0209&dept_cd=0213&cour_cd=CHEM300&cour_cls=01&cour_nm=전공심화연구I"}, :en {:professor "Kwangyeol Lee", :r true, :number "CHEM300-01", :name "UNDERGRADUATE ADVANCED RESEARCH I", :w false, :l false, :classification "Major Elective", :credit-hours "3(  6)", :schedule [], :x true, :href "http://infodepot.korea.ac.kr/lecture1/lecsubjectPlanViewEng.jsp?year=2015&term=1R&grad_cd=0136&col_cd=0209&dept_cd=0213&cour_cd=CHEM300&cour_cls=01&cour_nm=UNDERGRADUATE ADVANCED RESEARCH I"}}})

 (re-frame/register-handler
  :initialise-db
  (fn
    [_ _]
-   {:courses [{:name "Beginner CSS" :number "CSS101" :time "Mon(2) Wed(2)"
-               :credits "3" :type "Elective" :prof "Prof. A"}
-              {:name "Intermediate CSS" :number "CSS201" :time "Tue(5) Thu(5)"
-               :credits "3" :type "Elective" :prof "Prof. B"}
-              {:name "Advanced Javascript" :number "JS406" :time "Mon(6) Wed(6)"
-               :credits "3" :type "Major" :prof "Prof. C"}
-              {:name "ClojureScript" :number "CLJS303" :time "Fri(1,2)"
-               :credits "3" :type "Major" :prof "Prof. D"}
-              {:name "Clojure" :number "CLJ505" :time "Tue(3,4) Thu(3,4)"
-               :credits "3" :type "Major" :prof "Prof. D"}
-              {:name "How to Train Your Dragon" :number "DR505" :prof "Prof. E"
-               :time "Tue(7) Thu(7)" :credits "3" :type "Elective"}]
+   {:courses dummy-data
     :search-input ""}))

 (defn handle-search-input-entered
@@ -56,8 +64,8 @@
 (defn matches-query?
   [search-input course]
   (let [matches-input? (fn [key]
-                         (re-find (re-pattern (s/lower-case search-input))
-                                  (s/lower-case (key course))))]
+                         (re-find (re-pattern (string/lower-case search-input))
+                                  (string/lower-case (apply str (val course)))))]
     (if (= "" search-input)
       true
       (or (matches-input? :name)
@@ -74,24 +82,25 @@
     (fn []
       [:form {:style {:margin-bottom "1rem"}}
        [:div.row
-        [:div {:class "six columns"}
+        [:div {:class "five columns"}
          [:label {:for "search-courses"} "Course Search"]
          [:input.u-full-width
           {:id "search-courses"
            :type "search"
            :on-change #(re-frame/dispatch
                         [:search-input-entered (-> % .-target .-value)])
-           :placeholder "Course ID, Professor name, etc..."}]]]])))
+           :placeholder "Course ID, Title, Professor, etc..."}]]]])))

 (defn course-component
   "Individual course in search result list"
   [course]
-  [:li [:a (interpose ", " [(:name course)
-                            (:number course)
-                            (:prof course)
-                            (:time course)
-                            (:credits course)
-                            (:type course)])]])
+  [:li [:a (str
+            (get-in (val course) [:kr :name])
+            (get-in (val course) [:kr :number])
+            (get-in (val course) [:kr :professor])
+            (apply str (get-in (val course) [:kr :schedule]))
+            (get-in (val course) [:kr :credit-hours])
+            (get-in (val course) [:kr :classification]))]])

 (defn courses-component
   []
@@ -102,17 +111,18 @@
        [:div {:class "u-full-width"}
         [:ul
          (for [course (filter (partial matches-query? @search-input) @courses)]
-           ^{:key (:number course)} [course-component course])]]])))
+           ^{:key (key course)} [course-component course])]]])))

 (defn course-row-component
   [course]
   [:tr
-   [:td (:name course)]
-   [:td (:number course)]
-   [:td (:prof course)]
-   [:td (:time course)]
-   [:td (:credits course)]
-   [:td (:type course)]])
+   [:td (get-in (val course) [:c-id :kr :name])]
+   [:td (get-in (val course) [:c-id :kr :number])]
+   [:td (get-in (val course) [:c-id :kr :professor])]
+   [:td (get-in (val course) [:c-id :kr :schedule])]
+   [:td (get-in (val course) [:c-id :kr :credit-hours])]
+   [:td (get-in (val course) [:c-id :kr :classification])]
+   ])

 (defn courses-table-component
   []
@@ -137,21 +147,20 @@
   (let [courses (re-frame/subscribe [:courses])
         get-time (fn [cid] (get-in courses [cid :en :schedule]))]
     (fn []
-      [:h4 "Class Schedule"
+      [:h5 "Class Schedule"
        [:table.u-full-width
         [:thead
          [:tr
           [:th] [:th "Mon"] [:th "Tue"] [:th "Wed"] [:th "Thu"] [:th "Fri"]]]
         [:tbody
          (for [time-slot (range 1 8)]
-           [:tr
-            [:th time-slot]
-            [:td ""]
-            [:td ""]
-            [:td ""]
-            [:td ""]
-            [:td ""]
-            ])]]])))
+           ^{:key (hash time-slot)} [:tr
+                                     [:th time-slot]
+                                     [:td ""]
+                                     [:td ""]
+                                     [:td ""]
+                                     [:td ""]
+                                     [:td ""]])]]])))

 (defn home-page []
   [:div.container


refactor connection state handling

refactor connection state handling

--- src/cljs/lambdacd/db.cljs
+++ src/cljs/lambdacd/db.cljs
@@ -1,6 +1,7 @@
 (ns lambdacd.db
   (:require-macros [reagent.ratom :refer [reaction]])
   (:require [re-frame.core :as re-frame]))
+

 (def default-db
   {:history []
@@ -11,16 +12,22 @@
 (defn initialize-db-handler [_ _]
   default-db)

+
+(defn- set-connection-state-active [db]
+  (assoc db :connection-state :active))
+
 (defn history-updated-handler [db [_ new-history]]
-  (assoc db :history new-history
-            :connection-state :active))
+  (-> db
+      (assoc :history new-history)
+      (set-connection-state-active)))

 (defn history-subscription [db _]
   (reaction (:history @db)))

 (defn pipeline-state-updated-handler [db [_ new-history]]
-  (assoc db :pipeline-state new-history
-            :connection-state :active))
+  (-> db
+      (assoc :pipeline-state new-history)
+      (set-connection-state-active)))

 (defn pipeline-state-subscription [db _]
   (reaction (:pipeline-state @db)))


git weirdness, changed genomes

git weirdness, changed genomes

--- src/cljs/neat/genome.cljs
+++ src/cljs/neat/genome.cljs
@@ -14,7 +14,7 @@

 (defn genome
   ([settings] (genome settings default-mutate))
-  ([settings mutates] (mutate (base settings mutates))))
+  ([settings mutates] (mutates (base settings mutates))))

 (defn coin-flip []
   (rand-nth [true false]))


reduce duplication in template

reduce duplication in template

--- src/crucible/template.clj
+++ src/crucible/template.clj
@@ -5,28 +5,27 @@
             [crucible.parameters :refer [encode-parameter]]
             [crucible.outputs :refer [encode-output]]))

-(defn encode-key
+(defn- encode-key
   [k]
   (name (->PascalCase k)))

-(defn encode-template-element
+(defn- encode-template-element
   [encode [k v]]
   [(encode-key k) (encode v)])
+
+(defn- encode-elements
+  [template-map type-label encode-type-fn]
+  [(encode-key type-label)
+   (into {} (->> template-map
+                 type-label
+                 seq
+                 (map (partial encode-template-element encode-type-fn))))])

 (defn make-template
   [element-map]
   (reduce (fn [acc [k v]] (if (seq v) (assoc acc k v) acc))
           {}
-          (-> [["AWSTemplateFormatVersion" "2010-09-09"]]
-              (conj ["Parameters" (into {} (->> element-map
-                                                :parameters
-                                                seq
-                                                (map (partial encode-template-element encode-parameter))))])
-              (conj ["Resources" (into {} (->> element-map
-                                               :resources
-                                               seq
-                                               (map (partial encode-template-element encode-resource))))])
-              (conj ["Outputs" (into {} (->> element-map
-                                             :outputs
-                                             seq
-                                             (map (partial encode-template-element encode-output))))]))))
+          [["AWSTemplateFormatVersion" "2010-09-09"]
+           (encode-elements element-map :parameters encode-parameter)
+           (encode-elements element-map :resources encode-resource)
+           (encode-elements element-map :outputs encode-output)]))


inbox: Add 'state' arg to `column-title'.

--- src-cljs/pepa/workflows/inbox2.cljs
+++ src-cljs/pepa/workflows/inbox2.cljs
@@ -20,13 +20,13 @@
            goog.ui.IdGenerator))

 (defprotocol ColumnSource
-  (column-title [_])
+  (column-title [_ state])
   (column-pages  [_ state])
-
+  ;; TODO: Handle immutable colum sources
   (remove-pages! [_ state page-ids]))

 (defprotocol ColumnDropTarget
-  (accepts-drop? [_ state #_pages])     ;can't get data in drag-over
+  (accepts-drop? [_ state])     ;can't get data in drag-over
   (accept-drop!  [_ state pages]))

 (comment
@@ -49,7 +49,7 @@

 (defrecord InboxColumnSource [id]
   ColumnSource
-  (column-title [_]
+  (column-title [_ _]
     "Inbox")
   (column-pages [_ state]
     (get-in state [:inbox :pages]))
@@ -65,30 +65,42 @@
                               (remove #(contains? page-ids (:id %)))
                               pages)))))))

-(defrecord FakeColumnSource [id]
+(comment
+  (defrecord FakeColumnSource [id]
+    ColumnSource
+    (column-title [_ _]
+      "Fake")
+    (column-pages [_ state]
+      (get-in state [::fake-column-pages]))
+    (remove-pages! [_ state page-ids]
+      (go
+        (js/console.warn "Unimplemented: Removing pages from Fake...")))
+    ColumnDropTarget
+    (accepts-drop? [_ state]
+      true)
+    ;; TODO: Make immutable?
+    (accept-drop! [_ state new-pages]
+      (go
+        (println "dropping" (pr-str new-pages))
+        (om/transact! state ::fake-column-pages
+                      (fn [pages]
+                        (into pages
+                              (remove #(contains? (set (map :id pages)) (:id %)))
+                              new-pages)))
+        (println "Fake-saving...")
+        (<! (async/timeout 2000))
+        (println "Saved!")))))
+
+(defrecord DocumentColumnSource [id document-id]
   ColumnSource
-  (column-title [_]
-    "Fake")
+  (column-title [_ state]
+    (get-in state [:documents document-id :title]
+            "Untitled Document"))
   (column-pages [_ state]
-    (get-in state [::fake-column-pages]))
+    (get-in state [:documents document-id :pages]))
   (remove-pages! [_ state page-ids]
     (go
-      (js/console.warn "Unimplemented: Removing pages from Fake...")))
-  ColumnDropTarget
-  (accepts-drop? [_ state]
-    true)
-  ;; TODO: Make immutable?
-  (accept-drop! [_ state new-pages]
-    (go
-      (println "dropping" (pr-str new-pages))
-      (om/transact! state ::fake-column-pages
-                    (fn [pages]
-                      (into pages
-                            (remove #(contains? (set (map :id pages)) (:id %)))
-                            new-pages)))
-      (println "Fake-saving...")
-      (<! (async/timeout 2000))
-      (println "Saved!"))))
+      (js/console.warn "Unimplemented: Removing pages from Fake..."))))

 ;;; NOTE: We need on-drag-start in `inbox-column' and in
 ;;; `inbox-column-page' (the latter to handle selection-updates when
@@ -180,7 +192,7 @@
                             (handle-drop! (:id column)
                                           source-column
                                           page-ids)))}
-     [:header (column-title column)]
+     [:header (column-title column state)]
      [:ul.pages
       (om/build-all inbox-column-page (column-pages column state)
                     {:opts {:page-click! (fn [click]
@@ -221,8 +233,10 @@
   (init-state [_]
     (let [gen (IdGenerator.getInstance)
           columns [(->InboxColumnSource (.getNextUniqueId gen))
-                   (->FakeColumnSource (.getNextUniqueId gen))]]
-      {:columns (into {} (map (juxt :id identity))
+                   (->DocumentColumnSource (.getNextUniqueId gen) 1)
+                   (->DocumentColumnSource (.getNextUniqueId gen) 2)]]
+      {:columns (into {}
+                      (map (juxt :id identity))
                       columns)}))
   (will-mount [_]
     (api/fetch-inbox! state))


Clean up help output.

Clean up help output.

--- src/monocle/core.clj
+++ src/monocle/core.clj
@@ -8,12 +8,15 @@

 (def options
   [["-i" "--interface"
-    "Where to send output (stdout, stderr, amqp://HOST:PORT/VHOST|EXCH|KEY)"
+    (str "Where to send output (stdout,\n"
+         "                                "
+         " stderr, amqp://HOST:PORT/VHOST|EXCH|KEY)")
     :default "stdout"]
    ["-f" "--file" "File to monitor for content"]
    ["-o" "--offset-file" "File with offset information"]
    ["-b" "--batch" "Size of batches from FILE"
-    :default 25 :parse-fn #(Integer. %)]])
+    :default 25 :parse-fn #(Integer. %)]
+   ["-h" "--help" "Help!" :default false :flag true]])

 (defn amqp-opts [iface]
   (.split iface "\\|"))
@@ -42,12 +45,17 @@
                     (- c2 c))
         (set-new-offset! c2)))))

+(defn delete-trailing-whitespace [s]
+  (.replaceAll s "[ ]+\n" "\n"))
+
 (defn -main [& args]
-  (let [[{:keys [interface file offset-file batch] :as opts} args help]
+  (let [[{:keys [interface file offset-file batch help_] :as opts} args help]
         (apply cli/cli args options)]
     (when-not offset-file
       (log/fatalf "-o not supplied" offset-file))
     (when-not file
       (log/fatalf "-f not supplied" file))
+    (when help_
+      (println (delete-trailing-whitespace help)))
     (when (and offset-file file)
       (main opts))))


Added a :closest walk direction.

Added a :closest walk direction.

--- src/osmosis/core.clj
+++ src/osmosis/core.clj
@@ -34,9 +34,13 @@
     [4 #(play-scale-note root target-degree)]

     ; Walk down to the root
-    (if (= direction :up)
-      (seq-walk-in-key root target-degree 7)
-      (seq-walk-in-key root target-degree 0))))
+    (seq-walk-in-key
+      root target-degree
+      (case direction
+        :closest (if (> target-degree 3) 7 0)
+        :up 7
+        :down 0
+        0))))

 (defn random-seq-degree-in-key
   ([]


Updated version of component-path

Updated version of component-path

--- src/re_com/util.cljs
+++ src/re_com/util.cljs
@@ -139,13 +139,16 @@
 ;; ----------------------------------------------------------------------------

 (defn component-path [c]
-  (when-some [elem (some-> (or (some-> c
-                                       (.' :_reactInternalInstance))
-                               c)
-                           (.' :_currentElement))]
-             (let [name      (some-> (.' elem :type)
-                                     (.' :displayName))
-                   disp-name (clojure.string/replace name #"\$" ".")]
-               (if-some [pname (component-path (.' elem :_owner))]
-                        (str pname " > " disp-name)
-                        disp-name))))
+  (let [elem  (some-> (or (some-> c
+                                  (.' :_reactInternalInstance))
+                          c)
+                      (.' :_currentElement))
+        name  (some-> elem
+                      (.' :type)
+                      (.' :displayName)
+                      (clojure.string/replace #"\$" "."))
+        owner (some-> elem
+                      (.' :_owner)
+                      component-path
+                      (str " > "))]
+    (str owner name)))


another test that performs very differently on ibm java 6

--- dada-core/src/test/clojure/org/dada/core/test_clojure.clj
+++ dada-core/src/test/clojure/org/dada/core/test_clojure.clj
@@ -23,7 +23,10 @@

 (defrecord Value [v])

-(if (not (.contains (.toLowerCase (System/getProperty "java.vm.vendor")) "ibm")) ;TODO - these assumptions do not hold true on IBM - maybe we should generate code accordingly ?
+(defn ibm? []
+  (.contains (.toLowerCase (System/getProperty "java.vm.vendor")) "ibm"))
+
+(if (not (ibm?)) ;TODO - these assumptions do not hold true on IBM - maybe we should generate code accordingly ?
   (do

     ;; (deftest test-get
@@ -88,10 +91,12 @@
 (defrecord Bar (^Integer a))

 ;; int is faster (5x) - to be expected
-(deftest record-int-vs-integer
-  (let [f (Foo. 1)
-	b (Bar. 1)]
-    (is (faster 1000000000 (.a b)  (.a f)))))
+
+(if (not (ibm?))
+  (deftest record-int-vs-integer
+    (let [f (Foo. 1)
+	  b (Bar. 1)]
+      (is (faster 1000000000 (.a b)  (.a f))))))

 ;; interesting - reading an int out of a record and pssing it into
 ;; another fn (causing it to be auto-boxed) is still 5-10x faster than


updated

updated

--- src/dbquery/databases.clj
+++ src/dbquery/databases.clj
@@ -39,34 +39,30 @@
        {:error (.getMessage e#)}))
   )

+(defn ^:private rs-rows [rs cols offset limit]
+  (if (and (> offset 0) (= ResultSet/TYPE_SCROLL_INSENSITIVE (.getType rs)))
+    (.absolute rs offset)
+    )
+  (loop [rows [] count 0]
+    (if (and (.next rs) (< count limit))
+      (let [row (doall (map #(.getObject rs %) cols))]
+        (recur (conj rows row) (inc count))
+        )
+      rows
+      )
+    )
+  )
+
 (defn ^:private read-rs
-  ([rs & {:keys [offset limit columns] :or {offset 0 limit 100}}]
-   (let [rs-meta (.getMetaData rs)
-         col-size (inc (.getColumnCount rs-meta))
-         cols (if (columns) columns (doall (map #(.getColumnName rs-meta %) (range 1 col-size))))]
-     (if (and (> offset 0) (= ResultSet/TYPE_SCROLL_INSENSITIVE (.getType rs)))
-       (.absolute rs offset)
-       )
-     (loop [rows [] count 0]
-       (if (and (.next rs) (< count limit))
-         (let [row (doall (map #(.getObject rs %) (range 1 col-size)))]
-           (recur (conj rows row) (inc count))
-           )
-         {:columns cols :rows rows}
-         )
-       )
-     ))
-  ([rs] (read-rs rs (Integer/MAX_VALUE)))
-  ([rs cols limit]
-   (loop [rows [] count 0]
-     (if (and (.next rs) (< count limit))
-       (let [row (doall (map #(.getObject rs %) cols))]
-         (recur (conj rows row) (inc count))
-         )
-       {:columns cols :rows rows}
-       )
-     )
-   )
+  [rs & {:keys [offset limit columns] :or {offset 0 limit 100}}]
+  (if (some? columns)
+    {:columns columns :rows (rs-rows rs columns offset limit)}
+    (let [rs-meta (.getMetaData rs)
+          col-size (inc (.getColumnCount rs-meta))
+          cols (if (columns) columns (doall (map #(.getColumnName rs-meta %) (range 1 col-size))))]
+      {:columns cols :rows (rs-rows rs cols offset limit)}
+      )
+    )
   )

 (defn mk-ds [{:keys [dbms url user_name password]}]
@@ -96,14 +92,14 @@
   ([ds table limit]
    (db-query-with-resultset ds
                             [(str "SELECT * FROM " table)]
-                            #(read-rs % limit))
+                            #(read-rs % :limit limit))
    )
   ([ds table] (table-data ds table 100)))

 (defn tables [ds]
   (with-db-metadata [meta ds]
     (with-open [rs (.getTables meta nil nil "%" (into-array ["TABLE" "VIEW"]))]
-      (-> (read-rs rs ["TABLE_NAME"] 100)
+      (-> (read-rs rs :columns ["TABLE_NAME"])
           (:rows)
           flatten))))

@@ -114,7 +110,7 @@
             has-rs (.execute stmt sql)]
         (if (empty? sqls)
           (if has-rs
-            (read-rs (.getResultSet stmt) 100)
+            (read-rs (.getResultSet stmt))
             (.getUpdateCount stmt)
             )
           (recur (first sqls) (rest sqls)))
@@ -125,7 +121,7 @@
 (defn table-cols [ds name]
   (with-db-metadata [meta ds]
     (with-open [rs (.getColumns meta nil nil name "%")]
-      (read-rs rs ["COLUMN_NAME" "DATA_TYPE" "TYPE_NAME" "COLUMN_SIZE" "DECIMAL_DIGITS" "NULLABLE" "ORDINAL_POSITION"] 200))) )
+      (read-rs rs :columns ["COLUMN_NAME" "DATA_TYPE" "TYPE_NAME" "COLUMN_SIZE" "DECIMAL_DIGITS" "NULLABLE" "ORDINAL_POSITION"] :limit 200))) )

 (defn exec-query [ds {:keys [tables fields predicates offset limit]}]
   (with-open [con (.getConnection (:datasource ds))]
@@ -135,5 +131,5 @@
           where (if (empty? predicates) "" (str "where " (s/join " AND " predicates)))
           sql (str "select " (s/join "," fields) "from " (s/join "," tables) where)
           rs (.executeQuery stmt sql)]
-      (read-rs rs limit)
+      (read-rs rs :limit limit :offset offset)
       )))


print svn-supplied error on failure

print svn-supplied error on failure

--- src/revdiff/core.clj
+++ src/revdiff/core.clj
@@ -56,23 +56,16 @@
         (doseq [filename mf] (svndiff r1 r2 filename object show))
         (recur (drop 2 x))))))

-;; Try to explain why this has failed.
-
-(defn errmsg []
-  (println "\nError retrieving repository information. Perhaps:\n")
-  (println "- The supplied filename or URI is invalid, or")
-  (println "- Your valid svn authentication credentials are not cached.")
-  (println)
-  (System/exit 1))
-
 ;; Return a newest-first sequence of revision numbers in which the object
 ;; changed.

 (defn get-revlist [opts show object]
-  (let [x (java.io.ByteArrayInputStream. (.getBytes (log opts show object)))]
+  (let [result (log opts show object)
+        stream (java.io.ByteArrayInputStream. (.getBytes (:out result)))]
     (for [e (try
-              (xml-seq (parse x))
-              (catch Exception e (errmsg)))
+              (xml-seq (parse stream))
+              (catch Exception e
+                (println (:err result))))
           :when (seq (:attrs e))]
     (:revision (:attrs e)))))

@@ -91,7 +84,7 @@
     (if show (show-cmd cmd-components))
     (print "Fetching log... ")
     (flush)
-    (let [result (:out (apply sh cmd-components))]
+    (let [result (apply sh cmd-components)]
       (println)
       result)))


adds and updates docstrings

adds and updates docstrings

--- src/doctopus/template.clj
+++ src/doctopus/template.clj
@@ -28,12 +28,16 @@
   (enlive/sniptest main [[element enlive/first-of-type]] (f snippet)))

 (defn- append-to-element
+  "Given an an html string and an enlive-compiled html to-append, insert at the
+  end of the given element; defaults to :body"
   ([main to-append]
    (append-to-element main :body to-append))
   ([main element to-append]
    (add-to-element-with-fn main element to-append enlive/append)))

 (defn- prepend-to-element
+  "Given an an html string and an enlive-compiled html to-prepend, insert at the
+  beginning of the given element; defaults to :body"
   ([main to-prepend]
    (prepend-to-element main :body to-prepend))
   ([main element to-prepend]
@@ -51,13 +55,15 @@
   (apply str (base-template context)))

 (defn- app-context
+  "generates an enlive-encoded html description map for app-state; a known
+  element used to communicate context to the frontend cljs app on page load"
   [context]
   (enlive/html
     [:script#app-state {:type "application/json"} (json/write-str context)]))

 (defn add-omnibar
-  "given a string of HTML, returns a string with a the Doctopus omnibar inserted
-  at the end of its body"
+  "given a string of HTML, returns a string with a the Doctopus omnibar and
+  associated assets inserted into the appropriate places."
   [html-str context]
   (-> html-str
       (prepend-to-element :body (omnibar-html))


Refactor tango.export

Refactor tango.export

--- src/tango/export.clj
+++ src/tango/export.clj
@@ -12,9 +12,82 @@
             ))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; AdjPanelList/AdjList
+;; Utils
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defn- old-make-adjudicator-node [adjudicator-info]
+(defmacro def- [item value]
+  `(def ^{:private true} ~item ~value))
+
+(defn- format-date [date]
+  (tf/unparse (tf/formatter "yyyy-MM-dd") (tf/parse date)) )
+
+(defn- b2i [b]
+  (if (true? b) 1 0))
+
+(defn- get-db [data]
+  (let [conn (d/create-conn uidb/schema)]
+    (d/transact! conn [(uidb/sanitize data)])
+    (d/db conn)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; DancePerfect
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defn- make-dance-perfect-node [content]
+  (xml/element
+    :DancePerfect
+    {:Version "4.1"}
+    content))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; DancePerfect/CompData
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defn- make-comp-data-node [query-result]
+  (let [result (first (first query-result))
+        options (:competition/options result)]
+    (xml/element
+      :CompData
+      {:Name               (:competition/name result)
+       :Date               (format-date (:competition/date result))
+       :Place              (:competition/location result)
+       :Org                ""
+       :AdjOrderFinal      (b2i (:dance-competition/adjudicator-order-final options))
+       :AdjOrderOther      (b2i (:dance-competition/adjudicator-order-other options))
+       :SameHeatAllDances  (b2i (:dance-competition/same-heat-all-dances options))
+       :RadomHeats         (b2i (:dance-competition/random-order-in-heats options))
+       :RandomHeats        (b2i (:dance-competition/random-order-in-heats options))
+       :PreView            (b2i (:printer/preview options))
+       :HeatText           (b2i (:dance-competition/heat-text-on-adjudicator-sheet options))
+       :NameOnNumberSign   (b2i (:dance-competition/name-on-number-sign options))
+       :ClubOnNumberSign   (b2i (:dance-competition/club-on-number-sign options))
+       :SkipAdjLetter      (b2i (:dance-competition/skip-adjudicator-letter options))
+       :PrinterSelectPaper (b2i (:printer/printer-select-paper options))
+       :ChineseFonts       (b2i (:presentation/chinese-fonts options))
+       :ArialFont          (:presentation/arial-font options)
+       :CourierFont        (:presentation/courier-font options)
+       }
+
+      )))
+
+(def- make-comp-data-node-query
+  '[:find (pull ?e [:competition/name
+                    :competition/date
+                    :competition/location
+                    :competition/options])
+    :where [?e :competition/name]]
+  )
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; DancePerfect/AdjPanelList
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defn- make-adj-panel-list-node [content]
+  (xml/element
+    :AdjPanelList
+    {}
+    content))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; DancePerfect/AdjPanelList/AdjList
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defn- make-adjudicator-node [adjudicator-info]
   (let [name (:adjudicator/name adjudicator-info)
         id (:adjudicator/id adjudicator-info)
         country (:adjudicator/country adjudicator-info)]
@@ -23,91 +96,89 @@
                                :Country country})
     ))

-(defn- old-make-adj-list-node [query-result]
+(defn- make-adj-list-node [query-result]
   (let [adjudicator-infos (map first query-result)]
     (xml/element
       :AdjList
       {:Qty (count adjudicator-infos)}
-      (map old-make-adjudicator-node (sort-by :adjudicator/id adjudicator-infos)))
+      (map make-adjudicator-node (sort-by :adjudicator/id adjudicator-infos)))
     ))

-(defn- old-export-adj-list [db]
-  (let [query-result (d/q '[:find (pull ?id [*])
-                            :where
-                            [?id :adjudicator/id]] db)]
-    (old-make-adj-list-node query-result)))
+(def- make-adj-list-node-query
+  '[:find (pull ?e [*])
+    :where [?e :adjudicator/id]])

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; AdjPanelList/PanelList
+;; DancePerfect/AdjPanelList/PanelList
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defn- old-make-panel-adj-node [query-result seq-number]
+(defn- make-panel-adj-node [query-result seq-number]
   (xml/element
     :PanelAdj
     {:Seq seq-number
      :AdjNumber (:adjudicator/id query-result)}))

-(defn- old-make-panel-node [panel seq-number]
+(defn- make-panel-node [panel seq-number]
   (let [adjudicator-infos (:adjudicator-panel/adjudicators panel)]
     (xml/element
       :Panel
       {:Seq seq-number
        :Qty (count adjudicator-infos)}
       (reduce
-        (fn [state adj-info] (conj state (old-make-panel-adj-node adj-info (count state))))
+        (fn [state adj-info] (conj state (make-panel-adj-node adj-info (count state))))
         []
         adjudicator-infos))))

-(defn- old-make-panel-list-node [adjudicator-panels]
-  (xml/element
-    :PanelList
-    {:Qty (count adjudicator-panels)}
-    (reduce (fn [elements panel]
-              (conj elements (old-make-panel-node panel (count elements))))
-            []
-            adjudicator-panels)
-  ))
-
-(defn- old-export-panel-list [db]
-  (let [qr (d/q '[:find (pull ?id [{:adjudicator-panel/adjudicators
-                                                            [:adjudicator/id]}])
-                                          :where
-                                          [?id :adjudicator-panel/id]] db)
-        adjudicator-panels (reduce conj [] (map first qr))
+(defn- make-panel-list-node [qr]
+  (let [adjudicator-panels (reduce conj [] (map first qr))
         n (- 30 (count adjudicator-panels))
         padded-panels (repeat n {:adjudicator-panel/adjudicators []})
         all-panels (into adjudicator-panels padded-panels)]
-    (old-make-panel-list-node all-panels)))
+    (xml/element :PanelList
+                 {:Qty (count all-panels)}
+                 (reduce
+                   (fn [elements panel]
+                     (conj elements (make-panel-node panel (count elements))))
+                   []
+                   all-panels))))
+
+(def- make-panel-list-node-query
+  '[:find (pull ?e [{:adjudicator-panel/adjudicators [:adjudicator/id]}])
+    :where [?e :adjudicator-panel/id]])

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; AdjPanelList
+;; Export Definition
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defn- old-export-adj-panel-list [db]
-  (xml/element
-    :AdjPanelList
-    {}
-    (old-export-adj-list db)))
+(def- export-definition
+  {
+   :xml-factory make-dance-perfect-node
+   :content [{:xml-factory make-comp-data-node
+              :query make-comp-data-node-query}
+             {:xml-factory make-adj-panel-list-node
+              :content [{:xml-factory make-adj-list-node
+                         :query       make-adj-list-node-query}
+                        {:xml-factory make-panel-list-node
+                         :query       make-panel-list-node-query}
+                        ]}
+             ]})

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Utils
+;; Export
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defn- get-db [data]
-  (let [conn (d/create-conn uidb/schema)]
-    (d/transact! conn [(uidb/sanitize data)])
-    (d/db conn)))
-
-(defn- old-export-dance-perfect [db]
-  (xml/element
-      :DancePerfect
-      {:Version "4.1"}
-      [(old-export-adj-panel-list db)
-       (old-export-panel-list db)]
-      ))
-
-(defn old-export [data]
-  (let [db (get-db data)]
-    (old-export-dance-perfect db) ;; TODO: def queries in file and pass in query result
+(defn- export-xml [db export-def]
+  (let [xml-factory (:xml-factory export-def)
+        query (:query export-def)
+        content (:content export-def)
+        export-xml-with-db (partial export-xml db)
+        ]
+    (if (nil? query)
+      (xml-factory (map export-xml-with-db content))
+      (xml-factory (d/q query db)))
     ))

-(xml/indent-str
-  (old-export u/expected-small-example))
+(defn export [data export-def file]
+  (let
+    [db (get-db data)]
+    (spit file (xml/emit-str (export-xml db export-def)))))

+(export u/expected-small-example export-definition "/tmp/baz.xml")
+


Code cleanup.

Code cleanup.

--- test/open_company/unit/resources/company/company_create.clj
+++ test/open_company/unit/resources/company/company_create.clj
@@ -88,10 +88,10 @@
       (c/delete-company r/slug)
       (:sections (c/create-company
         (-> r/open
-          (assoc :mission {})
-          (assoc :press {})
-          (assoc :help {})
-          (assoc :challenges {})
-          (assoc :diversity {})
-          (assoc :update {}))
+          (assoc :mission {})
+          (assoc :press {})
+          (assoc :help {})
+          (assoc :challenges {})
+          (assoc :diversity {})
+          (assoc :update {}))
         r/coyote)) => {"progress" ["update" "challenges" "press" "help"] "company" ["diversity" "mission"]})))


Disable broken intersection test

Disable broken intersection test

--- test/aurora/btree_test.cljs
+++ test/aurora/btree_test.cljs
@@ -73,9 +73,9 @@
   5000
   (aurora.btree/iterator-prop 1))

-(defspec intersection-prop-test
-  500
-  (aurora.btree/intersection-prop 1))
+#_(defspec intersection-prop-test
+    500
+    (aurora.btree/intersection-prop 1))

 (comment
   (run-all-tests)


util/s3.clj: added get-object-stream

util/s3.clj: added get-object-stream

--- src/org/altlaw/util/s3.clj
+++ src/org/altlaw/util/s3.clj
@@ -41,3 +41,6 @@
   (into {} (.getMetadataMap
             (.getObjectDetails (get-s3) (get-bucket bucket-name)
                                object-key))))
+
+(defn get-object-stream [bucket-name object-key]
+  (.getDataInputStream (get-object bucket-name object-key)))


Cleanup indentation

Cleanup indentation

--- dev/user.clj
+++ dev/user.clj
@@ -71,112 +71,112 @@

 (comment

-  (reset)
+(reset)

-  ;; number of movies, total
-  (time (q '[:find (count ?e) :where [?e :movie/title]]
-           (-> system :db :conn db)))
+;; number of movies, total
+(time (q '[:find (count ?e) :where [?e :movie/title]]
+          (-> system :db :conn db)))

-  ;; number of movies with actors
-  (time
-    (let [d (-> system :db :conn db)]
-      (q '[:find (count ?e)
-           :where
-           [?e :movie/title]
-           [_ :actor/movies ?e]]
-         d)))
+;; number of movies with actors
+(time
+  (let [d (-> system :db :conn db)]
+    (q '[:find (count ?e)
+          :where
+          [?e :movie/title]
+          [_ :actor/movies ?e]]
+        d)))

-  ;; number of movies with no actors
-  (time
-    (let [d (-> system :db :conn db)
-          movies (q '[:find ?e :where [?e :movie/title]] d)]
-      (->> (map (fn [[id]] (d/entity d id)) movies)
-           (remove (fn [e] (:actor/_movies e)))
-           count)))
+;; number of movies with no actors
+(time
+  (let [d (-> system :db :conn db)
+        movies (q '[:find ?e :where [?e :movie/title]] d)]
+    (->> (map (fn [[id]] (d/entity d id)) movies)
+          (remove (fn [e] (:actor/_movies e)))
+          count)))

-  ;; retract video games
-  (let [d (-> system :db :conn db)]
-    (->> (q '[:find ?e ?name
-              :where
-              [?e :movie/title ?name]] d)
-         (filter (fn [[e n]] (not= -1 (.indexOf n "(VG)"))))
-         (mapv (fn [[e _]] [:db.fn/retractEntity e]))
-         (d/transact (-> system :db :conn))
-         (deref)
-         ))
+;; retract video games
+(let [d (-> system :db :conn db)]
+  (->> (q '[:find ?e ?name
+            :where
+            [?e :movie/title ?name]] d)
+        (filter (fn [[e n]] (not= -1 (.indexOf n "(VG)"))))
+        (mapv (fn [[e _]] [:db.fn/retractEntity e]))
+        (d/transact (-> system :db :conn))
+        (deref)
+        ))

-  ;; zipper
-  (let [d (-> system :db :conn db)
-        a (actor-name->eid d "Barth, Clayton")
-        actor-name (partial eid->actor-name d)
-        kevin (actor-name->eid d "Bacon, Kevin (I)")
-        tree (zipper d a)]
-    (time (some (fn [n] (when (= kevin n) n)) tree)))
+;; zipper
+(let [d (-> system :db :conn db)
+      a (actor-name->eid d "Barth, Clayton")
+      actor-name (partial eid->actor-name d)
+      kevin (actor-name->eid d "Bacon, Kevin (I)")
+      tree (zipper d a)]
+  (time (some (fn [n] (when (= kevin n) n)) tree)))

-  ;; bi-directional bfs
-  (def from-bfs
-    (let [d (-> system :db :conn db)
-          clay (actor-name->eid d "Barth, Clayton")
-          kevin (actor-name->eid d "Bacon, Kevin (I)")
-          neighbor-fn (partial neighbors d)]
-      (time (bidirectional-bfs clay kevin neighbor-fn)))
-    )
-
-  ;; queue-based search
+;; bi-directional bfs
+(def from-bfs
   (let [d (-> system :db :conn db)
         clay (actor-name->eid d "Barth, Clayton")
         kevin (actor-name->eid d "Bacon, Kevin (I)")
-        neighbor-fn (partial neighbors d)
-        actor-name (partial actor-or-movie-name d)]
-    (time (map actor-name (bfs clay kevin neighbor-fn))))
+        neighbor-fn (partial neighbors d)]
+    (time (bidirectional-bfs clay kevin neighbor-fn)))
+  )
+
+;; queue-based search
+(let [d (-> system :db :conn db)
+      clay (actor-name->eid d "Barth, Clayton")
+      kevin (actor-name->eid d "Bacon, Kevin (I)")
+      neighbor-fn (partial neighbors d)
+      actor-name (partial actor-or-movie-name d)]
+  (time (map actor-name (bfs clay kevin neighbor-fn))))

-  ;; query engine search (3 degrees)
+;; query engine search (3 degrees)
+(let [d (-> system :db :conn db)
+      clay (actor-name->eid d "Barth, Clayton")
+      kevin (actor-name->eid d "Bacon, Kevin (I)")
+      actor-name (partial eid->actor-name d)]
+  (time (q '[:find ?actor ?m1 ?target
+                          :in $ % ?actor ?target
+                          :where (acted-with ?actor ?m1 _)
+                          (acted-with ?m1 ?target _)]
+                        d acted-with-rules clay kevin)))
+
+;; query engine search (4 degrees)
+(let [d (-> system :db :conn db)
+      clay (actor-name->eid d "Barth, Clayton")
+      kevin (actor-name->eid d "Bacon, Kevin (I)")
+      actor-name (partial eid->actor-name d)]
+  (time (map (partial map actor-name)
+              (q '[:find ?actor ?m1 ?m2 ?target
+                          :in $ % ?actor ?target
+                          :where (acted-with ?actor ?m1 _)
+                          (acted-with ?m1 ?m2 _)
+                          (acted-with ?m2 ?target _)]
+                        d acted-with-rules clay kevin))))
+
+;; using path from rule
+(def from-path
   (let [d (-> system :db :conn db)
         clay (actor-name->eid d "Barth, Clayton")
         kevin (actor-name->eid d "Bacon, Kevin (I)")
-        actor-name (partial eid->actor-name d)]
-    (time (q '[:find ?actor ?m1 ?target
-                           :in $ % ?actor ?target
-                           :where (acted-with ?actor ?m1 _)
-                           (acted-with ?m1 ?target _)]
-                         d acted-with-rules clay kevin)))
-
-  ;; query engine search (4 degrees)
-  (let [d (-> system :db :conn db)
-        clay (actor-name->eid d "Barth, Clayton")
-        kevin (actor-name->eid d "Bacon, Kevin (I)")
-        actor-name (partial eid->actor-name d)]
-    (time (map (partial map actor-name)
-               (q '[:find ?actor ?m1 ?m2 ?target
-                           :in $ % ?actor ?target
-                           :where (acted-with ?actor ?m1 _)
-                           (acted-with ?m1 ?m2 _)
-                           (acted-with ?m2 ?target _)]
-                         d acted-with-rules clay kevin))))
-
-  ;; using path from rule
-  (def from-path
-    (let [d (-> system :db :conn db)
-          clay (actor-name->eid d "Barth, Clayton")
-          kevin (actor-name->eid d "Bacon, Kevin (I)")
-          ename  (partial actor-or-movie-name d)]
-      (time (set (map (fn [[p]] (concat p (list kevin)))
-                    (q '[:find ?path
-                        :in $ % ?actor ?target
-                        :where
-                        (acted-with-3 ?actor ?target ?path)]
-                      d acted-with-rules clay kevin)))))
-    )
+        ename  (partial actor-or-movie-name d)]
+    (time (set (map (fn [[p]] (concat p (list kevin)))
+                  (q '[:find ?path
+                      :in $ % ?actor ?target
+                      :where
+                      (acted-with-3 ?actor ?target ?path)]
+                    d acted-with-rules clay kevin)))))
+  )

-  ;; export movies and actors
-  (let [d (-> system :db :conn db)
-        reducer (fn [map [k v]] (assoc map k (conj (get map k []) v)))
-        actor-map (->> (kevin.expunge/actor-names "data/movies-small.list" d)
-                     (reduce reducer {}))]
-      (spit "resources/sample.edn" (with-out-str (pr actor-map))))
+;; export movies and actors
+(let [d (-> system :db :conn db)
+      reducer (fn [map [k v]] (assoc map k (conj (get map k []) v)))
+      actor-map (->> (kevin.expunge/actor-names "data/movies-small.list" d)
+                    (reduce reducer {}))]
+    (spit "resources/sample.edn" (with-out-str (pr actor-map))))

 ;; quick n dirty profiling


Simplifies data function.

Simplifies data function.

--- dev/user.clj
+++ dev/user.clj
@@ -47,8 +47,7 @@
 (defn data
   "Create n fake records and give them unique :_id values." [n]
   (map #(assoc %1 :_id %2)
-       (flatten (repeatedly (inc (/ n (count data/identities)))
-                            (fn [] data/identities)))
+       (flatten (repeat (inc (/ n (count data/identities))) data/identities))
        (range 1 (inc n))))

 (def d (data 1000))


Minor user ns tweaks.

Minor user ns tweaks.

--- dev/user.clj
+++ dev/user.clj
@@ -12,6 +12,7 @@
       [state :as state]
       [system :as system])
     (org.playasophy.wonderdome.display
+      [pixel-pusher :refer [pixel-pusher]]
       [processing :as processing])
     (org.playasophy.wonderdome.geometry
       [layout :as layout])
@@ -43,21 +44,32 @@
   (alter-var-root #'system
     (constantly
       (->
-        {:layout (layout/star dimensions)
-         :display (component/using
-                    (processing/display [1000 600] (:radius dimensions))
-                    [:layout :event-channel])
-         :handler (-> state/update-mode
-                      middleware/mode-selector
-                      (middleware/autocycle-modes (comp #{:button/press :button/repeat} :type))
-                      (middleware/log-events (comp #{} :type)))
-         :initial-state (state/initialize modes/config)}
+        {:layout
+         (layout/star dimensions)
+
+         :display
+         (component/using
+           (processing/display [1000 600] (:radius dimensions))
+           [:layout :event-channel])
+
+         :handler
+         (-> state/update-mode
+             middleware/mode-selector
+             (middleware/autocycle-modes (comp #{:button/press :button/repeat} :type))
+             (middleware/log-events (comp #{} :type)))
+
+         :initial-state
+         (state/initialize modes/config)}
+
         system/initialize
+
         (system/add-input :timer timer/timer
           (async/chan (async/dropping-buffer 3))
           timer-period)
+
         (system/add-input :gamepad gamepad/snes
           (async/chan (async/dropping-buffer 10)))
+
         ; TODO: audio parser
         )))
   :init)


Remove unncessary when checks

Remove unncessary when checks

--- src/reagent/impl/input.cljs
+++ src/reagent/impl/input.cljs
@@ -105,15 +105,13 @@
                 (fn? original-ref-fn)
                 (fn [el]
                   (set! (.-inputEl this) el)
-                  (when original-ref-fn
-                    (original-ref-fn el)))
+                  (original-ref-fn el))

                 ;; react/createRef object
                 (and original-ref-fn (.hasOwnProperty original-ref-fn "current"))
                 (fn [el]
                   (set! (.-inputEl this) el)
-                  (when original-ref-fn
-                    (set! (.-current original-ref-fn) el)))
+                  (set! (.-current original-ref-fn) el))

                 :else
                 (fn [el]


Tree-shaped artifacts list UI

Tree-shaped artifacts list UI

--- frontend/components/build_head.cljs
+++ frontend/components/build_head.cljs
@@ -196,6 +196,30 @@
    [:p "Use artifacts for screenshots, coverage reports, deployment tarballs, and more."]
    [:p "More information " [:a {:href (routes/v1-doc-subpage {:subpage "build-artifacts"})} "in our docs"] "."]])

+(defn artifacts-tree [artifacts]
+  (->> (for [artifact artifacts
+             :let [parts (-> artifact :path (string/split #"/"))]]
+         [(vec (remove #{""} parts)) artifact])
+       (reduce (fn [acc [parts artifact]]
+                 (let [loc (interleave (repeat :children) parts)]
+                   (assoc-in acc (concat loc [:artifact]) artifact)))
+               {})
+       :children))
+
+(defn artifacts-node [artifacts {:keys [show-node-indices? admin?] :as opts}]
+  (when (seq artifacts)
+    [:ul.build-artifacts-list
+     (for [[part {:keys [artifact children]}] (sort-by first artifacts)
+           :let [text (cond
+                        (not artifact) (str part "/") ; directory
+                        show-node-indices? (str part " (" (:node_index artifact) ")")
+                        :else part)
+                 url (:url artifact)
+                 tag (if (and url (not admin?)) ; Be extra careful about XSS of admins
+                       [:a {:href (:url artifact) :target "_blank"} text]
+                       [:span text])]]
+       [:li tag (artifacts-node children opts)])]))
+
 (defn build-artifacts-list [data owner {:keys [show-node-indices?] :as opts}]
   (reify
     om/IRender
@@ -203,25 +227,15 @@
       (let [artifacts-data (:artifacts-data data)
             artifacts (:artifacts artifacts-data)
             has-artifacts? (:has-artifacts? data)
-            admin? (:admin (:user data))]
+            node-opts {:admin? (:admin (:user data))
+                       :show-node-indices? show-node-indices?}]
         (html
          [:div.build-artifacts-container
           (if-not has-artifacts?
             (artifacts-ad)
             (if-not artifacts
               [:div.loading-spinner common/spinner]
-
-              [:ol.build-artifacts-list
-               (map (fn [artifact]
-                      (let [display-path (-> artifact
-                                             :pretty_path
-                                             cleanup-artifact-path
-                                             (str (when show-node-indices? (str " (" (:node_index artifact) ")"))))]
-                        [:li
-                         (if admin? ; Be extra careful about XSS of admins
-                           display-path
-                           [:a {:href (:url artifact) :target "_blank"} display-path])]))
-                    artifacts)]))])))))
+              (artifacts-node (artifacts-tree artifacts) node-opts)))])))))

 (defn tests-ad [owner]
   [:div


fix node indexes for ssh connections

fix node indexes for ssh connections

--- frontend/components/build_head.cljs
+++ frontend/components/build_head.cljs
@@ -126,14 +126,14 @@
          [:i.fa.fa-question-circle {:id "ssh-popover-hack" :title "SSH"}]]
         [:div.build-ssh-list
          [:dl.dl-horizontal
-          (map (fn [node]
+          (map (fn [node i]
                  (list
-                  [:dt (when (> 1 (count nodes)) [:span (:index node)])]
+                  [:dt (when (< 1 (count nodes)) [:span i])]
                   [:dd {:class (when (:ssh_enabled node) "connected")}
                    [:span (gstring/format "ssh -p %s %s@%s " (:port node) (:username node) (:public_ip_addr node))]
                    (when-not (:ssh_enabled node)
                      [:span.loading-spinner common/spinner])]))
-               nodes)]]
+               nodes (range))]]
         [:div.build-ssh-doc
          "Debugging Selenium browser tests? "
          [:a {:href "/docs/browser-debugging#interact-with-the-browser-over-vnc"}


Implement catchphrase achievement

Implement catchphrase achievement

--- src-clj/acha/achievement.clj
+++ src-clj/acha/achievement.clj
@@ -371,7 +371,29 @@
                                               (* 60 1000))))
                                  first)]
               :when c1]
-          {:commit-info c1})))))
+          {:commit-info c1}))))
+
+  (timeline-scanner :catchphrase
+    (fn [commits]
+      (->> commits
+        (group-by (juxt :email :message))
+        (filter (fn [[_ cs]] (<= 10 (count cs))))
+        (map (fn [[_ cs]] {:commit-info (first cs)})))))
+
+
+
+
+)
+
+;; catchphrase
+;; loneliness
+;; necromancer
+;; combo
+;; combo-breaker
+;; what-happended-here
+;; all-things-die
+;; good-boy
+

   ;;  TODO
   ;;  commenter


Use cheshire.core for JSON

Use cheshire.core for JSON

--- src/moodseer_clj/ajax.clj
+++ src/moodseer_clj/ajax.clj
@@ -1,7 +1,7 @@
 (ns moodseer-clj.ajax
   (:use [net.cgrand.enlive-html :as html])
   (:use [moodseer-clj.db])
-  (:require [clj-json.core :as json]))
+  (:use [cheshire.core :as json]))

 (def upcoming-test-list
   {:request-type "upcoming",
@@ -16,4 +16,3 @@
   []
   (json/generate-string upcoming-test-list))

-(defn album-track-info


JC | Update default coracle URI to use base URI

--- src/objective8/config.clj
+++ src/objective8/config.clj
@@ -22,31 +22,33 @@
           (log/error (str "Failed to look up environment variable \"" var-name "\" - no default provided")))
       default))))

+(def base-uri (get-var "BASE_URI" "localhost:8080"))
+
 (def ^:dynamic environment
-  {:uri-scheme (get-var "URI_SCHEME" "http")
-   :base-uri (get-var "BASE_URI" "localhost:8080")
+  {:uri-scheme                    (get-var "URI_SCHEME" "http")
+   :base-uri                      base-uri

-   :front-end-uri (get-var "BASE_URI" "localhost:8080")
-   :front-end-port (Integer/parseInt (get-var "APP_PORT" "8080"))
+   :front-end-uri                 base-uri
+   :front-end-port                (Integer/parseInt (get-var "APP_PORT" "8080"))

-   :api-uri (get-var "API_URI" "localhost:8081")
-   :external-api-uri (get-var "EXTERNAL_API_URI" "localhost:8081")
-   :api-port (Integer/parseInt (get-var "API_SERVER_PORT" "8081"))
+   :api-uri                       (get-var "API_URI" "localhost:8081")
+   :external-api-uri              (get-var "EXTERNAL_API_URI" "localhost:8081")
+   :api-port                      (Integer/parseInt (get-var "API_SERVER_PORT" "8081"))

-   :fake-twitter-mode (get-var "FAKE_TWITTER_MODE")
-   :api-credentials {:bearer-name (get-var "API_BEARER_NAME")
-                     :bearer-token (get-var "API_BEARER_TOKEN")}
-   :admins (get-var "ADMINS")
-   :db-config {:db (get-var "DB_NAME" "objective8")
-               :user (get-var "DB_USER" "objective8")
-               :password (get-var "DB_PASSWORD" "development") ;TODO password management
-               :host (get-var "DB_HOST" "localhost")
-               :port (get-var "DB_PORT" 5432)}
-   :google-analytics-tracking-id (get-var "GA_TRACKING_ID")
-   :twitter-credentials {:consumer-token (get-var "TWITTER_CONSUMER_TOKEN")
-                         :secret-token (get-var "TWITTER_CONSUMER_SECRET_TOKEN")}
+   :fake-twitter-mode             (get-var "FAKE_TWITTER_MODE")
+   :api-credentials               {:bearer-name  (get-var "API_BEARER_NAME")
+                                   :bearer-token (get-var "API_BEARER_TOKEN")}
+   :admins                        (get-var "ADMINS")
+   :db-config                     {:db       (get-var "DB_NAME" "objective8")
+                                   :user     (get-var "DB_USER" "objective8")
+                                   :password (get-var "DB_PASSWORD" "development") ;TODO password management
+                                   :host     (get-var "DB_HOST" "localhost")
+                                   :port     (get-var "DB_PORT" 5432)}
+   :google-analytics-tracking-id  (get-var "GA_TRACKING_ID")
+   :twitter-credentials           {:consumer-token (get-var "TWITTER_CONSUMER_TOKEN")
+                                   :secret-token   (get-var "TWITTER_CONSUMER_SECRET_TOKEN")}
    :stonecutter-auth-provider-url (get-var "STONECUTTER_AUTH_URL")
-   :stonecutter-client-id (get-var "STONECUTTER_CLIENT_ID")
-   :stonecutter-client-secret (get-var "STONECUTTER_CLIENT_SECRET")
-   :coracle-bearer-token (get-var "CORACLE_BEARER_TOKEN")
-   :coracle-post-uri (get-var "CORACLE_URI" "localhost:7000/activities")})
+   :stonecutter-client-id         (get-var "STONECUTTER_CLIENT_ID")
+   :stonecutter-client-secret     (get-var "STONECUTTER_CLIENT_SECRET")
+   :coracle-bearer-token          (get-var "CORACLE_BEARER_TOKEN")
+   :coracle-post-uri              (get-var "CORACLE_URI" (format "%s/activities" base-uri))})


Disable authentication.

Disable authentication.

--- src/forces_assemble/handler.clj
+++ src/forces_assemble/handler.clj
@@ -140,7 +140,7 @@

 (def no-authorization-required {})

-(def protected-resource authorization-required)
+(def protected-resource no-authorization-required)

 (def json-producer-resource
   {:available-media-types [application-json]})
@@ -153,7 +153,8 @@

 (defn is-request-from-user?
   [context expected-user-id]
-  (= expected-user-id (get-in context [::auth :user-id])))
+  ;(= expected-user-id (get-in context [::auth :user-id]))
+  true)

 (defresource user-notification-token [user-id]
   (merge protected-resource json-resource)


Fix import error

Fix import error

--- src/yada/representation.clj
+++ src/yada/representation.clj
@@ -6,7 +6,6 @@
    [cheshire.core :as json]
    [manifold.stream :refer (->source transform)])
   (:import
-   (yada.protocols ReadPortWrapper)
    (clojure.core.async.impl.channels ManyToManyChannel)
    (manifold.stream.async CoreAsyncSource)))


Don't need repl in core

Don't need repl in core

--- src-frontend/cljs/cljs_webrepl/core.cljs
+++ src-frontend/cljs/cljs_webrepl/core.cljs
@@ -5,7 +5,6 @@
    [cljsjs.clipboard :as clipboard]
    [reagent.core :as r :refer [atom]]
    [fipp.edn :as fipp]
-   [cljs-webrepl.repl :as repl]
    [cljs-webrepl.repl-thread :as repl-thread]
    [cljs-webrepl.mdl :as mdl]
    [cljs-webrepl.editor :as editor]


Restore netty "queue size" metric (#757)

--- src/riemann/transport.clj
+++ src/riemann/transport.clj
@@ -149,15 +149,18 @@
 (defonce instrumentation
   (let [^DefaultEventExecutorGroup executor shared-event-executor
         svc "riemann netty event-executor "]
-
     (reify Instrumented
       (events [this]
         (let [base {:state "ok"
                     :tags  ["riemann"]
-                    :time  (unix-time)}]
+                    :time  (unix-time)}
+              queue-size (reduce + (map #(.pendingTasks %)
+                                        (iterator-seq (.iterator executor))))]
                    (map (partial merge base)
                         [{:service (str svc "threads active")
-                          :metric (.. executor executorCount)}]))))))
+                          :metric (.. executor executorCount)}
+                         {:service (str svc "queue size")
+                          :metric queue-size}]))))))

 (defn handle
   "Handles a msg with the given core."


Remove println

Remove println

--- src/aurora/runtime/core.cljs
+++ src/aurora/runtime/core.cljs
@@ -55,7 +55,7 @@
              i 0]
         (cond
          (>= i 10) (do (println "Aborting!") cur)
-         (language/unchanged? prev cur) (do (println "Done!") cur)
+         (language/unchanged? prev cur) cur
          :else (let [next (language/tick (:rules env) cur)]
                  (language/add-facts-compat next :known|pretended aurora-facts)
                  (language/fixpoint! next)


Explicitly run reader fns, to document their structure.

--- src/klangmeister/synthesis.cljs
+++ src/klangmeister/synthesis.cljs
@@ -1,6 +1,11 @@
 (ns klangmeister.synthesis)

 ; Plumbing
+
+(defn run
+  "Convert a node (actually a reader fn) into a concrete audio node by supplying context and timing."
+  [node context at duration]
+  (node context at duration))

 (defn destination [context at duration]
   (.-destination context))
@@ -9,7 +14,7 @@
   "Plug an input into an audio parameter,
   accepting both numbers and ugens."
   (if (fn? input)
-    (.connect (input context at duration) param)
+    (-> input (run context at duration) (.connect param))
     (.setValueAtTime param input at)))

 (defn gain [level]
@@ -43,7 +48,7 @@
     (let [remainder (- duration attack decay sustain)
           hold (max 0.0 remainder)
           ugen (adshr attack decay sustain hold release)]
-      (ugen context at duration))))
+      (-> ugen (run context at duration)))))

 (defn percussive [attack decay]
   (envelope [attack 1.0] [decay 0.0]))
@@ -54,8 +59,8 @@
 (defn connect
   [ugen1 ugen2]
   (fn [context at duration]
-    (let [sink (ugen2 context at duration)]
-      (.connect (ugen1 context at duration) sink)
+    (let [sink (-> ugen2 (run context at duration))]
+      (-> ugen1 (run context at duration) (.connect sink))
       sink)))

 (defn connect-> [& nodes]
@@ -63,9 +68,9 @@

 (defn add [& ugens]
   (fn [context at duration]
-    (let [sink ((gain 1.0) context at duration)]
+    (let [sink (-> (gain 1.0) (run context at duration))]
       (doseq [ugen ugens]
-        (.connect (ugen context at duration) sink))
+        (-> ugen (run context at duration) (.connect sink)))
       sink)))

@@ -91,7 +96,7 @@
 (defn oscillator
   ([type freq detune]
    (fn [context at duration]
-     (doto ((oscillator type freq) context at duration)
+     (doto (-> (oscillator type freq) (run context at duration))
        (-> .-frequency (plug detune context at duration)))))
   ([type freq]
    (fn [context at duration]
@@ -132,4 +137,3 @@
     (let [maximum 5]
       (doto (.createDelay context maximum)
         (-> .-delayTime (plug time context at duration))))))
-