tic tac toe

tic tac toe

--- src/renderer/forge/renderer.cljs
+++ src/renderer/forge/renderer.cljs
@@ -1,4 +1,118 @@
 (ns forge.renderer
-  (:require [cljsjs.d3]))
+  (:require [reagent.core :as r]
+            [goog.dom :as d]))

-(.log js/console js/d3)
+(def empty-board [[{:size 100 :x 0   :y 0 :mark nil} {:size 100 :x 0   :y 100 :mark nil} {:size 100 :x 0   :y 200 :mark nil}]
+                  [{:size 100 :x 100 :y 0 :mark nil} {:size 100 :x 100 :y 100 :mark nil} {:size 100 :x 100 :y 200 :mark nil}]
+                  [{:size 100 :x 200 :y 0 :mark nil} {:size 100 :x 200 :y 100 :mark nil} {:size 100 :x 200 :y 200 :mark nil}]])
+
+(def st (r/atom {:size 3
+                 :turn 0
+                 :players 2
+                 :board empty-board}))
+
+(defn get-key
+  [categ]
+  (name (gensym categ)))
+
+(defn get-board
+  [board i j]
+  (get (get (:board @st) i) j))
+
+(defn take-turn
+  [x y]
+  (let [turn (:turn @st)]
+    (swap! st #(assoc % :turn (inc (:turn %))))
+    (swap! st (fn [new-st]
+                (assoc new-st :board (doall
+                                      (for [i (range 0 (:size new-st))]
+                                        (for [j (range 0 (:size new-st))
+                                              :let [item (get-board (:board new-st) i j)]]
+                                          (if (and (= (:x item) x) (= (:y item) y))
+                                            (assoc item :mark (mod turn 2))
+                                            item)))))))))
+
+(defn do-circle
+  [{:keys [x y]}]
+  [:circle {:key (get-key "circle")
+            :cx (+ x 50)
+            :cy (+ y 50)
+            :r 45
+            :stroke "red"
+            :stroke-width "2"
+            :fill "white"}])
+
+(defn do-x
+  [{:keys [x y]}]
+  (list
+    [:line {:key (get-key "line")
+            :x1 (+ x 5)
+            :y1 (+ y  5)
+            :x2 (+ x 95)
+            :y2 (+ y 95)
+            :stroke "blue"
+            :stroke-width "2"}]
+    [:line {:key (get-key "line")
+            :x1 (+ x 5)
+            :y1 (+ y 95)
+            :x2 (+ x 95)
+            :y2 (+ y  5)
+            :stroke "blue"
+            :stroke-width "2"}]))
+
+(defn show-mark
+  [mark coords]
+  (cond
+    (= mark 0) (do-circle coords)
+    (= mark 1) (do-x coords)
+    (nil? mark) nil))
+
+(defn rect
+  [{:keys [size x y mark]}]
+  (list [:rect {:key (get-key "rect")
+                :width size
+                :height size
+                :x x
+                :y y
+                :stroke "black"
+                :stroke-width 2
+                :style {:fill "white"}
+                :on-click (fn [_] (take-turn x y))}]
+        (show-mark mark {:x x :y y})))
+
+(defn board
+  []
+  [:svg {:width 300 :height 300 :style {:border "4px solid black"}}
+    (doall
+      (for [i (range 0 (:size @st))]
+        (for [j (range 0 (:size @st))]
+          (rect (get (get (:board @st) i) j)))))])
+
+(defn settings-form
+  []
+  [:form.form-inline
+    [:div.form-group
+      [:label {:for "game-mode"} "Game Mode"]
+      [:select#game-mode {:defaultValue (:players @st)}
+        [:option {:value 1} "One Player"]
+        [:option {:value 2} "Two Players"]]]
+    [:button {:type "button" :on-click (fn [] (swap! st #(assoc % :players (.-value (d/getElement "game-mode")) :board [])))} "Start"]])
+
+(defn panel
+  []
+  [:div.container
+    [:div.row
+      [:div.col-md-6
+        (settings-form)]]
+    [:hr]
+    [:div.row
+      [:div.col-md-6
+        [:div.board
+          (board)]]]])
+
+(defn init-game
+  []
+  (r/render-component [panel]
+    (.getElementById js/document "window")))
+
+(init-game)


Added process, parse-and-process, and slurp-csv.

--- src/semantic_csv/transducers.clj
+++ src/semantic_csv/transducers.clj
@@ -102,3 +102,59 @@
 ;;         ([results input]
 ;;          (if @fst
 ;;            (rf results)))))))
+
+(defn process
+  "This function wraps together the most frequently used input processing capabilities,
+  controlled by an `opts` hash with opinionated defaults:
+
+  * `:mappify` - bool; transform rows from vectors into maps using `mappify`.
+  * `:keyify` - bool; specify whether header/column names should be turned into keywords (default: `true`).
+  * `:header` - specify header to be used in mappify; as per `mappify`, first row will not be consumed as header
+  * `:structs` - bool; use structs instead of array-maps or hash-maps in mappify.
+  * `:remove-comments` - bool; remove comment lines, as specified by `:comment-re` or `:comment-char`. Also
+     removes empty lines. Defaults to `true`.
+  * `:comment-re` - specify a regular expression to use for commenting out lines.
+  * `:comment-char` - specify a comment character to use for filtering out comments; overrides comment-re.
+  * `:cast-fns` - optional map of `colname | index -> cast-fn`; row maps will have the values as output by the
+     assigned `cast-fn`.
+  * `:cast-exception-handler` - If cast-fn raises an exception, this function will be called with args
+    `colname, value`, and the result used as the parse value.
+  * `:cast-only` - Only cast the specified column(s); can be either a single column name, or a vector of them."
+  ([{:keys [mappify keyify header remove-comments comment-re comment-char structs cast-fns cast-exception-handler cast-only]
+     :or   {mappify         true
+            keyify          true
+            remove-comments true
+            comment-re      #"^\#"}
+     :as opts}]
+   (let [map-fn (when mappify
+                  (if structs
+                    (semantic-csv.transducers/structify {:keyify keyify :header header})
+                    (semantic-csv.transducers/mappify {:keyify keyify :header header}))) ;; use mappify or structify
+         remove-fn (when remove-comments
+                     (semantic-csv.transducers/remove-comments {:comment-re comment-re :comment-char comment-char}))
+         cast-with-fn (when cast-fns
+                        (semantic-csv.transducers/cast-with cast-fns {:exception-handler cast-exception-handler :only cast-only}))
+         ]
+     (apply comp (remove nil? [remove-fn map-fn cast-with-fn]))))
+  ; Use all defaults
+  ([]
+   (process {})))
+
+(defn parse-and-process
+  "This is a convenience function for reading a csv file using `clojure/data.csv` and passing it through `process`
+  with the given set of options (specified _last_ as kw_args, in contrast with our other processing functions).
+  Note that `:parser-opts` can be specified and will be passed along to `clojure-csv/parse-csv`"
+  [csv-readable & {:keys [parser-opts]
+                   :or   {parser-opts {}}
+                   :as   opts}]
+  (let [rest-options (dissoc opts :parser-opts)]
+    (transduce (process rest-options) conj []
+     (impl/apply-kwargs csv/parse-csv csv-readable parser-opts))))
+
+(defn slurp-csv
+  "This convenience function let's you `parse-and-process` csv data given a csv filename. Note that it is _not_
+  lazy, and must read in all data so the file handle can be closed."
+  [csv-filename & {:as opts}]
+  (let [rest-options (dissoc opts :parser-opts)]
+    (with-open [in-file (io/reader csv-filename)]
+       (impl/apply-kwargs parse-and-process in-file opts))))


Add display-filter call in image create example.

--- src/quil_cljs_examples/image/create.cljs
+++ src/quil_cljs_examples/image/create.cljs
@@ -17,7 +17,8 @@
 (defn draw []
 	(q/background 255)
 	(q/image @img 20 20)
-	(q/image @new-img 120 120))
+	(q/image @new-img 120 120)
+	(q/display-filter :invert))

 (defsketch create-image


Add secured-app

Add secured-app

--- src/todo_repl_webapp/handler.clj
+++ src/todo_repl_webapp/handler.clj
@@ -59,6 +59,12 @@
 (def app
   (handler/site app-routes))

+(def secured-app
+  (-> app
+    (friend/authenticate {:credential-fn
+                            (partial credentials/bcrypt-credential-fn users)
+                          :workflows [(workflows/interactive-form)]})))
+
 (defn -main [port]
   (jetty/run-jetty
     (handler/site app-routes)


Sign build-helper releases.

Sign build-helper releases.

--- etc/build-helper/project.clj
+++ etc/build-helper/project.clj
@@ -19,4 +19,5 @@
             :url "http://www.apache.org/licenses/LICENSE-2.0"
             :distribution :repo}
   :dependencies [[org.clojars.tcrawley/codox.core "0.6.3.2"]]
-  :eval-in-leiningen true)
+  :eval-in-leiningen true
+  :signing {:gpg-key "BFC757F9"})


Rework to use Scheme-style constructors and selectors.

--- Clojure/blackjack/src/blackjack/core.clj
+++ Clojure/blackjack/src/blackjack/core.clj
@@ -1,97 +1,131 @@
+  ;; To run this code: open a command prompt to the project directory, then type "lein run"
+
 (ns blackjack.core
   (:gen-class))

-(declare greedy-player-strategy many-games cautious-player-strategy inactive-player-strategy)
-
+(declare many-games
+         dealer-strategy
+         interactive-player-strategy greedy-player-strategy cautious-player-strategy inactive-player-strategy)
+
+;;; Card, deck, and game constructors and selectors.
+(defn make-card [suit kind]
+  (list suit kind))
+
+(defn card-suit [card]
+  (first card))
+
+(defn card-kind [card]
+  (second card))
 (defn new-deck []
   (for [suit (range 4)
         kind (range 1 14)]
-    {:suit suit :kind kind}))
-
+    (make-card suit kind)))
+
+(defn make-game [draw-pile player-hand dealer-hand]
+  (list draw-pile player-hand dealer-hand))
+
+(defn make-hand [card1 card2]
+  (list card1 card2))
+
+(defn add-to-hand [card hand]
+  (cons card hand))
+
+(defn draw-pile [game]
+  (first game))
+
+(defn player-hand [game]
+  (second game))
+
+(defn dealer-hand [game]
+  (second (next game)))
+
+(defn new-game []
+  (let [deck (shuffle (new-deck))
+        player (make-hand (first deck) (nth deck 2))
+        dealer (make-hand (second deck) (nth deck 3))
+        deck (drop 4 deck)]
+    (make-game deck player dealer)))
+
+
+;;; Utility functions.
+
+;; Returns a string describing a card.
 (defn card-string [card]
   (let [suits ["Spades" "Clubs" "Diamonds" "Hearts"]]
-    (str (case (:kind card)
+    (str (case (card-kind card)
            1 "Ace"
            11 "Jack"
            12 "Queen"
            13 "King"
-           (str (:kind card)))
-         " of " (nth suits (:suit card)))))
-
-(defn new-game []
-  (let [deck (shuffle (new-deck))]
-    {:player-hand (list (first deck) (second deck))
-     :dealer-hand (list (nth deck 2) (nth deck 3))
-     :deck (-> deck next next next next)}))
-
+           (str (card-kind card)))
+         " of " (nth suits (card-suit card)))))
+
+;; Gets the numeric value of a card.
 (defn card-value [card]
-  (cond (= 1 (:kind card)) 11
-        (<= 10 (:kind card)) 10
-        :else (:kind card)))
-
+  (let [kind (card-kind card)]
+    (cond (= 1 kind) 11
+          (<= 10 kind) 10
+          :else kind)))
+
+;; Gets the numeric value of a hand.
 (defn hand-total [hand]
+  ;; Find the simple sum of the card values in the hand, and also count the number of aces.
   (let [sum (reduce + 0 (map card-value hand))
-        aces (count (filter #(= 1 (:kind %)) hand))]
+        aces (count (filter #(= 1 (card-kind %)) hand))]
+    ;; If the sum is less than 21, use that sum. If it is over 21, then reduce by 10 for each ace until the score
+    ;; is under 21.
     (if (or (<= sum 22) (= 0 aces))
       sum
       (- sum (* 10 (min aces (int (Math/ceil (/ (- sum 21) 10)))))))))

+;; Causes the player to "hit". Returns a new game state in which the specified player has an additional card
+;; in their hand, with the draw-pile being reduced by the top card, and the other player's hand unchanged.
 (defn hit [game-state which-player]
-  (let [nextcard (first (:deck game-state))
-        deck (which-player game-state)
-        newdeck (cons nextcard deck)]
-    (assoc game-state
-      which-player newdeck
-      :deck (next (:deck game-state)))))
-
-(defn user-strategy [game-state]
-  "Lets the user decide whether to hit"
-  (if (< (hand-total (:player-hand game-state)) 21)
-    (do (println "hit or stay?")
-        (let [input (read-line)]
-          (if (= "hit" input)
-            (hit game-state :player-hand)
-            game-state)))
-    game-state))
-
-(defn dealer-strategy [game-state]
-  "Dealer always hits if less than 17"
-  (if (< (hand-total (:dealer-hand game-state)) 17)
-    (hit game-state :dealer-hand)
-    game-state))
-
-(defn do-turn [game-state strategy]
-  (strategy game-state))
-
-(defn user-turn [game-state]
-  (let [hand (:player-hand game-state)
+  ;; which-player will either be :player or :dealer
+  (let [next-card (first (draw-pile game-state))
+        new-player-hand (if (= :player which-player)
+                          (add-to-hand next-card (player-hand game-state))
+                          (player-hand game-state))
+        new-dealer-hand (if (= :dealer which-player)
+                          (add-to-hand next-card (dealer-hand game-state))
+                          (dealer-hand game-state))
+        new-draw-pile (next (draw-pile game-state))]
+    (make-game new-draw-pile new-player-hand new-dealer-hand)))
+
+(defn player-turn [game-state]
+  (let [hand (player-hand game-state)
         score (hand-total hand)]
     (println "Player hand:" (clojure.string/join ", " (map card-string hand))
              ";" score "points")
     (if (< score 21)
-      (let [next-state (do-turn game-state inactive-player-strategy)]
-        (if (not= (count hand) (count (:player-hand next-state)))
-          (user-turn next-state)
+      (let [next-state (interactive-player-strategy game-state)]
+        (if (not= (count hand) (count (player-hand next-state)))
+          (player-turn next-state)
           next-state))
       game-state)))

 (defn dealer-turn [game-state]
-  (let [hand (:dealer-hand game-state)
+  (let [hand (dealer-hand game-state)
         score (hand-total hand)]
   (println "Dealer's hand:" (clojure.string/join ", " (map card-string hand))
            ";" score "points")
-  (let [next-state (do-turn game-state dealer-strategy)]
-    (if (and (<= (hand-total (:player-hand game-state)) 21)
-             (not= (count hand) (count (:dealer-hand next-state))))
+  (let [next-state (dealer-strategy game-state)]
+    (if (and (<= (hand-total (player-hand game-state)) 21)
+             (not= (count hand) (count (dealer-hand next-state))))
       (do (println "Dealer hits")
           (dealer-turn next-state))
       next-state))))

+
+;; Plays one full game of blackjack using the given new game state. Returns 0 if the game is a tie,
+;; 1 if the player wins, -1 if the dealer wins.
 (defn one-game [game-state]
-  (println "Dealer is showing" (card-string (first (:dealer-hand game-state))))
-  (let [end-game (dealer-turn (user-turn game-state))
-        dealer-score (hand-total (:dealer-hand end-game))
-        player-score (hand-total (:player-hand end-game))]
+  (println "Dealer is showing" (card-string (first (dealer-hand game-state))))
+  (let [after-player (player-turn game-state)
+        end-game (dealer-turn after-player)
+        dealer-score (hand-total (dealer-hand end-game))
+        player-score (hand-total (player-hand end-game))]
+    ;; Player wins if player score is no larger than 21 AND (player score is greater than dealer, or dealer > 21).
     (if (and (<= player-score 21) (or (> player-score dealer-score) (> dealer-score 21)))
       1
       (if (= player-score dealer-score)
@@ -100,42 +134,74 @@

 (defn -main
   [& args]
-  ;(let [winner (one-game (new-game))]
-  ;  (println (case winner
-  ;             1 "Player wins!"
-  ;             -1 "Dealer wins!"
-  ;             :else "Tie game")))
-  ;)
-  (let [totals (many-games 1000 0 0 0)]
-    (println totals)))
-
-(defn many-games [n player-wins dealer-wins ties]
   (let [winner (one-game (new-game))]
-    (if (= n 0)
-      {:player-wins player-wins :dealer-wins dealer-wins :ties ties}
-      (many-games
-        (- n 1)
-        (if (= winner 1) (+ player-wins 1) player-wins)
-        (if (= winner -1) (+ dealer-wins 1) dealer-wins)
-        (if (= winner 0) (+ ties 1) ties)))))
-
+    (println (case winner
+               1 "Player wins!"
+               -1 "Dealer wins!"
+               :else "Tie game")))
+  )
+  ;(let [totals (map vector (many-games 1000 0 0 0) ["player" "dealer" "tie"])]
+    ;(println totals)))
+
+
+;;; Automation
+
+;; Runs n individual games. Returns a list of 3 values: the number of times the player won, the number of times
+;; the dealer won, the number of ties.
+(defn many-games
+  ([n] (many-games n 0 0 0))
+  ([n player-wins dealer-wins ties]
+   (let [winner (one-game (new-game))]
+     (if (= n 0)
+       (list player-wins dealer-wins ties)
+       (many-games
+         (- n 1)
+         (if (= winner 1) (+ player-wins 1) player-wins)
+         (if (= winner -1) (+ dealer-wins 1) dealer-wins)
+         (if (= winner 0) (+ ties 1) ties))))))
+
+
+  ;;; Strategies.
+;;; A strategy is a function that takes the current game state and returns a new game state representing a single
+;;; decision made by the corresponding player.
+
+;; Dealer strategies
+;; The dealer does not get to make decisions: they always hit if less than 17, and never if at or above 17.
+(defn dealer-strategy [game-state]
+  (if (< (hand-total (dealer-hand game-state)) 17)
+    (hit game-state :dealer)
+    game-state))
+
+;; Player strategies
+;; The interactive strategy bases whether to hit or stay on input from the user, unless they are at
+;; 21 or over.
+(defn interactive-player-strategy [game-state]
+    (if (< (hand-total (player-hand game-state)) 21)
+      (do (println "(h)it or (s)tay?")
+          (flush)
+          (let [input (read-line)]
+            (if (= "h" input)
+              (hit game-state :player)
+              game-state)))
+      game-state))
+
+;; The greedy player strategy always hits until they reach or exceed 21.
 (defn greedy-player-strategy [game-state]
-  "A greedy player always hits until they get 21 or bust"
   (if (< (hand-total (:player-hand game-state)) 21)
     (do (println "Player hits")
         (hit game-state :player-hand))
     (do (println "Player stays")
         game-state)))

+;; The cautious player strategy only hits when under 15.
 (defn cautious-player-strategy [game-state]
-  "A cautious player will only hit when under 15"
   (if (< (hand-total (:player-hand game-state)) 15)
     (do (println "Player hits")
         (hit game-state :player-hand))
     (do (println "P-layer stays")
         game-state)))

+;; The inactive player strategy never hits.
 (defn inactive-player-strategy [game-state]
-  "An inactive player never hits"
   (do (println "Player stays")
       game-state))


setTimeout --> setInterval

setTimeout --> setInterval

--- cljs-admin/tourneybot_admin/core.cljs
+++ cljs-admin/tourneybot_admin/core.cljs
@@ -118,7 +118,7 @@
       (update-games! password games always-nil always-nil))))

 (when-not in-dev-mode?
-  (js/setTimeout upload-games! upload-rate-ms))
+  (js/setInterval upload-games! upload-rate-ms))

 ;;------------------------------------------------------------------------------
 ;; Misc


Change 'location' prop to 'href'

Change 'location' prop to 'href'

--- src-cljs/frontend/components/pieces/page_header.cljs
+++ src-cljs/frontend/components/pieces/page_header.cljs
@@ -196,11 +196,12 @@
              (when (= platform "2.0")
                (popover/tooltip {:body
                                  (html [:span "This build ran on 2.0. "
-                                        [:a {:href "https://discuss.circleci.com/c/circleci-2-0"
-                                             :target "_blank"
-                                             :on-click #((om/get-shared owner :track-event) {:event-type :beta-link-clicked
-                                                                                :properties {:location "build-page"}})}
-                                         "Learn more"]])
+                                        (let [href "https://discuss.circleci.com/c/circleci-2-0"]
+                                          [:a {:href href
+                                               :target "_blank"
+                                               :on-click #((om/get-shared owner :track-event) {:event-type :beta-link-clicked
+                                                                                :properties {:href href}})}
+                                           "Learn more"])])
                                  :placement :bottom}
                                (engine-2)))]
             [:.actions actions]]))))))


