Fixed changes made to interp (probably accidental?)

--- src/clj/minijava/interp.clj
+++ src/clj/minijava/interp.clj
@@ -3,29 +3,35 @@
         clojure.contrib.pprint)
   (:import (minijava.ir.temp.label)))

-(defstruct env :temps :mem :labels)
-
-(def empty-env
-  (atom (struct env {} {} {})))
-
+(defstruct env :temps :mem :labels :methods)
+
+(def empty-env
+  (atom (struct env {} {} {} {})))
+
 (defn write-temp [env key val]
   (swap! env (fn [e k v] (assoc-in e [:temps k] v)) key val))
 (defn read-temp [env key]
   (get-in @env [:temps key]))
 (defn read-label [env key]
   (get-in @env [:labels key]))
-
+(defn write-mem [env addr val]
+  (swap! env (fn [e a v] (assoc-in e [:mem a] v)) addr val))
+(defn read-mem [env addr]
+  (get-in @env [:mem addr]))
+(defn read-method [env name]
+  (get-in @env [:methods name]))
+
 ;; eval-ir evaluates the linearized IR tree. Only types that
 ;; appear in the final tree have cases in the multimethod.
 ;; e.g. ESeq and Seq are gone after linearization
-
+
 ;; dispatch on type of first arg
 (defmulti eval-ir (fn [x y] (type x)))
-
+
 ;; this gets called if the program jumps to the very end
 (defmethod eval-ir clojure.lang.PersistentList$EmptyList [lst env]
   nil)
-
+
 ;; use lookahead to see if we jump or evaluate normally
 (defmethod eval-ir clojure.lang.ISeq [lst env]
   (cond (or (= (type (first lst)) :minijava.ir/Jump)
@@ -44,15 +50,7 @@
           :+ (+ e1 e2)
           :- (- e1 e2)
           :* (* e1 e2))))
-
-
-(defmethod eval-ir :minijava.ir/Call [exp env]
-  (let [func (:lbl (:lbl exp))
-        args (:args exp)]
-    (case func
-      "print" (println (eval-ir (first args) env))
-      (println "missing function"))))
-
+
 (defmethod eval-ir :minijava.ir/Const [exp env]
   (:val exp))

@@ -62,66 +60,85 @@
         lt (read-label env (:lbl (:t exp)))
         lf (read-label env (:lbl (:f exp)))]
     (case (:op exp)
-          :<  (if (< e1 e2)
-                (eval-ir lt env)
+          :< (if (< e1 e2)
+                (eval-ir lt env)
                 (eval-ir lf env))
           :!= (if (not (= e1 e2))
-                (eval-ir lt env)
+                (eval-ir lt env)
                 (eval-ir lf env))
-          :=  (if (= e1 e2)
-                (eval-ir lt env)
+          := (if (= e1 e2)
+                (eval-ir lt env)
                 (eval-ir lf env)))))
-
-
+
 ; Canonicalization removes eseqs and also seqs
 ;
 ;(defmethod eval-ir ::minijava.ir/ExpSeq [exp]
-;  (let [e (eval-ir (:exp exp))
-;          (eval-ir (:seqs exp))]
-;    (...)))
+; (let [e (eval-ir (:exp exp))
+; (eval-ir (:seqs exp))]
+; (...)))
 ;
 ;(defmethod eval-ir ::minijava.ir/Seq [exp])
-
+
 (defmethod eval-ir :minijava.ir/Move [exp env]
   (let [val (eval-ir (:src exp) env)
-        dst (:reg (:dst exp))]
-    (write-temp env dst val)))
-
+        dst (:dst exp)]
+    (cond (= (type dst) :minijava.ir/Temp)
+          (write-temp env (:reg dst) val)
+          (= (type dst) :minijava.ir/Mem)
+          (write-mem env (:adr dst) val))))
+
 (defmethod eval-ir :minijava.ir/Jump [exp env]
   (eval-ir (read-label env (:lbl exp)) env))
-
+
 ;; Labels and names don't do anything after the label
 ;; table is built. These should never be called since
 ;; eval-ir unpacks these directly.
 (defmethod eval-ir :minijava.ir/Label [exp env]
   nil)
-
 (defmethod eval-ir :minijava.ir/Name [exp env]
   nil)
-
+
+;; Mem does need to eval in case an operation is hiding
+;; in the address expression
 (defmethod eval-ir :minijava.ir/Mem [exp env]
-  nil)
-
+  (let [addr (eval-ir (:adr exp) env)]
+    (read-mem env addr)))
+
+;; This case needed for Mem case above
+(defmethod eval-ir java.lang.Integer [exp env]
+  exp)
+
 (defmethod eval-ir :minijava.ir/Temp [exp env]
-
-
+  (read-temp env (:reg exp)))
+
+;; Function call
+(defmethod eval-ir :minijava.ir/Call [exp env]
+  (let [fn-name (:lbl (:lbl exp))
+        args (map (fn [arg] (eval-ir arg env)) (:args exp))]
+    (case fn-name
+      "print" (println (first args))
+      "newObject" (println "Unimplemented stub")
+      "newArray" (println "Unimplemented stub")
+      (eval-ir (read-method env fn-name) env))))
+
 (defmethod eval-ir :minijava.ir/Statement [exp env]
   (do
     (eval-ir (:exp exp) env)
     nil)) ;; ensure no value returned
-
+
 ;; Build map of label code - should be efficient by persistence
 ;; of list data structure
 (defn build-label-map [stms map]
   (cond (empty? stms) map
         (= (type (first stms)) :minijava.ir/Label)
-          (build-label-map (rest stms)
-                           (assoc map (:lbl (first stms)) (rest stms)))
-        true (build-label-map (rest stms) map)))
-
+          (recur (rest stms)
+                 (assoc map (:lbl (first stms)) (rest stms)))
+        true (recur (rest stms) map)))
+
 ;; top-level eval for a sequence of statements
-(defn eval-prog [stms]
-  (let [labels (build-label-map stms (hash-map))]
-    (eval-ir stms
-             (atom (struct env (hash-map) (hash-map) labels)))))
- +(defn eval-prog
+  ([stms] (eval-prog stms (hash-map)))
+  ([stms methods]
+    (let [labels (build-label-map stms (hash-map))]
+      (eval-ir stms
+               (atom (struct env (hash-map) (hash-map) labels))))))


Add NVD3 graph - so much easier than raw D3!! Remove debugging. Add div heights.

