Consolidate notion of deactivation.

Consolidate notion of deactivation.

Now the same function is used to deactivate controllers directly, and
via their auto-bind watchers.

--- src/afterglow/controllers/ableton_push.clj
+++ src/afterglow/controllers/ableton_push.clj
@@ -1569,29 +1569,39 @@
   removing its MIDI listeners. If `:disconnected` is passed with a
   `true` value, it means that the controller has already been removed
   from the MIDI environment, so no effort will be made to clear its
-  display or take it out of User mode."
+  display or take it out of User mode.
+
+  You can also pass a watcher object created by [[auto-bind]] as
+  `controller`; this will both deactivate the controller being managed
+  by the watcher, if it is currently connected, and cancel the
+  watcher itself. In such cases, `:disconnected` is meaningless."
   [controller & {:keys [disconnected] :or {disconnected false}}]
-  {:pre [(= (type controller) :ableton-push)]}
-  (swap! (:task controller) (fn [task]
-                              (when task (at-at/kill task))
-                              nil))
-  (show/unregister-grid-controller @(:grid-controller-impl controller))
-  (doseq [f @(:move-listeners controller)] (f @(:grid-controller-impl controller) :deactivated))
-  (reset! (:move-listeners controller) #{})
-  (amidi/remove-global-handler! @(:midi-handler controller))
-
-  (when-not disconnected
-    (Thread/sleep 35) ; Give the UI update thread time to shut down
-    (clear-interface controller)
-    ;; Leave the User button bright, in case the user has Live
-    ;; running and wants to be able to see how to return to it.
-    (set-button-state controller (:user-mode control-buttons) :bright))
-
-  ;; Cancel any UI overlays which were in effect
-  (reset! (:overlays controller) (sorted-map-by >))
-
-  ;; And finally, note that we are no longer active.
-  (swap! active-bindings dissoc (:id controller)))
+  {:pre [(#{:ableton-push :push-watcher} (type controller))]}
+  (if (= (type controller) :push-watcher)
+    (do ((:cancel controller))  ; Shut down the watcher
+        (when-let [watched-controller @(:controller controller)]
+          (deactivate watched-controller)))  ; And deactivate the controller it was watching for
+    (do ;; We were passed an actual controller, not a watcher, so deactivate it.
+      (swap! (:task controller) (fn [task]
+                                  (when task (at-at/kill task))
+                                  nil))
+      (show/unregister-grid-controller @(:grid-controller-impl controller))
+      (doseq [f @(:move-listeners controller)] (f @(:grid-controller-impl controller) :deactivated))
+      (reset! (:move-listeners controller) #{})
+      (amidi/remove-global-handler! @(:midi-handler controller))
+
+      (when-not disconnected
+        (Thread/sleep 35) ; Give the UI update thread time to shut down
+        (clear-interface controller)
+        ;; Leave the User button bright, in case the user has Live
+        ;; running and wants to be able to see how to return to it.
+        (set-button-state controller (:user-mode control-buttons) :bright))
+
+      ;; Cancel any UI overlays which were in effect
+      (reset! (:overlays controller) (sorted-map-by >))
+
+      ;; And finally, note that we are no longer active.
+      (swap! active-bindings dissoc (:id controller)))))

 (defn deactivate-all
   "Deactivates all controller bindings which are currently active.
@@ -1776,10 +1786,3 @@
          :cancel cancel-handler}
         {:type :push-watcher}))))

-(defn cancel-auto-bind
-  "Shuts down a Push watcher returned by [[auto-bind]] so it will no
-  longer cause the specified Ableton Push device to be bound to a show
-  whenever it is connected."
-  [watcher]
-  {:pre [(= (type watcher) :push-watcher)]}
-  ((:cancel watcher)))


Add subsumption propagation

Add subsumption propagation

--- src/angelic/search/implicit/dash_astar.clj
+++ src/angelic/search/implicit/dash_astar.clj
@@ -22,7 +22,8 @@
 ;; TODO: tests !

 ;;;;; Subsumption
-;; TODO: propagate subsumption links
+;; TODO: Figure out why subsumption isn't more helpful.
+;; TODO: children wait on one (or more) subsumption parents.
 ;; TODO: wait on subsumption parent(s)?

 ;;;;; Pessimistic
@@ -54,7 +55,7 @@
 (def *collect-equal-outputs* true) ;; Collect identical output sets
 (def *decompose-cache*       true) ;; nil for none, or bind to hashmap
 (def *state-abstraction*     :eager ) ;; Or lazy or nil.
-(def *propagate-subusmption* false)
+(def *propagate-subsumption* true)

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -139,7 +140,7 @@
                                   Updates cost if up? and child must be held before publishing.")

   (publish-sp-child!   [s o] "Internal. O is a subproblem with output.  s must have output too.")
-  (get-all-children [s] "Internal.  Get children, including unpublished ones.")
+  (add-all-child-watcher! [s w] "Internal.  Get children, including unpublished ones.")

   (subsuming-sps       [s] "subproblems with same name, >= inp-set")
   (add-subsuming-sp!   [s subsuming-sp])
@@ -206,9 +207,7 @@
    (util/print-debug 2 "AC" sp child-sp)
    (when (canonical? sp)
      (schedule-subsumption! (sp-ts sp) (sp-ts child-sp))
-     (publish! all-child-ps child-sp)
-     (when *propagate-subusmption* #_ ::TODO) ;; TODO!!
-     )
+     (publish! all-child-ps child-sp))
    (if (and (get-output-set sp) (get-output-set child-sp))
     (publish-sp-child! sp child-sp)
     (do (summaries/connect! sp (sp-ts child-sp))
@@ -225,7 +224,7 @@
       (schedule-increase! (sp-ts s)))
     (publish! child-ps c))

-  (get-all-children    [s] (publications all-child-ps))
+  (add-all-child-watcher! [s w] (subscribe! all-child-ps w))

   (subsuming-sps [s] (keys subsuming-sp-set))
@@ -237,10 +236,19 @@
     (when-not (.containsKey subsuming-sp-set subsuming-sp)
       (.put subsuming-sp-set subsuming-sp true)
       (schedule-subsumption! (sp-ts subsuming-sp) (sp-ts s))
-      (when *propagate-subusmption*
-        #_ (add-child-watcher! )) ;; TODO!!
-
-      ))
+      (when *propagate-subsumption*
+        ;; TODO: efficiency, etc.
+        (add-all-child-watcher! s
+          (fn [child]
+            (let [can-child (canonicalize child)]
+              (add-all-child-watcher! subsuming-sp
+                (fn [subsuming-child]
+                  (let [can-subsuming-child (canonicalize subsuming-child)]
+                    (when (and (not (identical? can-child can-subsuming-child))
+                               (= (sp-name can-child) (sp-name can-subsuming-child)))
+                      #_(print ".")
+                      #_ (println [s subsuming-sp] "==>" [child subsuming-child])
+                      (add-subsuming-sp! can-child can-subsuming-child)))))))))))

   (refine-input    [s ni] (let [ret (ri-fn s ni)] (util/assert-is (= nm (sp-name ret))) ret)))