better documentation site

better documentation site

--- docs/src/cljs/om_bootstrap/docs.cljs
+++ docs/src/cljs/om_bootstrap/docs.cljs
@@ -9,6 +9,7 @@
             [om-bootstrap.nav :as n]
             [om-bootstrap.panel :as p]
             [om-bootstrap.random :as r]
+            [om-bootstrap.util :as u]
             [om-tools.core :refer-macros [defcomponent defcomponentk]]
             [om-tools.dom :as d :include-macros true]
             [schema.core :as s]
@@ -18,186 +19,217 @@
                    [schema.macros :as sm])
   (:import [goog.history EventType Html5History]))

+;; ## Helpers
+
+(defn example
+  ([item] (d/div {:class "bs-example"} item))
+  ([props item]
+     (d/div (u/merge-props props {:class "bs-example"})
+            item)))
+
 ;; ## Button Examples

 (defn button-example []
-  (b/toolbar {}
-             (b/button {} "Default")
-             (b/button {:bs-style "primary"} "Primary")
-             (b/button {:bs-style "success"} "Success")
-             (b/button {:bs-style "info"} "Info")
-             (b/button {:bs-style "warning"} "Warning")
-             (b/button {:bs-style "danger"} "Danger")
-             (b/button {:bs-style "link"} "Link")))
+  (example
+   (b/toolbar {}
+              (b/button {} "Default")
+              (b/button {:bs-style "primary"} "Primary")
+              (b/button {:bs-style "success"} "Success")
+              (b/button {:bs-style "info"} "Info")
+              (b/button {:bs-style "warning"} "Warning")
+              (b/button {:bs-style "danger"} "Danger")
+              (b/button {:bs-style "link"} "Link"))))

 (defn button-sizing []
-  (d/div
-   (b/toolbar {}
-              (b/button {:bs-style "primary" :bs-size "large"} "Large button")
-              (b/button {:bs-size "large"} "Large button"))
-   (b/toolbar {}
-              (b/button {:bs-style "primary" :bs-size "large"} "Default button")
-              (b/button {:bs-size "large"} "Large button"))
-   (b/toolbar {}
-              (b/button {:bs-style "primary" :bs-size "large"} "Small button")
-              (b/button {:bs-size "large"} "Large button"))
-   (b/toolbar {}
-              (b/button {:bs-style "primary" :bs-size "xsmall"}
-                        "Extra small button")
-              (b/button {:bs-size "large"} "Large button"))))
+  (example
+   [(b/toolbar {}
+                (b/button {:bs-style "primary" :bs-size "large"} "Large button")
+                (b/button {:bs-size "large"} "Large button"))
+    (b/toolbar {}
+               (b/button {:bs-style "primary"} "Default button")
+               (b/button {} "Default button"))
+    (b/toolbar {}
+               (b/button {:bs-style "primary" :bs-size "small"} "Small button")
+               (b/button {:bs-size "small"} "Small button"))
+    (b/toolbar {}
+               (b/button {:bs-style "primary" :bs-size "xsmall"} "Extra small button")
+               (b/button {:bs-size "xsmall"} "Extra small button"))]))

 (defn button-block []
   (d/div
-   (d/h3 "Button Examples")
+   (d/h1 {:id "buttons" :class "page-header"} "Buttons " (d/small "Button"))
+   (d/h2 {:id "button-options"} "Options")c
+
+   (d/p "Use any of the available button style types to quickly create a styled button. Just modify the " (d/code ":bs-style" ) " prop.")
    (button-example)
-   (d/h3 "Button Sizing")
+   (d/div {:class "bs-callout bs-callout-warning"}
+          (d/h4 "Button Spacing")
+          (d/p "Because React doesn't output newlines between elements, buttons on the same line are displayed flush against each other. To preserve the spacing between multiple inline buttons, wrap your button group in " (d/code "b/toolbar") "."))
+   (d/h2 "Sizes")
+   (d/p "Fancy larger or smaller buttons? Add "
+        (d/code ":bs-size large") ", "
+        (d/code ":bs-size small") ", or "
+        (d/code ":bs-size xsmall") " for additional sizes.")
    (button-sizing)
    (d/p "Create block level buttons—those that span the full width of a parent— by adding the block prop.")
-   (d/div {:class "well"
-           :style {:max-width 400
-                   :margin "0 auto 10px"}}
-          (b/button {:bs-style "primary" :bs-size "large" :block? true}
-                    "Block level button")
-          (b/button {:bs-size "large" :block? true}
-                    "Block level button"))
+   (example
+    (d/div {:class "well"
+            :style {:max-width 400
+                    :margin "0 auto 10px"}}
+           (b/button {:bs-style "primary" :bs-size "large" :block? true}
+                     "Block level button")
+           (b/button {:bs-size "large" :block? true}
+                     "Block level button")))
    (d/p "To set a buttons active state simply set the components active prop.")
-   (b/toolbar {}
-              (b/button {:bs-style "primary" :bs-size "large" :active? true}
-                        "Primary button")
-              (b/button {:bs-size "large" :bs-style "default" :active? true}
-                        "Button"))
+   (example
+    (b/toolbar {}
+               (b/button {:bs-style "primary" :bs-size "large" :active? true}
+                         "Primary button")
+               (b/button {:bs-size "large" :bs-style "default" :active? true}
+                         "Button")))
    (d/p "Make buttons look unclickable by fading them back 50%. To do
    this add the disabled attribute to buttons.")
-   (b/toolbar {}
-              (b/button {:bs-style "primary" :bs-size "large" :disabled? true}
-                        "Primary button")
-              (b/button {:bs-size "large" :bs-style "default" :disabled? true}
-                        "Button"))
+   (example
+    (b/toolbar {}
+               (b/button {:bs-style "primary" :bs-size "large" :disabled? true}
+                         "Primary button")
+               (b/button {:bs-size "large" :bs-style "default" :disabled? true}
+                         "Button")))
    (d/h3 "Button Groups")
    (d/p "Wrap a series of buttons in a button group.")
-   (b/button-group {}
-                   (b/button {} "Left")
-                   (b/button {} "Middle")
-                   (b/button {} "Right"))
+   (example
+    (b/button-group {}
+                    (b/button {} "Left")
+                    (b/button {} "Middle")
+                    (b/button {} "Right")))
    (d/p "Combine sets of buttongroups into a button toolbar for more
    complex components.")
-   (b/toolbar {}
-              (b/button-group {} (for [i (range 4)]
-                                   (b/button {} (str (inc i)))))
-              (b/button-group {} (for [i (range 4 7)]
-                                   (b/button {} (str (inc i)))))
-              (b/button-group {} (b/button {} 8)))
+   (example
+    (b/toolbar {}
+               (b/button-group {} (for [i (range 4)]
+                                    (b/button {} (str (inc i)))))
+               (b/button-group {} (for [i (range 4 7)]
+                                    (b/button {} (str (inc i)))))
+               (b/button-group {} (b/button {} 8))))

    (d/p "Instead of applying button sizing props to every button in a group, just add bs-size prop to the <ButtonGroup />.")
-   (let [buttons (for [s ["Left" "Middle" "Right"]]
-                   (b/button {} s))]
-     (b/toolbar {}
-                (b/toolbar {} (b/button-group {:bs-size "large"} buttons))
-                (b/toolbar {} (b/button-group {} buttons))
-                (b/toolbar {} (b/button-group {:bs-size "small"} buttons))
-                (b/toolbar {} (b/button-group {:bs-size "xsmall"} buttons))))))
+   (example
+    (let [buttons (for [s ["Left" "Middle" "Right"]]
+                    (b/button {} s))]
+      (b/toolbar {}
+                 (b/toolbar {} (b/button-group {:bs-size "large"} buttons))
+                 (b/toolbar {} (b/button-group {} buttons))
+                 (b/toolbar {} (b/button-group {:bs-size "small"} buttons))
+                 (b/toolbar {} (b/button-group {:bs-size "xsmall"} buttons)))))))

 ;; ## Panel Examples

 (defn panel-example []
   (d/div
    (d/p "By default, all the <Panel /> does is apply some basic border and padding to contain some content.")
-   (p/panel {} "Basic panel example.")
+   (example
+    (p/panel {} "Basic panel example."))
    (d/p "Easily add a heading container to your panel with the header prop.")
-   (p/panel {:header "Panel heading without title"}
-            "Panel content")
-   (p/panel {:header (d/h3 "Panel title")}
-            "Panel content")
+   (example
+    [(p/panel {:header "Panel heading without title"}
+              "Panel content")
+     (p/panel {:header (d/h3 "Panel title")}
+              "Panel content")])
    (d/p "Pass buttons or secondary text in the footer prop. Note that panel footers do not inherit colors and borders when using contextual variations as they are not meant to be in the foreground.")
-   (p/panel {:footer "Panel footer"} "Panel content")
+   (example
+    (p/panel {:footer "Panel footer"} "Panel content"))
    (d/p "Like other components, easily make a panel more meaningful to a particular context by adding a :bs-style prop.")
-   (for [style [nil "primary" "success" "info" "warning" "danger"]]
-     (p/panel (merge {:header (d/h3 "Panel title")}
-                     (when style {:bs-style style}))
-              "Panel content"))))
+   (example
+    (for [style [nil "primary" "success" "info" "warning" "danger"]]
+      (p/panel (merge {:header (d/h3 "Panel title")}
+                      (when style {:bs-style style}))
+               "Panel content")))))

 ;; ## Jumbotron Examples

 (defn jumbotron-example []
-  (r/jumbotron {}
-               (d/h1 "Hello, World!")
-               (d/p "This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.")
-               (d/p (b/button {:bs-style "primary"} "Learn More"))))
+  (example
+   (r/jumbotron {}
+                (d/h1 "Hello, World!")
+                (d/p "This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.")
+                (d/p (b/button {:bs-style "primary"} "Learn More")))))

 ;; ## Label Examples

 (defn label-examples []
-  (d/div
-   (d/h1 "Label " (r/label {} "New"))
-   (d/h2 "Label " (r/label {} "New"))
-   (d/h3 "Label " (r/label {} "New"))
-   (d/h4 "Label " (r/label {} "New"))
-   (d/h5 "Label " (r/label {} "New"))
-   (d/p "Label " (r/label {} "New"))))
+  (example
+   (d/div
+    (d/h1 "Label " (r/label {} "New"))
+    (d/h2 "Label " (r/label {} "New"))
+    (d/h3 "Label " (r/label {} "New"))
+    (d/h4 "Label " (r/label {} "New"))
+    (d/h5 "Label " (r/label {} "New"))
+    (d/p "Label " (r/label {} "New")))))

 (defn label-variations []
-  (d/div
-   (r/label {:bs-style "default"} "Default")
-   (r/label {:bs-style "primary"} "Primary")
-   (r/label {:bs-style "success"} "Success")
-   (r/label {:bs-style "info"} "Info")
-   (r/label {:bs-style "warning"} "Warning")
-   (r/label {:bs-style "danger"} "Danger")))
+  (example
+   [(r/label {:bs-style "default"} "Default")
+    (r/label {:bs-style "primary"} "Primary")
+    (r/label {:bs-style "success"} "Success")
+    (r/label {:bs-style "info"} "Info")
+    (r/label {:bs-style "warning"} "Warning")
+    (r/label {:bs-style "danger"} "Danger")]))

 ;; ## Well Examples

 (def default-well
-    (r/well {} "Look, I'm in a well!"))
+  (example
+   (r/well {} "Look, I'm in a well!")))

 (def optional-well-classes
-  (d/div
-   (r/well {:bs-size "large"} "Look, I'm in a large well!")
-   (r/well {:bs-size "small"} "Look, I'm in a small well!")))
+  (example
+   [(r/well {:bs-size "large"} "Look, I'm in a large well!")
+    (r/well {:bs-size "small"} "Look, I'm in a small well!")]))

 ;; ## Page Header

 (def header-example
-  (r/page-header {} "Example page header "
-                 (d/small "Subtext for header")))
+  (example
+   (r/page-header {} "Example page header "
+                  (d/small "Subtext for header"))))

 ;; ## Grid

 (def grid-example
   ;; Clearly this doesn't give me the coloring I need, but it's a
   ;; start toward what the bootstrap docs page gives me.
-  (d/div {:class "bs-example grids-examples"}
-         (g/grid {}
-                 (g/row {:class "show-grid"}
-                        (g/col {:xs 12 :md 8}
-                               (d/code {} "(g/col {:xs 12 :md 8})"))
-                        (g/col {:xs 6 :md 4}
-                               (d/code {} "(g/col {:xs 6 :md 4})")))
-                 (g/row {:class "show-grid"}
-                        (g/col {:xs 6 :md 4}
-                               (d/code {} "(g/col {:xs 6 :md 4})"))
-                        (g/col {:xs 6 :md 4}
-                               (d/code {} "(g/col {:xs 6 :md 4})"))
-                        (g/col {:xs 6 :md 4}
-                               (d/code {} "(g/col {:xs 6 :md 4})")))
-                 (g/row {:class "show-grid"}
-                        (g/col {:xs 6 :xs-offset 6}
-                               (d/code {} "(g/col {:xs 6 :xs-offset 6})")))
-                 (g/row {:class "show-grid"}
-                        (g/col {:md 6 :md-push 6}
-                               (d/code {} "(g/col {:md 6 :md-push 6})"))
-                        (g/col {:md 6 :md-pull 6}
-                               (d/code {} "(g/col {:md 6 :md-push 6})"))))))
+  (example {:class "grids-examples"}
+           (g/grid {}
+                   (g/row {:class "show-grid"}
+                          (g/col {:xs 12 :md 8}
+                                 (d/code {} "(g/col {:xs 12 :md 8})"))
+                          (g/col {:xs 6 :md 4}
+                                 (d/code {} "(g/col {:xs 6 :md 4})")))
+                   (g/row {:class "show-grid"}
+                          (g/col {:xs 6 :md 4}
+                                 (d/code {} "(g/col {:xs 6 :md 4})"))
+                          (g/col {:xs 6 :md 4}
+                                 (d/code {} "(g/col {:xs 6 :md 4})"))
+                          (g/col {:xs 6 :md 4}
+                                 (d/code {} "(g/col {:xs 6 :md 4})")))
+                   (g/row {:class "show-grid"}
+                          (g/col {:xs 6 :xs-offset 6}
+                                 (d/code {} "(g/col {:xs 6 :xs-offset 6})")))
+                   (g/row {:class "show-grid"}
+                          (g/col {:md 6 :md-push 6}
+                                 (d/code {} "(g/col {:md 6 :md-push 6})"))
+                          (g/col {:md 6 :md-pull 6}
+                                 (d/code {} "(g/col {:md 6 :md-push 6})"))))))

 ;; ## Tooltip

 (def tooltip-example
-  (d/div {:class "bs-example"}
-         (d/div {:style {:height 50}}
-                (r/tooltip {:placement "right"
-                            :position-left 150
-                            :position-top 50}
-                           (d/strong "Holy guacamole!")
-                           "Check this info."))))
+  (example {:style {:height 50}}
+           (r/tooltip {:placement "right"
+                       :position-left 150
+                       :position-top 50}
+                      (d/strong "Holy guacamole!")
+                      "Check this info.")))

 (comment

@@ -237,9 +269,10 @@

 (def alert-example
   "Basic alert styles:"
-  (r/alert {:bs-style "warning"}
-           (d/strong "Holy guacamole!")
-           "Best check yo self, you're not looking too good."))
+  (example
+   (r/alert {:bs-style "warning"}
+            (d/strong "Holy guacamole!")
+            "Best check yo self, you're not looking too good.")))

 (comment
   "TODO: Closeable alerts, just pass in a onDismiss function."
@@ -252,44 +285,44 @@
 ;; ## Popovers

 (def popover-example
-  (d/div {:class "bs-example"}
-         (d/div {:style {:height 120}}
-                (r/popover {:placement "right"
-                            :position-left 200
-                            :position-top 50
-                            :title "Popover right"}
-                           "And here's some "
-                           (d/strong "amazing")
-                           " content. It's very engaging. Right?"))))
+  (example
+   (d/div {:style {:height 120}}
+          (r/popover {:placement "right"
+                      :position-left 200
+                      :position-top 50
+                      :title "Popover right"}
+                     "And here's some "
+                     (d/strong "amazing")
+                     " content. It's very engaging. Right?"))))

 ;; ## Navs

 (def nav-example
   (let [on-select (fn [k _] (js/alert (str "Selected " k)))
-        example (fn [style]
-                  (n/nav {:bs-style style}
-                         (n/nav-item {:key 1 :href "/home" :active? true
-                                      :on-select on-select}
-                                     "nav-item 1 content")
-                         (n/nav-item {:key 2 :href "/home"
-                                      :on-select on-select}
-                                     "nav-item 2 content")
-                         (n/nav-item {:key 3 :href "/home" :disabled? true
-                                      :on-select on-select}
-                                     "nav-item 3 content")))]
+        nav-example (fn [style]
+                      (example
+                       (n/nav {:bs-style style}
+                              (n/nav-item {:key 1 :href "/home" :active? true
+                                           :on-select on-select}
+                                          "nav-item 1 content")
+                              (n/nav-item {:key 2 :href "/home"
+                                           :on-select on-select}
+                                          "nav-item 2 content")
+                              (n/nav-item {:key 3 :href "/home" :disabled? true
+                                           :on-select on-select}
+                                          "nav-item 3 content"))))]
     (d/div
      (d/p "Navs come in two styles, pills:")
-     (example "pills")
+     (nav-example "pills")
      (d/p "And tabs:")
-     (example "tabs"))))
+     (nav-example "tabs"))))

 ;; ## Badges

 (def badge-example
   (d/div
    (d/p "Easily highlight new or unread items by adding a <Badge> to links, Bootstrap navs, and more.")
-   (d/div {:class "bs-example grids-examples"}
-          (d/p "Badges" (r/badge {} 42)))))
+   (example (d/p "Badges" (r/badge {} 42)))))

 ;; ## Final Page Loading