--- src/cljs/om_sente/core.cljs
+++ src/cljs/om_sente/core.cljs
@@ -93,7 +93,7 @@
     (render-state [this {:keys [data]}]
                   (let [s (:data/text app)
                         t (make-target s)]
-                    (html [:div
+                    (html [:div {:style {:height 600}}
                            [:p (str "The string '" s "' represented as a bar chart:")]
                            (into [:svg {:id "display" :width "100%" :height graph-height}]
                                  (map (fn [v1 v2 o]
@@ -264,20 +264,58 @@
   (reify
     om/IDidMount
     (did-mount [this]
-               (println "d3 did-mount - draw line when first mounted")
                (line-graph (vec (make-target (:data/text app)))))
     om/IDidUpdate
     (did-update [this prev-props prev-state]
                 (when (graph-data-changing prev-props app)
-                  (println "d3 did-update app state change - redraw line")
                   (.remove (.-firstChild (om/get-node owner "d3-node")))
                   (line-graph (vec (make-target (:data/text app))))))
     om/IRender
     (render [this]
-            (println "d3 render state")
-            (dom/div #js {:react-key "d3-node" ;; ensure React knows this is non-reusable
+            (dom/div #js {:style #js {:height 300}
+                          :react-key "d3-node" ;; ensure React knows this is non-reusable
                           :ref "d3-node"       ;; label it so we can retrieve it via get-node
                           :id "d3-node"}))))   ;; set id so D3 can find it!
+
+(defn nv-line-graph
+  "Draw a graph of the supplied data using NVD3."
+  [raw-data]
+  (let [chart (.. js/nv -models lineChart
+                  (margin #js {:left 100})
+                  (useInteractiveGuideline true)
+                  (transitionDuration 350)
+                  (showLegend true)
+                  (showYAxis true)
+                  (showXAxis true))]
+    (.. chart -xAxis (axisLabel "Character") (tickFormat (.format js/d3 ",r")))
+    (.. chart -yAxis (axisLabel "ASCII") (tickFormat (.format js/d3 ",r")))
+    (.. js/d3 (select "#nv-node") (append "svg")
+        (datum #js [
+                    #js {:values (clj->js raw-data)
+                         :key "Text Data"
+                         :color "red"
+                         }
+                    ])
+        (call chart))))
+
+(defn nvd3-test
+  "Component that tests NVD3 graph."
+  [app owner]
+  (reify
+    om/IDidMount
+    (did-mount [this]
+               (nv-line-graph (mapv (fn [a b] {:y a :x b}) (make-target (:data/text app)) (range))))
+    om/IDidUpdate
+    (did-update [this prev-props prev-state]
+                (when (graph-data-changing prev-props app)
+                  (.remove (.-firstChild (om/get-node owner "nv-node")))
+                  (nv-line-graph (mapv (fn [a b] {:y a :x b}) (make-target (:data/text app)) (range)))))
+    om/IRender
+    (render [this]
+            (dom/div #js {:style #js {:height 500}
+                          :react-key "nv-node"
+                          :ref "nv-node"
+                          :id "nv-node"}))))

 (defn secured-application
   "Component that represents the secured portion of our application."
@@ -290,7 +328,8 @@
                    [:h1 "Test Sente"]
                    (om/build text-sender app {})
                    (om/build animated-bar-graph app {})
-                   (om/build d3-test app {})]))))
+                   (om/build d3-test app {})
+                   (om/build nvd3-test app {})]))))

 (defn application
   "Component that represents our application. Maintains session state.


game initialization

game initialization

--- src/cljs/triboard/core.cljs
+++ src/cljs/triboard/core.cljs
@@ -13,13 +13,35 @@

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

+(def empty-board
+  (let [column (vec (repeat board-height :empty))]
+    (vec (repeat board-width column))))
+
+(def all-positions
+  (vec
+    (for [x (range board-width)
+          y (range board-height)]
+      [x y])))
+
+(defn random-positions
+  "Draw n * m distincts random position"
+  [n m]
+  (let [pos (shuffle all-positions)
+        cut #(subvec pos (* % n) (* (inc %) n))]
+    (map cut (range m))))
+
+(defn init-positions
+  []
+  (let [pos (random-positions init-block-count 4)]
+    {:blue (nth pos 0)
+     :red (nth pos 1)
+     :green (nth pos 2)
+     :gray (nth pos 3)}))
+
 (defn new-board
   "Create a new board"
   []
-  (vec
-    (repeat board-width
-      (vec (repeat board-height :empty))
-      )))
+  empty-board)

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

@@ -43,8 +65,7 @@
    (into
      [:svg#board
       {:view-box (str "0 0 " board-width " " board-height)}]
-     (for [x (range board-width)
-           y (range board-height)]
+     (for [[x y] all-positions]
        ^{:key [x y]}
        (case (get-in @app-state [:board x y])
          :empty  [empty-cell x y])


Remove printing

Remove printing

--- src/clojure/cljam/tabix.clj
+++ src/clojure/cljam/tabix.clj
@@ -30,23 +30,22 @@
   [^DataInputStream rdr]
   (when-not (Arrays/equals ^bytes (lsb/read-bytes rdr 4) (.getBytes ^String tabix-magic))
     (throw (IOException. "Invalid TABIX file")))
-  (let [n-seq  (lsb/read-int rdr) _ (println "n-seq: " n-seq)
-        preset (lsb/read-int rdr) _ (println "preset: " preset)
-        sc     (lsb/read-int rdr) _ (println "sc: " sc)
-        bc     (lsb/read-int rdr) _ (println "bc: " bc)
-        ec     (lsb/read-int rdr) _ (println "ec: " ec)
-        meta   (lsb/read-int rdr) _ (println "meta: " meta)
-        skip   (lsb/read-int rdr) _ (println "skip: " skip)
-        len    (lsb/read-int rdr) _ (println "len: " len)
+  (let [n-seq  (lsb/read-int rdr)
+        preset (lsb/read-int rdr)
+        sc     (lsb/read-int rdr)
+        bc     (lsb/read-int rdr)
+        ec     (lsb/read-int rdr)
+        meta   (lsb/read-int rdr)
+        skip   (lsb/read-int rdr)
+        len    (lsb/read-int rdr)
         buf    (lsb/read-bytes rdr len)
         index  (loop [i 0
                       bin-index []
                       linear-index []]
                  (if (< i n-seq)
-                   (let [n-bin (lsb/read-int rdr) _ (println "n-bin: " n-bin)
+                   (let [n-bin (lsb/read-int rdr)
                          new-bin-index (doall (map (fn [_] (read-bin rdr)) (range n-bin)))
-                         _ (println new-bin-index)
-                         n-linear-index (lsb/read-int rdr) _ (println "n-linear-index: " n-linear-index)
+                         n-linear-index (lsb/read-int rdr)
                          new-linear-index (doall (map (fn [_] (lsb/read-long rdr)) (range n-linear-index)))]
                      (recur (inc i)
                             (conj bin-index new-bin-index)


Implement propose-transaction

Implement propose-transaction

--- src/clojure_fabric/core.clj
+++ src/clojure_fabric/core.clj
@@ -15,17 +15,29 @@
   (:import [org.hyperledger.fabric.sdk User Enrollment Peer Orderer]
            [org.bouncycastle.jcajce.provider.asymmetric.ec BCECPrivateKey]))

-(defprotocol Marshall
-  (marshall [obj]))
-
-;;; FIXME: call marshal from generated code when return type matches
-(extend-protocol Marshall
-  java.util.Collection
-  (marshall [obj]
-    (if (instance? clojure.lang.IPersistentSet obj)
-      obj
-      (seq obj))))
-
+
+;; (defprotocol Marshall
+;;   (marshall [obj]))
+
+;; ;;; FIXME: call marshal from generated code when return type matches
+;; (extend-protocol Marshall
+;;   java.util.Collection
+;;   (marshall [obj]
+;;     (if (instance? clojure.lang.IPersistentSet obj)
+;;       obj
+;;       (seq obj))))
+
+(defn- general-lru-cache-read [k lru-cache miss-hit-fn & fn-args]
+    (let [cache-hit (swap! lru-cache cache/hit k)]
+      (if-let [found (cache/lookup cache-hit k)]
+        found
+        (let [new-entry (apply miss-hit-fn fn-args)]
+        (swap! lru-cache cache/miss k new-entry)
+        new-entry))))
+
+;;;
+;;; Client internals
+;;;
 (defonce client-lru-cache
   ;; FIXME: magic number
   (atom (cache/lru-cache-factory {} :threshold 64)))
@@ -56,54 +68,88 @@
                                       (.getCert ^Enrollment enrollment))]
     (swap! client-lru-cache cache/evict cache-key)))

+;;;
+;;; Channel
+;;;
 (defrecord ClientOpts [roles account affiliation])

 (defn get-or-make-channel [client channel-id]
   (or (client/get-channel client channel-id) (client/new-channel client channel-id)))

-(defprotocol ChannelEndOpts
+(defprotocol IChannelEndOpts
   (new-channel-end [channel-end client])
   (get-channel-ends [channel-end client]))

+;;;
+;;; Orderer and Peer
+;;;
 ;; Channel ends are: Peers(Endorsers,...), Orderers
 (defrecord OrdererOpts [name grpc-url properties]
-  ChannelEndOpts
+  IChannelEndOpts
     (new-channel-end [{:keys [name grpc-url properties]} client]
     (client/new-orderer client name grpc-url properties))
   (get-channel-ends [this channel]
     (channel/get-orderers channel)))

 (defrecord PeerOpts [name grpc-url properties]
-  ChannelEndOpts
+  IChannelEndOpts
   (new-channel-end [{:keys [name grpc-url properties]} client]
-    (client/new-orderer client name grpc-url properties))
+    (client/new-peer client name grpc-url properties))
   (get-channel-ends [this channel]
     (channel/get-peers channel)))

-(defprotocol ChannelEnd
+(defprotocol IChannelEnd
   (add-channel-end-to-channel [channel-end channel]))

-(extend-protocol ChannelEnd
+(extend-protocol IChannelEnd
   Orderer
   (add-channel-end-to-channel [this channel]
     (channel/add-orderer channel this)))

-(extend-protocol ChannelEnd
+(extend-protocol IChannelEnd
   Peer
   (add-channel-end-to-channel [this channel]
     (channel/add-peer channel this)))

 ;;;
+;;; Chaincode
+;;;
+;;; Chaincode - a set of functions
+(defonce chaincode-lru-cache
+  ;; FIXME: magic number
+  (atom (cache/lru-cache-factory {} :threshold 64)))
+
+(defrecord ChaincodeOpts [name version path])
+(defn make-ChaincodeOpts [{:keys [name version path]}]
+  (->ChaincodeOpts (when name (str/trim name))
+                   (when version (str/trim version))
+                   (when path (str/trim path))))
+
+(defn- chaincode->hash [{:keys [name version path]}]
+  (hash (str name " " version " " path)))
+
+(defn make-chaincode [{:keys [name version path]}]
+  (-> (chaincode/new-builder)
+      (chaincode/set-name name)
+      (chaincode/set-version version)
+      (chaincode/set-path path)
+      (chaincode/build)))
+
+(defn get-or-make-chaincode [chaincode]
+  (general-lru-cache-read (chaincode->hash chaincode)
+                          chaincode-lru-cache
+                          make-chaincode
+                          chaincode))
+
+(defn evict-chaincode-from-cache [])
+
+;;;
 ;;; High level interface
 ;;;
 (defn get-or-make-client [msp-id name priv-key cert opts]
-  (let [cache-key (priv-key+cert->hash priv-key cert)
-        lru-cache (swap! client-lru-cache cache/hit cache-key)]
-    (if-let [existing-client (cache/lookup lru-cache cache-key)]
-      existing-client
-      (let [new-client (make-client msp-id name priv-key cert opts)]
-        (swap! client-lru-cache cache/miss cache-key new-client)
-        new-client))))
+  (general-lru-cache-read (priv-key+cert->hash priv-key cert)
+                          client-lru-cache
+                          make-client msp-id name priv-key cert opts))

 (defn add-channel-end
   ([client channel-id channel-end-opts]
@@ -116,13 +162,38 @@
                (empty? (get-channel-ends channel-end-opts (get-or-make-channel client channel-id))))
        (add-channel-end-to-channel (new-channel-end channel-end-opts client) channel)))))

-
-(defn propose-transaction [client channel-id]
-  (let [channel (get-or-make-channel client channel-id)
-        req (client/new-transaction-proposal-request client)]
-    (when-not (channel/is-initialized channel)
-      (channel/initialize channel))
-    )
+(defrecord TransactionOpts [fcn args ;; chaincode-language chaincode-endorsement-policy
+                            proposal-wait-time])
+
+(defn propose-transaction
+  ([client channel-id chaincode-opts transaction-opts]
+   (propose-transaction client channel-id chaincode-opts transaction-opts nil))
+  ([client channel-id chaincode-opts {:keys [fcn args proposal-wait-time]} peers]
+   (let [channel (get-or-make-channel client channel-id)
+         req (client/new-transaction-proposal-request client)]
+     (when-not (channel/is-initialized channel)
+       (channel/initialize channel))
+     (request/set-chaincode-id req (get-or-make-chaincode chaincode-opts))
+     ;; Transaction options
+     ;; FIXME: what about chaincode-language, chaincode-endorsement-policy ?
+     (when fcn
+       (request/set-fcn req fcn))
+     (when args
+       (request/set-args req args))
+     (when proposal-wait-time
+       (request/set-proposal-wait-time req proposal-wait-time))
+     ;; Send Tx proposal to peers
+     (apply channel/send-transaction-proposal channel req peers))))
+
+(defn order-transaction
+  ([client channel-id proposal-responses]
+   (order-transaction client channel-id proposal-responses nil))
+  ([client channel-id proposal-responses orderers]
+   ;; Send Tx to orderers
+   (apply channel/send-transaction (get-or-make-channel client channel-id) proposal-responses orderers))
+  ;; (defonce resp (channel/send-transaction-proposal chan req))
+  ;; (defonce future1 (channel/send-transaction chan resp (client/get-user-context cli)))
+  ;; (.get future1)
   )

 ;;;
@@ -136,7 +207,7 @@
 #_
 (comment
   (defonce cli
-   (get-or-make-client "Org1Msp"
+   (get-or-make-client "Org1MSP"
                 "PeerAdmin"
                 (-> (slurp "resources/creds/cd96d5260ad4757551ed4a5a991e62130f8008a0bf996e4e4b84cd097a747fec-priv")
                     (keys/str->private-key))
@@ -145,7 +216,13 @@

   (add-channel-end cli "mychannel" (map->OrdererOpts {:name "orderer0" :grpc-url "grpc://localhost:7050"}))
   (add-channel-end cli "mychannel" (map->PeerOpts {:name "peer0" :grpc-url "grpc://localhost:7051"}))
-
+  (defonce proresp (propose-transaction cli
+                                        "mychannel"
+                                        (make-ChaincodeOpts {:name "fabcar" :version "1.0" :path "resources/"})
+                                        (map->TransactionOpts {:fcn "createCar"
+                                                               ;; FIXME: marshall/unmarshall
+                                                               :args (java.util.ArrayList. ["CAR10" "Chevy" "Volt" "Red" "Nick"])
+                                                               :proposal-wait-time 10000})))
   )
 #_
 (comment
@@ -211,11 +288,11 @@
                             (chaincode/set-path "resources/")
                             (chaincode/build)))
   (request/set-chaincode-id req chaincode-id)
-  (request/set-fcn req "some_function")
+  (request/set-fcn req "createCar")
   ;; timeout
   (request/set-proposal-wait-time req 10000)
   ;; FIXME: marshall
-  (request/set-args req ["some args"])
+  (request/set-args req (java.util.ArrayList. ["CAR10" "Chevy" "Volt" "Red" "Nick"]))

   (defonce resp (channel/send-transaction-proposal chan req))
   (defonce future1 (channel/send-transaction chan resp (client/get-user-context cli)))


Minor change to dev util.

Minor change to dev util.

--- src/cmr/common/dev/util.clj
+++ src/cmr/common/dev/util.clj
@@ -50,10 +50,11 @@
   (sh/sh "say" "-v" "Victoria" text))

 (defn copy-to-clipboard
-  "Copies the string into the clipboard"
+  "Copies the string into the clipboard and returns the string"
   [s]
   (let [clipboard (.getSystemClipboard (Toolkit/getDefaultToolkit))]
-    (.setContents clipboard (StringSelection. s) nil)))
+    (.setContents clipboard (StringSelection. s) nil))
+  s)

 (defn message->regex
   "Converts an expected message into the a regular expression that matches the exact string.


Use ref hook to store function component state

--- src/reagent/impl/component.cljs
+++ src/reagent/impl/component.cljs
@@ -374,8 +374,6 @@
       (cache-react-class compiler f res))))

 (defn as-class [tag compiler]
-  (if (nil? compiler)
-    (js/console.error "as-class" tag compiler))
   (if-some [cached-class (cached-react-class compiler tag)]
     cached-class
     (fn-to-class compiler tag)))
@@ -415,19 +413,12 @@
               (error (str "Error rendering component" (comp-name)))))))
       (functional-wrap-render compiler c))))