@@ -524,9 +532,9 @@

 ;; TODO: sa options...
 (defn implicit-dash-a*
-  [henv & {gather :gather d :d   s :s    choice-fn :choice-fn local? :local?  dir :dir :as m
-      :or {gather true   d true s :eager choice-fn last       local? true     dir :right}}]
-  (assert (every? #{:gather :d :s :choice-fn :local? :dir} (keys m)))
+  [henv & {gather :gather d :d   s :s    choice-fn :choice-fn local? :local?  dir :dir   prop :prop :as m
+      :or {gather true   d true s :eager choice-fn last       local? true     dir :right prop true}}]
+  (assert (every? #{:gather :d :s :choice-fn :local? :dir :prop} (keys m)))
   (assert (contains? #{:left :right} dir))
   (assert (contains? #{nil false :eager :deliberate} s))
   (when s (assert d))
@@ -536,6 +544,7 @@
             *decompose-cache*       (when d (HashMap.))
             *state-abstraction*     s
             *left-recursive*        (= dir :left)
+            *propagate-subsumption* prop
  ;            summaries/*cache-method* c
             ]
     (summaries/solve


File auto gen name fixes

File auto gen name fixes

--- src/aerobio/htseq/tnseq.clj
+++ src/aerobio/htseq/tnseq.clj
@@ -237,14 +237,15 @@
                                   (let [crec (conj (coll/takev 2 crec) k)
                                         csv (str (cljstr/join "-" crec) ".csv")
                                         ef (expfacts (dec (offsets k)))]
-                                    (conj v csv ef)))
+                                    (conj v csv ef (offsets k))))
                                 %1))
                        mapsvec
                        compvec)]
      (if aggr?
        (mapv (fn[grp]
                (when (seq grp)
-                 (let [l (->> grp last first fs/basename (str/split #"-")
+                 (let [grp (sort-by last grp)
+                       l (->> grp last first fs/basename (str/split #"-")
                               last (str/split #"\.") first)
                        g (mapv (fn[[_ _ csv _]]
                                  [(fs/join aggr csv) (fs/join fit csv)])


Comments and docstrings

Comments and docstrings

--- src/com/frereth/server/comms/registrar.clj
+++ src/com/frereth/server/comms/registrar.clj
@@ -92,11 +92,6 @@
                   :value "Log In"}]})

 (defn define-initial-auth-world
-  "Because I'm having issues sending data in a format that makes sense to render.
-Raw HTML was/is a giant FAIL.
-Creating my own DSL to describe Om seems like a horrible idea.
-Enlive/kioo is super attractive...but the model of specifying URLs to get the template to render fails abjectly.
-So give salono a shot."
   []
   (let [body (define-world-in-sablono)]
     {:data (assoc body
@@ -155,7 +150,7 @@
        (log/debug "Trying to supply the Action channel in response to:\n"
                   pretty-msg))
   (log/warn "Set up a web server and switch back to serving data that way")
-  ;; TODO: Set up a web server and go back to doing it this way
+  ;; TODO: Set up a web server and go back to just sending the URL
   (assoc msg
          :action-url {:port 7841  ; FIXME: Magic Number
                       ;; TODO: Pull this from a config file/env var instead


fix variable name

fix variable name

--- src/devops_101_pipeline/deploy_scripts.clj
+++ src/devops_101_pipeline/deploy_scripts.clj
@@ -28,6 +28,6 @@
     basedir))

 (defn deploy [basedir ctx]
-  (prepare-deploy-scripts args)
+  (prepare-deploy-scripts basedir)
   (shell/bash ctx basedir
               "bash ./deploy-app.sh"))


Add key-fn and value-fn to parsing

Add key-fn and value-fn to parsing

--- src/main/clojure/clojure/data/json_new.clj
+++ src/main/clojure/clojure/data/json_new.clj
@@ -16,8 +16,9 @@

 ;;; JSON READER

-(def ^:dynamic ^:private *keywordize*)
 (def ^:dynamic ^:private *bigdec*)
+(def ^:dynamic ^:private *key-fn*)
+(def ^:dynamic ^:private *value-fn*)

 (declare -parse)

@@ -81,8 +82,11 @@
                   (recur element result)
                   (throw (Exception. "JSON error (non-string key in object)")))
                 (recur nil
-                       (assoc! result (if *keywordize* (keyword key) key)
-                               element)))))))))
+                       (let [out-key (*key-fn* key)
+                             out-value (*value-fn* out-key element)]
+                         (if (= *value-fn* out-value)
+                           result
+                           (assoc! result out-key out-value)))))))))))

 (defn- parse-hex-char [^PushbackReader stream]
   ;; Expects to be called with the head of the stream AFTER the
@@ -209,11 +213,6 @@
   "Parse a single item of JSON data from a java.io.Reader. Options are
   key-value pairs, valid options are:

-     :keywordize boolean
-
-        If true (default) convert JSON property names from strings
-        into keywords.
-
      :bigdec boolean

         If true use BigDecimal for decimal numbers instead of Double.
@@ -226,15 +225,39 @@
      :eof-value Object

         Object to return if the stream is empty and eof-error? is
-        false. Default is nil."
+        false. Default is nil.
+
+     :key-fn function
+
+        Single-argument function called on JSON property names; return
+        value will replace the property names in the output. Default
+        is clojure.core/keyword.
+
+     :value-fn function
+
+        Function to transform values in the output. For each JSON
+        property, value-fn is called with two arguments: the property
+        name (transformed by key-fn) and the value. The return value
+        of value-fn will replace the value in the output. If value-fn
+        returns itself, the property will be omitted from the output.
+
+        Finally, value-fn is called with one argument, the whole
+        object, and may return any any substitute value.
+
+        The default value-fn is (fn ([v] v) ([k v] v))."
   [reader & options]
-  (let [{:keys [keywordize eof-error? eof-value bigdec]
-         :or {keywordize false
-              bigdec false
-              eof-error? true}} options]
-    (binding [*keywordize* keywordize
-              *bigdec* bigdec]
-      (-parse reader eof-error? eof-value))))
+  (let [{:keys [eof-error? eof-value bigdec key-fn value-fn]
+         :or {bigdec false
+              eof-error? true
+              key-fn keyword
+              value-fn (fn ([v] v) ([k v] v))}} options]
+    (binding [*bigdec* bigdec
+              *key-fn* key-fn
+              *value-fn* value-fn]
+      (let [out-value
+            (*value-fn* (-parse reader eof-error? eof-value))]
+        (when-not (= *value-fn* out-value)
+          out-value)))))

 (defn parse-string
   "Reads one JSON value from input String. Options are the same as for


+:chat's :obj

+:chat's :obj

--- src/babel/encyclopedia.cljc
+++ src/babel/encyclopedia.cljc
@@ -277,7 +277,8 @@
          :subj {:human true}}

         {:pred :chat
-         :subj {:human true}}
+         :subj {:human true}
+         :obj {:human true}}

         {:pred :come
          :subj {:animate true}}


Fix bugs found by property testing & better logging

--- src/onyx/messaging/immutable_messenger.clj
+++ src/onyx/messaging/immutable_messenger.clj
@@ -93,18 +93,28 @@
                         (is-next-barrier? messenger m))))
          first)))

+(defn barrier->str [barrier]
+  (str "B: " [(:replica-version barrier) (:epoch barrier)]))
+
+(defn subscriber->str [subscriber]
+  (str "S: " [(:src-peer-id subscriber) (:dst-task-id subscriber)]
+       " STATE: " (barrier->str (:barrier subscriber))))
+
 (defn take-messages [messenger subscriber]
   (let [ticket (curr-ticket messenger subscriber)
         next-ticket (inc ticket)
         message (get-message messenger subscriber ticket)
-        skip-to-barrier? (and (< (inc (:position subscriber)) ticket)
-                              ;; Only skip ahead when unblocked. Otherwise we may skip over next barriers
-                              (or (nil? (:barrier subscriber))
+        skip-to-barrier? (or (nil? (:barrier subscriber))
+                             (and (< (inc (:position subscriber)) ticket)
                                   (unblocked? messenger subscriber)))]
     (cond skip-to-barrier?
           ;; Skip up to next barrier so we're aligned again,
           ;; but don't move past actual messages that haven't been read
-          (let [[position next-barrier] (next-barrier messenger subscriber ticket)]
+          (let [max-index (if (nil? (:barrier subscriber))
+                            (dec (count (get-messages messenger subscriber)))
+                            ticket)
+                [position next-barrier] (next-barrier messenger subscriber max-index)]
+            (debug (:peer-id messenger) (subscriber->str subscriber) (barrier->str next-barrier))
             {:ticket (if position
                        (max ticket (inc position))
                        ticket)
@@ -141,11 +151,14 @@

 (defn take-ack [messenger {:keys [src-peer-id dst-task-id position] :as subscriber}]
   (let [messages (get-in messenger [:message-state src-peer-id dst-task-id])
-        ack (first (filter ack? (drop (inc position) messages)))]
+        [idx ack] (->> messages
+                       (map (fn [idx msg] [idx msg]) (range))
+                       (drop (inc position))
+                       (filter (fn [[idx ack]]
+                                 (= (:replica-version ack) (m/replica-version messenger))))
+                       (first))]
     (if ack
-      (if (= (:replica-version ack) (m/replica-version messenger))
-        (assoc subscriber :barrier-ack ack :position (inc position))
-        (assoc subscriber :position (inc position)))
+      (assoc subscriber :barrier-ack ack :position idx)
       subscriber)))

 (defn set-barrier-emitted [subscriber]
@@ -201,6 +214,8 @@
   (set-replica-version [messenger replica-version]
     (-> messenger
         (assoc-in [:replica-version peer-id] replica-version)
+        (update-in [:subscriptions peer-id]
+                   (fn [ss] (mapv #(assoc % :barrier-ack nil :barrier nil) ss)))
         (m/set-epoch 0)))

   (replica-version [messenger]
@@ -218,24 +233,19 @@
     (update-in messenger [:epoch peer-id] inc))

   (receive-acks [messenger]
-    (reduce (fn [messenger _]
-              (let [subscriber (first (messenger->subscriptions messenger))]
-                (if (:barrier-ack subscriber)
-                  messenger
-                  (update-first-subscriber messenger (constantly (take-ack messenger subscriber))))))
-            messenger
-            (messenger->subscriptions messenger)))
+    (update-in messenger
+               [:subscriptions peer-id]
+               (fn [ss]
+                 (mapv (fn [s] (take-ack messenger s)) ss))))

   (flush-acks [messenger]
-    (reduce (fn [messenger _]
-              (let [subscriber (first (messenger->subscriptions messenger))]
-                (update-first-subscriber messenger (constantly (assoc subscriber :barrier-ack nil)))))
-            messenger
-            (messenger->subscriptions messenger)))
+    (update-in messenger
+               [:subscriptions peer-id]
+               (fn [ss]
+                 (mapv #(assoc % :barrier-ack nil) ss))))

   (all-acks-seen?
     [messenger]
-    (info "All acks seen? " (vec (messenger->subscriptions messenger)))
     (if (empty? (remove :barrier-ack (messenger->subscriptions messenger)))
       (:barrier-ack (first (messenger->subscriptions messenger)))
       false))
@@ -246,6 +256,9 @@
       (let [new-messenger (reduce (fn [m _]
                                     (let [subscriber (first (messenger->subscriptions m))
                                           {:keys [message ticket] :as result} (take-messages m subscriber)]
+                                      (debug (:peer-id messenger) "MSG:"
+                                             (if message message "nil")
+                                             "New sub:" (subscriber->str (:subscriber result)))
                                       (cond-> m
                                         ticket (set-ticket (:src-peer-id subscriber) (:dst-task-id subscriber) ticket)
                                         true (update-first-subscriber (constantly (:subscriber result)))
@@ -285,21 +298,17 @@

   (all-barriers-seen?
     [messenger]
-    (info "CALL BARRIES SEEN"
-          (vec (remove #(found-next-barrier? messenger %)
-                    (messenger->subscriptions messenger)))
-          )
     (empty? (remove #(found-next-barrier? messenger %)
                     (messenger->subscriptions messenger))))

   (ack-barrier
     [messenger]
     (as-> messenger mn
-      (m/next-epoch mn)
       (reduce (fn [m p]
                 (write m p (->BarrierAck peer-id (:dst-task-id p) (m/replica-version mn) (m/epoch mn))))
               mn
               (get publications peer-id))
+      (m/next-epoch mn)
       (update-in mn
                  [:subscriptions peer-id]
                  (fn [ss]


(CTH-91) Change websocket send from text to binary

This commit changes the second parameter to the websocket send function
to be a binary array instead of a string. This should increase
performance on the websocketpp side since we're avoiding utf-8
validation.

--- src/puppetlabs/cthun/connection_states.clj
+++ src/puppetlabs/cthun/connection_states.clj
@@ -92,7 +92,7 @@
                  (inc! metrics/total-messages-out)
                  (mark! metrics/rate-messages-out)
                  (let [message (message/add-hop message "deliver")]
-                   (jetty-adapter/send! websocket (cheshire/generate-string message)))))
+                   (jetty-adapter/send! websocket (byte-array (map byte (cheshire/generate-string message)))))))
       (catch Exception e
         (.start (Thread. (fn [] (handle-delivery-exception message))))))))


Add genre stats to scratch

Add genre stats to scratch

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

@@ -205,4 +205,15 @@
        :in $ ?t
        :where [?m :movie/title ?t]
        [?m :movie/genre ?g]] d "Going to Pieces: The Rise and Fall of the Slasher Film (2006)"))
+
+;; Genres and counts
+
+(def genre-counts (let [d (-> system :db :conn db)]
+                    (q '[:find ?g (count ?e)
+                         :in $
+                         :where
+                         [?e :movie/genre ?gid]
+                         [?gid :db/ident ?g]] d)))
+
+(pprint (map (fn [[g c]] [(name g) c]) (sort-by peek genre-counts)))
 )


Return op in result.

Return op in result.

--- src/cbfg/world-storage.cljs
+++ src/cbfg/world-storage.cljs
@@ -30,13 +30,26 @@
     {:opaque-id opaque-id :status :ok
      :key key :sq (dec (:next-sq storage2)) :cas cas}))

+(defn storage-del [storage opaque-id key]
+  (let [storage2 (swap! storage
+                        #(-> %
+                             (dissoc-in [:changes (get-in % [:keys key :sq])])
+                             (dissoc-in [:keys key])
+                             (assoc-in [:changes (:next-sq %)]
+                                       {:key key :sq (:next-sq %) :deletion true})
+                             (update-in [:next-sq] inc)))]
+    {:opaque-id opaque-id :status :ok
+     :key key :sq (dec (:next-sq storage2))}))
+
 (defn make-storage-cmd-handlers [storage]
   {"get" [["key"]
           (fn [c] {:rq #(ago storage-cmd-get %
-                             (storage-get storage (:opaque-id c) (:key c)))})]
+                             (assoc (storage-get storage (:opaque-id c) (:key c))
+                               :op "get"))})]
    "set" [["key" "val"]
           (fn [c] {:rq #(ago storage-cmd-set %
-                             (storage-set storage (:opaque-id c) (:key c) (:val c)))})]
+                             (assoc (storage-set storage (:opaque-id c) (:key c) (:val c))
+                               :op "set"))})]
    "del" [["key"]
           (fn [c] {:rq (fn [actx]
                          (ago storage-cmd-del actx


Fix funny NPE.

Fix funny NPE.

--- src/clj/nonojure/random.clj
+++ src/clj/nonojure/random.clj
@@ -20,7 +20,7 @@
      :solution (map #(apply str %) rows)}))

-(defn test [n m]
+(defn test-random [n m]
   (let [puzzle (generate-puzzle n m)]
    (println (format "\nPuzzle %dx%d" n m))
    (doseq [row (:solution puzzle)] (println row))


Add reset button

Add reset button

--- src/cljs/subman/search.cljs
+++ src/cljs/subman/search.cljs
@@ -14,7 +14,11 @@
   [{:keys [value]}] [:div.input-group.input-group-lg.col-xs-12.search-input
                      {:data-spy "affix"
                       :data-offset-top "40"}
-                     [:span.input-group-addon [:i.fa.fa-search]]
+                     [:span.input-group-addon (if (= "" @value)
+                                                [:i.fa.fa-search]
+                                                [:a {:on-click #(reset! value "")
+                                                     :href "#"}
+                                                 [:i.fa.fa-chevron-left]])]
                      [:input.form-control {:type "text"
                                            :placeholder "Type search query"
                                            :on-change #(reset! value (-> % .-target .-value))


docker time to unix ts support #260

docker time to unix ts support
#260

--- src/cljs/swarmpit/time.cljs
+++ src/cljs/swarmpit/time.cljs
@@ -1,8 +1,9 @@
 (ns swarmpit.time
   (:require [clojure.contrib.humanize :as humanize]
-            [clojure.string :as str]
-            [cljs-time.core :refer [after? to-default-time-zone now]]
-            [cljs-time.format :as format]))
+            [cljs-time.coerce :refer [to-epoch]]
+            [cljs-time.core :refer [after? to-default-time-zone now minus minutes]]
+            [cljs-time.format :as format]
+            [clojure.string :as str]))

 (def docker-format
   (format/formatters :date-time-no-ms))
@@ -18,6 +19,18 @@
   [datetime]
   (->> (trim-ms datetime)
        (format/parse docker-format)))
+
+(defn to-unix
+  [datetime]
+  (let [dt (parse datetime)]
+    (and dt (quot dt 1000))))
+
+(defn to-unix-past
+  [minutes-to-history]
+  (let [dt (minus
+             (now)
+             (minutes minutes-to-history))]
+    (and dt (quot dt 1000))))

 (defn- shift-future-date
   [date]


Display selected and targeted terrain stats in status area

--- src/cljs/zetawar/views.cljs
+++ src/cljs/zetawar/views.cljs
@@ -273,11 +273,22 @@

 (defn status-info [{:as view-ctx :keys [conn translate]}]
   (let [[hover-q hover-r] @(subs/hover-hex conn)]
-    [:p.hidden-xs.hidden-sm
-     (translate :hover-tile-location)
-     (if hover-q
-       (str hover-q ", " hover-r)
-       (translate :none))]))
+    [:div
+     [:p.hidden-xs.hidden-sm
+      (translate :hover-tile-location)
+      (if hover-q
+        (str hover-q ", " hover-r)
+        (translate :none))]
+     (when @(subs/selected-unit conn)
+       [:p "Selected: "
+        (interleave
+         ["Movement Cost: ", " Attack Bonus: ", " Armor Bonus: "]
+         @(subs/selected-stats conn))])
+     (when @(subs/targeted-hex conn)
+       [:p "Targeted: "
+        (interleave
+         ["Movement Cost: ", " Attack Bonus: ", " Armor Bonus: "]
+         @(subs/targeted-stats conn))])]))

 (def armor-type-abbrevs
   {:unit-type.armor-type/personnel "P"


Use ajax-opts fn for managed-ajax

Use ajax-opts fn for managed-ajax

--- frontend/utils/ajax.cljs
+++ frontend/utils/ajax.cljs
@@ -88,8 +88,7 @@
         clj-ajax/transform-opts)))

 ;; TODO prefixes not implemented
-(defn ajax [method url message channel & {:keys [params keywords? context headers format]
-                                          :or {keywords? true format :json}
+(defn ajax [method url message channel & {:keys [context]
                                           :as opts}]
   (let [uuid frontend.async/*uuid*
         base-opts {:method method
@@ -106,34 +105,21 @@
         ajax-opts
         clj-ajax/ajax-request)))

-;; This is all very mess, it should be cleaned up at some point
 (defn managed-ajax [method url & {:keys [params keywords? headers format response-format csrf-token]
                                   :or {keywords? true
                                        response-format :json
                                        format :json
-                                       csrf-token true}}]
+                                       csrf-token true}
+                                  :as opts}]
   (let [channel (chan)
-        accept (case format
-                 :json "application/json"
-                 :xml "applicatin/xml")]
-    (-> {:format (case format
-                   :json (clj-ajax/json-request-format)
-                   :xml (xml-request-format))
-         :response-format (case format
-                            :json (json-response-format {:keywords? keywords? :url url :method method})
-                            :xml (xml-response-format))
-         :keywords? keywords?
-         :params params
-         :headers (merge {:Accept accept}
-                         (when (and csrf-token (re-find #"^/" url))
-                           {:X-CSRFToken (utils/csrf-token)})
-                         headers)
-         :handler #(put! channel (assoc % :status :success :scopes (scopes-from-response %)))
-         ;; TODO: clean this up
-         :error-handler #(put! channel (normalize-error-response % {:url url}))
-         :finally #(close! channel)}
-        clj-ajax/transform-opts
-        (assoc :uri url :method method)
+        base-opts {:method method
+                   :uri url
+                   :handler #(put! channel (assoc % :status :success :scopes (scopes-from-response %)))
+                   :error-handler #(put! channel (normalize-error-response % {:url url}))
+                   :finally #(close! channel)}]
+    (-> base-opts
+        (merge opts)
+        ajax-opts
         clj-ajax/ajax-request)
     channel))


Re-order markdown rendering

Re-order markdown rendering

--- frontend/utils/docs.cljs
+++ frontend/utils/docs.cljs
@@ -77,16 +77,16 @@
                           (filter (js->clj val :keywordize-keys true)))))))

 (defn replace-asset-paths [html]
-  (let [re (js/RegExp. "\"asset:/(.*?)\"" "g")]
+  (let [re (js/RegExp. "\\(asset:/(/.*?)\\)" "g")]
     (.replace html re (fn [s match]
-                        (stefon/asset-path match)))))
+                        (str "(" (stefon/asset-path match) ")")))))

 (defn render-markdown [input]
   (when input
     (-> input
-        js/marked
         replace-asset-paths
-        replace-variables)))
+        replace-variables
+        js/marked)))

 (defn new-context []
   (let [context (js/Object.)]


activate submit chat learning state

activate submit chat learning state

--- src-cljs/frontend/controllers/controls.cljs
+++ src-cljs/frontend/controllers/controls.cljs
@@ -1121,6 +1121,7 @@
   [browser-state message {:keys [chat-body]} state]
   (let [{:keys [entity-id state]} (frontend.db/get-entity-id state)]
     (-> state
+      (assoc-in state/chat-submit-learned-path true)
       (handle-cmd-chat (chat-cmd chat-body) chat-body)
       (assoc-in [:chat :entity-id] entity-id))))


Улучшение параметризации omut select

Улучшение параметризации omut select

--- src-cljs/ixinfestor/omut.cljs
+++ src-cljs/ixinfestor/omut.cljs
@@ -910,7 +910,11 @@
             (= sv no-select-v)) nil sv)))

-(defn select [app _ {:keys [on-change-fn]}]
+(defn select [app _ {:keys [on-change-fn
+                            value-field-key
+                            title-field-key]
+                     :or {value-field-key :id
+                          title-field-key :keyname}}]
   (reify
     om/IRender
     (render [_]
@@ -925,10 +929,9 @@
                 (when on-change-fn (on-change-fn v))))}

        (doall
-        (map (fn [{:keys [id title keyname]}]
-               (println id title keyname)
-               (dom/option #js {:value (str id)} keyname " " title))
-             (into [{:id no-select-v :title "Выбрать..."}] (@app :list)))) ))))
+        (map (fn [row]
+               (dom/option #js {:value (str (value-field-key row))} (title-field-key row)))
+             (into [{value-field-key no-select-v title-field-key "Выбрать..."}] (@app :list)))) ))))

 (defn select-form-group  [app _ {:keys [label
                                         type


Fix NPE when creating client register

Fix NPE when creating client register

--- src/copycat_jepsen/core.clj
+++ src/copycat_jepsen/core.clj
@@ -2,7 +2,7 @@
     (:require [clojure [pprint :refer :all]
                [string :as str]]
               [clojure.java.io :as io]
-              [clojure.tools.logging :refer [debug info warn]]
+              [clojure.tools.logging :refer [debug info warn error]]
               [copycat-jepsen.util :as cutil]
               [figaro.core :as figaro]
               [jepsen [core :as jepsen]
@@ -21,7 +21,8 @@
                [util :as net/util]]
               [jepsen.os.debian :as debian]
               [jepsen.checker.timeline :as timeline])
-  (:import (java.util.concurrent ExecutionException)))
+  (:import (java.util.concurrent ExecutionException)
+           (net.kuujo.copycat Copycat CopycatClient CopycatReplica)))

 (defn- node-id [node]
   (Integer/parseInt (subs (name node) 1)))
@@ -72,7 +73,7 @@
         jarfile         "/root/.m2/repository/net/kuujo/copycat/copycat-server-example/0.6.0-SNAPSHOT/copycat-server-example-0.6.0-SNAPSHOT-shaded.jar"]
     (info node "starting copycat")
     (meh (c/exec :truncate :--size 0 "/var/log/copycat.log"))
-    (meh (c/exec :rm "/opt/copycat/examples/server/*.log"))
+    (meh (c/su (c/exec :rm "/opt/copycat/examples/server/*.log")))
     (c/su
       (c/cd "/opt/copycat/examples/server"
             (c/exec :java :-jar jarfile local-node-arg other-node-args
@@ -108,15 +109,18 @@
                                    :port 5555)
                         nodes)]
       ;(Thread/sleep 15000)
-      (info "connecting to " (name node))
-      (while (try (assoc this :client (figaro/client node-set))
-                  false
-                  (catch Exception e
-                    (debug node "Connection attempt failed. Retrying...")
-                    (Thread/sleep 2000)
-                    true)))
-      (debug node "Client connected!")
-      (assoc this :register (figaro/dist-atom client "register"))))
+      (info "connecting for" (name node))
+      (while
+        (try
+          (let [client (figaro/client node-set)]
+            (debug node "Client connected!")
+            (assoc this :client client)
+            (assoc this :register (figaro/dist-atom client "register")))
+          false
+          (catch Exception e
+            (debug node "Connection attempt failed. Retrying..." e)
+            (Thread/sleep 2000)
+            true)))))

   (invoke! [this test op]
     (case (:f op)


NativeStore dependencies

NativeStore dependencies

--- src/derive/nativestore.cljs
+++ src/derive/nativestore.cljs
@@ -33,6 +33,93 @@
 (defprotocol ITransactionalStore
   (-transact! [store f args]))

+;;
+;; Native Dependencies
+;; ============================
+
+;; A dependency representation is:
+;;
+;; #js { _root: #js [<id_i> ...]
+;;       <idx_name>: #js [start end] }
+;;
+;; The root is a sorted list of object IDs (reference traversal or direct lookups)
+;; The remaining index lookups maintain value ranges traversed
+;; These become set intersection and range overlap calculations when testing
+;; for the impact of a transaction
+;;
+;; The left side dependency is mutated and returned by all operations
+;;
+
+(defn- sorted-insert!
+  "Mutates r1.  Keep list of merged IDs in sorted order"
+  [r1 r2]
+  (goog.array.forEach r2 (fn [v i a] (goog.array.binaryInsert r1 v))))
+
+(defn- merge-range!
+  "Mutates r1. The updated range becomes the union of the two ranges"
+  [compfn range1 range2]
+  (let [r1s (aget range1 0)
+        r1e (aget range1 1)
+        r2s (aget range2 0)
+        r2e (aget range2 1)]
+    (when (< (compfn r2s r1s) 0)
+      (aset range1 0 r2s))
+    (when (> (compfn r2e r1e) 0)
+      (aset range1 1 r2e))))
+
+(defn- merge-index!
+  "Merge the index range or root set"
+  [nset idx range1 range2]
+  (if (nil? idx) ; root?
+    (sorted-insert! range1 range2)
+    (merge-range! (comparator-fn idx) range1 range2)))
+
+
+(defn- intersect?
+  "Do two sorted sets of integers intersect?"
+  [this other]
+  (let [tlen (.-length this)
+        olen (.-length other)]
+    (loop [i 0 j 0]
+      (if (or (= i tlen) (= j olen))
+        false
+        (let [v1 (aget this i)
+              v2 (aget other j)]
+          (cond (= v1 v2) true
+                (> (compare v1 v2) 0) (recur i (inc j))
+                :default (recur (inc i) j)))))))
+
+(defn- overlap?
+  "Does the interval of other overlap this?"
+  [compfn range1 range2]
+  (let [r1s (aget range1 0)
+        r1e (aget range1 1)
+        r2s (aget range2 0)
+        r2e (aget range2 1)]
+    (not (or (> (compfn r2s r1e) 0)
+             (< (compfn r2e r1s) 0)))))
+
+(defn- match-index?
+  [nset idx this-range other-range]
+  (if (nil? idx) ; root?
+    (intersect? this-range other-range)
+    (overlap? (comparator-fn idx) this-range other-range)))
+
+(deftype NativeDependencySet [store deps]
+  IDependencySet
+  (merge-deps [this other]
+    (goog.object.forEach
+     other (fn [v k] (merge-index! this (get-index store k) (aget deps k) v)))
+    this)
+  (match-deps [this other]
+    (goog.object.some
+     other (fn [v k] (match-index? this (get-index store k) (aget deps k) v)))
+    this))
+
+(defn make-dependencies
+  ([store] (NativeDependencySet. store #js {}))
+  ([store init] (NativeDependencySet. store init)))
+
 ;;
 ;; Instance protocols
 ;; ============================


fix(ccw.swt): remove warning for redefinition of dosync

--- ccw.core/src/clj/ccw/swt.clj
+++ ccw.core/src/clj/ccw/swt.clj
@@ -1,4 +1,5 @@
 (ns ccw.swt
+  (:refer-clojure :exlude (dosync))
   (:import ccw.util.DisplayUtil))

 (import 'org.eclipse.swt.SWT)


No more pomegranate dependency

No more pomegranate dependency

--- jvm-runner/src/clojure/codewars/runner/clojure.clj
+++ jvm-runner/src/clojure/codewars/runner/clojure.clj
@@ -2,8 +2,33 @@
   (:require [codewars.runner :refer [run]]
             [codewars.util :as util]
             [codewars.clojure.test]
-            [cemerick.pomegranate :as pom])
-  (:import [codewars.java TempDir]))
+            [clojure.java.io :as io]
+            [dynapath.util :as dp])
+  (:import [codewars.java TempDir])
+  (:refer-clojure :exclude (add-classpath)))
+
+;; Extracted from cemerick.pomegranate
+(defn- classloader-hierarchy
+  "Returns a seq of classloaders, with the tip of the hierarchy first.
+   Uses the current thread context ClassLoader as the tip ClassLoader if one is not provided."
+  ([] (classloader-hierarchy (.. Thread currentThread getContextClassLoader)))
+  ([tip]
+    (->> tip
+      (iterate #(.getParent %))
+      (take-while boolean))))
+
+(defn- add-classpath
+  "A fixed version of the (deprecated) `add-classpath` in clojure.core."
+  ([jar-or-dir classloader]
+     (if-not (dp/add-classpath-url classloader (.toURL (.toURI (io/file jar-or-dir))))
+       (throw (IllegalStateException. (str classloader " is not a modifiable classloader")))))
+  ([jar-or-dir]
+    (let [classloaders (classloader-hierarchy)]
+      (if-let [cl (last (filter dp/addable-classpath? classloaders))]
+        (add-classpath jar-or-dir cl)
+        (throw (IllegalStateException. (str "Could not find a suitable classloader to modify from "
+                                            classloaders)))))))
+

 (defmethod run "clojure"
   [{:keys [:setup :solution :fixture] :as opts}]
@@ -12,7 +37,6 @@
         (util/write-code! "clojure" dir fixture)]
     (when setup (util/write-code! "clojure" dir setup))
     (util/write-code! "clojure" dir solution)
-    (pom/add-classpath dir)
-    fixture-ns
-    (require [fixture-ns])
+    (add-classpath dir)
+    (require fixture-ns)
     (codewars.clojure.test/run-tests fixture-ns)))


Router sockets are tricky.

Router sockets are tricky.

Hard-code the auth and action sockets from/to the Client to give me an error
if/when I try to send a malformed message

--- src/frereth_server/comm.clj
+++ src/frereth_server/comm.clj
@@ -36,6 +36,9 @@
   (start
    [this]
    (let [sock (zmq/socket context (socket-type this))]
+     ;; TODO: Make this another option. It's really only
+     ;; for debugging.
+     (zmq/set-router-mandatory sock 1)
      (zmq/bind sock (build-url url))
      (assoc this :socket sock)))

@@ -53,6 +56,9 @@
   (start
    [this]
    (let [sock (zmq/socket context (socket-type this))]
+     ;; TODO: Make this another option. It's really only
+     ;; for debugging.
+     (zmq/set-router-mandatory sock 1)
      (zmq/bind sock (build-url url))
      (assoc this :socket sock)))


Added docs.

Added docs.

--- src/com/lemondronor/turboshrimp/navdata.clj
+++ src/com/lemondronor/turboshrimp/navdata.clj
@@ -646,6 +646,8 @@
     (let [option-header (get-ushort bb)
           option-type (which-option-type option-header)
           option-size (get-ushort bb)]
+      ;; From the developer guide: "The checksum is always the last
+      ;; option (data block) in the navdata packet."
       (if (= option-type :checksum)
         (do
           (check-checksum (get-uint bb) bb)


fix: catch exception in callbacker

fix: catch exception in callbacker

--- src/gml_to_featured/api.clj
+++ src/gml_to_featured/api.clj
@@ -141,8 +141,10 @@
        {:status 500, :body "No such file"})))

 (defn- callbacker [uri result]
-  (http/post uri {:body (cheshire.core/generate-string result)
-                  :headers {"Content-Type" "application/json"}}))
+  (try
+    (http/post uri {:body    (cheshire.core/generate-string result)
+                    :headers {"Content-Type" "application/json"}})
+    (catch Exception e (log/error "Callback error" e))))

 (defn api-routes [process-chan stats]
   (defroutes api-routes


Call overlays for pitch bend messages.

Call overlays for pitch bend messages.

--- src/afterglow/controllers.clj
+++ src/afterglow/controllers.clj
@@ -439,6 +439,14 @@
                 result)))
           (seq (:overlays @state)))

+    :pitch-bend
+    (some (fn [[k overlay]]
+            (let [result (handle-pitch-bend overlay message)]
+              (when (= result :done)
+                (swap! state update-in [:overlays] dissoc k))
+              result))
+          (seq (:overlays @state)))
+
     ;; Nothing we process
     false))


Fix get-all-problem

Fix get-all-problem

--- src/antlion_clojure/redis.clj
+++ src/antlion_clojure/redis.clj
@@ -50,7 +50,7 @@
           read-string))

 (defn get-all-problem []
-  (wcar* (car/hkeys key-problem)))
+  (wcar* (car/hgetall key-problem)))

 (defn del-problem
   [problem]


pred encender from light to turn-on

pred encender from light to turn-on

--- src/babel/espanol/lexicon.clj
+++ src/babel/espanol/lexicon.clj
@@ -359,6 +359,7 @@
                             :pronoun true
                             :reflexive true
                             :sem subject-semantics}}}})
+
    "dibujar" {:synsem {:cat :verb
                       :sem {:pred :draw}}}

@@ -465,7 +466,7 @@

    "encender" {:espanol {:boot-stem "enciend"}
              :synsem {:cat :verb
-                      :sem {:pred :light}}}
+                      :sem {:pred :turn-on}}}

    "encontrar" (let [shared-part-of-encontrar
                   {:synsem {:cat :verb}}]


from preterito-stem to pret-stem

from preterito-stem to pret-stem

--- src/babel/espanol/lexicon.clj
+++ src/babel/espanol/lexicon.clj
@@ -474,7 +474,7 @@
    "poder"
    (let [shared-part-of-poder
                    {:espanol {:boot-stem "pued"}
-                    {:preterito-stem "pud"}
+                    {:pret-stem "pud"}
                     :synsem {:cat :verb}}]
      [(merge shared-part-of-poder
              {:synsem {:pred :can}})


fix typo

fix typo

--- src/babel/espanol/lexicon.clj
+++ src/babel/espanol/lexicon.clj
@@ -291,8 +291,7 @@
    "enojarse"
    (let [subject-semantics (ref {:human true})
          subject-agr (ref :top)]
-     {:espanol
-      :synsem {:cat :verb
+     {:synsem {:cat :verb
                :sem {:pred :get-angry
                      :reflexive true
                      :subj subject-semantics


set {:propernoun true}

set {:propernoun true}

--- src/babel/espanol/lexicon.clj
+++ src/babel/espanol/lexicon.clj
@@ -450,7 +450,7 @@
                             :sem subject-semantics}}}})
    "llamarse"
    (let [subject-semantics (ref {:human true})
-         called-semantics (ref :top)
+         called-semantics (ref {:propernoun true})
          subject-gender (ref :top)
          subject-person (ref :top)
          subject-number (ref :top)]
@@ -473,6 +473,7 @@
                                   :gender subject-gender}
                             :pronoun false
                             :cat :noun
+                            :sem called-semantics
                             :subcat '()}}}})

    "me" {:synsem {:cat :noun


fixed rain dependency.

fixed rain dependency.

--- src/clj/forma/source/rain.clj
+++ src/clj/forma/source/rain.clj
@@ -10,6 +10,7 @@
 (ns forma.source.rain
   (:use cascalog.api
         [forma.hadoop.io :only (get-bytes)]
+        [forma.hadoop.predicate :only (window->array)]
         [forma.source.modis :only (hv->tilestring)]
         [forma.reproject :only (project-to-modis
                                 dimensions-at-res)])


Add News Team

Add News Team

--- src/clj/game/cards-assets.clj
+++ src/clj/game/cards-assets.clj
@@ -293,7 +293,20 @@
    "Net Police"
    {:recurring (effect (set-prop card :rec-counter (:link runner)))
     :effect (effect (set-prop card :rec-counter (:link runner)))}
-
+
+   "News Team"
+   {:access {:req (req (not= (first (:zone card)) :deck))
+             :msg (msg "giver the runner 2 tags or -1 agenda points")
+             :effect (effect (resolve-ability
+                               {:player :runner
+                                :prompt "Take 2 tags or take News Team as -1 agenda points?"
+                                :choices ["take 2 tags" "add News Team to score area"]
+                                :effect (req (if (= target "add News Team to score area")
+                                                 (do (gain state :runner :agenda-point -1)
+                                                     (move state :runner card :scored nil))
+                                                 (gain :runner :tag 2)))}
+                               card targets))}}
+
    "PAD Campaign"
    {:events {:corp-turn-begins {:msg "gain 1 [Credits]" :effect (effect (gain :credit 1))}}}


Removed unnecessary threading macro on query-memory-thread

--- src/clj/memento/db/memory.clj
+++ src/clj/memento/db/memory.clj
@@ -115,6 +115,5 @@
 (defn query-memory-thread
   "Returns a list with all the memories belonging to a root id"
   [id]
-  (->> (db/get-thread-by-root-id *db* {:id id})
-       (map set-memory-status)))
+  (map set-memory-status (db/get-thread-by-root-id *db* {:id id})))


Fix state staying the same

Fix state staying the same

--- src/clj/puertorico/server.clj
+++ src/clj/puertorico/server.clj
@@ -83,7 +83,7 @@
 (defmethod transition :default [etype state & _]
   state)

-(defn calc-state [cstream]
+(defn calc-state []
   (reduce
     (fn [state [etype & eargs]]
       (transition etype state eargs))
@@ -95,7 +95,7 @@
      :bank {:vp 0
             :field-count 0
             :building nil}}
-      cstream))
+      @estream))

 ; (let [
 ;               checked-turn
@@ -191,7 +191,9 @@

 (defn estream-handler [k r os ns]
   (println k))
-
+
+(check-fields (calc-state))
+
 (defn ws-handler [req]
   (with-channel req channel
     (on-close channel (fn [status]
@@ -201,18 +203,16 @@

     (add-watch estream :estream estream-handler)

-    (send! channel (pr-str (calc-state @estream)))
+    (send! channel
+           (pr-str (calc-state)))

-    (on-receive channel (fn [data]
-                          (let [parsed (edn/read-string data)
-                                new-state (calc-state @estream)
-                                cf (check-fields new-state)
-                                new-state (calc-state @estream)]
-                            (if (= :reset parsed)
+    (on-receive channel (fn [client-data]
+                          (let [client-data (edn/read-string client-data)]
+                            (if (= :reset client-data)
                               (reset-game)
-                              (swap! estream conj parsed))
+                              (swap! estream conj client-data))
                             (doseq [chan @connections]
-                              (send! chan (pr-str new-state))))))))
+                              (send! chan (pr-str (calc-state)))))))))

 (defroutes pr-routes
   (GET "/ws" [] ws-handler))


Ignore hidden files.

Ignore hidden files.

--- src/clj/shadow/cljs/build.clj
+++ src/clj/shadow/cljs/build.clj
@@ -143,7 +143,8 @@
         root-len (inc (count root-path))]
     (for [file (file-seq root)
           :let [abs-path (.getAbsolutePath file)]
-          :when (is-cljs-resource? abs-path)
+          :when (and (is-cljs-resource? abs-path)
+                     (not (.isHidden file)))
           :let [rel-path (.substring abs-path root-len)]]
       {:name rel-path
        :file file


test for Apocalypse turning Tri-maf Contact facedown, no meat damage done

--- src/clj/test/cards-events.clj
+++ src/clj/test/cards-events.clj
@@ -26,6 +26,33 @@
     (is (= 0 (:tag (get-runner)))) ; no new tags
     (is (= 5 (:credit (get-runner)))) ; no change in credits
     (is (= 8 (:credit (get-corp))))))
+
+(deftest apocalypse-turn-facedown
+  "Apocalypse - Turn Runner cards facedown without firing their leave play effects"
+  (do-game
+    (new-game (default-corp [(qty "Launch Campaign" 2) (qty "Ice Wall" 1)])
+              (default-runner [(qty "Tri-maf Contact" 3) (qty "Apocalypse" 3)]))
+    (play-from-hand state :corp "Ice Wall" "New remote")
+    (play-from-hand state :corp "Launch Campaign" "New remote")
+    (play-from-hand state :corp "Launch Campaign" "New remote")
+    (take-credits state :corp)
+    (play-from-hand state :runner "Tri-maf Contact")
+    (core/gain state :runner :click 2)
+    (core/click-run state :runner {:server "Archives"})
+    (core/no-action state :corp nil)
+    (core/successful-run state :runner nil)
+    (core/click-run state :runner {:server "R&D"})
+    (core/no-action state :corp nil)
+    (core/successful-run state :runner nil)
+    (core/click-run state :runner {:server "HQ"})
+    (core/no-action state :corp nil)
+    (core/successful-run state :runner nil)
+    (play-from-hand state :runner "Apocalypse")
+    (is (= 0 (count (core/all-installed state :corp))) "All installed Corp cards trashed")
+    (is (= 3 (count (:discard (get-corp)))) "3 Corp cards in Archives")
+    (let [tmc (get-in @state [:runner :rig :facedown 0])]
+      (is (:facedown (refresh tmc)) "Tri-maf Contact is facedown")
+      (is (= 3 (count (:hand (get-runner)))) "No meat damage dealt by Tri-maf's leave play effect"))))

 (deftest demolition-run
   "Demolition Run - Trash at no cost"


Refactoring for CCS-1791

Refactoring for CCS-1791

--- src/clj_mrazik/dictionary.clj
+++ src/clj_mrazik/dictionary.clj
@@ -46,38 +46,43 @@
           1 (green  "yes")
           2 (yellow "with caution")))

+(defn print-field
+    [title word key]
+    (str (bold (str title ": ")) (get word key) " "))
+
+(defn use-it
+    [w]
+    (str (bold "use it: ") (yes-no-with-caution w :use) " "))
+
 (defn incorrect-forms
     [w]
     (str reset
-         (bold "class: ")           (:class w) " "
-         (bold "use it: ")          (yes-no-with-caution w :use) " "
-         (bold "description: ")     (:description w) " "
-         (bold "source: ")          (:source w) " "
-         (bold "incorrect forms: ") (:incorrect_forms w) " "
-         (bold "see also: ")        (:see_also w)
-))
+         (print-field "class"           w :class)
+         (use-it                        w)
+         (print-field "description"     w :description)
+         (print-field "source"          w :source)
+         (print-field "incorrect forms" w :incorrect_forms)
+         (print-field "see also"        w :see_also)))

 (defn correct-forms
     [w]
     (str reset
-         (bold "class: ")           (:class w) " "
-         (bold "use it: ")          (yes-no-with-caution w :use) " "
-         (bold "description: ")     (:description w) " "
-         (bold "source: ")          (:source w) " "
-         (bold "correct forms: ")   (:correct_forms w) " "
-         (bold "see also: ")        (:see_also w)
-))
+         (print-field "class"           w :class)
+         (use-it                        w)
+         (print-field "description"     w :description)
+         (print-field "source"          w :source)
+         (print-field "correct forms"   w :correct_forms)
+         (print-field "see also"        w :see_also)))

 (defn preferred-forms
     [w]
     (str reset
-         (bold "class: ")           (:class w) " "
-         (bold "use it: ")          (yes-no-with-caution w :use) " "
-         (bold "description: ")     (:description w) " "
-         (bold "source: ")          (:source w) " "
-         (bold "preferred forms: ") (:correct_forms w) " "
-         (bold "see also: ")        (:see_also w)
-))
+         (print-field "class"           w :class)
+         (use-it                        w)
+         (print-field "description"     w :description)
+         (print-field "source"          w :source)
+         (print-field "preferred forms" w :correct_forms)
+         (print-field "see also"        w :see_also)))

 (defn find-word
     [word]


Add log message when fruit rots

Add log message when fruit rots

--- src/cljc/robinson/update.cljc
+++ src/cljc/robinson/update.cljc
@@ -2723,6 +2723,8 @@
                                               (assoc m k (get v :num-harvestable-cells 0)))
                                             {}
                                             (get-in state [:world :places])))
+        world-time     (rw/get-time state)
+        fruit-rotted?  (atom false)
         ;viewport-cells (apply concat
         ;                 (map-indexed (fn [vy line]
         ;                                (map-indexed (fn [vx cell]
@@ -2771,7 +2773,7 @@
                 ;; chance of dropped a fruit
                 (if (= (rr/uniform-int 0 300) 0)
                   ;; make the fruit item and find an adjacent free cell to drop it into
-                  (let [item    (assoc (ig/id->item (get cell :fruit-type)) :rot-time (+ (rw/get-time state) (rr/uniform-int 25 35)))
+                  (let [item    (assoc (ig/id->item (get cell :fruit-type)) :rot-time (+ world-time (rr/uniform-int 25 35)))
                         adj-xys (remove (fn [[x y]] (or (not (rv/xy-in-viewport? state x y))
                                                          (rw/type->collide?
                                                            (get (rw/get-cell state x y) :type))))
@@ -2816,18 +2818,26 @@
             ;; rot fruit
             ;; TODO: only rot fruit if it is in the set of visible cells.
             (as-> xy-fns
-              (if (some (fn [item] (< (get item :rot-time (rw/get-time state)) (rw/get-time state)))
+              (if (some (fn [item] (< (get item :rot-time world-time) world-time))
                                         cell-items)
-                (conj xy-fns [[wx wy]
-                              (fn rot-cell-fruit [cell]
-                                (update-in cell [:items] (fn [items]
-                                  (remove (fn [item] (< (get item :rot-time (rw/get-time state))
-                                                        (rw/get-time state)))
-                                           items))))])
+                (do
+                  ;; display a message when fruit rots in the players view. Since update-cells
+                  ;; is called before update-visiblity, we'll decrement the time by one.
+                  (when (= (get cell :discovered) (dec world-time))
+                    (reset! fruit-rotted? true))
+                  (conj xy-fns [[wx wy]
+                                (fn rot-cell-fruit [cell]
+                                  (update-in cell [:items] (fn [items]
+                                    (remove (fn [item] (< (get item :rot-time world-time)
+                                                          world-time))
+                                             items))))]))
                 xy-fns)))))
       []
       (vec (rv/cellsxy-in-viewport state)))]
     (as-> state state
+      (if @fruit-rotted?
+        (rc/append-log state "The fruit rots away.")
+        state)
       (rw/update-cells state xy-fns)
       (reduce-kv (fn [state place-id harvest-count]
                    (assoc-in state [:world :places place-id :num-harvestable-cells] harvest-count))


exposable ports routes

exposable ports routes

#58

--- src/cljc/swarmpit/routes.cljc
+++ src/cljc/swarmpit/routes.cljc
@@ -7,11 +7,13 @@
        "/login"         {:post :login}
        "/password"      {:post :password}
        "/distribution/" {"public"     {:get {"/repositories" :public-repositories
-                                             "/tags"         :public-repository-tags}}
+                                             "/tags"         :public-repository-tags
+                                             "/ports"        :public-repository-ports}}
                          "dockerhub"  {""  {:get  :dockerhub-users
                                             :post :dockerhub-user-create}
                                        "/" {:get    {[:id "/repositories"] :dockerhub-repositories
                                                      [:id "/tags"]         :dockerhub-repository-tags
+                                                     [:id "/ports"]        :dockerhub-repository-ports
                                                      [:id]                 :dockerhub-user}
                                             :delete {[:id] :dockerhub-user-delete}
                                             :post   {[:id] :dockerhub-user-update}}}
@@ -19,6 +21,7 @@
                                             :post :registry-create}
                                        "/" {:get    {[:id "/repositories"] :registry-repositories
                                                      [:id "/tags"]         :registry-repository-tags
+                                                     [:id "/ports"]        :registry-repository-ports
                                                      [:id]                 :registry}
                                             :delete {[:id] :registry-delete}
                                             :post   {[:id] :registry-update}}}}


Use time difference for timer

Use time difference for timer

Rather than relying on setTimeout to be accurate.

--- src/cljs/minesweeper/app.cljs
+++ src/cljs/minesweeper/app.cljs
@@ -27,12 +27,15 @@
      :time 0
      :board (generate-board width height bombs)}))

+(def seconds-difference (comp #(/ % 1000) -))
+
 (defn game-timer []
-  (let [kill (chan 1)]
+  (let [then (js/Date.)
+        kill (chan 1)]
     (go (loop []
           (let [[v c] (alts! [kill (timeout 1000)])]
             (when-not (identical? c kill)
-              (swap! app-state update-in [:game :time] inc)
+              (swap! app-state assoc-in [:game :time] (seconds-difference (js/Date.) then))
               (recur)))))
     kill))

@@ -43,8 +46,9 @@
     (swap! app-state update-in [:game] reset-game)
     (swap! app-state assoc-in [:game :timer] timer)))

-(start-game)

+(when-not (seq (get-in @app-state [:game :board]))
+  (start-game))

 ;; Om components


Fixed my nickname ;-)

Fixed my nickname ;-)

Thanks for mention of me!

--- src/cljs/netrunner/about.cljs
+++ src/cljs/netrunner/about.cljs
@@ -58,7 +58,7 @@
         [:a {:href "https://github.com/mtgred/netrunner/wiki/Jinteki.net-Guide" :target "_blank"} "Jinteki.net Guide"] " on the Github wiki." ]]]

      [:h3 "Contributors"]
-     [:p "A big props to Neal Terrell (nealpro), Joel Koepp (JoelCFC25) and Dominic Kexel (queuseven) who actively contribute to the success of the project with regular code submissions, the management of the issue tracker and answers to questions in the chat. It would not be the same without your help."]
+     [:p "A big props to Neal Terrell (nealpro), Joel Koepp (JoelCFC25) and Dominic Kexel (queueseven) who actively contribute to the success of the project with regular code submissions, the management of the issue tracker and answers to questions in the chat. It would not be the same without your help."]
      [:p "Many thanks to all the donators. Your contributions and kind words are greatly appreciated. You help finance fast servers and keep the developer motivated."]
      [:ul.list.compact
       (for [d (:donators cursor)]


stack is now default index page (atleast till dashboard page is finished)

--- src/cljs/swarmpit/router.cljs
+++ src/cljs/swarmpit/router.cljs
@@ -34,7 +34,7 @@
   [location]
   ;; Render to service list by default as we don't have any index page right now
   (if (= :index (:handler location))
-    (set-route {:handler :service-list})
+    (set-route {:handler :stack-list})
     (set-route location)))

 (defn start


Add a TODO for the server

Add a TODO for the server

--- src/clojure/picard/server.clj
+++ src/clojure/picard/server.clj
@@ -280,6 +280,10 @@
              :bytes-to-send  bytes-to-send
              :bytes-expected bytes-expected
              :responded?     responded?
+             ;; TODO, this isn't exactly correct since 304 responses
+             ;; won't send the body, and we also need to handle the
+             ;; case of transfer-encoding: chunked w/ a single chunk
+             ;; passed with the response.
              :chunked?       (= (hdrs "transfer-encoding") "chunked")
              :next-dn-fn     (when (not responded?) stream-or-finalize-response)
              :keepalive?     (and (.keepalive? current-state)


Remove hiccup specific code from layouts.html

--- src/incise/layouts/html.clj
+++ src/incise/layouts/html.clj
@@ -1,8 +1,6 @@
 (ns incise.layouts.html
   (:require [incise.parsers.core]
-            [robert.hooke :refer [with-scope add-hook]]
-            (hiccup [core :refer [html]]
-                    [page :refer [html5]])))
+            [robert.hooke :refer [with-scope add-hook]]))

 (declare ^:dynamic *site-options*)
 (declare ^:dynamic *parse*)
@@ -30,11 +28,11 @@
        (binding [*site-options* site-options#
                  *parse* parse#]
          (let [~destructuring [*site-options* *parse*]]
-           (with-scope (html5 ~@body)))))))
+           (with-scope ~@body))))))

 (defmacro defpartial
   "Defines a 'partial' which is baically some hiccup markup. An arguments vector
-   is required and can be used to destructure the dynamic vars set by a layout."
+  is required and can be used to destructure the dynamic vars set by a layout."
   [sym-name doc-string? destructuring & body]
   (let [[doc-string destructuring body]
         (if (string? doc-string?)
@@ -44,7 +42,7 @@
        ~doc-string
        [& args#]
        (let [~destructuring [*site-options* *parse* args#]]
-         (html ~@body)))))
+         ~@body))))

 (defmacro repartial
   "Replace the given var in a layout with a new function which will be called in


feat(core): open access for parser API

feat(core): open access for parser API

--- src/datascript_mori/core.cljs
+++ src/datascript_mori/core.cljs
@@ -2,6 +2,8 @@
   (:require
     [datascript.core :as d]
     [datascript.js :as djs]
+    [datascript.parser :as dp]
+    [datascript.pull-parser :as dpp]
     [mori :as m]
     [mori.extra :as me]))

@@ -13,6 +15,9 @@
 (def ^:export js_to_Datom        djs/js->Datom)
 (def ^:export pull_result_to_js  djs/pull-result->js)
 (def ^:export keywordize  djs/keywordize)
+
+(def ^:export parse_query dp/parse-query)
+(def ^:export parse_pull dpp/parse-pull)

 (def ^:export DB_ID :db/id)
 (def ^:export DB_FN_CALL :db.fn/call)


Reduce whitespace in translations

Reduce whitespace in translations

--- src/discuss/translations.cljs
+++ src/discuss/translations.cljs
@@ -4,65 +4,66 @@
 (def available [[:de "deutsch"]
                 [:en "english"]])

-(def translations {:de {:common     {:and              "und"
-                                     :author           "Autor"
-                                     :back             "Zurück"
-                                     :chars-remaining  "Zeichen verbleibend"
-                                     :close            "Schließen"
-                                     :hello            "Hallo"
-                                     :issue            "Diskussionsthema"
-                                     :login            "Login"
-                                     :logout           "Logout"
-                                     :options          "Einstellungen"
-                                     :save             "Speichern"
-                                     :show-discuss     "Zeige discuss"
-                                     :start-discussion "Starte die Diskussion"}
-                        :discussion {:add-argument "Ein neues Argument hinzufügen"
-                                     :current      "Aktuelle Diskussion"
-                                     :restart      "Neustarten"
-                                     :submit       "Abschicken"}
-                        :errors     {:login "Login fehlgeschlagen. Vermutlich sind die Zugangsdaten nicht korrekt."}
-                        :find       {:find-statement "Finde Aussage in Diskussion"}
-                        :login      {:nickname "Benutzername"
-                                     :password "Passwort"}
-                        :nav        {:home "Start"
-                                     :find "Suchen"}
-                        :options    {:heading "Einstellungen"
-                                     :lang    "Interface-Sprache"}
-                        :references {:jump       "Springe in die Diskussion"
-                                     :usages     "In welchen Argumenten wird dieser Textausschnitt verwendet?"
-                                     :where-used "Wo wird diese Referenz verwendet?"
-                                     :find-statement "Finde Aussage in der Diskussion"
-                                     :clipboard  "Ziehe diese Referenzen in das Textfeld beim Erzeugen eines neuen Arguments, um die Referenz zu nutzen."}}
-                   :en {:common     {:and              "and"
-                                     :author           "Author"
-                                     :back             "Back"
-                                     :chars-remaining  "characters remaining"
-                                     :close            "Close"
-                                     :hello            "Hello"
-                                     :issue            "Issue"
-                                     :login            "Login"
-                                     :logout           "Logout"
-                                     :options          "Options"
-                                     :save             "Save"
-                                     :show-discuss     "Show discuss"
-                                     :start-discussion "Start Discussion"}
-                        :discussion {:add-argument "Add a new argument"
-                                     :current      "Current Discussion"
-                                     :restart      "Restart"
-                                     :submit       "Submit"}
-                        :errors     {:login "Could not login. Maybe your credentials are wrong."}
-                        :find       {:find-statement "Find statement in the discussion"}
-                        :login      {:nickname "Nickname"
-                                     :password "Password"}
-                        :nav        {:home "Home"
-                                     :find "Find"}
-                        :options    {:heading "Options"
-                                     :lang    "Language of Interface"}
-                        :references {:jump       "Jump into the discussion"
-                                     :usages     "In which arguments has this reference been used?"
-                                     :where-used "Where has this reference been used?"
-                                     :clipboard  "Drag these references into the input field when creating a new argument."}}})
+(def translations
+  {:de {:common     {:and              "und"
+                     :author           "Autor"
+                     :back             "Zurück"
+                     :chars-remaining  "Zeichen verbleibend"
+                     :close            "Schließen"
+                     :hello            "Hallo"
+                     :issue            "Diskussionsthema"
+                     :login            "Login"
+                     :logout           "Logout"
+                     :options          "Einstellungen"
+                     :save             "Speichern"
+                     :show-discuss     "Zeige discuss"
+                     :start-discussion "Starte die Diskussion"}
+        :discussion {:add-argument "Ein neues Argument hinzufügen"
+                     :current      "Aktuelle Diskussion"
+                     :restart      "Neustarten"
+                     :submit       "Abschicken"}
+        :errors     {:login "Login fehlgeschlagen. Vermutlich sind die Zugangsdaten nicht korrekt."}
+        :find       {:find-statement "Finde Aussage in Diskussion"}
+        :login      {:nickname "Benutzername"
+                     :password "Passwort"}
+        :nav        {:home "Start"
+                     :find "Suchen"}
+        :options    {:heading "Einstellungen"
+                     :lang    "Interface-Sprache"}
+        :references {:jump       "Springe in die Diskussion"
+                     :usages     "In welchen Argumenten wird dieser Textausschnitt verwendet?"
+                     :where-used "Wo wird diese Referenz verwendet?"
+                     :find-statement "Finde Aussage in der Diskussion"
+                     :clipboard  "Ziehe diese Referenzen in das Textfeld beim Erzeugen eines neuen Arguments, um die Referenz zu nutzen."}}
+   :en {:common     {:and              "and"
+                     :author           "Author"
+                     :back             "Back"
+                     :chars-remaining  "characters remaining"
+                     :close            "Close"
+                     :hello            "Hello"
+                     :issue            "Issue"
+                     :login            "Login"
+                     :logout           "Logout"
+                     :options          "Options"
+                     :save             "Save"
+                     :show-discuss     "Show discuss"
+                     :start-discussion "Start Discussion"}
+        :discussion {:add-argument "Add a new argument"
+                     :current      "Current Discussion"
+                     :restart      "Restart"
+                     :submit       "Submit"}
+        :errors     {:login "Could not login. Maybe your credentials are wrong."}
+        :find       {:find-statement "Find statement in the discussion"}
+        :login      {:nickname "Nickname"
+                     :password "Password"}
+        :nav        {:home "Home"
+                     :find "Find"}
+        :options    {:heading "Options"
+                     :lang    "Language of Interface"}
+        :references {:jump       "Jump into the discussion"
+                     :usages     "In which arguments has this reference been used?"
+                     :where-used "Where has this reference been used?"
+                     :clipboard  "Drag these references into the input field when creating a new argument."}}})

 (defn- prepend-translation
   "Lookup given key and prepend some string to it."


Add generator for unique react-keys

Add generator for unique react-keys

--- src/discuss/utils/common.cljs
+++ src/discuss/utils/common.cljs
@@ -3,13 +3,14 @@
             [clojure.walk :refer [keywordize-keys]]
             [cljs.pprint :as pp]
             [cognitect.transit :as transit]
-            [discuss.config :as config]
-            [goog.fx.dom :as fx]))
+            [discuss.config :as config]))

 (defn prefix-name
   "Create unique id for DOM elements."
   [name]
   (str config/project "-" name))
+
+(defonce counter (atom 0))

 (defonce app-state
          (atom {:discussion {}
@@ -47,6 +48,11 @@
       converted)))

 ;; Get
+(defn get-unique-key
+  "Return unique react-key."
+  []
+  (str (:name config/project) "-unique-react-key-" (swap! counter inc)))
+
 (defn get-cursor
   "Return a cursor to the corresponding key in the app-state."
   [key]


reordered secondary menu in video page

reordered secondary menu in video page

--- src/distillery/view/video.clj
+++ src/distillery/view/video.clj
@@ -106,10 +106,10 @@
    :title job-name
 ;   :js-code "videojs.options.flash.swf = 'video-js.swf';"
    :secondary-menu {"Übersicht" (jshref "innerpage('overview')")
+                    "Cloud" (jshref "innerpage('cloud')")
                     "Transcript" (jshref "innerpage('transcript')")
-                    "Glossar" (jshref "innerpage('glossary')")
-                    "Cloud" (jshref "innerpage('cloud')")
-                    "Kategorien" (jshref "innerpage('categories')")}
+                    "Kategorien" (jshref "innerpage('categories')")
+                    "Glossar" (jshref "innerpage('glossary')")}
    :page
      [(render-headline args)
       (render-video args)


[build system] regen boot/myocamlbuild.boot

git-svn-id: e7e61699ce1738538ffebb75374fbea0924bc775@7953 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02


coerce priority to integer

coerce priority to integer

--- src/rester/core.clj
+++ src/rester/core.clj
@@ -228,9 +228,16 @@
                  :when key]
              [(keyword (str/lower-case key)) (or value true)])))

+(defn- to-int [s]
+  (try
+    (if (empty? s) 0
+        (Integer/parseInt s))
+    (catch Exception e 0)))
+
 (defn tests-from [file sheet]
   (let [tests (->> (map #(zipmap fields %) (read-rows file sheet))
                    (filter #(not (str/blank? (:test %))))
+                   (map #(update % :priority to-int))
                    (map-indexed #(-> %2 (assoc :placeholders (placeholders-of %2) :id %1)
                                      (update :extractions str->map #"\s*=\s*"))))
         extractors (for [t tests :when (:extractions t)] [(:id t) (map first (:extractions t))])
@@ -283,9 +290,9 @@
         exec-test (fn [test]
                     (if (:done test) test
                         (let [{:keys [before after skip ignore]} (:options test)
-                              deps (map #(nth test-agents %) (:deps test))]
-                          (log/info "executing " (:id test))
-                          (if (every? (comp :done deref) deps)
+                              deps (map #(nth test-agents %) (:deps test))
+                              pending (filter (comp not :done deref) deps)]
+                          (if (empty? pending)
                             (assoc
                              (cond
                                (and skip-tag (= skip-tag skip)) (assoc test :ignored "skip requested")
@@ -302,7 +309,9 @@
                                                (if t (exec-test-case t opts))))))
                                :else (assoc test :skipped "dependents failed"))
                              :done true)
-                            test))))]
+                            (do
+                              (log/infof "%s blocked by %s" (:id test) (str/join "," (map (comp :id deref) pending)))
+                              test)))))]

     (doseq [[priority agents] (sort-by first (group-by (comp :priority deref) test-agents))
             :let [pending (atom (into #{} (map (comp :id deref) agents)))


more testing functions

more testing functions

git-svn-id: 03a8048b5ee8463be5048a3801110fb50f378627@11076 d0ab736e-dc22-4aeb-8dc9-08def0aa14fd

--- acqEngine/src/org/micromanager/test/saving.clj
+++ acqEngine/src/org/micromanager/test/saving.clj
@@ -2,7 +2,8 @@
   (:import (java.util.concurrent LinkedBlockingQueue)
            (mmcorej TaggedImage)
            (java.nio ByteBuffer ByteOrder)
-           (java.io RandomAccessFile))
+           (java.io FileOutputStream RandomAccessFile)
+           (java.nio.channels FileChannel$MapMode))
   (:require [org.micromanager.mm :as mm])
   (:use [org.micromanager.mm :only (core)]))

@@ -91,7 +92,7 @@
    images to a file using the direct byte buffer method."
   [num-images]
     (let [filename (str "D:/AcquisitionData/test" (rand-int 100000) ".dat")
-          file (RandomAccessFile. filename "rw")
+          file (FileOutputStream. filename false)
           channel (.getChannel file)]
       (try
         (let [buffer-queue (time (byte-buffer-queue num-images))]
@@ -103,6 +104,21 @@
         (catch Exception e (println e))
         (finally (.close file)))
       filename))
+
+(defn acquire-and-map
+  [num-images]
+  (let [buffer-queue (time (byte-buffer-queue num-images))]
+    (let [filename (str "D:/AcquisitionData/test" (rand-int 100000) ".dat")
+          file (RandomAccessFile. filename "rw")
+          channel (.getChannel file)
+          out (.. file getChannel (map FileChannel$MapMode/READ_WRITE 0 (* num-images 2560 2160 2)))]
+      (try
+        (dotimes-timed [i num-images] 100
+                       (let [pixels (.take buffer-queue)]
+                         (.put out pixels)))
+        (catch Exception e (println e))
+        (finally (.close file))))))
+

 (defn acquire-and-store-in-ram
   "Simulate running a sequence acquisition, and store


Fix kube examples

Fix kube examples

--- example-config.clj
+++ example-config.clj
@@ -22,8 +22,8 @@
  :node-pool-cloud-config {:provider :kube
                           :api-url "http://localhost:8001"
                           :api-url :kubernetes-service ;; or if running shale inside kube, use the internal api
-                          :label :label {:app :selenium} ;; add all containers w/ metadata label :app :selenium
-                          :port-name "selenium" ;; connect
+                          :kube/label :label {:app :selenium} ;; add all containers w/ metadata label :app :selenium
+                          :kube/port-name "selenium" ;; connect
                           }

  ;; if you just need a static list of nodes, provide that instead


Convert property keys to camel-cased strings when passing them to JS

--- src/main/workflo/macros/screen/om_next.cljs
+++ src/main/workflo/macros/screen/om_next.cljs
@@ -1,7 +1,9 @@
 (ns workflo.macros.screen.om-next
-  (:require [om.next :as om]
+  (:require [clojure.walk :refer [walk]]
+            [om.next :as om]
             [workflo.macros.screen.bidi :as sb]
             [workflo.macros.screen :as scr]
+            [workflo.macros.util.string :refer [kebab->camel]]
             [workflo.macros.view :refer-macros [defview]]))

 ;;;; Remember the active screen
@@ -104,16 +106,29 @@
                                   (-> item meta :om-path))))
                (vals layout))))

+(defn camel-cased-prop-map
+  "Convert a Clojure map with Om Next properties to a map
+   where all keys are camel-cased strings that can be accessed
+   like object properties in JS/React."
+  [m]
+  (walk (fn [[k v]]
+          [(kebab->camel (name k))
+           (cond-> v (map? v) camel-cased-prop-map)])
+        identity
+        m))
+
 (defview RootWrapper
   [{workflo/screen [workflo [navigation layout]]}]
   (render
-   (let [{:keys [workflo/navigation workflo/layout]} screen]
-     ((:factory (root-component))
-      (if (:js? (root-component))
-        #js {:navigation navigation
-             :layout (realize-layout layout)}
+   (let [navigation (:workflo/navigation screen)
+         layout     (realize-layout (:workflo/layout screen))
+         root-info  (root-component)]
+     ((:factory root-info)
+      (if (:js? root-info)
+        #js {:navigation (camel-cased-prop-map navigation)
+             :layout (camel-cased-prop-map layout)}
         {:navigation navigation
-         :layout (realize-layout layout)})))))
+         :layout layout})))))

 ;;;; Routing


Update client.clj

Update client.clj

--- src/muon_clojure/client.clj
+++ src/muon_clojure/client.clj
@@ -11,7 +11,7 @@
            (java.util Map)))

 #_(def amazon-url
-  "amqp://sentinel:lkjljkllj@ec2-52-28-16-238.eu-central-1.compute.amazonaws.com")
+  "amqp://BORKED")
 (def amazon-url
   "amqp://localhost")


fix post notifications

fix post notifications

--- server/src/gratefulplace/db/transactions/posts.clj
+++ server/src/gratefulplace/db/transactions/posts.clj
@@ -18,11 +18,11 @@
   (let [{:keys [topic-id author-id]} params
         users (users-to-notify-of-post topic-id author-id)
         topic (c/mapify (db/ent topic-id) mr/ent->topic)]
-        (email/send-reply-notification users params topic)))
+        (email/send-reply-notification users topic params)))

 (defn- after-create-post
   [result params]
-  (future (notify-users-of-post params)))
+  (future (notify-users-of-post result params)))

 (defn create-post
   [params]


Remove extraneous args to pink-noise in monomestep example

--- src/overtone/examples/monome/monomestep.clj
+++ src/overtone/examples/monome/monomestep.clj
@@ -36,7 +36,7 @@
        kick (* (* kickenv 7) (sin-osc (+ 40 (* kickenv kickenv kickenv 200))))
        kick (clip2 kick 1)

-       snare (* 3 (pink-noise [1 1]) (apply + (* (decay (impulse (/ bpm 240) 0.5) [0.4 2]) [1 0.05])))
+       snare (* 3 (pink-noise) (apply + (* (decay (impulse (/ bpm 240) 0.5) [0.4 2]) [1 0.05])))
        snare (+ snare (bpf (* 4 snare) 2000))
         snare (clip2 snare 1)
        beat (* beat-vol (+ kick snare))


trace as t

trace as t

--- dev/user.clj
+++ dev/user.clj
@@ -1,7 +1,7 @@
 (ns user
   (:use midje.repl)
   (:require
-     [clojure.tools.trace :refer (deftrace trace trace-ns trace-vars)]
+     [clojure.tools.trace :refer (deftrace trace trace-ns trace-vars) :as t]
      [clojure.java.io :as io]
      [clojure.string :as str]
      [clojure.pprint :refer (pprint)]


add growth page to links

add growth page to links

--- src/pc/http/admin/inner.clj
+++ src/pc/http/admin/inner.clj
@@ -25,6 +25,7 @@
                                [:div {:style "padding: 40px"}
                                 [:div [:a {:href "/teams"} "Teams"]]
                                 [:div [:a {:href "/users"} "Users"]]
+                                [:div [:a {:href "/growth"} "Growth"]]
                                 [:div [:a {:href "/early-access"} "Early Access"]]
                                 [:div [:a {:href "/graphs"} "User Graphs"]]
                                 [:div [:a {:href "/clients"} "Clients"]]


Remove the repl debug helpers

Remove the repl debug helpers

I don't think they ever worked properly and println is much simpler at
the repl

--- dev/user.clj
+++ dev/user.clj
@@ -1,41 +0,0 @@
-(ns user
-  (:require [robert.hooke :as rh]
-            [clojure.tools.logging :as log]))
-
-;; inspiration from
-;; http://martintrojer.github.io/clojure/2014/03/09/working-with-coreasync-blocking-calls/
-
-(defn debug [{:keys [name ns]} f & args]
-  (log/debug "Calling " (ns-name ns) "/" name " with " args)
-  (apply f args))
-
-(defn enable-debug [var]
-  (log/debug "Enabling debugging for" var)
-  (robert.hooke/add-hook var (partial debug (meta var))))
-
-(defn disable-debug [var]
-  (log/debug "Disabling debugging for" var)
-  (robert.hooke/clear-hooks var))
-
-(defn public-fns [sym]
-  (->> sym
-   find-ns
-   ns-publics
-   vals
-   (filter #(fn? (deref %)))))
-
-(defn debug-ns [sym]
-  (->> (public-fns sym)
-   ;; remove dups
-   (remove #(:robert.hooke/hooks (meta (deref %)))) ; this doesn't seem to work
-   (map enable-debug)
-   doall))
-
-(defn undebug-ns [sym]
-  (->> (public-fns sym)
-   ;; (filter #(:robert.hooke/hook (meta (deref %))))
-   (map disable-debug)
-   doall))
-
-(comment
-  (debug-ns 'mdr2.db))


fix tests

fix tests

--- test/unifn_test.clj
+++ test/unifn_test.clj
@@ -1,4 +1,4 @@
-(ns unifn.core-test
+(ns unifn-test
   (:require [unifn :as u]
             [matcho.core :as matcho]
             [clojure.test :refer :all]


Fix project filtering in dashboard.

Fix project filtering in dashboard.

--- src/uxbox/ui/dashboard/projects.cljs
+++ src/uxbox/ui/dashboard/projects.cljs
@@ -108,7 +108,8 @@
   (letfn [(on-term-change [event]
             (-> (dom/get-target event)
                 (dom/get-value)
-                (dd/set-project-filtering)))
+                (dd/set-project-filtering)
+                (rs/emit!)))
           (on-clear [event]
             (rs/emit! (dd/clear-project-filtering)))]
     (html


add exeception trace

add exeception trace

--- src/riak_mesos/executor.clj
+++ src/riak_mesos/executor.clj
@@ -11,9 +11,13 @@
                              (println "[launchTask] Sending status Update")
                              (exec/send-status-update driver {:task-id (:task-id task-info)
                                                               :state :task-running}))
-                 (frameworkMessage [driver bytes] (let [command-string (read-string (String. bytes "UTF-8"))]
-                                                    (println "[frameworkMessage] Running command " command-string )
-                                                    (future (apply clojure.java.shell/sh  (clojure.string/split command-string #"\s+") ))))))
+                 (frameworkMessage [driver bytes]
+                                   (try
+                                     (let [command-string (read-string (String. bytes "UTF-8"))]
+                                     (println "[frameworkMessage] Running command " command-string )
+                                     (future (apply clojure.java.shell/sh  (clojure.string/split command-string #"\s+") )))
+                                     (catch Exception e
+                                       (.printStackTrace e))))))


Remove old and unused file with confusing name

--- src/rill/event_listener.clj
+++ src/rill/event_listener.clj
@@ -1,13 +0,0 @@
-(ns rill.event-listener
-  (:require [rill.event-store :as store]))
-
-(def long-poll-seconds 20)
-
-(defn listener
-  [event-store stream-id version callback]
-  (loop [version version]
-    (recur (reduce (fn [v e]
-                     (callback e)
-                     (inc v))
-                   (store/retrieve-events-since event-store stream-id version long-poll-seconds)))))
-


replace - with space in test name

replace - with space in test name

--- test/clj/lambdacd/internal/pipeline_state_test.clj
+++ test/clj/lambdacd/internal/pipeline_state_test.clj
@@ -59,7 +59,7 @@
               2 { [1 2] {:bar "baz"}}} (initial-pipeline-state config))))))

 (deftest notify-when-most-recent-build-running-test
-  (testing "that we are being notified when the first step of the pipeline-is-finished"
+  (testing "that we are being notified when the first step of the pipeline is finished"
     (let [pipeline-state (atom {0 {}})
           call-counter (atom 0)
           callback (fn [& _] (swap! call-counter inc))]


Failing test

Failing test

--- _test/check_exercises.clj
+++ _test/check_exercises.clj
@@ -11,5 +11,5 @@
     (doseq [problem problems]
       (load-file (str problem "/example.clj"))
       (load-file (str problem "/" (string/replace problem \- \_) "_test.clj")))
-    (is (zero? (:fail (apply run-tests
-                        (map #(symbol (str % "-test")) problems)))))))
+    (is (odd? (:fail (apply run-tests
+                       (map #(symbol (str % "-test")) problems)))))))


Add rsp type that properly implements catacumba protocols.

This is a compatibility layer for future support of
content negotiation on catacumba.

--- src/uxbox/frontend/core.clj
+++ src/uxbox/frontend/core.clj
@@ -4,7 +4,23 @@
 ;;
 ;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>

-(ns uxbox.frontend.core)
+(ns uxbox.frontend.core
+  (:require [catacumba.impl.handlers :as cih]
+            [catacumba.serializers :as csz])
+  (:import ratpack.handling.Context
+           ratpack.http.Response
+           ratpack.http.MutableHeaders))

-(defmulti -handler
-  (comp (juxt :type :dest) second vector))
+
+(deftype Rsp [data]
+  cih/ISend
+  (-send [_ ctx]
+    (let [^Response response (.getResponse ^Context ctx)
+          ^MutableHeaders headers (.getHeaders response)]
+      (.set headers "content-type" "application/transit+json")
+      (cih/-send (csz/encode data :transit+json) ctx))))
+
+(defn rsp
+  "A shortcut for create a response instance."
+  [data]
+  (Rsp. data))


Find the bounds of a form with smarter string searching

Fixes Day8/re-frame-debux#3

--- src/day8/re_frame_10x/view/event.cljs
+++ src/day8/re_frame_10x/view/event.cljs
@@ -6,6 +6,7 @@
             [mranderson047.reagent.v0v7v0.reagent.core :as reagent]
             [mranderson047.re-frame.v0v10v2.re-frame.core :as rf]
             [zprint.core :as zp]
+            [goog.string]
             [clojure.string :as str])
   (:require-macros [day8.re-frame-10x.utils.macros :refer [with-cljs-devtools-prefs]]
                    [day8.re-frame-10x.utils.re-com :refer [handler-fn]]))
@@ -94,19 +95,34 @@
            :padding          "0px 3px"}
    :child [components/simple-render (:result line) [@(rf/subscribe [:epochs/current-epoch-id]) code-execution-id (:id line)]]])

+(defn find-bounds
+  "Try and find the bounds of the form we are searching for. Uses some heuristics to
+  try and avoid matching partial forms, e.g. 'default-|weeks| for the form 'weeks."
+  [form search-form]
+  (let [search-str (zp/zprint-str search-form)
+        form-str   (zp/zprint-str form)
+        re         (re-pattern (str "(\\s|\\(|\\[|\\{)" "(" (goog.string.regExpEscape search-str) ")"))
+        result     (.exec re form-str)]
+    (if (some? result)
+      (let [index        (.-index result)
+            pre-match    (aget result 1)
+            matched-form (aget result 2)
+            index        (+ index (count pre-match))]
+        [index (+ index (count matched-form))])
+      ;; If the regex fails, fall back to string index just in case.
+      (let [start  (str/index-of form-str search-str)
+            length (if (and (some? search-str) (some? start))
+                     (count (pr-str search-str))
+                     0)]
+        [start (+ start length)]))))

 (defn event-expression
   [form]
   (let [highlighted-form @(rf/subscribe [:code/highlighted-form])
         form-str         (zp/zprint-str form)
-        search-str       highlighted-form
-        start            (str/index-of form-str search-str)
-        length           (if (some? search-str)
-                           (count (pr-str search-str))
-                           0)
-        before           (subs form-str 0 start)
-        end-index        (+ start length)
-        highlight        (subs form-str start end-index)
+        [start-index end-index] (find-bounds form highlighted-form)
+        before           (subs form-str 0 start-index)
+        highlight        (subs form-str start-index end-index)
         after            (subs form-str end-index)]
     ;(println ">> event-expression:" (pr-str (subs (pr-str highlighted-form) 0 30)))
     ; DC: We get lots of React errors if we don't force a creation of a new element when the highlight changes. Not really sure why...