@@ -299,33 +332,80 @@
   []
   (render [_]
           (d/div
-           (button-block)
-           (d/h3 "Panels")
-           (panel-example)
-           (d/h3 "Jumbotron")
-           (jumbotron-example)
-           (d/h3 "Label Examples")
-           (label-examples)
-           (d/h3 "Label Variations")
-           (label-variations)
-           (d/h3 "Well!")
-           default-well
-           optional-well-classes
-           (d/h3 "Page Header")
-           header-example
-           (d/h3 "Grid")
-           grid-example
-           (d/h3 "Tooltip")
-           tooltip-example
-           (d/h3 "Positioned Tooltip (in progress)")
-           (d/h3 "Alert")
-           alert-example
-           (d/h3 "Popover")
-           popover-example
-           (d/h3 "Nav")
-           nav-example
-           (d/h3 "Badges")
-           badge-example)))
+           (d/div {:class "bs-docs-header" :id "content"}
+                  (d/div {:class "container"}
+                         (d/h1 "Components")))
+           (d/div
+            {:class "container bs-docs-container"}
+            (d/div
+             {:class "row"}
+             (d/div
+              {:class "col-md-9" :role "main"}
+              (d/div {:class "lead"}
+                     "This page lists the Om-Bootstrap components. For each component, we provide:"
+                     (d/ul
+                      (d/li "Usage instructions")
+                      (d/li "An example code snippet")
+                      (d/li "The rendered result of the example snippet"))
+                     "Click \"show code\" below the rendered component to reveal the snippet.")
+              (d/div
+               {:class "bs-docs-section"}
+               (button-block)
+               (d/h3 "Panels")
+               (panel-example)
+               (d/h3 "Jumbotron")
+               (jumbotron-example)
+               (d/h3 "Label Examples")
+               (label-examples)
+               (d/h3 "Label Variations")
+               (label-variations)
+               (d/h3 "Well!")
+               default-well
+               optional-well-classes
+               (d/h3 "Page Header")
+               header-example
+               (d/h3 "Grid")
+               grid-example
+               (d/h3 "Tooltip")
+               tooltip-example
+               (d/h3 "Positioned Tooltip (in progress)")
+               (d/h3 "Alert")
+               alert-example
+               (d/h3 "Popover")
+               popover-example
+               (d/h3 "Nav")
+               nav-example
+               (d/h3 "Badges")
+               badge-example))
+             (d/div
+              {:class "col-md-3"}
+              (d/div {:class "bs-docs-sidebar hidden-print"
+                      :role "complementary"}
+                     (n/nav
+                      {:class "bs-docs-sidenav"}
+                      (n/nav-item {:href "#buttons"} "Buttons")
+                      (n/nav-item {} "Panels")
+                      (n/nav-item {} "Modals")
+                      (n/nav-item {} "Tooltips")
+                      (n/nav-item {} "Popovers")
+                      (n/nav-item {} "Progress bars")
+                      (n/nav-item {} "Navs")
+                      (n/nav-item {} "Navbars")
+                      (n/nav-item {} "Toggleable Tabs")
+                      (n/nav-item {} "Pager")
+                      (n/nav-item {} "Alerts")
+                      (n/nav-item {} "Carousels")
+                      (n/nav-item {} "Grids")
+                      (n/nav-item {} "List group")
+                      (n/nav-item {} "Labels")
+                      (n/nav-item {} "Badges")
+                      (n/nav-item {} "Jumbotron")
+                      (n/nav-item {} "Page header")
+                      (n/nav-item {} "Wells")
+                      (n/nav-item {} "Glyphicons")
+                      (n/nav-item {} "Tables")
+                      (n/nav-item {} "Input"))
+                     (d/a {:class "back-to-top" :href "#top"} "Back to top"))))))))

 (defonce app-state
   (atom {:text "Hi!"}))