-(def fun-component-state #js {})
-
 (defn functional-render [compiler jsprops]
   (if util/*non-reactive*
     ;; Non-reactive component needs just the render fn and argv
     (functional-do-render compiler jsprops)
     (let [argv (.-argv jsprops)
           tag (.-reagentRender jsprops)
-          ;; Create persistent ID for each rendered functional component,
-          ;; this is used to store internal Reagent state, like render
-          ;; reaction etc. in a separate store where changes doesn't
-          ;; trigger render.
-          [id _] (react/useState (js/Symbol))

           ;; Use counter to trigger render manually.
           [_ update-count] (react/useState 0)
@@ -436,29 +427,30 @@
           ;; To support form-2 components, even the render fn needs to
           ;; be stored as it is created during the first render,
           ;; and subsequent renders need to retrieve the created fn.
-          reagent-state (or (gobj/get fun-component-state id)
-                            ;; TODO: Could also initialize using jsprops object here.
-                            ;; TODO: Allow cljsMountOrder name to optimized.
-                            (let [obj #js {:forceUpdate (fn [] (update-count inc))
-                                           :cljsMountOrder (batch/next-mount-count)
-                                           ;; Use reagentRender name, as that is also used
-                                           ;; by class components, and some checks.
-                                           ;; ReagentRender is replaced with form-2 inner fn,
-                                           ;; constructor refers to the original fn.
-                                           :constructor tag}]
-                              ;; These names can be optimized, so they can't be set in
-                              ;; object literal.
-                              (set! (.-reagentRender obj) tag)
-                              (gobj/set fun-component-state id obj)
-                              obj))
-
+          state-ref (react/useRef)
+
+          _ (when-not (.-current state-ref)
+              (let [obj #js {}]
+                (set! (.-forceUpdate obj) (fn [] (update-count inc)))
+                (set! (.-cljsMountOrder obj) (batch/next-mount-count))
+                ;; Use reagentRender name, as that is also used
+                ;; by class components, and some checks.
+                ;; reagentRender is replaced with form-2 inner fn,
+                ;; constructor refers to the original fn.
+                (set! (.-constructor obj) tag)
+                (set! (.-reagentRender obj) tag)
+
+                (set! (.-current state-ref) obj)))
+
+          reagent-state (.-current state-ref)
+
+          ;; FIXME: Access cljsRatom using interop forms
           rat (gobj/get reagent-state "cljsRatom")]

       (react/useEffect
         (fn mount []
           (fn unmount []
-            (some-> (gobj/get reagent-state "cljsRatom") ratom/dispose!)
-            (gobj/remove fun-component-state id)))
+            (some-> (gobj/get reagent-state "cljsRatom") ratom/dispose!)))
         ;; Ignore props - only run effect once on mount and unmount
         #js [])


remove debug statement

remove debug statement

--- src/overtone/event.clj
+++ src/overtone/event.clj
@@ -23,8 +23,6 @@
   (dosync
    (let [handlers (get @handler-ref* event-type {})
          arity (if (= clojure.lang.Var (class handler)) -1 (arg-count handler))]
-     (println "registering handler with arity: " arity " and class: " (class handler))
-
      (alter handler-ref* assoc event-type (assoc handlers key [handler arity]))
      true)))


add a fn to grant access to private docs

--- src/pc/models/cust.clj
+++ src/pc/models/cust.clj
@@ -1,7 +1,9 @@
 (ns pc.models.cust
   "cust is what would usually be called user, we call it cust b/c
    Clojure has already taken the name user in the repl"
-  (:require [pc.datomic :as pcd]
+  (:require [clojure.tools.logging :as log]
+            [pc.datomic :as pcd]
+            [pc.models.flag :as flag-model]
             [datomic.api :refer [db q] :as d]))

@@ -79,3 +81,7 @@
                  :where [[_ :google-account/sub ?sub ?tx]
                          [?tx :db/txInstant ?i]]}
                db (:google-account/sub cust))))
+
+(defn turn-on-private-docs [db email]
+  (let [cust (find-by-email db email)]
+    (flag-model/add-flag cust :flags/private-docs)))


link to the code

link to the code

--- src/pc/views/admin.clj
+++ src/pc/views/admin.clj
@@ -179,7 +179,9 @@
              (anti-forgery/anti-forgery-field)
              [:input {:type "hidden" :name "client-id" :value client-id}]
              [:input {:type "submit" :value "refresh"}]]]
-       [:td (get-in stats [:stats :code-version])]
+       [:td (let [v (get-in stats [:stats :code-version])]
+              [:a {:href (str "https://github.com/dwwoelfel/precursor/commit/" v)}
+               v])]
        [:td (get-in stats [:stats :chat-count])]
        [:td (get-in stats [:stats :unread-chat-count])]
        [:td (get-in stats [:stats :transaction-count])]


Made twist function cleaner

Made twist function cleaner

--- src/scramblyzer/reid_parser.clj
+++ src/scramblyzer/reid_parser.clj
@@ -82,14 +82,13 @@

 (defn twist
   [piece-name amount]
-  "Twist a piece by the amount given.
-  e.g., UF twisted becomes FU"
-  (let [sides (seq piece-name)
-        times (mod amount (count sides))]
-    (cond (= times 0) piece-name
-          :else (twist
-                  (join (concat (rest sides) (list (first sides))))
-                  (dec times)))))
+  (let [sides (vec (seq piece-name))
+        size (count sides)]
+    (join
+      (map sides
+           (map #(mod % size)
+                (range amount
+                       (+ size amount)))))))

 (defn- permute
   [base permutation]


fixed rain test

fixed rain test

--- test/clj/forma/source/rain_test.clj
+++ test/clj/forma/source/rain_test.clj
@@ -36,7 +36,7 @@
         ascii-map {:corner [0 -90] :travel [+ +] :step 0.5 :nodata -999}
         m-res "500"]
     (resample-rain m-res ascii-map file-tap pix-tap test-rain-data)
-    => (produces [["precl" "500" "32" "2000-01-01" 8 6 0 0 100]])))
+    => (produces [["precl" "500" "32" "2000-01-01" 8 6 0 0 100.0]])))

 ;; TODO: Mod for rain. Used to be for MODIS.
 ;;


Cleaned up uses

Cleaned up uses

--- test/forma/trends/analysis_test.clj
+++ test/forma/trends/analysis_test.clj
@@ -1,17 +1,12 @@
 (ns forma.trends.analysis-test
   (:use [forma.trends.analysis] :reload)
-  (:use [midje.sweet]
-        [forma.matrix.utils]
-        [forma.trends.stretch]
+  (:use [cascalog.api]
+        [midje sweet cascalog]
         [forma.trends.data]
-        [forma.utils]
-        [cascalog.api]
-        [midje.cascalog]
-        [clojure.math.numeric-tower :only (sqrt floor abs expt)]
-        [clojure.test :only (deftest)])
-  (:require [incanter.core :as i]
-            [incanter.stats :as s]
-            [forma.schema :as schema]))
+        [forma.schema :only (timeseries-value)]
+        [forma.trends.stretch :only (ts-expander)]
+        [clojure.math.numeric-tower :only (floor abs expt)]
+        [clojure.test :only (deftest)]))

 (defn num-equals [expected]
   (fn [actual] (== expected actual)))
@@ -178,7 +173,7 @@
         end 136
         [ndvi-ts reli-ts rain-ts] ((juxt :ndvi :reli :rain) m)]
     (vec (map
-          (partial schema/timeseries-value start end)
+          (partial timeseries-value start end)
           (transpose
            (telescoping-long-trend 23 start end ndvi-ts reli-ts rain-ts))))))

@@ -193,7 +188,7 @@
   (let [start 135
         end 136
         [ndvi-ts reli-ts] ((juxt :ndvi :reli) m)]
-    (schema/timeseries-value start end
+    (timeseries-value start end
      (telescoping-short-trend 30 10 23 start end ndvi-ts reli-ts))))

 (deftest long-trends-test


Don't compare first datom in each tx as the timestamp changes each time

--- test/onyx/plugin/input_log_test.clj
+++ test/onyx/plugin/input_log_test.clj
@@ -135,10 +135,16 @@

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

+(type #inst "2015-08-19T13:27:59.256-00:00")
+
 (fact (map (fn [result]
              (if (= result :done)
                :done
-               (dissoc result :id))) results)
+               ;; drop tx datom and id
+               (-> result
+                   (update :data rest)
+                   (dissoc :id))))
+           results)
       =>
       [{:data '([13194139534312 50 #inst "2015-08-19T13:27:59.237-00:00" 13194139534312 true]
                 [63 10 :com.mdrogalis/people 13194139534312 true]


Fix drop tx datom from expected too

Fix drop tx datom from expected too


add account ID for referencing SSL certs

--- src/terraboot/core.clj
+++ src/terraboot/core.clj
@@ -5,7 +5,7 @@
             [clj-yaml.core :as yaml]
             [clojure.pprint :refer [pprint]]))

-(def account-id "12345")
+(def account-id "165664414043")
 (def default-sgs ["allow_outbound" "allow_ssh"])

 (letfn [(merge-in* [a b]


Make entity fn return joined map instead of tuples

--- src/todomvc/rules.cljs
+++ src/todomvc/rules.cljs
@@ -140,10 +140,22 @@
 ;  [:?id])
 ;  [?todo <- Todo (= id ?id)])
 ;
+(defn entity-tuples->entity-map
+  "Takes list of tuples for a single entity and returns single map"
+  [tups]
+  (reduce
+    (fn [acc [e a v]]
+      (merge acc {:db/id e
+                  a      v}))
+    {} tups))
+
 (defquery entity- [:?eid]
   [?entity <- :all [[e a v]] (= e ?eid)])

-(defn entity [session id] (mapv :?entity (query session entity- :?eid id)))
+(defn entity [session id]
+  (entity-tuples->entity-map
+    (mapv :?entity (query session entity- :?eid id))))
+
 ;; MVCtodo uses sequential ids. Since this is a horrible idea, I'm skipping it this pass.
 ;(defquery find-max-id
 ;  []
@@ -185,9 +197,9 @@
   [tups]
   (->> (group-by :?e tups)
     (mapv (fn [[id ent]]
-           (into {:db/id id}
-             (reduce (fn [m tup] (assoc m  (:?a tup) (:?v tup)))
-               {} ent))))))
+            (into {:db/id id}
+              (reduce (fn [m tup] (assoc m (:?a tup) (:?v tup)))
+                {} ent))))))

 (defn attr-ns [attr]
@@ -195,11 +207,8 @@

 (cljs.pprint/pprint (clara-tups->maps all-done))

+(println "Done count: " (query session find-done-count))
+
+(println facts)
+
 (cljs.pprint/pprint (entity session (:db/id (first (clara-tups->maps all-done)))))
-
-
-(println "Done count: " (query session find-done-count))
-
-(println facts)
-
-(map->tuple (showing-tx (random-uuid) :all))


Update docstring.

Update docstring.

--- src/enoki_lang_clj/core.clj
+++ src/enoki_lang_clj/core.clj
@@ -137,7 +137,7 @@
   (nxt parser))

 (defn -main
-  "🍄 goes in, shit comes out."
+  "🍄 goes in, 💩 comes out."
   [& args]
   (let [ast (parser (slurp *in*))]
     (if (map? ast)


fix tags in tag endpoint

fix tags in tag endpoint

--- src/semtag_web/client/view.cljs
+++ src/semtag_web/client/view.cljs
@@ -83,7 +83,7 @@
      (case attr
        :namespace (td-model (:value row))
        :url (td-url (:value row))
-       :tags (td-tags (string/join ";" (:value row)))
+       :tags (td-tags (:value row))
        [:td (str (:value row))])
      ]))


fix parsing

fix parsing

Signed-off-by: Koleman Nix <9f9effdfeb1aae8da61017791c660428b97c5749@gmail.com>

--- markov-clj/src/markov_clj/markov.clj
+++ markov-clj/src/markov_clj/markov.clj
@@ -1,5 +1,4 @@
 (ns markov-clj.markov)
-

 (defn parse-corpus [s]
   (clojure.string/split s #"\s+"))
@@ -23,7 +22,7 @@
     (assoc database key {val 1})))

 (defn build-database [corpus n] (->> corpus
-                                     ;; parse-corpus
+                                     parse-corpus
                                      (generate-tuples (inc n) ,,)
                                      (map index-tuple ,,)
                                      (reduce index-frequencies {} ,,)))
@@ -74,3 +73,5 @@
                                   (interpose " " ,,)
                                   (apply str ,,)))]
     (repeatedly generation-fn)))
+
+(println "\n" (first (generate (parse-corpus (slurp "resources/koleman_tweets.txt")) 1)))


Copy tweaks

Copy tweaks

--- src-cljs/frontend/components/about.cljs
+++ src-cljs/frontend/components/about.cljs
@@ -182,7 +182,7 @@
             [:div.text-center
              [:img.hero-logo {:src (utils/cdn-path "/img/outer/enterprise/logo-circleci.svg")}]]
             [:h1.text-center "About Us"]
-            [:h3.text-center "CircleCI was founded in 2011 with the mission of giving every developer state of the art automated testing and continuous integration tools."]]]]
+            [:h3.text-center "CircleCI was founded in 2011 with the mission of giving every developer state-of-the-art automated testing and continuous integration tools."]]]]
          [:div.row.text-center
           (common/sign-up-cta owner "about")]]
         [:div.outer-section
@@ -208,10 +208,13 @@
            [:div.story.col-xs-12
             [:h2 "Our story"]
             [:p
-             "CircleCI provides development and software teams the confidence to build, test, "
+             "CircleCI provides development teams the confidence to build, test, "
              "and deploy—quickly and consistently—across numerous platforms. Built to address "
-             "the demanding needs for today's application development environments, CircleCI "
-             "supports all types of software testing including web, mobile and container (Docker) environments."]
+             "the demanding needs of today's application development environments, CircleCI "
+             "supports every component of a modern application, including mobile apps (iOS and Android), "
+             "conventional web applications (built with platforms like Rails and Django), "
+             "browser-based apps (built with frameworks like AngularJS and Ember), "
+             "and containerized apps (built with tools like Docker)."]
             [:p
              "CircleCI makes continuous integration and continuous deployment simple and easy for "
              "thousands of companies like Shopify, Cisco, Sony and Trunk Club, so they can ship "


If scheduling an already-running service tag, stop current run.

--- src/midje/util/scheduling.clj
+++ src/midje/util/scheduling.clj
@@ -5,12 +5,14 @@

 (def scheduled-futures (atom {}))

+(defn stop [service-tag]
+  (.cancel (service-tag @scheduled-futures) true)
+  (swap! scheduled-futures dissoc service-tag))
+
 (defn schedule [service-tag function interval]
+  (when (@scheduled-futures service-tag)
+    (stop service-tag))
   (let [executor (ScheduledThreadPoolExecutor. 1)
         future (.scheduleWithFixedDelay executor function 0 interval TimeUnit/MILLISECONDS)]
     (swap! scheduled-futures assoc service-tag future)))

-(defn stop [service-tag]
-  (.cancel (service-tag @scheduled-futures) true)
-  (swap! scheduled-futures dissoc service-tag))
-


fixed helper sections

fixed helper sections

* display "brute" images without CSS classes to prevent jQuery to act on "click"
* added red cross image to archive helper section

--- src/instapapure/servlet.clj
+++ src/instapapure/servlet.clj
@@ -51,6 +51,9 @@

 (def nav-separator " ♢ ")

+(def delete-image
+  [:img.delete {:src "/public/i/cross.png" :title "Delete it"}])
+
 (defn star-image [displayed]
   [:img.star {:src "/public/i/star.png"
               :title "Unstar it"
@@ -59,8 +62,6 @@
   [:img.star-empty {:src "/public/i/star-empty.png"
               :title "Star it"
               :style (str "display: " (if displayed "inline" "none"))}])
-(def delete-image
-  [:img.delete {:src "/public/i/cross.png" :title "Delete it"}])

 (defn nav-header [type header-type header-title href]
   (if (= type header-type)
@@ -161,17 +162,19 @@
     [:div.help
       [:p [:em "Nothing in the archive?"]]
       [:p "When you have read an unread article, it will be moved to the archive.
-          It will remain there until you delete it."]]))
+          It will remain there until you delete it by clicking on "
+          [:img {:src "/public/i/cross.png"}]
+          " on the right of the article's title."]]))

 (defn starred-help []
   (html
     [:div.help
       [:p [:em "Nothing starred?"]]
       [:p "If you find a good article you really like, you can \"star\" it by
-        clicking on " (star-empty-image true) " at the left of the article. Starred article will always
-        be displayed in the " (link-to "/starred" "Starred") " section
-        whether they have been read or not"]
-      [:p "To \"unstar\" a starred article, click on " (star-image true) "."]]))
+        clicking on " [:img {:src "/public/i/star-empty.png"}] " at the left of the article's title.
+        Starred article will always be displayed in the "
+        (link-to "/starred" "Starred") " section whether they have been read or not"]
+      [:p "To \"unstar\" a starred article, click on " [:img {:src "/public/i/star.png"}]  "."]]))

 (defn articles-page
   [type articles advice-section]


Update for new Timbre version

Update for new Timbre version

--- src/kinesis_logger/core.clj
+++ src/kinesis_logger/core.clj
@@ -16,7 +16,7 @@
    ;; reduce logging from the slf4j adapter to WARN
    :middleware [(fn min-level-for-ns [msg]
                   (when
-                      (or (not= "slf4j-timbre.adapter" (:?ns-str msg))
+                      (or (not (re-matches #"^com.amazonaws.services.kinesis.*" (:?ns-str msg)))
                           (log/level>= (:level msg) :warn))
                     msg))]


arm: mvebu: generate DTBs for supported SoCs

Add the necessary dtb-$(CONFIG_...) entries so that "make dtbs"
generates the Device Tree Blobs that correspond to the selected mvebu
SoCs.

Signed-off-by: Thomas Petazzoni <a5d87d2bd7c424ee5cbdb4e978635bf653d5a005@free-electrons.com>
Signed-off-by: Arnd Bergmann <f2c659f01951776204a6c5b902787d9019fbeebd@arndb.de>

--- arch/arm/mach-mvebu/Makefile.boot
+++ arch/arm/mach-mvebu/Makefile.boot
@@ -1 +1,3 @@
 zreladdr-y := 0x00008000
+dtb-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-db.dtb
+dtb-$(CONFIG_MACH_ARMADA_370_XP) += armada-xp-db.dtb


missing parameter

missing parameter

--- src/leiningen/fore_prob.clj
+++ src/leiningen/fore_prob.clj
@@ -89,7 +89,7 @@
 (defn- has-problem-tests?
   "test if the current project has tests for a given problem"
   [tests problem]
-  (boolean (re-find (re-pattern (str "\\(" (prob->fn problem) "\\b")))))
+  (boolean (re-find (re-pattern (str "\\(" (prob->fn problem) "\\b")) tests)))

 (defn- has-problem-src?
   "test if the current project has the function for a given problem"


[#1808] Ensure multiple-type and multiple-id

--- backend/src/akvo/lumen/update.clj
+++ backend/src/akvo/lumen/update.clj
@@ -50,7 +50,8 @@
                                      :reason [reason]}))

 (defn- apply-transformation-log [conn table-name importer-columns original-dataset-columns last-transformations dataset-id version]
-  (let [importer-columns (mapv (fn [{:keys [title id type key caddisflyResourceUuid] :as column}]
+  (let [importer-columns (mapv (fn [{:keys [title id type key caddisflyResourceUuid
+                                            multiple-id multiple-type] :as column}]
                                  (cond-> {"type" (name type)
                                           "title" title
                                           "columnName" (name id)
@@ -58,7 +59,9 @@
                                           "direction" nil
                                           "hidden" false}
                                    key                   (assoc "key" (boolean key))
-                                   caddisflyResourceUuid (assoc "caddisflyResourceUuid" caddisflyResourceUuid)))
+                                   caddisflyResourceUuid (assoc "caddisflyResourceUuid" caddisflyResourceUuid)
+                                   multiple-type (assoc "multipleType" multiple-type)
+                                   multiple-id (assoc "multipleId" multiple-id)))
                                importer-columns)]
     (update-dataset-version conn {:dataset-id      dataset-id
                                   :version         version


Implement code for "Life without a..."

Implement code for "Life without a..."

Write the code for the "Life without a templating language" section.
This section demonstrates using functional programming to implement
features that templating languages might provide.

--- basic/om-tut/src/om_tut/core.cljs
+++ basic/om-tut/src/om_tut/core.cljs
@@ -10,11 +10,16 @@

 (defonce app-state (atom {:list ["Lion" "Zebra" "Buffalo" "Antelope"]}))

+(defn stripe [text background-color]
+  (let [st #js {:backgroundColor background-color}]
+    (dom/li #js {:style st} text)))
+
 (om/root
  (fn [data owner]
    (om/component
     (apply dom/ul #js {:className "animals"}
-           (map (fn [text] (dom/li nil text)) (:list data)))))
+           (map stripe (:list data) (cycle ["#ff0" "#fff"])))))
+
  app-state
  {:target (. js/document (getElementById "app0"))})


hide :password/:passphrase keys in loader creation exceptions.

--- src/ancient_clj/io.clj
+++ src/ancient_clj/io.clj
@@ -16,11 +16,20 @@

 ;; ## Helper

+(defn- sanitize
+  [m k]
+  (if (contains? m k)
+    (assoc m k '<hidden>)
+    m))
+
 (defn- throw-loader-exception!
   [opts]
-  (throw
-    (IllegalArgumentException.
-      (format "cannot create loader from: %s" (pr-str opts)))))
+  (let [sanitized-opts (-> opts
+                           (sanitize :password)
+                           (sanitize :passphrase))]
+    (throw
+      (IllegalArgumentException.
+        (format "cannot create loader from: %s" (pr-str opts))))))

 (def ^:private get-scheme
   (let [m {:https :http


Fix a regression from private board invite notifications where if there wasn't an invite the board update would fail.

--- src/oc/storage/api/boards.clj
+++ src/oc/storage/api/boards.clj
@@ -106,14 +106,13 @@
 (defn- valid-board-update? [conn org-slug slug board-props]
   (if-let* [org (org-res/get-org conn org-slug)
             board (board-res/get-board conn (:uuid org) slug)
-            notifications (:private-notifications board-props)
             board-data (dissoc board-props :private-notifications)]
     (let [updated-board (merge board (board-res/clean board-data))]
       (if (lib-schema/valid? common-res/Board updated-board)
         {:existing-org org
          :existing-board board
          :board-update updated-board
-         :notifications notifications}
+         :notifications (:private-notifications board-props)}
         [false, {:board-update updated-board}])) ; invalid update
     true)) ; No org or board, so this will fail existence check later

@@ -181,9 +180,9 @@
             org (:existing-org ctx)
             board (:existing-board ctx)
             updated-board (:board-update ctx)
-            notifications (:notifications ctx)
             updated-result (board-res/update-board! conn (:uuid updated-board) updated-board)]
-    (let [current-authors (set (:authors updated-result))
+    (let [notifications (:notifications ctx)
+          current-authors (set (:authors updated-result))
           current-viewers (set (:viewers updated-result))
           new-authors (-> ctx :data :authors)
           new-viewers (-> ctx :data :viewers)]


Wip: Find tasks.

Wip: Find tasks.

--- src/onyx/coordinator/impl.clj
+++ src/onyx/coordinator/impl.clj
@@ -180,15 +180,30 @@
 (defn find-active-task-ids [sync sorted-tasks]
   (filter (fn [task] (not (task-complete? sync task))) sorted-tasks))

-(defn next-incomplete-task [sync job-id]
-  (let [incomplete-tasks (extensions/bucket-at sync :task job-id)
-        sorted-tasks (sort-tasks-by-phase sync incomplete-tasks)
+(defn next-inactive-task [sync job-id]
+  (let [inactive-tasks (extensions/bucket-at sync :task job-id)
+        sorted-tasks (sort-tasks-by-phase sync inactive-tasks)
         active-tasks (find-active-task-ids sync sorted-tasks)]
     (filter (fn [t] (not (contains? active-tasks (:id t)))) sorted-tasks)))
+
+(defn find-incomplete-concurrent-tasks [sync job-id]
+  (let [tasks (extensions/bucket-at sync :task job-id)
+        active (find-active-task-ids sync tasks)]
+    (filter (fn [task]
+              (let [task-data (extensions/read-place sync task)]
+                (= (:task/consumption task-data) :concurrent)))
+            active)))
+
+(defn sort-tasks-by-peer-count [sync tasks])
+
+(defn next-active-task [sync job-id]
+  (let [incomplete-tasks (find-incomplete-concurrent-tasks sync job-id)]
+    (sort-tasks-by-peer-count sync incomplete-tasks)))

 (defmethod extensions/next-tasks ZooKeeper
   [sync]
   (let [job-seq (job-candidate-seq (incomplete-jobs-ids sync)
                                    (last-offered-job sync))
-        incomplete-candidates (mapcat (partial next-incomplete-task sync) job-seq)]))
-
+        inactive-candidates (mapcat (partial next-inactive-task sync) job-seq)
+        active-candidates (mapcat (partial next-active-task sync) job-seq)]))
+


Bug: returned empty component every time

--- src/onyx/state/bookkeeper.clj
+++ src/onyx/state/bookkeeper.clj
@@ -96,13 +96,13 @@
   (component/start [component]
     (if (arg-or-default :onyx.bookkeeper/server? env-config)
       (let [local-quorum? (arg-or-default :onyx.bookkeeper/local-quorum? env-config)
-          ports (if local-quorum?
-                  (arg-or-default :onyx.bookkeeper/local-quorum-ports env-config)
-                  (vector (arg-or-default :onyx.bookkeeper/port env-config)))]
-      (assoc component :servers (mapv (fn [port]
-                                        (component/start (->BookieMonitor env-config log port)))
-                                      ports))
-      component)))
+            ports (if local-quorum?
+                    (arg-or-default :onyx.bookkeeper/local-quorum-ports env-config)
+                    (vector (arg-or-default :onyx.bookkeeper/port env-config)))]
+        (assoc component :servers (mapv (fn [port]
+                                          (component/start (->BookieMonitor env-config log port)))
+                                        ports)))
+      component))
   (component/stop [component]
     (if (arg-or-default :onyx.bookkeeper/server? env-config)
       (doseq [server (:servers component)]


Revert max pending.

Revert max pending.

--- src/onyx_benchmark/submit.clj
+++ src/onyx_benchmark/submit.clj
@@ -44,7 +44,7 @@
       [{:onyx/name :in
         :onyx/ident :generator
         :onyx/type :input
-        :onyx/max-pending 500000
+        :onyx/max-pending 300000
         :onyx/medium :generator
         :onyx/consumption :concurrent
         :onyx/batch-size batch-size}


[#1032] Required backend changes due to flow-api changes

--- backend/src/akvo/lumen/import/flow.clj
+++ backend/src/akvo/lumen/import/flow.clj
@@ -52,7 +52,7 @@
 (defn form-instances
   "Returns a lazy sequence of form instances"
   [headers-fn form]
-  (let [initial-url (str (:formInstancesUrl form) "?pageSize=300")]
+  (let [initial-url (str (:formInstancesUrl form) "&page_size=300")]
     (form-instances* headers-fn initial-url)))

 (defn data-points*
@@ -68,7 +68,7 @@
   (loop [all-data-points []
          response (data-points* headers-fn
                                 (str (:dataPointsUrl survey)
-                                     "?pageSize=300"))]
+                                     "&page_size=300"))]
     (if-let [url (get response "nextPageUrl")]
       (recur (into all-data-points (get response "dataPoints"))
              (data-points* headers-fn url))
@@ -162,16 +162,28 @@
                       {:form-id form-id
                        :survey-id (:id survey)}))))

+;; Transforms the structure
+;; {question-group-id -> [{question-id -> response}]
+;; to
+;; {question-id -> first-response}
+(defn question-responses
+  "Returns a map from question-id to the first response iteration"
+  [responses]
+  (->> (vals responses)
+       (map first)
+       (apply merge)))
+
 (defn response-data
   [form responses]
-  (reduce (fn [response-data {:keys [type id]}]
-            (if-let [response (get-in responses [id "0"])]
-              (assoc response-data
-                     (keyword (format "c%s" id))
-                     (render-response type response))
-              response-data))
-          {}
-          (questions form)))
+  (let [responses (question-responses responses)]
+    (reduce (fn [response-data {:keys [type id]}]
+              (if-let [response (get responses id)]
+                (assoc response-data
+                       (keyword (format "c%s" id))
+                       (render-response type response))
+                response-data))
+            {}
+            (questions form))))

 (defn form-data
   "Returns a lazy sequence of form data, ready to be inserted as a lumen dataset"


plugin - wait for the karma server to start

Fixes #71


Review

Review

--- src/literate_2048/core.cljs
+++ src/literate_2048/core.cljs
@@ -12,12 +12,11 @@
 ;; # Board and tiles

 ;; The board on which the game is played consist of 16 squares ordered in 4 rows
-;; and 4 columns. People seem to get really mad when they see the same number
-;; over and over again, so let's give the number 4 a better name.
+;; and 4 columns. We say 4 is the board's order.

 (def board-order
-  "Number of squares on a board's row or column. It is also the count of rows
-   rows and columns and the square root of the total number of squares."
+  "Number of squares on a board row or column. It's also the count of rows and
+   columns and the square root of the total number of squares."
   4)

 ;; The choosen representation for the board is a vector of 16 (4*4) elements.
@@ -30,13 +29,12 @@
 ;; An empty square is represented by nil.

 (def empty-board
-  "A vector of board-order^2 nils."
+  "Vector containing board-order^2 nil elements."
   (vec (repeat (* board-order board-order) nil)))

 ;; Every time a tile is added to the board, it randomly appears in a empty
-;; square. It's easy to choose what that square would be by getting the indexes
-;; of the nil elements of the board representation, shuffling them and taking
-;; the first.
+;; square. We can choose a square by getting the indexes of the nil elements and
+;; taking the first one after shuffling them.

 (defn nil-indexes
   "Returns a set with the indexes of the nil elements of v."
@@ -49,13 +47,12 @@
   (-> v nil-indexes shuffle first))

 ;; Then, we associate the index with a new tile in the board representation. A
-;; function that builds the tile must be provided because the details about what
-;; a tile looks like aren't really important and somebody else should take care
-;; of them.
+;; function that builds the tile must be provided because we don't really care
+;; about its details.

 (defn add-tile
-  "Takes a board and returns a new one with one more tile, where tile-fn is a
-   function that returns a new tile."
+  "Takes a board and returns a new one with one empty square replaced by the
+   return value of tile-fn."
   [tile-fn board]
   (assoc board (rand-nil-index board) (tile-fn)))

@@ -63,8 +60,8 @@
 ;; necessary for the player to make the first move.

 (defn initial-board
-  "Returns a board with two (random) tiles, where tile-fn is a function that
-   returns a new tile."
+  "Returns a board with two tiles returned by tile-fn, which will be called
+   twice."
   [tile-fn]
   (let [f (partial add-tile tile-fn)]
     (-> empty-board f f)))
@@ -72,9 +69,9 @@
 ;; # Tile synthesis

 ;; The goal of the game is to merge tiles together until a tile that is not able
-;; to be merged appears. Thus, we need a way to tell if a tile can be merged
-;; with another tiles and a mechanism to obtain the result of the merge of two
-;; given tiles.
+;; to be merged appears. Thus, we need to tell if a tile can be merged with
+;; another tiles and a mechanism to obtain the result of the merge of two given
+;; tiles.

 ;; Since 'merge' is already a map operation, let's name the process 'synthesis'.

@@ -83,23 +80,24 @@
   (-synth? [this]
     "Returns true if the tile can participate in a synthesis.")
   (-synth [this other]
-    "Returns the result of the synthesis, another ITile when they can be
-    synthesized or nil when they can't. No tile can be synthesized with nil."))
+    "Returns the result of the synthesis of the tile with other, which is
+     another ITile when they can be synthesized or nil when they can't. No tile
+     can be synthesized with nil."))

 ;; While two tiles might be able to participate in a synthesis they might not be
 ;; able to be synthesized together.

-;; To synthesize a sequence of tiles, take the first two and try to synthesize
-;; them:
+;; To synthesize a sequence of tiles, take the first two and:
 ;; - If they can be synthesized, accumulate the result of their synthesis and
 ;;   repeat the process for the rest of the tiles (a tile can't be synthesized
 ;;   more than once in one process).
 ;; - If they can't be synthesized, accumulate the first tile and repeat the
-;;   process for all the tiles except that firstone.
+;;   process for all the tiles except that first one.
 ;; - If there's only one tile, accumulate it. (This can be reduced to the
 ;;   previous directive if we try to synthesize the tile with nil.)
 ;; - When there are no more tiles the process is done, and the accumulation is
 ;;   its result.
+
 (defn synth-adjacent
   "Returns a sequence of the elements of tiles, replacing adjacent elements with
    the result of applying -synth to them when is not logically false."
@@ -138,15 +136,15 @@
 ;; into a tile with the total value of the two tiles that collided. The
 ;; resulting tile cannot merge with another tile again in the same move.

-;; While the entire process looks overwhelming, it turns out that it is easy to
-;; move a single row to the left. If a row is a sequence of tiles and/or nil
-;; elements, then:
+;; While the entire process looks overwhelming, it turns out that it is pretty
+;; easy to move a single row to the left. If a row is a sequence of 4 elements,
+;; containing tiles and/or nil elements, then:
 ;; - applying compact to the sequence solves the 'sliding' part of the problem,
-;; - and applying synth-adjacent to that solves the 'merge' part.
+;; - and applying synth-adjacent to the result solves the 'merge' part.
 ;; However, the previous function applications lead to an undesired consequence,
 ;; the resulting sequence is not a proper row. It might be shorter because of
-;; the lack of nil elements. Fortunately, nils should be aligned to the right
-;; and can be appended with take-exactly.
+;; the lack of nil elements. Fortunately, in this case, nils must be aligned to
+;; the right and can be appended with take-exactly.

 (defn slide-synth-line
   [line]
@@ -159,16 +157,17 @@
 ;; function, it just need to be provided with the right line argument.

 ;; A line is a sequence that represents the flow of the tiles during a move. In
-;; other words, is a row or a column of the board, where the closest a square is
-;; is to edge of the board the tiles are sliding to, the sooner it appears in
-;; the sequence.
+;; other words, is a row or a column of the board where the closest a square is
+;; to edge of the board the tiles are sliding to, the sooner it appears in the
+;; sequence.

 ;; The slide and synthesis of the whole board can be summarized as:
 ;; - Obtaining the lines. Rows are partitions of 4 elements of our board
-;;   representation and columns are transposition of them.
+;;   representation and columns are transposition of them. For the 'right' and
+;;   'up' move, rows and columns need to be reversed to obtain the proper line.
 ;; - Slide and synth the lines.
-;; - Turn the resulting sequences (rows or columns) back to our board
-;; representation.
+;; - Turn the resulting sequences, that is rows or columns possibly reversed
+;;   back to our board representation.

 (defn slide-synth
   "Returns the result of sliding and synthesizing the tiles of board in the
@@ -189,7 +188,7 @@

 (defn move
   "Slides and synthesizes the tiles of board in the given direction, and return
-   the result when is different from board."
+   the result when it is different from board."
   [tile-fn board direction]
   (let [board' (slide-synth board direction)]
     (when (not= board board') (add-tile tile-fn board'))))
@@ -202,100 +201,120 @@
   [board]
   (some (complement -synth?) (compact board)))

-;; The player loses the game when there are no more moves left, that is, sliding
-;; and synthesizing the board on every direction yields the same original board.
+;; The player loses the game when there are no more possible moves, that is,
+;; sliding and synthesizing the board on every direction yields the same
+;; original board.
+
+(defn lost?
+  "Returns true when applying slide-synth to board and every possible direction
+   always returns board."
+  [board]
+  (apply = board (map (partial slide-synth board) [:left :right :up :down])))
+
 ;; The game ends when the player wins or loses.

 (defn ended?
-  "Returns true if won? is truthy for board or when applying slide-synth to
-   board and every possible direction always returns board."
+  "Returns true if won? or lost? is truthy for board."
   [board]
-  (or (won? board)
-      (apply = board
-             (map (partial slide-synth board) [:left :right :up :down]))))
+  (or (won? board) (lost? board)))

 ;; # Rendering

 ;; Because manually manipulating the DOM is messy, we'll let
-;; [Quiescent](https://github.com/levand/quiescent) do the work, which is an
-;; abstraction over [React](http://facebook.github.io/react) that leverages
-;; immutability. All we need to do is provide a data structure which tells how
-;; we want the DOM to look like at a given moment, but before getting into it
-;; lets define a couple of helper functions.
-
-;; An element is positioned on the board by specifying the classes "pos" and
-;; "pos-i-j", where i and j are numbers from 0 to 3 representing the row and
-;; the column of the element, respectively. The following function translates a
-;; vector with the element position, that is, the row and the column, to a
-;; string of theese classes.
-
-(defn pos-classes
-  [[i j]]
-  (str "pos pos-" i "-" j))
-
-;; Also, tiles are styled differently according to their value. We'll use the
-;; class "tile" to identify an element as a tile and "tile-val", where val is
-;; the value of the tile, to apply the correct color, font size, shadow, etc.
-
-(defn tile-classes
-  [val]
-  (str "tile tile-" val))
-
-;; To paint the squares of the board, we need to render the following HTML
-
-;;

-;;

-;;

-;;      ...
-;;

+;; [Quiescent](https://github.com/levand/quiescent) do it for us instead.
+;; Quiescent is an abstraction over [React](http://facebook.github.io/react)
+;; that leverages immutability. We are responsible only for supplying a
+;; specification of what the UI should look like. Quiescent will rely on React
+;; to generate the minimal set of changes that need to be applied to the DOM.
+
+;; Elements are placed on the board on well established positions by wrapping
+;; them in a div with the "pos" and "pos-i-j" classes, where i and j are numbers
+;; from 0 to 3 that stand for the row and the column that defines the position.
+;; For instance, the following markup places an element on the bottom-left
+;; corner.
+
+;;

+;;
 ;;

-;; The squares-view function, when supplied with 4, returns a virtual
-;; representation of that.
+;; While that is enough to position an element, a problem arises if we want to
+;; rely on CSS transitions to animate the translation of the element as its
+;; position changes over time. Without getting into much detail, when React
+;; updates the DOM it tries to do it in the most efficiently manner by recycling
+;; what is already in the DOM. It does not provide (by default) any guarantee
+;; that the same DOM element will be used for our example div across render
+;; passes. Fortunately, the only reason React can't keep a mapping between the
+;; elements of our specification and the elements of the DOM is because it
+;; doesn't have a way to identify the elements of the specification. We can
+;; provide React the information it needs by assigning a key to our divs. The
+;; [official documentation](http://facebook.github.io/react/docs/reconciliation.html)
+;; is a great place to learn more about React's reconciliation process.
+
+(defn pos-view
+  "Returns a div wrapping content with positioning classes derived from pos,
+   which is a two-element vector containing a row and a column. Optionally, a
+   React key can be provided."
+  ([pos content] (pos-view pos nil content))
+  ([[i j] key content]
+     (d/div {:className (str "pos pos-" i "-" j)
+             :key key}
+       content)))
+
+;; A square is just a div with the square class.
+
+;;

+
+(defn square-view
+  "Returns a div with a square class."
+  []
+  (d/div {:className "square"}))
+
+;; To render the board we need to draw a square in every position.

 (defn squares-view
+  "Returns a div containing a square for each position of a board with a given
+   order."
   [order]
   (apply d/div {:className "squares"}
     (for [i (range order) j (range order)]
-      (d/div {:className (str "square " (pos-classes [i j]))}))))
-
-;; A tile with a value of 2 that just appeared on the bottom-left corner will
-;; look something like this
-
-;;

-;;
2

-;;

-
-;; The tiles-view function, takes a sequence of tiles and renders them inside a
-;; div with the "tiles" class. Each element of the sequence is a map with the
-;; :val and :pos keys, 2 and [3 0] from the example. A :classes key may be
-;; provided to apply extra classes to the tile element, like "reveal" from the
-;; example. As we'll see in a moment, theese classes are needed to animate the
-;; appearence of new tiles. There is one last detail. When React updates the
-;; DOM, it tries to do it in the most efficiently manner and does not provide
-;; any warantee by default that the same DOM element will be used for the same
-;; tile across render passes. This is a problem for us because the CSS
-;; translation animations happens when the "pos-i-j" class of a DOM element
-;; changes. The goods news is that we can instruct React to do it if we identify
-;; indentify every tile uniquely with a :key. To learn more about React's
-;; reconciliation process see
-;; [this](http://facebook.github.io/react/docs/reconciliation.html) and
-;; [this](http://facebook.github.io/react/docs/multiple-components.html).
+      (pos-view [i j] (square-view)))))
+
+;; Tiles are styled differently according to their value. We'll use the
+;; class "tile" to apply styles shared by all tiles and "tile-val", where val is
+;; the tile's value, to apply the right color, font size, shadow, etc. However,
+;; a tile might have another classes.
+
+;;
2

+
+;; The previous markup represents a tile with a value of two which has been just
+;; added to the board. Extra classes, such as "fade-in", are needed to animate
+;; the appearence of new tiles.
+
+(defn tile-view
+  "Returns a div with tile classes whose content is val. Another classes can be
+   provided."
+  ([val] (tile-view val ""))
+  ([val classes] (d/div {:className (str classes " " (str "tile tile-" val))}
+                   val)))
+
+;; Of course there are a lot of tiles that need to be rendered.

 (defn tiles-view
-  [s]
+  "Returns a div with the tiles class containing the tiles provided. Tiles are
+   wrapped in a div with their position. Each tile is a map that must contain
+   :val (something with a str value) and :pos (two-element vector containing a
+   row and a column number). Optionally, it can also contain :key (a React key)
+   and :classes (string to be concatenated with the default tile classes)."
+  [tiles]
   (apply d/div {:className "tiles"}
     (map (fn [{:keys [val pos key classes]}]
-           (d/div {:className (pos-classes pos)
-                   :key key}
-             (d/div {:className (str classes " " (tile-classes val))}
-               val)))
-         s)))
-
-;; Finally, a Quiescent component will render the squares and the tiles. To
-;; learn more about Quiescent you can read the
-;; [docs](https://github.com/levand/quiescent/blob/master/docs.md) or just the
-;; [source](https://github.com/levand/quiescent/tree/master/src).
+           (pos-view pos key (tile-view val classes)))
+         tiles)))
+
+;; Finally, we can put toghether the board with the squares and the tiles in a
+;; Quiescent component. To learn more about Quiescent components you can read
+;; the
+;; [official documentation](https://github.com/levand/quiescent/blob/master/docs.md).

 (q/defcomponent SquareBoard
   [tiles order]
@@ -313,25 +332,28 @@
 ;; - :key, some keyword that uniquely identifies the tile
 ;; - :new, the boolean true
 ;; The same function will also take two tiles and return the result of merging
-;; them together, that is a new tile described by:
+;; them together, that is, a new tile described by:
 ;; - :val, the sum of the :val of the source tiles
-;; - :key, some keywords that uniquely identifies the tile
-;; - :src, a vector containing the source tiles that originated this one
+;; - :key, some keyword that uniquely identifies the tile
+;; - :src, a vector containing the source tiles, responsible for originating
+;;   this one
+
+;; ## Specification

 (defn build-tile
   "Returns a map with :val associated to val and :key to an unique keyword. If
-   no val is supplied it defaults to 2 most of the time, but it might be 4, and
-   the key :new is mapped to true. Alternatively, when applied to two tiles, x
-   and y, the result is the same as calling it with the sum of the tiles :val
-   and associng the key :src to a vector of the two."
+   no val is supplied, it defaults to 2 most of the time but it might default to
+   4, and the key :new is mapped to true. Alternatively, when applied to two
+   tiles, x and y, the result is the same as calling it with the sum of the
+   tiles :val and associng the key :src to a vector containing x and y."
   ([] (assoc (build-tile (if (< (rand) 0.8) 2 4)) :new true))
   ([val] {:val val :key (keyword (gensym ""))})
   ([x y] (assoc (build-tile (+ (:val x) (:val y))) :src [x y])))

-;; Before going further, an implementation of the ITile protocol (presented in
-;; section 'Tile synthesis') must be provided. The synthesis of two tiles with
-;; the same :val is another tile (described below), but the synthesis of two
-;; tiles with different :val is nil. A tile with a :val of 2048 can't be
+;; Before going further, an implementation of the ITile protocol, presented in
+;; section 'Tile synthesis', must be provided. The synthesis of two tiles with
+;; the same :val is another tile (described above), but the synthesis of two
+;; tiles with different :val is nil. Also, a tile with a :val of 2048 can't be
 ;; synthesized anymore.

 (extend-type cljs.core/PersistentArrayMap
@@ -351,20 +373,25 @@
 ;; As you can probably guess, our board representation needs to be transformed
 ;; into something that SquareBoard (defined in section 'Rendering') can make
 ;; sense of. Additionaly, the transformation must remove the novelty when the
-;; slide phase is rendered. The next steps illustrate a way to achieve that:
-;; - Keep only the tiles of the board (remove the empty squares) and associate
-;;   on each one :pos to a vector with the column and the row of the square the
-;;   it is located.
+;; slide phase is rendered. The next steps illustrate a way to achieve that.
+;; - Keep only the tiles of the board by removing the empty squares and
+;;   associate on each one :pos to a vector with the column and the row of the
+;;   square the it is located.
 ;; - If no novelty must be present, remove new tiles and replace synthesized
-;;   tiles with the original ones. Those tiles will have the position of the
+;;   tiles with the original ones. Those tiles will have the position of their
 ;;   synthesis because during the animation they need to slide there before
 ;;   being merged.
-;; - Associate :classes with "fade-in" on the tiles with the key :new to animate
-;;   its appearence by scaling them to its actual size from an almost invisible
-;;   one.
-;; - Associate :classes with "highlight" on tiles with the key :src to animate
-;;   its appearence by scaling them to a size a little bigger and then back to
-;;   its original size.
+;; - Associate :classes with "fade-in" on the tiles containing the :new key to
+;;   animate its appearence by scaling them to its actual size from an almost
+;;   invisible dimension. For the first turn there will be exactly two new
+;;   tiles. For the others there will be always one.
+;; - Associate :classes with "highlight" on tiles containing the :src key to
+;;   animate its appearence by scaling them to a size a little bigger and then
+;;   back to its original dimension. The board does not necessarily have to
+;;   contain any synthesized tiles.
+;; - Sort the tiles by their :key to ensure React doesn't remove and insert any
+;;   DOM elements breaking the CSS transition as discussed in the 'Rendering'
+;;   section.

 (defn board->tiles
   "Returns a sequence of tiles taken from board with their :pos and sorted by
@@ -400,9 +427,10 @@
       (d/div {:className "end-message"}
         (if (won? board) "You win!" "You lose!")))))

-;; A target DOM element also needs to be specified when rendering a Quiescent
-;; component. Because we'll need to perform two renders per move (one for each
-;; animation phase) it's convenient to hide such details in a render function.
+;; When rendering a Quiescent component a target DOM element needs to be
+;; provided along with the component and its data. Because we'll need to perform
+;; two renders per move (one for each animation phase) it is convenient to hide
+;; such details in a render function.

 (defn render
   "Renders the Game component to the DOM node with the 'game' id with the given
@@ -411,15 +439,17 @@
   (q/render (Game {:board board :phase phase})
             (.getElementById js/document "game")))

+;; ## Event handling
+
 ;; Our board representation only describes how the board looks at a given point
 ;; in time. Tiles that are the result of a synthesis or have been added will no
 ;; longer be novelty the next time the player makes a move. That's why moves are
 ;; made on a board with no transient data, none of its tiles have a :new or a
-;; :src key
+;; :src key.

 (defn handle-move
   "Performs a new move on board in the given direction after removing transient
-   data from the tiles (:new and :src keys). Returns the new board or nil when
+   data from the tiles (:new and :src keys). Returns the new board, or nil when
    no change occurs."
   [board direction]
   (move build-tile (map #(dissoc % :new :src) board) direction))
@@ -442,12 +472,11 @@
      c))

 ;; The second function will return a channel only with the events that we care
-;; about, that is keyup events of the document that happens when an arrow key is
-;; pressed. Also, we would like something more descriptive than the raw DOM
-;; event. So, we'll take every keyup event of the document, map it to its key
-;; code, stop if they don't belong to an arrow key or map it to either :left,
-;; :up, :right or :down when they do. The second function returns a channel that
-;; does just that.
+;; about, that is, keyup events of the document that happens when an arrow key
+;; is pressed. Also, we would like something more descriptive than a raw DOM
+;; event. We'll take every keyup event of the document, map it to its key code,
+;; stop if they don't belong to an arrow key or map it to either :left, :up,
+;; :right or :down when they do.

 (defn keys-chan
   "Returns a channel of :left, :up, :right and :down events sourced from arrow
@@ -459,26 +488,37 @@
                                 (filter (set (keys key-map)))
                                 (map key-map))))))

-;; Finally we arrived to the part where we put everything together, the game
-;; loop. The loop's bindings will serve us to keep the state we need, that is,
-;; the board and the action we want to perform. On each iteration, we either
-;; render the board or wait for a move event. Rendering the board means:
-;; - render the board in the translation phase,
-;; - wait for the transition animations,
-;; - render the board in the reveal phase, and
-;; - wait for the appearence animations.
-;; - If the game didn't end, start another iteration for the board and the :wait
-;;   action, but
-;; - if it did, stop looping.
-;; Wait for a move event means:
-;; - wait for a key event,
-;; - if the move was valid, loop again with the new board and the :render
-;;   action, but
-;; - if it wasn't valid, keep waiting for a valid move event with the current
-;;   board.
-;; The loop is started with a random initial board and the :render action. Even
-;; though there's nothing to show in the first translation phase, it happens so
-;; dast that it doesn't matters.
+;; ## The game loop
+
+;; Finally we arrived to the part where we put everything together. We'll start
+;; a loop that renders the board or waits for a event to make a move. The loop's
+;; bindings will serve us to keep the state we need to perform either of the
+;; previous actions on each iteration. The loop begins with a random initial
+;; board and the :render action.
+
+;; ### Rendering the board
+
+;; When the value of the action binding is :render:
+
+;; - we render the board in the translation phase,
+;; - and wait a bit while the translation animation finishes.
+;; - Then, we render the board again but in the reveal phase,
+;; - and wait while the appearence animation finishes.
+;; - Now, if the game ended we exit the loop, but, if it didn't, we start
+;;   another iteration for the current board and the :wait action.
+
+;; Even though there's nothing to show in the first translation phase, it
+;; happens so fast that it doesn't really matters.
+
+;; ### Waiting for a move event
+
+;; When the value of the action binding is :wait:
+
+;; - we wait for a key event, and try to perform a move in it's direction.
+;; - If the move was valid, that is something changed, we loop again with the
+;;   new board that results from the move and the :render action.
+;; - But, if it wasn't valid, we'll keep waiting for a valid move. We iterate
+;;   with the current board and the :wait action.

 (let [keys (keys-chan)]
   (go-loop [board (initial-board build-tile)


removing dead code

removing dead code

--- src/midje/util/colorize.clj
+++ src/midje/util/colorize.clj
@@ -14,11 +14,6 @@

 (defn reverse-color-choice? []
   (= (colorize-choice) "REVERSE"))
-
-(defn colorizing? []
-  (let [default (default-color-choice?)
-        reverse (reverse-color-choice?)]
-    (or default reverse)))

 (defn colorizing? []
   (not (= (colorize-choice) "FALSE")))


remove a stray inspect, scroll to top of page by default

--- frontend/controllers/navigation.cljs
+++ frontend/controllers/navigation.cljs
@@ -29,7 +29,6 @@
 (defn scroll-to-fragment!
   "Scrolls to the element with id of fragment, if one exists"
   [fragment]
-  (utils/inspect fragment)
   (when-let [node (sel1 (str "#" fragment))]
     (let [main (sel1 "main.app-main")]
       (set! (.-scrollTop main) (.-y (goog.style.getContainerOffsetToScrollInto node main))))))
@@ -55,9 +54,10 @@
 (defmethod post-navigated-to! :default
   [history-imp navigation-point args previous-state current-state]
   (set-page-title! (str/capitalize (name navigation-point)))
-  (when (:_fragment args)
+  (if (:_fragment args)
     ;; give the page time to render
-    (js/requestAnimationFrame #(scroll-to-fragment! (:_fragment args)))))
+    (js/requestAnimationFrame #(scroll-to-fragment! (:_fragment args)) 32)
+    (js/requestAnimationFrame #(set! (.-scrollTop (sel1 "main.app-main")) 0) 32)))

 (defmethod post-navigated-to! :navigate!
   [history-imp navigation-point path previous-state current-state]


Improve textual content.

Improve textual content.

--- src/mtrx9/views/statics.clj
+++ src/mtrx9/views/statics.clj
@@ -7,11 +7,10 @@
     [:div
       [:h1 "MTRX9"]
       [:p "Keep an eye on many things."]
-      [:p "1 character at a time."]
-      [:p "3 dimensions:"]
+      [:p "Simple monitoring in 3 dimensions:"]
       [:ul
         [:li "streams"]
-        [:li "values"]
+        [:li "chars"]
         [:li "time"]]
       [:div
         (form-to [:post "/matrices"]
@@ -21,7 +20,7 @@
   (layout/sidebar-right "About | MTRX9"
     [:div
       [:h1 "About"]
-      [:p "MTRX9 is written in Clojure."]
+      [:p "MTRX9 is written in Clojure. It uses Websockets."]
       [:p "Fork it on " [:a {:href "https://github.com/tiredpixel/mtrx9"} "GitHub"] "."]
       [:p "Tweet " [:a {:href "https://twitter.com/mtrx9"} "@mtrx9"] "."]
       [:p "More sleep lost by " [:a {:href "http://www.tiredpixel.com"} "tiredpixel"] "."]]))


Generalisation of the thread macro to all monads.

--- src/asid/error_flow.clj
+++ src/asid/error_flow.clj
@@ -25,19 +25,24 @@
               m
               (f m)))])

-(defn add-monadic-expr [insert form]
+(defn bind-monadic-expr-into-form [insert form]
   (list 'm-bind insert (if (seq? form)
                          `(fn [bound#] (~(first form) bound# ~@(rest form)))
                          `(fn [bound#] (~form bound#)))))

-(defmacro f->
-  ([x]
-     `(monad/with-monad failure-m ~x))
-  ([x form]
-     `(monad/with-monad failure-m
-        ~(add-monadic-expr x form)))
-  ([x form & more]
-     `(f-> (f-> ~x ~form) ~@more)))
+(defmacro m->
+  ([m x]
+     `(monad/with-monad ~m ~x))
+  ([m x form]
+     `(monad/with-monad ~m
+        ~(bind-monadic-expr-into-form x form)))
+  ([m x form & more]
+     `(m-> ~m (m-> ~m ~x ~form) ~@more)))
+
+(defmacro fail->
+  ([x] `(m-> ~failure-m ~x))
+  ([x form] `(m-> failure-m ~x ~form))
+  ([x form & more] `(fail-> (fail-> ~x ~form) ~@more)))

 (defn- succeed [v]
   v)
@@ -51,25 +56,25 @@
     m))

 (fact
-  (f-> 10 (+ 9)) => 19
-  (f-> {} succeed) => {}
-  (f-> 10 (+ 9) (- 11)) => 8)
+  (fail-> 10 (+ 9)) => 19
+  (fail-> {} succeed) => {}
+  (fail-> 10 (+ 9) (- 11)) => 8)

 (defn- short-steps [limit]
-  (f-> {:limit 50}
-       (fail limit)))
+  (fail-> {:limit 50}
+          (fail limit)))

 (fact
   (short-steps 10) => {:limit 50}
   (short-steps 100) => (partial instance? Failure))

 (defn- more-steps [limit]
-  (f-> {}
-       succeed
-       (include :limit 50)
-       (fail limit)
-       (include :value 100)
-       (show :value)))
+  (fail-> {}
+          succeed
+          (include :limit 50)
+          (fail limit)
+          (include :value 100)
+          (show :value)))

 (fact
   (more-steps 10) => 100


fix command line behavior of (defn sentences)

--- src/babel/english.cljc
+++ src/babel/english.cljc
@@ -74,21 +74,29 @@
    (parse/parse (preprocess input) model)))

-(defn sentences [ & [spec model]]
-  (let [model (if model model (medium))
-        spec (if spec
-               (unifyc spec {:modified false})
-               {:modified false
-                :synsem {:cat :verb}})]
-    (repeatedly #(println (str (let [expr (generate spec
-                                                    :model model)
-                                     fo (fo expr :show-notes false)]
+(defn sentences [ & [count spec model]]
+  (let [count (or count 100)
+        model (or model (medium))
+        spec (or (and spec
+                      (unifyc spec {:modified false}))
+                 {:modified false
+                  :synsem {:cat :verb}})]
+    (println (str "count: " count))
+    (println (str "spec:" spec))
+    (doall (take count (repeatedly
+                        #(let [expr (generate spec
+                                              :model model)
+                               fo (fo expr :show-notes false)]
+                           (let [to-print
                                  (cond
                                    (empty? fo) (str "(failed)")
                                    true
                                    (str (string/capitalize (nth fo 0))
                                         (string/join "" (rest (vec fo)))
-                                        "."))))))))
+                                        "."))]
+                             (println to-print))))))))

+
+


List files

List files

--- src/bookshelf/core.clj
+++ src/bookshelf/core.clj
@@ -1,5 +1,6 @@
 (ns bookshelf.core
   (:gen-class)
+  (:use [clojure.string :as str])
   (:use [ring.adapter.jetty :as jetty])
   (:use [ring.middleware.reload :as reload])
   (:use [ring.middleware.stacktrace :as stacktrace])
@@ -11,8 +12,11 @@
     (.write w "hello\n"))
   "wrote to file")

+(defn library-files []
+  (file-seq (clojure.java.io/file "/Users/dan/GoogleDrive/Literature/iPad")))
+
 (defroutes handler
-  (GET "/" [] "Hello World")
+  (GET "/" [] (str/join "<br>" (library-files)))
   (GET "/write" [] (write-to-file))
   (route/not-found "Invalid request"))


support :conditional, :future, and :present exceptions

--- src/babel/espanol/morphology/verbs.cljc
+++ src/babel/espanol/morphology/verbs.cljc
@@ -22,6 +22,8 @@
 (defn reflexive-to-infinitive [reflexive-infinitive]
   "e.g.: quedarse -> quedar"
   (string/replace reflexive-infinitive #"se$" ""))
+
+(declare number-and-person)

 (defn conditional [word  & [ {usted :usted
                               vosotros :vosotros
@@ -43,9 +45,12 @@
         vosotros (if vosotros vosotros true)
         ustedes (if ustedes ustedes false)
         person (get-in word '(:agr :person))
-        number (get-in word '(:agr :number))]
-
+        number (get-in word '(:agr :number))
+        number-and-person (number-and-person number person)]
     (cond
+     (get-in word [:condicional number-and-person])
+     (get-in word [:condicional number-and-person])
+
      (and (= person :1st) (= number :sing) ar-type)
      (str stem "aría")
      (and (= person :1st) (= number :sing) er-type)
@@ -151,6 +156,9 @@
         number (get-in word '(:agr :number))]

     (cond
+     (get-in word [:futuro number-and-person])
+     (get-in word [:futuro number-and-person])
+
      (and (= person :1st) (= number :sing) ar-type)
      (str stem "aré")
      (and (= person :1st) (= number :sing) er-type)
@@ -371,9 +379,11 @@
         last-stem-char-is-e (re-find #"er$" infinitive)
         is-care-or-gare? (re-find #"[cg]ar$" infinitive)
         person (get-in word '(:agr :person))
-        number (get-in word '(:agr :number))]
-
+        number (get-in word '(:agr :number))
+        number-and-person (number-and-person number person)]
     (cond
+     (get-in word [:present number-and-person])
+     (get-in word [:present number-and-person])

      (and (= person :1st) (= number :sing))
      (str stem "o")
@@ -607,3 +617,18 @@
              "??")
          (exception message))))))

+(defn number-and-person [number person]
+  (cond (and (= person :1st) (= number :sing))
+        :1sing
+        (and (= person :1st) (= number :plur))
+        :1plur
+        (and (= person :2nd) (= number :sing))
+        :2sing
+        (and (= person :2nd) (= number :plur))
+        :2plur
+        (and (= person :3rd) (= number :sing))
+        :3sing
+        (and (= person :3rd) (= number :plur))
+        :3plur
+        true
+        nil))


close tab. still needs to be added to the tab panel

--- src/brevis/ui/core.clj
+++ src/brevis/ui/core.clj
@@ -175,6 +175,13 @@
                           (select-file))]
       (spit selected
             (get-text-from-tab tab-idx)))))
+
+(defn a-close-tab
+  "Close the currently selected tab. Should check if it has been saved.. oops."
+  [e]
+  (let [tab-idx (.getSelectedIndex (:tabbed-panel @editor-window))]
+    (when tab-idx
+      (.removeTabAt  (:tabbed-panel @editor-window) tab-idx))))

 (declare save-IDE-state)
 (defn a-exit  [e]
@@ -521,6 +528,7 @@
   (let [action-new (action :handler a-new :name "New" :tip "Create a new file.")
         action-open (action :handler a-open :name "Open" :tip "Open a file")
         action-save (action :handler a-save :name "Save" :tip "Save the current file.")
+        action-close-tab (action :handler a-close-tab :name "Close tab" :tip "Close the current tab.")
         action-exit (action :handler a-exit :name "Exit" :tip "Exit the editor.")
         action-copy (action :handler a-copy :name "Copy" :tip "Copy selected text to the clipboard.")
         action-paste (action :handler a-paste :name "Paste" :tip "Paste text from the clipboard.")
@@ -537,7 +545,7 @@
                                       :tip (str (:group %) "/" (:name %)))
                              (:projects @current-profile))
         menus (menubar
-                :items [(menu :text "File" :items [action-new action-open action-save action-save-as action-exit])
+                :items [(menu :text "File" :items [action-new action-open action-save action-save-as action-close-tab action-exit])
                         (menu :text "Edit" :items [action-copy action-cut action-paste])
                         (menu :text "Run" :items [action-eval-file])
                         (menu :text "Projects" :items (into [] action-projects))


clear search button

clear search button

--- src/cljs/swarmpit/component/header.cljs
+++ src/cljs/swarmpit/component/header.cljs
@@ -123,6 +123,7 @@
          {:placeholder      (str "Search " (string/lower-case title) " ...")
           :onChange         on-change-fn
           :defaultValue     query
+          :type             "search"
           :fullWidth        true
           :classes          {:root  "Swarmpit-appbar-search-root"
                              :input "Swarmpit-appbar-search-input"}
@@ -138,6 +139,7 @@
          {:placeholder      (str "Search " (string/lower-case title) " ...")
           :onChange         on-change-fn
           :defaultValue     query
+          :type             "search"
           :fullWidth        true
           :classes          {:root  "Swarmpit-appbar-search-mobile-root"
                              :input "Swarmpit-appbar-search-mobile-input"}
@@ -254,4 +256,4 @@
              (appbar-mobile-section search-fn actions)
              (user-menu menuAnchorEl)))
          (mobile-actions-menu actions mobileMoreAnchorEl)
-         (mobile-search search-fn title mobileSearchOpened)]))))+         (mobile-search search-fn title mobileSearchOpened)]))))


fixing merge error

fixing merge error

--- src/cljs/wombats_web_client/routes.cljs
+++ src/cljs/wombats_web_client/routes.cljs
@@ -27,17 +27,10 @@
   (defroute "/simulator" []
     (re-frame/dispatch [:set-active-panel :simulator-panel]))

+ (defroute "/welcome" []
+    (re-frame/dispatch [:set-active-panel :welcome-panel]))
+
   (defroute "/account" []
     (re-frame/dispatch [:set-active-panel :account-panel]))

-  (defroute "/welcome" []
-    (re-frame/dispatch [:set-active-panel :welcome-panel]))
-
-  (defroute "/signout" []
-    (sign-out-event)
-    (set! (-> js/window .-location .-hash) "#/"))
-
-  ;; --------------------
-  (hook-browser-navigation!))
   (pushy/start! history))
-


exception handling/exit func

exception handling/exit func

--- src/clojure/zensols/actioncli/parse.clj
+++ src/clojure/zensols/actioncli/parse.clj
@@ -3,6 +3,10 @@
     zensols.actioncli.parse
   (:require [clojure.string :as str])
   (:use [clojure.tools.cli :refer [parse-opts summarize]]))
+
+(def ^:dynamic *dump-jvm-on-error*
+  "Bind this from the REPL to avoid a system exit when testing the CLI."
+  true)

 (def ^:private help
   ["-h" "--help" :default false])
@@ -30,6 +34,21 @@
   (str (name command) "\t"
        (:description (command commands)) "\n"
        (:summary (parse-opts nil (:options (command commands)))) "\n\n"))
+
+(defn handle-exception
+  "Handle exceptions thrown from CLI commands."
+  [e]
+  (if (instance? java.io.FileNotFoundException e)
+    (binding [*out* *err*]
+      (println (format "io error: %s" (.getMessage e))))
+    (binding [*out* *err*]
+      (println (format "error: %s"
+                       (if ex-data
+                         (.getMessage e)
+                         (.toString e))))))
+  (if *dump-jvm-on-error*
+    (System/exit 1)
+    (throw e)))

 (defn- error-msg [errors]
   (str "The following errors occurred while parsing your command:\n\n"


Fix wrong pos calculation on write-bytes implementation for nio ByteBuffer.

--- src/bytebuf/buffer.clj
+++ src/bytebuf/buffer.clj
@@ -36,7 +36,8 @@
       tmpbuf))
   (write-bytes [buff pos size data]
     (let [oldpos (.position buff)]
-      (.put buff data, 0, size)
+      (.position buff pos)
+      (.put buff data 0 size)
       (.position buff oldpos)))

   ByteBuf


Cosmetic changes on catacumba.core ns.

Cosmetic changes on catacumba.core ns.

--- src/catacumba/core.clj
+++ src/catacumba/core.clj
@@ -14,6 +14,4 @@
  [catacumba.impl.handlers
   get-request-headers
   set-response-headers!
-  send!]
-
-)
+  send!])


Changed text of replay button.

Changed text of replay button.

--- src/cbfg/world/t1.cljs
+++ src/cbfg/world/t1.cljs
@@ -69,7 +69,7 @@
                             "   ●"
                             req
                             "   <button id='replay-" ts "'>"
-                            "    < replay requests to here</button>"
+                            "    replay requests to here ></button>"
                             "
"
                             (map (fn [[resp-ts resp]]
                                    ["<li class='evt evt-" resp-ts


refactor

refactor

--- src/chat/server/db.clj
+++ src/chat/server/db.clj
@@ -148,19 +148,22 @@
     (->> (d/resolve-tempid db-after tempids new-id)
          (d/entity db-after))))

+(defn- get-users-subscribed-to-thread [thread-id]
+  (d/q '[:find [?user-id ...]
+         :in $ ?thread-id
+         :where
+         [?user :user/id ?user-id]
+         [?user :user/subscribed-thread ?thread]
+         [?thread :thread/id ?thread-id]]
+       (d/db *conn*)
+       thread-id))
+
 (defn create-message! [attrs]
-  (let [subscribed-users (d/q '[:find [?user ...]
-                                :in $ ?thread-id
-                                :where
-                                [?user :user/subscribed-thread ?thread]
-                                [?thread :thread/id ?thread-id]]
-                              (d/db *conn*)
-                              (attrs :thread-id))
-        ; show thread for all users subscribed to thread
-        add-open-transactions (map (fn [user]
-                                     [:db/add user
+  (let [; show thread for all users subscribed to thread
+        add-open-transactions (map (fn [user-id]
+                                     [:db/add [:user/id user-id]
                                       :user/open-thread [:thread/id (attrs :thread-id)]])
-                                   subscribed-users)
+                                   (get-users-subscribed-to-thread (attrs :thread-id)))
         ; upsert thread
         thread-data {:db/id (d/tempid :entities)
                      :thread/id (attrs :thread-id)}


addig NewContract and DataRow impl, still no ticks

--- src/clj/ibclj/core.clj
+++ src/clj/ibclj/core.clj
@@ -1,18 +1,6 @@
 (ns ibclj.core
+  [:import  com.ib.controller.ApiController])

-
-  )
-
-
-(comment
-
-  ;(:import [com.ib.controller.ApiController] )
-  ;(import 'com.ib.controller.ApiController)
-
-  [:import ;;com.ib.controller.ApiConnection
-   com.ib.controller.ApiController]
-
-  )

 (defn create-controller []
   (reify
@@ -26,6 +14,19 @@

     ))

+(defn create-contract [symbol]
+  (doto (com.ib.controller.NewContract.)
+    (.symbol symbol)
+    (.secType com.ib.controller.Types$SecType/STK)
+    (.expiry "")
+    (.strike 0.0)
+    (.right com.ib.controller.Types$Right/None)
+    (.multiplier "")
+    (.exchange "SMART")
+    (.currency "USD")
+    (.localSymbol "")
+    (.tradingClass "")))
+
 (defn api-ctrl []
   (com.ib.controller.ApiController. (create-controller)
                                     (reify com.ib.controller.ApiConnection$ILogger
@@ -33,18 +34,34 @@
                                     (reify com.ib.controller.ApiConnection$ILogger
                                       (log [this s] (print s)))))

+(defn create-row []
+  (reify
+    com.ib.controller.ApiController$ITopMktDataHandler
+    (tickPrice [this tick-type p auto-execute?]
+      (println (format "tick: %s price: %s" tick-type  p)))
+    (tickSize [this tick-type size]
+      (println (format "type: %s size: %s" tick-type " " size)))
+    (tickString [this tick-type val]
+      (println (format  "Last time, type: %s value: %d") val))
+    (marketDataType [this data-type]
+      (println "Frozen? " (= data-type com.ib.controller.Types$MktDataType/Frozen)))
+    (tickSnapshotEnd [this] (println "tick snapshot end"))
+    ))
+

 (defn start []
-  (let [api (api-ctrl)]
+  (let [api (api-ctrl)
+        c (create-contract "VXX")
+        row (create-row)]
     (.connect api "localhost" 7497 5)
+    (.reqTopMktData api c "" false row)
+
     (Thread/sleep 1000)
+    (.cancelTopMktData api row)
     (.disconnect api)))

 (defn -main
   "the main function"
   []
- (start)
-
-
-      )
+  (start))


[hotfix][tests] Remove wrong -rest.port=8081 from mesos start arguments.

Dynamic arguments hould be prefixed with -D. Despite that the config key is not
needed because it is set in the flink-conf.yaml already.

--- flink-jepsen/src/jepsen/flink/db.clj
+++ flink-jepsen/src/jepsen/flink/db.clj
@@ -293,7 +293,6 @@
                                                                       "-Djobmanager.rpc.address=$(hostname -f) "
                                                                       "-Djobmanager.heap.mb=2048 "
                                                                       "-Djobmanager.rpc.port=6123 "
-                                                                      "-rest.port=8081 "
                                                                       "-Dmesos.resourcemanager.tasks.mem=2048 "
                                                                       "-Dtaskmanager.heap.mb=2048 "
                                                                       "-Dtaskmanager.numberOfTaskSlots=2 "


make org-settings load projects and store nav-data in state

--- frontend/controllers/navigation.cljs
+++ frontend/controllers/navigation.cljs
@@ -155,38 +155,6 @@
           (state-utils/reset-current-project %)
           %))))

-
-(defmethod navigated-to :org-settings
-  [history-imp navigation-point {:keys [subpage org-name]} state]
-  (mlog "Navigated to subpage:" subpage)
-  (-> state
-      (assoc :navigation-point navigation-point)
-      (assoc :org-settings-subpage subpage)
-      (assoc :org-settings-org-name org-name)
-      (#(if (state-utils/stale-current-org? % org-name)
-          (state-utils/reset-current-org %)
-          %))))
-
-(defmethod post-navigated-to! :org-settings
-  [history-imp navigation-point {:keys [org-name subpage]} previous-state current-state]
-  (let [api-ch (get-in current-state [:comms :api])]
-    (if (get-in current-state state/org-plan-path)
-      (mlog "plan details already loaded for" org-name)
-      (utils/ajax :get
-                  (gstring/format "/api/v1/organization/%s/plan" org-name)
-                  :org-plan
-                  api-ch
-                  :context {:org-name org-name}))
-    (if (= org-name (get-in current-state state/org-name-path))
-      (mlog "organization details already loaded for" org-name)
-      (utils/ajax :get
-                  (gstring/format "/api/v1/organization/%s/settings" org-name)
-                  :org-settings
-                  api-ch
-                  :context {:org-name org-name})))
-  (set-page-title! (str "Org settings - " org-name)))
-
-
 ;; XXX: find a better place for all of the ajax functions, maybe a separate api
 ;;      namespace that knows about all of the api routes?
 (defmethod post-navigated-to! :project-settings
@@ -229,3 +197,37 @@

   ;; XXX: check for XSS
   (set-page-title! (str "Edit settings - " project-name)))
+
+
+(defmethod navigated-to :org-settings
+  [history-imp navigation-point {:keys [subpage org-name] :as args} state]
+  (mlog "Navigated to subpage:" subpage)
+  (-> state
+      (assoc :navigation-point navigation-point)
+      (assoc :nagivation-data args)
+      (assoc :org-settings-subpage subpage)
+      (assoc :org-settings-org-name org-name)
+      (#(if (state-utils/stale-current-org? % org-name)
+          (state-utils/reset-current-org %)
+          %))))
+
+(defmethod post-navigated-to! :org-settings
+  [history-imp navigation-point {:keys [org-name subpage]} previous-state current-state]
+  (let [api-ch (get-in current-state [:comms :api])]
+    (when-not (seq (get-in current-state state/projects-path))
+      (api/get-projects api-ch))
+    (if (get-in current-state state/org-plan-path)
+      (mlog "plan details already loaded for" org-name)
+      (utils/ajax :get
+                  (gstring/format "/api/v1/organization/%s/plan" org-name)
+                  :org-plan
+                  api-ch
+                  :context {:org-name org-name}))
+    (if (= org-name (get-in current-state state/org-name-path))
+      (mlog "organization details already loaded for" org-name)
+      (utils/ajax :get
+                  (gstring/format "/api/v1/organization/%s/settings" org-name)
+                  :org-settings
+                  api-ch
+                  :context {:org-name org-name})))
+  (set-page-title! (str "Org settings - " org-name)))