Make beachball rotation speed controlable

--- src/clojure/playasophy/wonderdome/mode/beachball.clj
+++ src/clojure/playasophy/wonderdome/mode/beachball.clj
@@ -7,6 +7,8 @@
     [playasophy.wonderdome.util.control :as control]))

+(def speed-bounds [(/ sphere/tau 36) (* sphere/tau 3)])
+
 (defrecord BeachballMode
   [theta speed colors]

@@ -14,30 +16,24 @@

   (update
     [this event]
-    (condp = [(:type event) (:input event)]
+    (case [(:type event) (:input event)]
       [:time/tick nil]
       (let [elapsed (or (:elapsed event) 0.0)
             delta (* (/ elapsed 1000) speed)
             theta' (mod (+ theta delta) sphere/tau)]
         (assoc this :theta theta'))

-#_(      [:button/press :L]
-      (assoc this :speed 1)
+      [:button/press :L]
+      (assoc this :speed (first speed-bounds))

       [:button/press :R]
-      (assoc this :speed 10)
-
-      [:button/press :A]
-      (assoc this :length 2)
-
-      [:button/press :B]
-      (assoc this :length 10)
-
-      [:axis/direction :x-axis]
-      (assoc this :hue (control/adjust hue event :rate 0.20 :min-val -1.0 :max-val 2.0))
+      (assoc this :speed (second speed-bounds))

       [:axis/direction :y-axis]
-      (assoc this :saturation (control/adjust saturation event :rate 0.3)))
+      (assoc this :speed (control/adjust speed event
+                                         :rate (/ sphere/tau 12)
+                                         :min-val (first speed-bounds)
+                                         :max-val (second speed-bounds)))

       this))


Add test for fix of #120

Add test for fix of #120

--- test/clj/lambdacd/steps/support_test.clj
+++ test/clj/lambdacd/steps/support_test.clj
@@ -45,8 +45,14 @@

 (defn some-step-saying-hello [args ctx]
   {:status :success :out "hello"})
+
 (defn some-step-saying-world [args ctx]
   {:status :success :out "world"})
+
+(defn some-step-printing-to-intermediate-output [args ctx]
+  (capture-output ctx
+    (println "helloworld")
+    {:status :success}))

 (defn some-step-with-additional-arguments [args ctx hello world]
   {:status :success :hello hello :world world})
@@ -75,8 +81,6 @@
       (print-to-output ctx printer "Hello")
       (print-to-output ctx printer "World")
       (is (= "Hello\nWorld\n" (printed-output printer))))))
-
-; TODO: add tests that show that intermediate results of chaining work

 (deftest chain-steps-test
   (testing "chain-steps and always-chain-steps"
@@ -109,6 +113,15 @@
                (testing "that overlapping string-outputs get concatenated"
                  (is (map-containing {:status :success
                                       :out    "hello\nworld"} (unit-under-test {} (some-ctx) some-step-saying-hello some-step-saying-world))))
+               (testing "that intermediate outputs are kept while step is running"
+                 (let [result-channel (async/chan 100)
+                       ctx (some-ctx-with :result-channel result-channel)]
+                   (unit-under-test {} ctx some-step-saying-hello some-step-printing-to-intermediate-output)
+                   (is (= [{:status :running}
+                           {:status :success :out "hello"}
+                           {:status :running :out "hello"}
+                           {:status :running :out "hello\nhelloworld\n"}
+                           {:status :success :out "hello\nhelloworld\n"}] (slurp-chan result-channel)))))
                (testing "that the context is passed to all the steps"
                  (let [result (unit-under-test {} (some-ctx-with :v 42)
                                               some-step-returning-the-context-passed-in


todomvc: bump carry dep

todomvc: bump carry dep

--- examples/todomvc/project.clj
+++ examples/todomvc/project.clj
@@ -26,7 +26,7 @@
                                            [cljsjs/jquery-ui "1.11.4-0"]
                                            [cljsjs/filesaverjs "1.1.20151003-0"]]}

-             :clojars-deps {:dependencies [[carry "0.2.0"]
+             :clojars-deps {:dependencies [[carry "0.3.0"]
                                            [carry-debugger "0.3.0"]
                                            [carry-history "0.3.0"]
                                            [carry-logging "0.1.0"]


Removing expectation on current time since timers no longer take start-time as a parameter

--- test/time_tracker/timers/pubsub_test.clj
+++ test/time_tracker/timers/pubsub_test.clj
@@ -40,8 +40,7 @@
                               :timer-id     (:id timer1)
                               :started-time current-time}))
         (let [command-response (test-helpers/try-take!! response-chan)]
-          (is (= (:id timer1) (:id command-response)))
-          (is (= current-time (:started-time command-response)))))
+          (is (= (:id timer1) (:id command-response)))))

       (testing "Unowned timer"
         (ws/send-msg socket (json/encode


Fix tests

Fix tests

--- backend/src/akvo/lumen/lib/transformation/engine.clj
+++ backend/src/akvo/lumen/lib/transformation/engine.clj
@@ -257,6 +257,10 @@
   (throw (ex-info (str "unimplemented defmulti columns-used for tx: " (:op applied-transformation))
                   {:transformation applied-transformation})))

+(defmethod columns-used nil
+  [applied-transformation columns]
+  [])
+
 (defn undif-columns [tx columns]
   (let [columns (reduce #(assoc % (:columnName %2) %2) {} columns)
         cc (->> tx :changedColumns vals)


(PDB-5216) Test stream-query-result query id logging too

It's the other query path.

--- test/puppetlabs/puppetdb/http/query_logging_test.clj
+++ test/puppetlabs/puppetdb/http/query_logging_test.clj
@@ -1,9 +1,13 @@
 (ns puppetlabs.puppetdb.http.query-logging-test
   (:require
+   [clojure.java.io :as io]
    [clojure.string :as str]
    [clojure.test :refer :all]
+   [clojure.walk :refer [keywordize-keys]]
    [puppetlabs.kitchensink.core :as kitchensink]
+   [puppetlabs.puppetdb.cheshire :as json]
    [puppetlabs.puppetdb.cli.services :as svcs]
+   [puppetlabs.puppetdb.testutils.catalogs :refer [replace-catalog]]
    [puppetlabs.puppetdb.testutils.db :refer [with-test-db *db*]]
    [puppetlabs.puppetdb.testutils.http
     :refer [call-with-http-app query-response with-http-app*]]
@@ -41,17 +45,27 @@
 (defn prep-logs [logs]
   (->> @logs (map :message) keep-only-pdbquery-logs))

+(def catalog-1
+  (-> "puppetlabs/puppetdb/cli/export/tiny-catalog.json"
+      io/resource slurp json/parse-string keywordize-keys))
+
 (deftest queries-are-logged-when-log-queries-is-true
   (tk-log/with-log-level "puppetlabs.puppetdb.query-eng" :debug
     (with-test-db
+      (replace-catalog catalog-1)
       (with-http-app* #(assoc % :log-queries true)
         (doseq [[query ast-exp sql-exp]
+                ;; produce-streaming-body
                 [[["/v4" ["from" "nodes"]]
                   "\"from\" \"nodes\""
                   "latest_report_noop_pending"]
                  [["/v4" ["from" "facts"]]
                   "\"from\" \"facts\""
-                  "(jsonb_each((stable||volatile)))"]]]
+                  "(jsonb_each((stable||volatile)))"]
+                 ;; stream-query-result
+                 [["/v4/catalogs/myhost.localdomain" []]
+                  "\"from\" \"catalogs\""
+                  "row_to_json(edge_data)"]]]
           (with-logged-event-maps events
             (is (= 200 (:status (apply query-response :get query))))


minor fixes

minor fixes

--- core/src/samsara_core/main.clj
+++ core/src/samsara_core/main.clj
@@ -159,7 +159,8 @@
 (defn show-console-progress!
   [config]
   (if (-> config :console-progress :enabled)
-    (let [topic (-> config :topics :input-topic)
+    ;; TODO: fix this: shows only one stream stats
+    (let [topic (-> config :streams first :input-topic)
           metric (str "pipeline." topic ".in.size")
           sleep-time (-> config :console-progress :display-every)]
       (stoppable-thread
@@ -215,8 +216,9 @@

 (defn start-processing! [config-file]
-  (let [{{:keys [input-topic input-partitions output-topic]}
-         :topics :as config} (init! config-file)
+  ;; TODO: only displaying the first stream
+  (let [{[{:keys [input-topic input-partitions output-topic]}]
+         :streams :as config} (init! config-file)
          input-partitions (if (= input-partitions identity) :all input-partitions)]
     ;; starting nrepl
     (start-nrepl! (:nrepl config))


ignore output from inactive containers

ignore output from inactive containers

--- frontend/controllers/ws.cljs
+++ frontend/controllers/ws.cljs
@@ -65,15 +65,21 @@

 (defmethod ws-event :build/append-action
   [pusher-imp message {:keys [data channel-name]} state]
-  (let [build (:current-build state)]
-    (if-not (= (pusher/build-channel build) channel-name)
-      (do
-        (mlog "Ignoring event for old build channel: " channel-name)
-        state)
-      (let [{action-index :step container-index :index output :out} (js->clj data :keywordize-keys true)]
-        (-> state
-            (update-in [:current-build] build-model/fill-containers container-index action-index)
-            (update-in [:current-build :containers container-index :actions action-index :output] vec)
-            (update-in [:current-build :containers container-index :actions action-index :output]
-                       conj output)
-            (update-in [:current-build :containers container-index :actions action-index] action-model/format-latest-output))))))
+  (let [build (:current-build state)
+        {action-index :step container-index :index output :out} (js->clj data :keywordize-keys true)]
+    (cond (not= (pusher/build-channel build) channel-name)
+          (do (mlog "Ignoring event for old build channel: " channel-name)
+              state)
+
+          (not= container-index (get-in build [:current-container-id] 0))
+          (do (mlog "Ignoring output for inactive container: " container-index)
+              state)
+
+          :else
+          (let [{action-index :step container-index :index output :out} (js->clj data :keywordize-keys true)]
+            (-> state
+                (update-in [:current-build] build-model/fill-containers container-index action-index)
+                (update-in [:current-build :containers container-index :actions action-index :output] vec)
+                (update-in [:current-build :containers container-index :actions action-index :output]
+                           conj output)
+                (update-in [:current-build :containers container-index :actions action-index] action-model/format-latest-output))))))


Add routes to sente server component

Add routes to sente server component

--- src/clj/com/palletops/bakery/sente.clj
+++ src/clj/com/palletops/bakery/sente.clj
@@ -1,9 +1,11 @@
 (ns com.palletops.bakery.sente
   "A sente component.
-  Requires [com.taoensso/sente \"0.15.1\"]"
+  Requires [com.taoensso/sente \"0.15.1\"] and [compojure \"1.1.8\"]."
   (:require
    [clojure.core.async :as async :refer [chan close! go-loop]]
    [com.palletops.leaven.protocols :refer [ILifecycle]]
+   [compojure.core :refer [GET POST routes]]
+   [compojure.route :refer [resources]]
    [taoensso.sente :as sente]
    [taoensso.timbre :as timbre]))

@@ -11,11 +13,23 @@
   [req]
   (str (java.util.UUID/randomUUID)))

-(defn start [{:keys [msg-handler path sente-config announce-fn]}]
-  {:pre [msg-handler]}
+(defn sente-routes
+  "Return the Ring routes required for Sente."
+  [path chan-sock-atom]
+  (let [ajax-get-or-ws-handshake-fn (delay
+                                     (:ajax-get-or-ws-handshake-fn
+                                      @chan-sock-atom))
+        ajax-post-fn (delay (:ajax-post-fn @chan-sock-atom))]
+    (routes
+     (GET  path request (@ajax-get-or-ws-handshake-fn request))
+     (POST path request (@ajax-post-fn request)))))
+
+(defn start [{:keys [msg-handler path sente-config announce-fn]} chan-sock-atom]
+  {:pre [msg-handler chan-sock-atom]}
   (let [chan-sock (sente/make-channel-socket! path sente-config)
         router (sente/start-chsk-router-loop!
                 msg-handler (:ch-recv chan-sock))]
+    (reset! chan-sock-atom chan-sock)
     (when announce-fn
       (announce-fn chan-sock))
     {:router router
@@ -28,28 +42,35 @@

 (defrecord Sente
-    [config channel-socket router]
+    [config channel-socket router routes chan-sock-atom]
   ILifecycle
   (start [component]
     (if channel-socket
       component
-      (merge component (start config))))
+      (merge component (start config chan-sock-atom))))
   (stop [component]
     (if channel-socket
       (do
         (stop channel-socket router)
-        (assoc component :channel-socket nil :router nil))
+        (assoc component :channel-socket nil :router nil :routes nil))
       component)))

 (defn sente
   "Return a sente component, routing messages to `msg-handler`.
   `announce-fn` will be called on start with the channel socket as an
-  argument."
+  argument.  The `:routes` key will contain Ring routes for handling
+  asynchronous requests, which need to be injected into your
+  application's routes.  The `:path` key can be used to override the
+  default path for these routes."
   [{:keys [path msg-handler announce-fn sente-config]}]
-  (map->Sente
-   {:config {:path (or path "/chsk")
-             :msg-handler msg-handler
-             :announce-fn announce-fn
-             :sente-config (merge {:type :auto
-                                   :user-id-fn random-id}
-                                  sente-config)}}))
+  (let [chan-sock-atom (atom nil)
+        config {:path (or path "/chsk")
+                :msg-handler msg-handler
+                :announce-fn announce-fn
+                :sente-config (merge {:type :auto
+                                      :user-id-fn random-id}
+                                     sente-config)}]
+    (map->Sente
+     {:config config
+      :chan-sock-atom chan-sock-atom
+      :routes (sente-routes (:path config) chan-sock-atom)})))


Cleanup

Cleanup

--- src/cljs/hacker_agent/hacker-base.cljs
+++ src/cljs/hacker_agent/hacker-base.cljs
@@ -22,11 +22,10 @@
   (let [type-chan (type (chan))]
     (fn [x] (= type-chan (type x)))))

-(defn- closer-path [data path]
-  (conj (vec (cons data path)) :-closer))
-
 (defn- save-channel-closer! [data path channel]
-  (swap! channel-closers assoc-in (closer-path data path) channel))
+  (swap! channel-closers assoc-in
+         (conj (vec (cons data path)) :-closer)
+         channel))

 (defn- close-channel! [data path]
   (let [identifier (cons data path)]


handle-card-click! should be triggered only for non-matched cards

--- src/cljs/react_cljs_blogpost/core.cljs
+++ src/cljs/react_cljs_blogpost/core.cljs
@@ -42,21 +42,24 @@

 (defn card [card-state]
   (letfn [(handle-card-click! [event]
-            ; pair of cards was revealed, now let's go for another pair step
-            (if (= (revealed-cards-count) 2)
-              (hide-nonmatch!))
+            (when-not (@card-state :matched)
+              ;; pair of cards was revealed, now let's go for another pair step
+              (when (= (revealed-cards-count) 2)
+                (hide-nonmatch!))

-            ;reveal next card in step
-            (reveal-card! card-state)
+              ;; reveal next card in step
+              (reveal-card! card-state)

-            ;if 2 of cards are revealed, we have to check parity
-            (if (and (= (revealed-cards-count) 2)
-                     (= (:last-symbol @state)
-                        (:symbol @card-state)))
-              (mark-match! (:symbol @card-state)))
+              ;; if 2 of cards are revealed, we have to check parity
+              (when (and (= (revealed-cards-count) 2)
+                         (= (:last-symbol @state)
+                            (:symbol @card-state)))
+                (mark-match! (:symbol @card-state)))

-            ;let's remember last symbol to make comparison in subsequent steps
-            (swap! state assoc :last-symbol (:symbol @card-state)))]
+              ;; let's remember last symbol to make comparison in subsequent steps
+              (swap! state assoc :last-symbol (:symbol @card-state))
+              (when (= (matched-cards-count) board-size)
+                (swap! state assoc :started false))))]

     [:div.card
      {:onClick handle-card-click!


[n.d.shared-prefs] Add attribution

[n.d.shared-prefs] Add attribution

--- src/clojure/neko/data/shared_prefs.clj
+++ src/clojure/neko/data/shared_prefs.clj
@@ -1,5 +1,6 @@
 (ns neko.data.shared-prefs
-  "Utilities for interoperating with SharedPreferences class."
+  "Utilities for interoperating with SharedPreferences class. The original idea
+  is by Artur Malabarba."
   (:require [clojure.data :as data])
   (:import [android.content Context SharedPreferences SharedPreferences$Editor]
            neko.App))


using batch

using batch

--- src/celestial/puppet_standalone.clj
+++ src/celestial/puppet_standalone.clj
@@ -18,7 +18,7 @@
     [clojure.core.strint :only (<<)]
     [celestial.core :only (Provision)]
     [celestial.model :only (pconstruct)]
-    [celestial.ssh :only (copy execute step)]
+    [supernal.sshj :only (copy batch)]
     [taoensso.timbre :only (debug info error warn)]
     ))

@@ -26,13 +26,13 @@
 (defn copy-module [remote {:keys [src name]}]
   {:pre [(remote :host) src name]}
   "Copy a opsk module into server"
-  (copy remote src "/tmp"))
+  (copy src "/tmp" remote ))

 (defn copy-yml-type [{:keys [type hostname puppet-std] :as _type} remote]
   (let [path (<< "/tmp/~{hostname}.yml") f (file path)
         name (get-in puppet-std [:module :name])]
     (spit f (yaml/generate-string (select-keys _type [:classes])))
-    (copy remote path (<< "/tmp/~{name}/"))
+    (copy path (<< "/tmp/~{name}/") remote )
     (.delete f)))

 (defn as-root [remote cmd]
@@ -45,11 +45,9 @@
     (let [puppet-std (type :puppet-std) module (puppet-std :module) sudo ()]
      (try
       (copy-module remote module)
-      (execute remote
-        (step :extract "cd /tmp" (<< "tar -xzf ~(:name module).tar.gz")))
+      (batch "cd /tmp" (<< "tar -xzf ~(:name module).tar.gz") remote)
       (copy-yml-type type remote)
-      (execute remote
-          (step :run (<< "cd /tmp/~(:name module)") (as-root remote "./scripts/run.sh")))
+      (batch (<< "cd /tmp/~(:name module)") (as-root remote "./scripts/run.sh") remote)
       (finally
         #_(execute remote (step :cleanup "cd /tmp" (<< "rm -rf ~(:name module)*"))))))))


use slingshot throw+

use slingshot throw+

--- src/clj/clj_money/authorization.clj
+++ src/clj/clj_money/authorization.clj
@@ -53,8 +53,9 @@
           action
           @auth-context)
         auth-fns)
-      (throw (ex-info (format "No authorization rules registered for %s." tag)
-                      {:action action :resource tag})))))
+      (throw+ {:type ::no-rules
+               :action action
+               :resource tag}))))

 (defn authorize
   "Raises an error if the current user does not have


remove unused require

remove unused require

--- src/clj/clj_money/models/prices.clj
+++ src/clj/clj_money/models/prices.clj
@@ -10,7 +10,6 @@
                                                    with-transacted-storage]]
             [dgknght.app-lib.core :refer [assoc-if]]
             [dgknght.app-lib.validation :as v :refer [with-validation]]
-            [dgknght.app-lib.dates :as dates]
             [clj-money.find-in-chunks :as ch]
             [clj-money.models :as models]
             [clj-money.models.settings :as settings]


Removed extra functions, fixed formatting of output of telescoping-trends

--- src/clj/forma/hadoop/jobs/forma.clj
+++ src/clj/forma/hadoop/jobs/forma.clj
@@ -137,56 +137,15 @@

 (defn calculate-trends
   "Calculates all trend statistics for a timeseries, also returns the
-   period index of the last element of the series"
+   period index of the last element of the series. No longer calculates
+   short trend statistic."
   [window long-block start-idx ts rain-ts]
   (let [end-idx (series-end ts start-idx)
         short-rain (first (f/shorten-ts ts rain-ts))]
     (flatten [end-idx
-              (a/short-stat long-block window ts)
+;;              (a/short-stat long-block window ts)
               (a/long-stats ts short-rain)
               (a/hansen-stat ts)])))
-
-(defn new-trends
-  "Calculates all trend statistics for a timeseries, also returns the
-   period index of the last element of the series. Same as
-   calculate-trends but does NOT include the short trends statistic."
-   [window long-block start-idx ts rain-ts]
-  (let [end-idx (series-end ts start-idx)
-        short-rain (first (f/shorten-ts ts rain-ts))]
-    (flatten [end-idx
-              (a/long-stats ts short-rain)
-              (a/hansen-stat ts)])))
-
-(defn test-trends-perf
-  "Rough performance stats:
-
-   hansen-stat - 40 ms
-   long-stats - 55 ms
-   short-stat - 95 ms (in current trends)
-   short-stat - 7 ms (optimized - run once)
-
-Usage:
-     (ts-trends {:est-start \"2005-12-19\" :est-end \"2013-03-06\" :t-res \"16\" :window 10 :long-block 30} 693)"
-  [{:keys [est-start est-end t-res window long-block]}
-   ts-start-period]
-  (let [val-ts (repeatedly 350 (partial rand-int 10000))
-        rain-ts (repeatedly 350 (partial rand-int 10000))
-        [start-idx end-idx] (date/relative-period t-res ts-start-period
-                                                  [est-start est-end])
-        tele-start-idx (inc start-idx)
-        tele-end-idx (inc end-idx)
-        calculate #(calculate-trends window long-block
-                                     ts-start-period % rain-ts)
-        new-calculate #(new-trends window long-block
-                                   ts-start-period % rain-ts)]
-    (prn "Normal trends")
-    (time (dotimes [_ 10] (last (first (map (comp vec calculate) ;; force realization
-                                            (f/tele-ts tele-start-idx tele-end-idx val-ts))))))
-    (prn "Optimized trends")
-    (time (dotimes [_ 10]
-            (let [a (a/short-stat long-block window val-ts)
-                  b (last (first (map (comp vec new-calculate) ;; force realization
-                                      (f/tele-ts tele-start-idx tele-end-idx val-ts))))])))))

 (defmapcatop telescoping-trends
   "Maps `calculate-trends` onto each part of an ever-lengthening subset
@@ -207,13 +166,12 @@
         ;;that series).
         short-stats (take-last (count tele-series)
                                (a/short-stat-all long-block window (last tele-series)))
-        calculate #(new-trends window long-block
+        calculate #(calculate-trends window long-block
                                ts-start-period % rain-ts)
         all-trends-but-short (mu/transpose
                               (map calculate tele-series))]
-    [(concat (take 1 all-trends-but-short)
-             [short-stats]
-             (take-last 3 all-trends-but-short))]))
+    [(into [(first all-trends-but-short) (vec short-stats)]
+           (take-last 3 all-trends-but-short))]))

 (defn analyze-trends
   "Accepts an est-map and a source for both ndvi and rain timeseries.


fix parsing issue in deckbuilder

fix parsing issue in deckbuilder

--- src/cljs/netrunner/deckbuilder.cljs
+++ src/cljs/netrunner/deckbuilder.cljs
@@ -18,7 +18,7 @@
 (defn found? [query cards]
   (some #(if (= (.toLowerCase (:title %)) query) %) cards))

-(defn match [query cards]
+(defn search [query cards]
   (filter #(if (= (.indexOf (.toLowerCase (:title %)) query) -1) false true) cards))

 (defn lookup [side query]
@@ -31,7 +31,7 @@
          (cond (zero? (count matches)) query
                (or (= (count matches) 1) (identical-cards? matches)) (first matches)
                (found? subquery matches) (found? subquery matches)
-               (<= i (count query)) (recur (inc i) (match subquery matches))
+               (<= i (count query)) (recur (inc i) (search subquery matches))
                :else query))))))

 (defn parse-line [side line]
@@ -154,7 +154,7 @@
       (take 10 (filter #(not= (.indexOf (.toLowerCase (:title %)) (.toLowerCase query)) -1) cards)))))

 (defn handle-edit [owner]
-  (let [text (-> owner (om/get-node "deck-edit") .-value)]
+  (let [text (.-value (om/get-node owner "deck-edit"))]
     (om/set-state! owner :deck-edit text)
     (om/set-state! owner [:deck :cards] (parse-deck (om/get-state owner [:deck :identity :side]) text))))


Changed some let definitions so they no longer masker clojure functions  and

--- src/clojush/instructions/common.clj
+++ src/clojush/instructions/common.clj
@@ -77,15 +77,15 @@
   [type]
   (fn [state]
     (if (not (empty? (rest (rest (type state)))))
-      (let [first (stack-ref type 0 state)
-            second (stack-ref type 1 state)
-            third (stack-ref type 2 state)]
+      (let [first-item (stack-ref type 0 state)
+            second-item (stack-ref type 1 state)
+            third-item (stack-ref type 2 state)]
         (->> (pop-item type state)
              (pop-item type)
              (pop-item type)
-             (push-item second type)
-             (push-item first type)
-             (push-item third type)))
+             (push-item second-item type)
+             (push-item first-item type)
+             (push-item third-item type)))
       state)))

 (define-registered exec_rot (with-meta (rotter :exec) {:stack-types [:exec] :parentheses 3}))
@@ -118,11 +118,11 @@
   [type]
   (fn [state]
     (if (not (empty? (rest (type state))))
-      (let [first (stack-ref type 0 state)
-            second (stack-ref type 1 state)]
+      (let [first-item (stack-ref type 0 state)
+            second-item (stack-ref type 1 state)]
         (->> (pop-item type state)
              (pop-item type)
-             (push-item (= first second) :boolean)))
+             (push-item (= first-item second-item) :boolean)))
       state)))

 (define-registered exec_eq (with-meta (eqer :exec) {:stack-types [:exec :boolean] :parentheses 0}))


:nail_care:

--- src/com/wsscode/pathom/connect.cljc
+++ src/com/wsscode/pathom/connect.cljc
@@ -143,7 +143,7 @@
                     1)))))

 (defn pick-resolver [{::keys [indexes dependency-track]
-                      :as env}]
+                      :as    env}]
   (let [k (-> env :ast :key)
         e (p/entity env)]
     (if-let [attr-resolvers (get-in indexes [::index-oir k])]


Allow lein to build 2.9.6- & 2.9.7+ versions

--- src/docker_clojure/dockerfile/lein.clj
+++ src/docker_clojure/dockerfile/lein.clj
@@ -1,6 +1,5 @@
 (ns docker-clojure.dockerfile.lein
-  (:require [clojure.string :as str]
-            [docker-clojure.dockerfile.shared :refer :all]))
+  (:require [docker-clojure.dockerfile.shared :refer :all]))

 (def distro-deps
   {:debian-slim {:build   #{"wget" "gnupg"}
@@ -23,7 +22,7 @@
          "WORKDIR /tmp"
          ""
          "# Download the whole repo as an archive"
-         "RUN \\"]
+         "RUN set -eux; \\"]
         (concat-commands install-dep-cmds)
         (concat-commands
           ["mkdir -p $LEIN_INSTALL"
@@ -33,14 +32,22 @@
            (str "echo \"" (get-in installer-hashes ["lein" build-tool-version]) " *lein-pkg\" | sha256sum -c -")
            "mv lein-pkg $LEIN_INSTALL/lein"
            "chmod 0755 $LEIN_INSTALL/lein"
-           "wget -q https://github.com/technomancy/leiningen/releases/download/$LEIN_VERSION/leiningen-$LEIN_VERSION-standalone.zip"
-           "wget -q https://github.com/technomancy/leiningen/releases/download/$LEIN_VERSION/leiningen-$LEIN_VERSION-standalone.zip.asc"
-           "gpg --batch --keyserver keys.openpgp.org --recv-key 20242BACBBE95ADA22D0AFD7808A33D379C806C3"
+           "export GNUPGHOME=\"$(mktemp -d)\""
+           "export FILENAME_EXT=jar"
+           "if printf '%s\\n%s\\n' \"2.9.7\" \"$LEIN_VERSION\" | sort -cV; then \\
+              gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys 6A2D483DB59437EBB97D09B1040193357D0606ED; \\
+            else \\
+              gpg --batch --keyserver hkps://keyserver.ubuntu.com --recv-keys 20242BACBBE95ADA22D0AFD7808A33D379C806C3; \\
+              FILENAME_EXT=zip; \\
+           fi"
+           "wget -q https://github.com/technomancy/leiningen/releases/download/$LEIN_VERSION/leiningen-$LEIN_VERSION-standalone.$FILENAME_EXT"
+           "wget -q https://github.com/technomancy/leiningen/releases/download/$LEIN_VERSION/leiningen-$LEIN_VERSION-standalone.$FILENAME_EXT.asc"
            "echo \"Verifying file PGP signature...\""
-           "gpg --batch --verify leiningen-$LEIN_VERSION-standalone.zip.asc leiningen-$LEIN_VERSION-standalone.zip"
-           "rm leiningen-$LEIN_VERSION-standalone.zip.asc"
+           "gpg --batch --verify leiningen-$LEIN_VERSION-standalone.$FILENAME_EXT.asc leiningen-$LEIN_VERSION-standalone.$FILENAME_EXT"
+           "gpgconf --kill all"
+           "rm -r \"$GNUPGHOME\" leiningen-$LEIN_VERSION-standalone.$FILENAME_EXT.asc"
            "mkdir -p /usr/share/java"
-           "mv leiningen-$LEIN_VERSION-standalone.zip /usr/share/java/leiningen-$LEIN_VERSION-standalone.jar"]
+           "mv leiningen-$LEIN_VERSION-standalone.$FILENAME_EXT /usr/share/java/leiningen-$LEIN_VERSION-standalone.jar"]
           (empty? uninstall-dep-cmds))
         (concat-commands uninstall-dep-cmds :end)
         (concat


added contract test for isolated fns

added contract test for isolated fns

--- test/fogus/me/contract_tests.clj
+++ test/fogus/me/contract_tests.clj
@@ -36,6 +36,27 @@
   (is (= 10 ((partial doubler-contract-full #(* 2 %)) 5)))
   (is (thrown? Error ((partial doubler-contract-full #(* 3 (+ %1 %2))) 2 3))))

+(def doubler-contract-full-and-isolated-fn
+     (contract doubler
+       [x]
+       :requires
+       pos?
+       :ensures
+       (= (* 2 x) %)
+
+       [x y]
+       :requires
+       (pos? x)
+       (pos? y)
+       :ensures
+       (= (* 2 (+ x y)) %)))
+
+(deftest doubler-contract-full-and-isolated-fn-test
+  (is (= 10 ((partial doubler-contract-full-and-isolated-fn #(* 2 (+ %1 %2))) 2 3)))
+  (is (= 10 ((partial doubler-contract-full-and-isolated-fn #(+ %1 %1 %2 %2)) 2 3)))
+  (is (= 10 ((partial doubler-contract-full-and-isolated-fn #(* 2 %)) 5)))
+  (is (thrown? Error ((partial doubler-contract-full-and-isolated-fn #(* 3 (+ %1 %2))) 2 3))))
+

 (def doubler-contract-arity1
      (contract doubler
@@ -51,6 +72,20 @@
   (is (thrown? Error ((partial doubler-contract-arity1 #(* 3 %)) 5)))
   (is (thrown? Error ((partial doubler-contract-arity1 #(* 2 %)) -5))))

+(def doubler-contract-arity1-and-isolated-fn
+     (contract doubler
+       [x]
+       :requires
+       pos?
+       :ensures
+       (= (* 2 x) %)))
+
+(deftest doubler-contract-arity1-and-isolated-fn-test
+  (is (= 10 ((partial doubler-contract-arity1-and-isolated-fn #(* 2 %)) 5)))
+  (is (= 10 ((partial doubler-contract-arity1-and-isolated-fn #(* 2 %)) 5)))
+  (is (thrown? Error ((partial doubler-contract-arity1-and-isolated-fn #(* 3 %)) 5)))
+  (is (thrown? Error ((partial doubler-contract-arity1-and-isolated-fn #(* 2 %)) -5))))
+

 (def doubler-contract-no-requires
      (contract doubler
@@ -62,6 +97,19 @@
   (is (= 10 ((partial doubler-contract-no-requires #(* 2 %)) 5)))
   (is (= -10 ((partial doubler-contract-no-requires #(* 2 %)) -5)))
   (is (thrown? Error ((partial doubler-contract-no-requires #(* 3 %)) 5))))
+
+
+(def doubler-contract-no-requires-and-isolated-fn
+     (contract doubler
+       [x]
+       :ensures
+       pos?
+       (= (* 2 x) %)))
+
+(deftest doubler-contract-no-requires-and-isolated-fn-test
+  (is (= 10 ((partial doubler-contract-no-requires-and-isolated-fn #(* 2 %)) 5)))
+  (is (thrown? Error ((partial doubler-contract-no-requires-and-isolated-fn #(* 2 %)) -5)))
+  (is (thrown? Error ((partial doubler-contract-no-requires-and-isolated-fn #(* 3 %)) 5))))

 (def doubler-contract-no-ensures
@@ -76,9 +124,25 @@
   (is (thrown? Error ((partial doubler-contract-no-ensures #(* 2 %)) -5))))

+(def doubler-contract-no-ensures-and-isolated-fn
+     (contract doubler
+       [x]
+       :requires
+       pos?))
+
+(deftest doubler-contract-no-ensures-and-isolated-fn-test
+  (is (= 10 ((partial doubler-contract-no-ensures-and-isolated-fn #(* 2 %)) 5)))
+  (is (= 15 ((partial doubler-contract-no-ensures-and-isolated-fn #(* 3 %)) 5)))
+  (is (thrown? Error ((partial doubler-contract-no-ensures-and-isolated-fn #(* 2 %)) -5))))
+
+
 (deftest contract-test
   (doubler-contract-test)
   (doubler-contract-arity1-test)
   (doubler-contract-no-requires-test)
-  (doubler-contract-no-ensures-test))
+  (doubler-contract-no-ensures-test)
+  (doubler-contract-full-and-isolated-fn-test)
+  (doubler-contract-arity1-and-isolated-fn-test)
+  (doubler-contract-no-requires-and-isolated-fn-test)
+  (doubler-contract-no-ensures-and-isolated-fn-test))


Update output test.

Update output test.

--- test/onyx/plugin/output_test.clj
+++ test/onyx/plugin/output_test.clj
@@ -1,14 +1,39 @@
 (ns onyx.plugin.output-test
   (:require [clojure.java.jdbc :as jdbc]
-            [midje.sweet :refer :all]
+            [com.stuartsierra.component :as component]
             [honeysql.core :as sql]
+            [onyx.system :refer [onyx-development-env]]
             [onyx.queue.hornetq-utils :as hq-util]
             [onyx.plugin.sql]
-            [onyx.api])
+            [onyx.api]
+            [midje.sweet :refer :all])
   (:import [org.hornetq.api.core.client HornetQClient]
            [org.hornetq.api.core TransportConfiguration HornetQQueueExistsException]
            [org.hornetq.core.remoting.impl.netty NettyConnectorFactory]
            [com.mchange.v2.c3p0 ComboPooledDataSource]))
+
+(def id (java.util.UUID/randomUUID))
+
+(def env-config
+  {:hornetq/mode :vm
+   :hornetq/server? true
+   :hornetq.server/type :vm
+   :zookeeper/address "127.0.0.1:2185"
+   :zookeeper/server? true
+   :zookeeper.server/port 2185
+   :onyx/id id})
+
+(def peer-config
+  {:hornetq/mode :vm
+   :zookeeper/address "127.0.0.1:2185"
+   :onyx/id id
+   :onyx.peer/inbox-capacity 100
+   :onyx.peer/outbox-capacity 100
+   :onyx.peer/job-scheduler :onyx.job-scheduler/round-robin})
+
+(def dev (onyx-development-env env-config))
+
+(def env (component/start dev))

 (defn transform [{:keys [word] :as segment}]
   {:rows [{:word word}]})
@@ -18,7 +43,7 @@
    :subprotocol "mysql"
    :subname "//127.0.0.1:3306"
    :user "root"
-   :password "password"})
+   :password ""})

 (defn pool [spec]
   {:datasource
@@ -45,7 +70,7 @@
    :subprotocol "mysql"
    :subname "//127.0.0.1:3306/onyx_output_test"
    :user "root"
-   :password "password"})
+   :password ""})

 (def conn-pool (pool db-spec))

@@ -73,23 +98,6 @@

 (hq-util/create-queue! hq-config in-queue)
 (hq-util/write-and-cap! hq-config in-queue words 1)
-
-(def id (str (java.util.UUID/randomUUID)))
-
-(def coord-opts
-  {:hornetq/mode :vm
-   :hornetq/server? true
-   :hornetq.server/type :vm
-   :zookeeper/address "127.0.0.1:2185"
-   :zookeeper/server? true
-   :zookeeper.server/port 2185
-   :onyx/id id
-   :onyx.coordinator/revoke-delay 5000})
-
-(def peer-opts
-  {:hornetq/mode :vm
-   :zookeeper/address "127.0.0.1:2185"
-   :onyx/id id})

 (def workflow {:input {:transform :output}})

@@ -120,27 +128,30 @@
     :sql/subprotocol "mysql"
     :sql/subname "//127.0.0.1:3306/onyx_output_test"
     :sql/user "root"
-    :sql/password "password"
+    :sql/password ""
     :sql/table :words
     :onyx/batch-size 1000
     :onyx/doc "Writes segments from the :rows keys to the SQL database"}])

-(def conn (onyx.api/connect :memory coord-opts))
+(def v-peers (onyx.api/start-peers! 1 peer-config))

-(def v-peers (onyx.api/start-peers conn 1 peer-opts))
+(def job-id (onyx.api/submit-job
+             peer-config
+             {:catalog catalog :workflow workflow
+              :task-scheduler :onyx.task-scheduler/round-robin}))

-(def job-id (onyx.api/submit-job conn {:catalog catalog :workflow workflow}))
+;; @(onyx.api/await-job-completion conn (str job-id))

-@(onyx.api/await-job-completion conn (str job-id))
+(Thread/sleep 15000)

 (def sql-map {:select [:*] :from [:words]})

 (def results (jdbc/query conn-pool (sql/format sql-map)))

+(fact results => (map-indexed (fn [k x] (assoc x :id (inc k))) words))
+
 (doseq [v-peer v-peers]
   ((:shutdown-fn v-peer)))

-(onyx.api/shutdown conn)
+(component/stop env)

-(fact results => (map-indexed (fn [k x] (assoc x :id (inc k))) words))
-


fix promise usage

fix promise usage

--- figwheel-repl/src/figwheel/repl.cljc
+++ figwheel-repl/src/figwheel/repl.cljc
@@ -226,7 +226,7 @@
      (swap! reload-promise-chain next-promise-fn))))

 (defn ^:export after-reloads [f]
-  (swap! reload-promise-chain #(.then % (fn [_] (Promise. f)))))
+  (swap! reload-promise-chain #(.then % (f))))

 ;; --------------------------------------------------------------
 ;; REPL print forwarding


Clean up imports

Clean up imports

--- frontend/controllers/navigation.cljs
+++ frontend/controllers/navigation.cljs
@@ -1,8 +1,8 @@
 (ns frontend.controllers.navigation
-  (:require [cljs.core.async :as async :refer [>! <! alts! chan sliding-buffer close! tap mult]]
+  (:require [cljs.core.async :as async :refer [>! <! alts! chan sliding-buffer close!]]
             [clojure.string :as str]
             [frontend.analytics :as analytics]
-            [frontend.async :refer [put! filter-ch]]
+            [frontend.async :refer [put!]]
             [frontend.api :as api]
             [frontend.changelog :as changelog]
             [frontend.components.documentation :as docs]


Prevent body overscroll on Mac

Prevent body overscroll on Mac

--- src/braid/client/ui/styles/body.cljs
+++ src/braid/client/ui/styles/body.cljs
@@ -7,6 +7,9 @@
     :font-family "\"Open Sans\", Helvetica, Arial, sans-serif"
     :font-size "12px"
     :background "#F2F2F2"}
+   ; prevent overscroll:
+   {:height "100%"
+    :overflow "hidden"}
    [:textarea :input
     {:font-family "inherit"
      :font-size "1em"}]])


catch exceptions in transfer-shard

catch exceptions in transfer-shard

--- src/clj/elephantdb/common/domain.clj
+++ src/clj/elephantdb/common/domain.clj
@@ -5,6 +5,7 @@
             [hadoop-util.transfer :as transfer]
             [jackknife.core :as u]
             [jackknife.logging :as log]
+            [clojure.java.io :as io]
             [elephantdb.common.shard :as shard]
             [elephantdb.common.config :as conf]
             [elephantdb.common.status :as status])
@@ -346,32 +347,6 @@
 (defalias throttle transfer/throttle
   "Returns a throttling agent for use in throttling domain updates.")

-(defn try-times*
-  "Executes thunk. If an exception is thrown, will retry. At most n retries
-  are done. If still some exception is thrown it is bubbled upwards in
-  the call chain."
-  [n thunk]
-  (loop [n n]
-    (if-let [result (try
-                      [(thunk)]
-                      (catch Exception e
-                        (when (zero? n)
-                          (throw e))))]
-      (result 0)
-      (recur (dec n)))))
-
-(defmacro try-times
-  "Executes body. If an exception is thrown, will retry. At most n retries
-  are done. If still some exception is thrown it is bubbled upwards in
-  the call chain."
-  [[n] & body]
-  `(try-times* ~n (fn [] ~@body)))
-
-(defmacro with-timeout
-  [[ms] & body]
-  `(let [^java.util.concurrent.Future f# (future ~@body)]
-     (.get f# ~ms java.util.concurrent.TimeUnit/MILLISECONDS)))
-
 (defn transfer-shard!
   "Transfers the supplied shard (specified by `idx`) from the supplied
   remote version's remote store to the appropriate path on the local
@@ -382,19 +357,17 @@
         remote-store (.remoteStore domain)
         remote-fs    (.getFileSystem remote-store)
         remote-path  (.shardPath remote-store idx version)
-        local-path   (.shardPath local-store idx version)
-        timeout-ms (* 6 60 1000)]
+        local-path   (.shardPath local-store idx version)]
     (if (.exists remote-fs (h/path remote-path))
-      (do (log/info (format "Copying %s to %s." remote-path local-path))
-          (try
-            (try-times [3]
-                       (with-timeout [timeout-ms]
-                         (transfer/rcopy remote-fs remote-path local-path
-                                         :throttle throttle)))
-            (catch Exception e
-              (log/error e)
-              (throw e)))
-          (log/info (format "Copied %s to %s." remote-path local-path)))
+      (do
+        (try
+          (log/info (format "Copying %s to %s." remote-path local-path))
+          (transfer/rcopy remote-fs remote-path local-path
+                          :throttle throttle)
+          (log/info (format "Copied %s to %s." remote-path local-path))
+          (catch Exception e
+            (log/error (format "Error copying %s to %s: %s" remote-path local-path e))
+            (throw e))))
       (do (log/info "Shard doesn't exist. Creating shard # " idx)
           (.createShard local-store idx version)))))


Lesson <div> qtip - ensure they stay within the window

Signed-off-by: Pang Yan Han <22594c345857f664c61cd411f607c4d40a9d4af9@gmail.com>

--- src/cljs/cljs_nusmods/timetable.cljs
+++ src/cljs/cljs_nusmods/timetable.cljs
@@ -76,6 +76,10 @@
 ;                                          `:lessonType`
 ;   }

+(def ^{:doc     "jQuery window selector"
+       :private true}
+  $window ($ js/window))
+
 (def ^{:doc     "Minimum number of rows for a day in the Timetable"
        :private true}
   TIMETABLE-MIN-ROWS-FOR-DAY 2)
@@ -941,8 +945,9 @@
                                        " @ " venue)))
       (.qtip $divElem
              (js-obj "content"  (js-obj "text" $qtipContent)
-                     "position" (js-obj "my" "center left"
-                                        "at" "center right")
+                     "position" (js-obj "my"       "center left"
+                                        "at"       "center right"
+                                        "viewport" $window)

                      "style"
                      (js-obj "classes"


Rename some functions to indicate that they are for selected modules

Signed-off-by: Pang Yan Han <22594c345857f664c61cd411f607c4d40a9d4af9@gmail.com>

--- src/cljs/cljs_nusmods/timetable.cljs
+++ src/cljs/cljs_nusmods/timetable.cljs
@@ -182,7 +182,7 @@
   (sort (fn [a b] (< (:lessonType a) (:lessonType b)))
         preToUrlHashLessonGroupSeq))

-(defn- get-PreToUrlHashLessonGroup-seq-for-module
+(defn- get-PreToUrlHashLessonGroup-seq-for-selected-module
   "Given the module code of a module that has been selected, returns a sequence
    of `PreToUrlHashLessonGroup` objects for that module."
   [moduleCode]
@@ -191,20 +191,21 @@
           :lessonGroup (:label lessonTypeVal)})
        (get ModulesSelected moduleCode)))

-(defn- get-PreToUrlHashModule-for-module
+(defn- get-PreToUrlHashModule-for-selected-module
   "Retrieves a `PreToUrlHashModule` for a selected module."
   [moduleCode]
   {:moduleCode moduleCode,

    :preToUrlHashLessonGroupSeqSorted
    (sort-PreToUrlHashLessonGroup-seq
-     (get-PreToUrlHashLessonGroup-seq-for-module moduleCode))})
+     (get-PreToUrlHashLessonGroup-seq-for-selected-module moduleCode))})

 (defn- set-document-location-hash-based-on-modules-order
   "Sets document.location.hash based on the `ModulesSelectedOrder` global."
   []
   (let [preToUrlHashModuleSeq
-        (map #(get-PreToUrlHashModule-for-module %1) ModulesSelectedOrder)]
+        (map #(get-PreToUrlHashModule-for-selected-module %1)
+             ModulesSelectedOrder)]
     (.log js/console (str "ModulesSelectedOrder = " (.stringify js/JSON (clj->js ModulesSelectedOrder))))
     (aset (aget js/document "location") "hash"
           (clojure.string/join


Swap where scrolling waits

Swap where scrolling waits

Previously, the set-timeout happened *before* the scroll event was
dispatched.  Now the event is dispatched immediately but the switch
isn't toggled back on for a second.  This should yield a nicer scrolling
behavior.

--- src/cljs/comic_reader/scrolling.cljs
+++ src/cljs/comic_reader/scrolling.cljs
@@ -8,12 +8,12 @@
         throttler (fn []
                     (when (not @running)
                       (toggle!)
-                      (.setTimeout js/window
-                                   #(js/requestAnimationFrame
-                                     (fn []
-                                       (rf/dispatch [key])
-                                       (toggle!)))
-                                   1000)))]
+                      (js/requestAnimationFrame
+                       (fn []
+                         (rf/dispatch [key])
+                         (.setTimeout js/window
+                                      #(toggle!)
+                                      1000)))))]
     (.addEventListener target type throttler)))

 (defn setup-scrolling-events! []


run core benchmarks longer

run core benchmarks longer

--- benchmarks/cheshire/test/benchmark.clj
+++ benchmarks/cheshire/test/benchmark.clj
@@ -37,7 +37,7 @@
 (deftest t-bench-core
   (println "---------- Core Benchmarks ----------")
   (bench/with-progress-reporting
-    (bench/quick-bench (core/decode (core/encode test-obj)) :verbose))
+    (bench/bench (core/decode (core/encode test-obj)) :verbose))
   (println "-------------------------------------"))

 (deftest t-bench-custom


One more diff

One more diff

--- src/demo/web/http_kit_comparison.clj
+++ src/demo/web/http_kit_comparison.clj
@@ -20,6 +20,7 @@

   Differences:
   - Channel passed as callback param instead of macro param
+  - send! provides :on-success and :on-error callbacks
   - Channel not closed after send, by default
   - All ring body types supported
   - Automatic chunking of large (>16K) content"


working version, but slow

working version, but slow

--- src/help_me_im_dumb/query_engine.clj
+++ src/help_me_im_dumb/query_engine.clj
@@ -23,17 +23,12 @@
 (defn idf-score
   "for a given docs and a term find idf"
   [term]
-  (/
-    (float index/TOTAL-DOCS)
-    (float (if (index/DICTIONARY (read-string term)) (index/DICTIONARY (read-string term)) 1))
-    ))
+  (Math/log
+    (/
+      (float index/TOTAL-DOCS)
+      (float (if (count (index/term->postings term)) (count (index/term->postings term)) 1))
+      )))

-(index/initialize-index)
-(index/DICTIONARY "run")
-(idf-score "run")
-
-(index/DICTIONARY "water")
-(idf-score "water")

 (defn tf-score
   "given 1 doc and 1 term find term freq"


Changed to data

Changed to data

--- src/leiningen/new/figwheel/core.cljs
+++ src/leiningen/new/figwheel/core.cljs
@@ -14,10 +14,10 @@
 {{#om?}}

 (om/root
-  (fn [app owner]
+  (fn [data owner]
     (reify om/IRender
       (render [_]
-        (dom/h1 nil (:text app)))))
+        (dom/h1 nil (:text data)))))
   app-state
   {:target (. js/document (getElementById "app"))})
 {{/om?}}{{#reagent?}}


Remove outdated comment.

Remove outdated comment.

--- src/onyx/plugin/messaging_output.clj
+++ src/onyx/plugin/messaging_output.clj
@@ -31,7 +31,6 @@
   (let [base-enc ^onyx.messaging.serializers.base_encoder.Encoder (pub/base-encoder pub)
         enc (pub/segment-encoder pub)]
     (if (zero? (segment-encoder/segment-count enc))
-      ;; fake success code, as we don't have any more segments to send
       (.position ^io.aeron.Publication (.publication pub))
       (let [segments-len (- (segment-encoder/offset enc)
                             (base-encoder/length base-enc))]