Cleanup - Limit the visibility of functions at the moment.

--- src/app/clj/fnx/meta/expose.clj
+++ src/app/clj/fnx/meta/expose.clj
@@ -14,33 +14,33 @@
 ;; * We want only functions, not the other vars: We can spot them because they have an `:arglists` in their meta.
 ;; * Get the public vars with `ns-publics`
 ;;
-(defn ns-public-fn
+(defn- ns-public-fn
   "Given a ns symbol, returns all the public fns of this ns."
   [ns] (do (require ns)
            (filter #(:arglists (meta %))
                    (vals (ns-publics (find-ns ns))))))

-(defn fun-str "Transform a function name without the #' in front of its name."
+(defn- fun-str "Transform a function name without the #' in front of its name."
   [s]
   (join "" (drop 2 s)))

-(defn resolve-str "Wrapper around 'resolve' to deal with string representing #'namespace/function"
+(defn- resolve-str "Wrapper around 'resolve' to deal with string representing #'namespace/function"
   [s]
   (resolve (symbol (fun-str s))))

-(defn list-ns "List the fnx namespaces to expose."
+(defn- list-ns "List the fnx namespaces to expose."
   [prefix-ns]
   (filter #(.contains (str (ns-name %)) prefix-ns) (all-ns)))

-(defn fn-name "Transform a list of parameters into a function name"
+(defn- fn-name "Transform a list of parameters into a function name"
   [& s]
   (str "#'" (join "/" [(join "." (butlast s)) (last s)])))

-(defn apply-fn "Apply the function fun to the map args"
+(defn- apply-fn "Apply the function fun to the map args"
   [f args]
   (apply f (vals args)))

-(defn load-ns! "Get the namespaces from the file namespaces-to-load"
+(defn- load-ns! "Get the namespaces from the file namespaces-to-load"
   []
   (clojure.string/split (slurp "namespaces-to-load") #"\n"))


Fixed 'summary' title

Fixed 'summary' title

--- src/arachnida/html_renderer.clj
+++ src/arachnida/html_renderer.clj
@@ -225,7 +225,7 @@
                 [:h1 (str "Author: " author-name)]
                 [:div {:class "panel panel-primary"}
                     [:div {:class "panel-heading"}
-                        "Summary for 2015"]
+                        "Summary"]
                     [:table {:class "table table-condensed table-hover table-bordered" :rules "all"}
                         [:tr [:td "Commits:"]
                              [:td (:commits_count statistic)]]


Add debug logging.

Add debug logging.

Tell us whether the db is old or new.

--- src/boefie_invest/handler.clj
+++ src/boefie_invest/handler.clj
@@ -38,6 +38,7 @@

   (if (env :dev) (parser/cache-off!))
   (when-not (schema/initialized?)
+    (timbre/debug "Initializing database schema")
     (schema/init-db schema/db-spec))
   ;;start the expired session cleanup job
   (cronj/start! session-manager/cleanup-job)


remove duplicate

remove duplicate

--- src/babel/francais/lexicon.cljc
+++ src/babel/francais/lexicon.cljc
@@ -405,10 +405,6 @@
              {:synsem {:sem {:pred :do}}})
          (unify shared-part-of-faire
                 {:synsem {:sem {:pred :make}}})])
-
-   "former" {:synsem {:cat :verb
-                     :sem {:pred :form}}}
-

    "former" {:synsem {:cat :verb
                      :sem {:pred :form}}}


Revert 'add reflexive=true => essere=true': buggy commit

This reverts commit b4b9af9a92d9ab65191ccb4584f396b095c988a3.

--- src/babel/italiano/grammar.cljc
+++ src/babel/italiano/grammar.cljc
@@ -688,14 +688,7 @@
                    :infl :future}}
          {:synsem {:cat :verb
                    :sem {:tense :conditional}
-                   :infl :conditional}}
-         ;; </inflection-semantics correspondences>
-
-         ;; reflexive expressions are always essere=true.
-         {:synsem {:cat :verb
-                   :sem {:reflexive true}
-                   :essere true}}]]
-
+                   :infl :conditional}}]]
     (let [with-defaults
           (remove #(= :fail %)
                   (map (fn [default]


fix comment

fix comment

--- src/babel/italiano/grammar.cljc
+++ src/babel/italiano/grammar.cljc
@@ -441,7 +441,7 @@
                            :synsem {:aux true
                                     :cat :verb}})

-                   ;; these two following rules are kind of complicated and made more so by
+                   ;; this rule is kind of complicated and made more so by
                    ;; dependence on auxilary sense of "avere" which supplies the
                    ;; obj-agr agreement between the object and the main (non-auxilary) verb.
                    ;; Note use of :reflexive below.


remove (atom)  from "dopo"

remove (atom)  from "dopo"

--- src/babel/italiano/lexicon.cljc
+++ src/babel/italiano/lexicon.cljc
@@ -43,8 +43,10 @@
         non-comparative-adjective it-pos/non-comparative-adjective

         preposition (let [shared (atom :top)]
-                      {:synsem {:sem {:obj shared}
+                      {:synsem {:cat :prep
+                                :sem {:obj shared}
                                 :subcat {:1 {:sem shared}}}})
+
         pronoun-acc it-pos/pronoun-acc
         pronoun-reflexive it-pos/pronoun-reflexive
         reflexive (let [subject-semantics (atom {:animate true})
@@ -60,7 +62,6 @@
                                            :pronoun true
                                            :reflexive true
                                            :sem subject-semantics}}}})
-
         reflexive-obj-is-subcat3
         (let [subject-semantics (atom :top)]
           (unify reflexive
@@ -898,14 +899,9 @@
                    :pred :donna
                    :child false}}}
    "dopo"
-   (let [time (atom {:time true})]
-     {:synsem {:cat :prep
-               :sem {:pred :after
-                     :obj time}
-               :subcat {:1 {:cat :noun
-                            :subcat '()
-                            :sem time}
-                        :2 '()}}})
+     {:unify [preposition]
+      :synsem {:sem {:pred :after
+                     :obj {:time true}}}}
    "dopodomani"
      {:unify [sentential-adverb]
       :synsem {:cat :sent-modifier
@@ -947,7 +943,6 @@
    "esprimere" {:italiano {:passato "espresso"}
                 :synsem {:cat :verb
                          :sem {:pred :express}}}
-
    "essere"
    (let [essere-common
          (let [infl (atom :top)


remove "dell" (should be parsed/generated via morphology)

--- src/babel/italiano/lexicon.cljc
+++ src/babel/italiano/lexicon.cljc
@@ -806,11 +806,6 @@
                 :def :partitivo
                 :agr {:number :plur
                       :gender :masc}}}
-      "dell"
-      {:synsem {:cat :det
-                :def :partitivo
-                :agr {:number :sing
-                      :gender :top}}}
       "della"
       {:synsem {:cat :det
                 :def :partitivo
@@ -2092,7 +2087,6 @@
                                    :1plur "vogliamo"
                                    :2plur "volete"
                                    :3plur "vogliono"}}}
-
    ":top" {:synsem :top
            :top true}
    ":top-noun" {:synsem {:cat :noun}


Use node->label to get label during graphviz render

--- test/com/wsscode/pathom/connect/planner_test.cljc
+++ test/com/wsscode/pathom/connect/planner_test.cljc
@@ -58,14 +58,9 @@
                                                      :color (if (= node-id root) "blue" "#F3F3F3")
                                                      :label (str
                                                               (str node-id " | ")
-                                                              #_
-                                                              (if attrs
-                                                                (str (str/join "," attrs) " | "))
-                                                              (or
-                                                                (::pcp/source-sym node)
-                                                                (::pc/sym node)
-                                                                (if (::pcp/run-and node) "AND")
-                                                                (if (::pcp/run-or node) "OR")))}
+                                                              #_(if attrs
+                                                                  (str (str/join "," attrs) " | "))
+                                                              (pcp/node->label node))}
                                               (get-in env [::pc/index-resolvers (::pc/sym node) ::pc/dynamic-resolver?])
                                               (assoc
                                                 :fontcolor "white"


CLJS-887: browser repl should serve CSS

CLJS-887: browser repl should serve CSS

--- src/clj/cljs/repl/browser.clj
+++ src/clj/cljs/repl/browser.clj
@@ -111,7 +111,8 @@
       (.endsWith path ".js")
       (.endsWith path ".cljs")
       (.endsWith path ".map")
-      (.endsWith path ".html")))
+      (.endsWith path ".html")
+      (.endsWith path ".css")))
   send-static)

 (defmulti handle-post (fn [m _ _ ] (:type m)))


implement Executive Search Firm

implement Executive Search Firm

--- src/clj/game/cards-assets.clj
+++ src/clj/game/cards-assets.clj
@@ -251,7 +251,6 @@
    "Eve Campaign"
    (campaign 16 2)

-
    "Executive Boot Camp"
    {:derezzed-events {:runner-turn-ends corp-rez-toast}
     :flags {:corp-phase-12 (req (some #(not (rezzed? %)) (all-installed state :corp)))}
@@ -268,6 +267,19 @@
                  :cost [:credit 1]
                  :label "Search R&D for an asset"
                  :effect (effect (trash card) (move target :hand) (shuffle! :deck))}]}
+
+   "Executive Search Firm"
+   {:abilities [{:prompt "Choose an executive, sysop, or character to add to HQ"
+                 :msg (msg "add " (:title target) " to HQ and shuffle R&D")
+                 :activatemsg "searches R&D for an executive, sysop, or character"
+                 :choices (req (cancellable (filter #(or (has-subtype? % "Executive")
+                                                         (has-subtype? % "Sysop")
+                                                         (has-subtype? % "Character"))
+                                                    (:deck corp))
+                                            :sorted))
+                 :cost [:click 1]
+                 :label "Search R&D for an executive, sysop, or character"
+                 :effect (effect (move target :hand) (shuffle! :deck))}]}

    "Exposé"
    {:advanceable :always


add build id to debug email

add build id to debug email

--- src/clj/runbld/util/debug.clj
+++ src/clj/runbld/util/debug.clj
@@ -64,7 +64,7 @@

 (defn send-log [{{:keys [to]} :debug
                  {:keys [from] :as email-cfg} :email
-                 :keys [job-name]
+                 :keys [id job-name]
                  :as opts}]
   (when to
     ((:logger opts) "Sending debug log to" (email/obfuscate-addr to))
@@ -72,7 +72,7 @@
      email-cfg
      {:from from
       :to to
-      :subject (str "runbld debug log for " job-name)
+      :subject (str "runbld debug log for " job-name " - " id)
       :body [{:type "text/plain; charset=utf-8"
               :content (string/join "\n" @debug-log)}]})))


fix updating deleted evidence

fix updating deleted evidence

--- src/clj/salava/factory/db.clj
+++ src/clj/salava/factory/db.clj
@@ -69,9 +69,8 @@
   ""
   [ctx user-id badge-id]
   (let [badge-updates (select-badge-updates {:user_id user-id :id badge-id} (u/get-db-1 ctx))
-        evidence (select-user-badge-evidence {:id badge-id} (u/get-db ctx))
-        updates (if-not (empty? evidence) (assoc badge-updates :evidence evidence) badge-updates)]
-    {"user" {user-id {"badge" {badge-id updates}}}}))
+        evidence (select-user-badge-evidence {:id badge-id} (u/get-db ctx))]
+    {"user" {user-id {"badge" {badge-id (assoc badge-updates :evidence evidence)}}}}))

 (defn- issued-by-factory [ctx badge]


Use the new defcomponent-2 macro

Use the new defcomponent-2 macro

--- src/cljs/comic_reader/ui.cljs
+++ src/cljs/comic_reader/ui.cljs
@@ -10,8 +10,16 @@
 (defn site-element [comic]
   ^{:key (:id comic)}
   [:li [:a (:name comic)]])
+(defn get-sites-list [db]
+  )

-(defn site-list [comic-list]
+(re-frame/register-sub
+ :sites-list
+ (fn [app-db v]
+   (reaction (get-sites-list @app-db))))
+
+(defcomponent-2 site-list
+  [comic-list]
   (with-optional-tail
     [:div [:h1 "Comics List"]]
     (cond


Remove default user-face I was using for testing

--- src/cljs/koeeoadi/config.cljs
+++ src/cljs/koeeoadi/config.cljs
@@ -38,16 +38,6 @@
    {:face/id 11 :face/name "type"                       :face/color-fg {:color/id 2  :color/hex  "#268bd2"} :face/underline nil :face/bold nil :face/italic nil}
    {:face/id 12 :face/name "variable-name"              :face/color-fg {:color/id 0  :color/hex  "#6c71c4"} :face/underline nil :face/bold nil :face/italic nil}])

-(def user-faces-list
-  [{:face/id 0
-    :face/name "user-face-1"
-    :face/color-fg nil
-    :face/color-bg nil
-    :face/underline true
-    :face/bold true
-    :face/italic true
-    :face/editor :emacs}])
-
 (def initial-code "c")

 ;; TODO Initialize this using theme/data
@@ -58,6 +48,6 @@
    :theme/map         themes
    :code/map          code
    :faces/list        faces-list
-   :user-faces/list   user-faces-list
+   :user-faces/list   []
    :colors/list       colors-list
    :code-chunks/list  (get-in code [initial-code :code-chunks/list])})


- Introduced as-system

- Introduced as-system

--- src/clojure/alfresco/auth.clj
+++ src/clojure/alfresco/auth.clj
@@ -19,10 +19,16 @@
             AuthenticationUtil$RunAsWork]))

 ; TODO memoize the result
+;;
 (defn admin
   "Returns the current Administrator user name."
   []
   (AuthenticationUtil/getAdminUserName))
+
+(defn admin
+  "Returns the current Administrator user name."
+  []
+  (AuthenticationUtil/getSystemUserName))

 (defmacro run-as
   "Runs the provided form while impersonating the given user.
@@ -32,8 +38,8 @@
   scope of the authorisation context (which is probably not what's intended)."
   [user & f]
   `(let [work# (reify AuthenticationUtil$RunAsWork
-                     (~'doWork [~'this]
-                               ~@f))]
+                 (~'doWork [~'this]
+                   ~@f))]
      (AuthenticationUtil/runAs work# ~user)))

 (defmacro run-as-fn
@@ -52,6 +58,15 @@
   [& f]
   `(run-as (admin) ~@f))

+(defmacro as-system
+  "Runs the provided form as system.
+  WARNING: the form you pass to this macro should not return a lazy
+  sequence that include calls to repository functions, as when/if they are
+  eventually evaluated, the calls to those functions will occur outside the
+  scope of the authorisation context (which is probably not what's intended)."
+  [& f]
+  `(run-as (system) ~@f))
+
 (defn whoami
   "Returns the currently valid user name"
   []


Working bookkeeper stateful check code

Working bookkeeper stateful check code

Currently missing: compaction events.

--- test/onyx/state/log/bookkeeper_stateful_check.clj
+++ test/onyx/state/log/bookkeeper_stateful_check.clj
@@ -6,13 +6,16 @@
             [onyx.state.state-extensions :as state-ext]
             [onyx.messaging.dummy-messenger :refer [dummy-messenger]]
             [onyx.peer.task-lifecycle :as task-lifecycle :refer [->WindowState]]
+            [clojure.core.async :refer [chan close!]]
             [clojure.test.check :refer [quick-check] :as tc]
             [clojure.test.check.generators :as gen]
             [clojure.test.check.properties :as prop]
             [clojure.test.check.clojure-test :refer [defspec]]
             [onyx.test-helper :refer [load-config]]
             [clojure.test :refer :all]
+            [onyx.monitoring.no-op-monitoring :refer [no-op-monitoring-agent]]
             [onyx.state.log.bookkeeper :as log-bk]
+            [onyx.log.commands.common]
             [com.gfredericks.test.chuck :refer [times]]
             [com.gfredericks.test.chuck.clojure-test :refer [checking]]))

@@ -35,75 +38,92 @@
                         :onyx.bookkeeper/write-batch-size 1
                         :onyx.bookkeeper/write-batch-timeout 10000000))

-(def initial-bookkeeper-state {:logs [[]] :ledger-ids [0]})
-
-(def bookkeeper-state (atom initial-bookkeeper-state))
 (def bookkeeper-peer-state (atom nil))

 (defn add-to-bookkeeper [arg]
-  (swap! bookkeeper-state (fn [bs-state]
-                            (update-in bs-state [:logs (last (:ledger-ids bs-state))] conj arg))))
+  (let [event (:event @bookkeeper-peer-state)
+        state-log (:onyx.core/state-log event)
+        ack-promise (promise)]
+    (state-ext/store-log-entry state-log event (fn [] (deliver ack-promise :done)) arg)
+    ;; Wait until it's acked
+    @ack-promise))
+
+(defn init-state [& args]
+  [])
+
+(defn new-pipeline []
+  (let [pipeline {:onyx.core/task-id :task-id
+                  :onyx.core/monitoring (no-op-monitoring-agent)
+                  :onyx.core/kill-ch (chan)
+                  :onyx.core/task-kill-ch (chan)
+                  :onyx.core/peer-opts peer-config}]
+    (-> pipeline
+        (assoc :onyx.core/window-state (->WindowState (state-ext/initialize-filter :set pipeline) (init-state)))
+        (assoc :onyx.core/state-log (state-ext/initialize-log :bookkeeper pipeline)))))
+
+(def previous-peer-state (atom nil))
+
+(defn new-log-after-crash []
+  (let [pipeline (new-pipeline)]
+    (reset! previous-peer-state @bookkeeper-peer-state)
+    (swap! bookkeeper-peer-state assoc :event pipeline)))
+
+(defn close-peer [event]
+  (close! (:onyx.core/task-kill-ch event))
+  (state-ext/close-log (:onyx.core/state-log event) event))
+
+(def crash-and-playback-spec
+  {:model/args (fn [state]
+                 [])
+   :next-state (fn [state [arg] result]
+                 state)
+   :real/postcondition (fn [prev-state next-state args result]
+                         (try
+                           (let [playback-state (state-ext/playback-log-entries (:onyx.core/state-log (:event @bookkeeper-peer-state))
+                                                                                (:event @bookkeeper-peer-state)
+                                                                                (init-state)
+                                                                                (fn [state entry]
+                                                                                (conj state entry)))]
+                             (= next-state playback-state))
+                              (finally
+                                ;; cleanup *after* we playback and test, as this is realistic in cases where
+                                ;; a log may not have been cleaned up
+                                (close-peer (:event @previous-peer-state)))))
+   :real/command #'new-log-after-crash})
+

 (def add-to-log-espec
   {:model/args (fn [state]
                  [gen/int])
    :next-state (fn [state [arg] result]
                  (conj state arg))
-   :real/postcondition (fn [prev-state next-state [arg] result]
-                         (= (reduce into [] (:logs @bookkeeper-state)) next-state))
    :real/command #'add-to-bookkeeper})

-(defn switch-to-next-ledger []
-  (swap! bookkeeper-state (fn [bs-state]
-                            (-> bs-state
-                                (update :logs conj [])
-                                (update :ledger-ids conj (inc (apply max (:ledger-ids bs-state))))))))
+(defn new-peer-log []
+  (reset! bookkeeper-peer-state {:ledger-ids []
+                                 :event-log []})
+  ;; must setup before new-pipeline so that ledger id is recorded
+  (swap! bookkeeper-peer-state assoc :event (new-pipeline)))

-(def peer-crash-new-log-spec
-  {:model/args (fn [state]
-                 [])
-   :next-state (fn [state [arg] result]
-                 state)
-   ;:real/postcondition (fn [prev-state next-state [arg] result]
-   ;                      (= (reduce into [] (:logs @bookkeeper-state)) next-state))
-   :real/command #'switch-to-next-ledger})
-
-(defn new-peer-log []
-  (let [bk-peer-val {:ledger-ids []
-                     :event-log []
-                     :event (let [pipeline {:onyx.core/peer-opts peer-config}]
-                              (-> pipeline
-                                  ;(assoc :onyx.core/window-state (->WindowState (state-ext/initialize-filter :set pipeline) {}))
-                                  (assoc :onyx.core/state-log (state-ext/initialize-log :bookkeeper pipeline))))}]
-    (reset! bookkeeper-state initial-bookkeeper-state)
-    (reset! bookkeeper-peer-state bk-peer-val)))
-
-(defn close-peer-log [state]
-  (let [real-state-event (:event @bookkeeper-peer-state)]
-    (info " Closing log")
-    (state-ext/close-log (:onyx.core/state-log real-state-event) real-state-event)))
+(defn close-peer-cleanup [state]
+  (close-peer (:event @bookkeeper-peer-state)))

 (def log-spec
   {:commands {:add-to-log add-to-log-espec
-              :peer-crash-new-log peer-crash-new-log-spec}
+              :crash-and-playback crash-and-playback-spec}
    :real/setup #'new-peer-log
-   :real/cleanup #'close-peer-log
-   :real/postcondition (fn [final-state]
-                         (= (reduce into [] (:logs @bookkeeper-state)) final-state))
-   :initial-state (fn [setup] [])
-   ;:model/generate-command (fn [state]
-   ;                          (gen/elements [(gen/return :add-to-log)
-   ;                                         (gen/return :peer-crash-new-log)]))
-   })
-
+   :real/cleanup #'close-peer-cleanup
+   :real/postcondition (fn [state] true)
+   :initial-state #'init-state})

 (deftest log-test-correct
   (with-redefs [log-bk/assign-bookkeeper-log-id-spin (fn [event new-ledger-id]
-                                                       (swap! bookkeeper-peer-state
-                                                              (fn [ps]
-                                                                (update ps :ledger-ids conj new-ledger-id))))]
+                                                       (swap! bookkeeper-peer-state update :ledger-ids conj new-ledger-id))
+                log-bk/event->ledger-ids (fn [event]
+                                           (:ledger-ids @bookkeeper-peer-state))
+                onyx.log.commands.common/peer-slot-id (fn [event] 0)]
     (let [env (onyx.api/start-env env-config)]
       (try
-        (is (specification-correct? log-spec))
+        (is (specification-correct? log-spec {:num-tests 10}))
         (finally
           (onyx.api/shutdown-env env))))))


fix indentation

fix indentation

--- src/braid/server/db/message.clj
+++ src/braid/server/db/message.clj
@@ -6,7 +6,7 @@

 (defn create-message!
   [conn {:keys [thread-id group-id id content user-id created-at
-           mentioned-user-ids mentioned-tag-ids]}]
+                mentioned-user-ids mentioned-tag-ids]}]

   ; upsert-thread
   (when-not (d/entity (d/db conn) [:thread/id thread-id])


refactor variable names in process-shot

refactor variable names in process-shot

--- src/clj/battlebots/game/bot/decisions/shoot.clj
+++ src/clj/battlebots/game/bot/decisions/shoot.clj
@@ -75,15 +75,15 @@
     (if (shot-should-progress? should-progress? cell-at-point energy)
       (let [cell-energy (:energy cell-at-point)
             remaining-energy (Math/max 0 (- energy (or cell-energy 0)))
-            energy-delta (- energy remaining-energy)
-            updated-cell (resolve-shot-cell cell-at-point energy-delta shot-uuid)
+            damage (- energy remaining-energy)
+            updated-cell (resolve-shot-cell cell-at-point damage shot-uuid)
             updated-dirty-arena (au/update-cell dirty-arena point updated-cell)
             updated-players (:players (reduce (fn [players update-fn]
                                                 (update-fn players))
                                               {:players players
                                                :shooter-id shooter-id
                                                :cell cell-at-point
-                                               :damage energy-delta}
+                                               :damage damage}
                                               [reward-shooter
                                                update-victim-energy]))]
         {:game-state (merge game-state {:dirty-arena updated-dirty-arena


Fix per https://github.com/MastodonC/kixi.hecuba/pull/643#commitcomment-13184215

--- src/cljs/kixi/hecuba/tabs/hierarchy/xyplot.cljs
+++ src/cljs/kixi/hecuba/tabs/hierarchy/xyplot.cljs
@@ -242,7 +242,7 @@
         filtered-y-data (filter (fn [m] (not (some #(= % (timestamp-key m)) missing-timestamps))) y-data)
         x-raw-data (->> filtered-x-data (sort-by :timestamp) (mapv :value) (map js/parseFloat))
         y-raw-data (->> filtered-y-data (sort-by :timestamp) (mapv :value) (map js/parseFloat))
-        data {:values (mapv (fn [a b] (vector a b)) x-raw-data y-raw-data)}
+        data {:values (mapv (fn [x y] (vector x y)) x-raw-data y-raw-data)}
         reg-line (calc-linear-regression-line (:values data))
         data (assoc data :line reg-line)
         x-range [(->> data :values (map first) (apply min))


Improve config related names

Improve config related names

--- src/clj/comic_reader/config.clj
+++ src/clj/comic_reader/config.clj
@@ -2,11 +2,11 @@
   (:require [com.stuartsierra.component :as component]
             [environ.core :refer [env]]))

-(defprotocol PConfig
+(defprotocol Config
   (database-uri [cfg])
   (norms-dir [cfg]))

-(defrecord Config [database-uri norms-dir]
+(defrecord EnvConfig [database-uri norms-dir]
   component/Lifecycle

   (start [component]
@@ -18,16 +18,16 @@
   (stop [component]
     component)

-  PConfig
+  Config
   (database-uri [cfg] (:database-uri cfg))

   (norms-dir [cfg] (:norms-dir cfg)))

 (extend-type clojure.lang.APersistentMap
-  PConfig
+  Config
   (database-uri [cfg] (:database-uri cfg))

   (norms-dir [cfg] (:norms-dir cfg)))

 (defn new-config []
-  (map->Config {}))
+  (map->EnvConfig {}))


Actually scrape the chapter list

Actually scrape the chapter list

--- src/clj/comic_reader/server.clj
+++ src/clj/comic_reader/server.clj
@@ -31,9 +31,12 @@

 (defn get-comic-imgs [{{:keys [site comic chapter page]} :params
                        :as request}]
-  (if-let [comic-urls nil]
-    (edn-response)
-    (edn-response (gen-error-data request) 404)))
+  (println (:uri request))
+  (let [chapter-list (scrape/fetch-list
+                      (sites/chapter-list-data site comic))]
+   (if-let [comic-urls nil]
+     (edn-response)
+     (edn-response (gen-error-data request) 404))))

 (c/defroutes routes
   (c/GET "/" [] (hp/html5


Add in usage of normalize.css for goodness

--- src/clj/comic_reader/server.clj
+++ src/clj/comic_reader/server.clj
@@ -67,7 +67,8 @@
 (c/defroutes routes
   (c/GET "/" [] (hp/html5
                  [:head
-                  (hp/include-css "css/foundation.css")
+                  (hp/include-css "css/normalize.css"
+                                  "css/foundation.css")
                   [:style "img {width: 100%;} ul {list-style-type:none;}"]
                   (hp/include-js "js/vendor/modernizr.js")]
                  [:body


fix Pawn bug preventing successful runs when hosted on non-ICE

--- src/clj/game/cards-programs.clj
+++ src/clj/game/cards-programs.clj
@@ -424,22 +424,19 @@
                  :msg (msg "host it on " (if (:rezzed target) (:title target) "a piece of ICE"))
                  :effect (effect (host target card))}]
     :events {:successful-run
-             {:effect (req (let [i (ice-index state (:host card))
+             {:req (req (= (:type (:host card)) "ICE"))
+              :effect (req (let [i (ice-index state (:host card))
                                  nextice (when (> i 0) (nth (get-in @state
-                                                              (vec (concat [:corp] (:zone (:host card))))) (dec i)))]
+                                                            (vec (concat [:corp] (:zone (:host card))))) (dec i)))]
                              (if (pos? i)
                                (host state side nextice card)
                                (do (resolve-ability state side
-                                     {:prompt "Install a Caïssa program from Grip or Heap?" :choices ["Grip" "Heap"]
-                                      :msg (msg "install a Caïssa program from " target)
-                                      :effect (req (let [p target]
-                                                     (resolve-ability state side
-                                                       {:prompt "Choose a Caïssa program to install"
-                                                        :choices (req (filter #(has? % :subtype "Caïssa")
-                                                                        ((if (= p "Heap") :discard :hand) runner)))
-                                                        :effect (effect (runner-install target {:no-cost true}))} card nil)))}
-                                    card nil)
-                                   (trash state side card)))))}}}
+                                     {:prompt "Choose a Caïssa program to install from your Grip or Heap"
+                                      :show-discard true
+                                      :choices {:req #(and (has? % :subtype "Caïssa")
+                                                           (#{[:hand] [:discard]} (:zone %)))}
+                                      :effect (effect (runner-install target {:no-cost true}))} card nil)
+                                    (trash state side card)))))}}}

    "Pheromones"
    {:recurring (effect (set-prop card :rec-counter (:counter card)))


Fix cursor drawing

Fix cursor drawing

--- src/clj/robinson/glterminal.clj
+++ src/clj/robinson/glterminal.clj
@@ -566,7 +566,7 @@
                 [col c]    (map-indexed vector line)]
           ;;(log/info "row" row "col" col "c" c)
           (let [chr        (or (get c :fx-character) (get c :character))
-                highlight  (= @cursor-xy [col row])
+                highlight  (= @cursor-xy [col (- rows row 1)])
                 [fg-r fg-g fg-b] (if highlight
                                    (or (get c :fx-bg-color)  (get c :bg-color))
                                    (or (get c :fx-fg-color)  (get c :fg-color)))


Split on windows file separator in `lumo.utils/mkdirs` (#198)

--- src/cljs/bundled/lumo/util.cljs
+++ src/cljs/bundled/lumo/util.cljs
@@ -71,7 +71,7 @@
                   (not (js/$$LUMO_GLOBALS.fs.existsSync new-path))
                   js/$$LUMO_GLOBALS.fs.mkdirSync)
                 new-path))
-      "/" (rest (string/split target-dir #"/")))))
+      "/" (rest (string/split target-dir #"[/\\]")))))

 (defn bundled-resource? [x]
   (and (goog/isObject x) (= (.-type x) "bundled")))


Don't link to the manga websites

Don't link to the manga websites

--- src/cljs/comic_reader/main.cljs
+++ src/cljs/comic_reader/main.cljs
@@ -38,7 +38,7 @@
                (apply dom/ul nil
                       (map (fn [{:keys [name url]}]
                              (dom/li nil
-                                     (dom/a #js {:href url} name)))
+                                     (dom/a nil name)))
                            (:sites data)))))))
  app-state
  {:target (. js/document (getElementById "main-area"))})


Add a ticker component

Add a ticker component

--- src/cljs/hacker_agent/core.cljs
+++ src/cljs/hacker_agent/core.cljs
@@ -31,6 +31,25 @@
     [:li [:a {:href "#"} "Threads"]]
     [:li [:a {:href "#"} "Comments"]]
     [:li [:a {:href "#"} "Show"]]]])
+
+(def ticker
+  (r/create-class
+   {:component-will-receive-props (fn [this new-props]
+                                    (let [old-val (:value (r/props this))
+                                          new-val (:value (get new-props 1))]
+                                      (when-not (= old-val new-val)
+                                        (r/set-state this {:updated? true}))))
+    :component-did-update (fn [this old-props old-children]
+                            (when (:updated? (r/state this))
+                              (r/set-state this {:updated? false})))
+    :render (fn [this]
+              [:div.nav
+               {:style (if (:updated? (r/state this))
+                         {}
+                         {:overflow :hidden
+                          :transition "all 3s ease-in"
+                          :opacity 0})}
+               [:p (:value (r/props this))]])}))

 (declare comment-list)
 (defn comment [data]


Keywords for optional node id params in game.clj.

The various game-editing functions (add-san-move, add-uci-move,
add-map-move, add-san-move-sequence, add-comment, etc.) used to
take the node ID as an optional parameter. In preparation for adding
additional optional parameters to some of these functions, switch to
using keyword parameters.

--- src/clojure/clj_chess/game.cljc
+++ src/clojure/clj_chess/game.cljc
@@ -162,7 +162,7 @@
   "Adds a move in short algebraic notation to a game at a given node
   id. The move is added as the last child. If no node id is supplied,
   the current node of the game is used."
-  [game san-move & [node-id]]
+  [game san-move & {:keys [node-id]}]
   (add-move game board/move-from-san san-move
             (or node-id (-> game :current-node :node-id))))

@@ -171,7 +171,7 @@
   "Adds a move in UCI notation to a game at a given node id. The move is
   added as the last child. If no node id is supplied, the current node of the
   game is used."
-  [game uci-move & [node-id]]
+  [game uci-move & {:keys [node-id]}]
   (add-move game board/move-from-uci uci-move
             (or node-id (-> game :current-node :node-id))))

@@ -180,7 +180,7 @@
   "Adds a map move (see documentation for clj-chess.board/board-to-map) to a
   game at a given node id. The move is added as the last child. If no node id
   is supplied, the current node of the game is used."
-  [game map-move & [node-id]]
+  [game map-move & {:keys [node-id]}]
   (add-move game board/move-from-map map-move
             (or node-id (-> game :current-node :node-id))))

@@ -200,7 +200,7 @@
   "Like add-san-move, but adds a sequence of moves rather than a single move.
   This is faster than calling add-san-move multiple times, because we don't
   have to unzip and zip the tree for each added move."
-  [game san-moves & [node-id]]
+  [game san-moves & {:keys [node-id]}]
   (add-move-sequence game board/move-from-san san-moves
                      (or node-id (-> game :current-node :node-id))))

@@ -209,7 +209,7 @@
   "Like add-uci-move, but adds a sequence of moves rather than a single move.
   This is faster than calling add-uci-move multiple times, because we don't
   have to unzip and zip the tree for each added move."
-  [game uci-moves & [node-id]]
+  [game uci-moves & {:keys [node-id]}]
   (add-move-sequence game board/move-from-uci uci-moves
                      (or node-id (-> game :current-node :node-id))))

@@ -217,7 +217,7 @@
 (defn add-key-value-pair
   "Adds a key value pair to the map at the given node id of the game. If no
   node id is supplied, the key value pair is added at the current node."
-  [game key value & [node-id]]
+  [game key value & {:keys [node-id]}]
   (let [z (-> (game-zip game (or node-id (-> game :current-node :node-id)))
               (zip-add-key-value-pair key value))
         g (assoc game :root-node (zip/root z))]
@@ -229,7 +229,7 @@
   Uses current node if no node id is supplied. Adding a comment at the root
   of the game has no effect; if you want to add a comment before the first
   move of the game, use add-pre-comment instead."
-  [game cmt & [node-id]]
+  [game cmt & {:keys [node-id]}]
   (add-key-value-pair game :comment cmt node-id))

@@ -239,7 +239,7 @@
   displayed *before* the move rather than after. It is probably only useful
   for the first move of the game or the first move of a recursive annotation
   variation."
-  [game cmt & [node-id]]
+  [game cmt & {:keys [node-id]}]
   (add-key-value-pair game :pre-comment cmt node-id))

@@ -247,7 +247,7 @@
   "Removes a node (by default, the current node) from the game, and returns
   a modified game with the current node set to the parent of the deleted
   node."
-  [game & [node-id]]
+  [game & {:keys [node-id]}]
   (let [node-id (or node-id (-> game :current-node :node-id))
         z (game-zip game node-id)
         zr (zip/remove z)]


Resolved merge conflict.

Resolved merge conflict.

--- src/cmr/umm/test/generators.clj
+++ src/cmr/umm/test/generators.clj
@@ -105,8 +105,8 @@
 (def collections
   (gen/fmap (fn [[entry-title product temporal-coverage]]
               (let [entry-id (str (:short-name product) "_" (:version-id product))]
-                (c/->UmmCollection entry-id entry-title product)))
-            (gen/tuple entry-titles products)))
+                (c/->UmmCollection entry-id entry-title product temporal-coverage)))
+            (gen/tuple entry-titles products temporal-coverages)))

 ;;; granule related
 (def granule-urs
@@ -120,6 +120,7 @@

 (def coll-refs
   (gen/one-of [coll-refs1 coll-refs2]))
+
 (def granules
   (gen/fmap (fn [[granule-ur coll-ref]]
               (g/->UmmGranule granule-ur coll-ref))


debug

debug

--- src/syncserver/core.clj
+++ src/syncserver/core.clj
@@ -20,7 +20,8 @@
   (swap! current-state
     (fn [cs]
       (let [nk (inc (:current cs))]
-          (.put cache! nk state)
+      (.put cache! nk state)
+      (println "just stored" (.getIfPresent cache! nk))
       (assoc cs :state state :current nk)))))

 (defn arg-count [f]


Controller example improvements.

Controller example improvements.

* Removed unused code.
* Added T/L keys for takeoff/land.
* Added C/V keys to switch between forward & down camera.

--- examples/controller.clj
+++ examples/controller.clj
@@ -1,27 +1,17 @@
 (ns controller
   (:require [clojure.java.io :as io]
+            [clojure.tools.logging :as log]
             [com.lemondronor.turboshrimp :as ar-drone]
             [com.lemondronor.turboshrimp.pave :as pave]
             [com.lemondronor.turboshrimp.xuggler :as video]
             [com.lemonodor.gflags :as gflags]
             [seesaw.core :as seesaw])
-  (:import [java.awt.event InputEvent KeyEvent]))
+  (:import [java.awt.event InputEvent KeyEvent]
+           [java.awt Graphics]
+           [java.awt.image BufferedImage]
+           [java.net Socket]
+           [javax.swing JPanel]))

-
-(defn data-display [text id]
-  (seesaw/grid-panel
-   :columns 2
-   :items [(seesaw/make-widget [:fill-h 10])
-           (seesaw/label :text text)
-           (seesaw/label :id id :text "0")]))
-
-
-(defn glue-button [id text]
-  (seesaw/horizontal-panel
-   :items
-   [(seesaw/make-widget :fill-h)
-    (seesaw/button :id id :text text)
-    (seesaw/make-widget :fill-h)]))

 (defn make-ui []
@@ -35,10 +25,15 @@
     :size [1280 :by 720])))

-(def default-speed 0.5)
-
+;; Keys are WASD/QZ, with Shift to "strafe":
+;; W / S  -  Move forward / Move backward
+;; A / D  -  Yaw left / Yaw right
+;; Q / Z  -  Climb / Descend
+;; Shift-A / Shift D  - Move left / Move right.

 (def key-actions
+  ;; Checked in order as they appear here, so make sure to put keys
+  ;; with mods first.
   [[{:code KeyEvent/VK_A :mod InputEvent/SHIFT_MASK} ar-drone/left]
    [{:code KeyEvent/VK_D :mod InputEvent/SHIFT_MASK} ar-drone/right]
    [{:code KeyEvent/VK_W} ar-drone/front]
@@ -46,7 +41,13 @@
    [{:code KeyEvent/VK_A} ar-drone/counter-clockwise]
    [{:code KeyEvent/VK_D} ar-drone/clockwise]
    [{:code KeyEvent/VK_Q} ar-drone/up]
-   [{:code KeyEvent/VK_Z} ar-drone/down]])
+   [{:code KeyEvent/VK_Z} ar-drone/down]
+   [{:code KeyEvent/VK_T} ar-drone/takeoff :continuous? false]
+   [{:code KeyEvent/VK_L} ar-drone/land :continuous? false]
+   [{:code KeyEvent/VK_C} #(ar-drone/command % :switch-camera :forward)
+    :continuous? false]
+   [{:code KeyEvent/VK_V} #(ar-drone/command % :switch-camera :down)
+    :continuous? false]])

 (defn key-descriptor-matches? [descriptor ^KeyEvent evt]
@@ -58,50 +59,80 @@

 (defn find-key-action [evt actions]
   (if-let [e (some #(if (key-descriptor-matches? (first %) evt) %) actions)]
-    e
+    (rest e)
     nil))

-(defn make-key-controller [ui drone]
-  (seesaw/listen
-   ui
-   :key (fn [^KeyEvent e]
-          (let [id (.getID e)]
-            (cond
-              (= id KeyEvent/KEY_PRESSED)
-              (if-let [action (find-key-action e key-actions)]
-                (println action))
-              (= id KeyEvent/KEY_RELEASED)
-              (if-let [action (find-key-action e key-actions)]
-                (println "STOPPING" action)))))))
+(def default-speed 0.5)

-(defn make-controller [ui drone]
-  (make-key-controller ui drone))
+(defn make-key-controller [drone]
+  (fn [^KeyEvent e]
+    (let [id (.getID e)]
+      (when-let [action (find-key-action e key-actions)]
+        (let [[action-fn & {:keys [continuous?]
+                            :or {continuous? true}}] action]
+          (let [action-args (cons
+                             drone
+                             (cond
+                               (and (= id KeyEvent/KEY_PRESSED) continuous?)
+                               (list default-speed)
+                               (and (= id KeyEvent/KEY_RELEASED) continuous?)
+                               (list 0.0)
+                               :else
+                               '()))]
+            (when (or (= id KeyEvent/KEY_PRESSED)
+                      (and (= id KeyEvent/KEY_RELEASED) continuous?))
+              (println "Running" action-fn action-args)
+              (apply action-fn action-args))))))))
+
+
+(def drone-video-port 5555)
+
+
+(defn connect-video-controller [ui drone]
+  (let [is (.getInputStream (Socket. (:hostname drone) drone-video-port))
+        fq (pave/make-frame-queue)
+        ^JPanel view (seesaw/select ui [:#video])
+        decoder (video/decoder)]
+    (doto
+        (Thread.
+         (fn []
+           (loop [frame (pave/read-frame is)]
+             (if frame
+               (pave/queue-frame fq frame)
+               (log/info "No frame?"))
+             (recur (pave/read-frame is)))))
+      (.setDaemon true)
+      (.start))
+    (doto
+        (Thread.
+         (fn []
+           (loop [frame (pave/pull-frame fq 1000)]
+             (if frame
+               (let [^BufferedImage image (decoder frame)]
+                 (seesaw/invoke-now
+                  (.drawImage
+                   (.getGraphics view)
+                   image
+                   0 0
+                   (.getWidth view) (.getHeight view)
+                   view)))
+               ;;(log/info "Delayed frame" frame fq)
+               )
+             (recur (pave/pull-frame fq 1000)))))
+      (.setDaemon true)
+      (.start))))

 (defn -main [& args]
   (let [ui (make-ui)
-        fq (pave/make-frame-queue)
-        is (io/input-stream (first args))
-        decoder (video/decoder)
         drone (ar-drone/make-drone)]
     (-> ui seesaw/pack! seesaw/show!)
-    (let [view (seesaw/select ui [:#video])]
-      (make-controller ui drone)
-      (doto
-          (Thread.
-           (fn []
-             (loop []
-               (let [image (-> fq
-                               pave/pull-frame
-                               decoder)]
-                 (seesaw/invoke-now
-                  (.drawImage (.getGraphics view) image 0 0 1280 720 view)))
-               (recur))))
-        (.start))
-      (loop [frame (pave/read-frame is)]
-        (when frame
-          (pave/queue-frame fq frame)
-          (Thread/sleep 30)
-          (recur (pave/read-frame is)))))))
+    (seesaw/listen ui :key (make-key-controller drone))
+    (connect-video-controller ui drone)
+    (ar-drone/connect! drone)
+    ;;(doseq [i (range 10)]
+    ;;  (ar-drone/command drone :flat-trim)
+    ; ; (Thread/sleep 500))
+    ))


Use new Mockito verify functions in kstreams component test

--- clstreams/test/clstreams/kstreams/component_test.clj
+++ clstreams/test/clstreams/kstreams/component_test.clj
@@ -29,7 +29,7 @@

        [{:keys [producer]}]
        ((is (nil? producer))
-        (-> producer-mock Mockito/verify .close))))))
+        (mkto/verify-> producer-mock .close))))))

 (deftest test-idempotent-producer-component
   (let [producer-mock (mkto/mock KafkaProducer)
@@ -69,7 +69,7 @@

        [{:keys [kstreams]}]
        ((is (nil? kstreams))
-        (-> kstreams-mock Mockito/verify .close))))))
+        (mkto/verify-> kstreams-mock .close))))))

 (deftest test-idempotent-topology-component
   (let [builder-mock (mkto/mock KStreamBuilder)


Update containium.standalone to use cassandra 2.0

--- src/containium/standalone.clj
+++ src/containium/standalone.clj
@@ -7,7 +7,7 @@
             [containium.systems.config :refer (map-config)]
             [containium.systems.repl :as repl]
             [containium.systems.elasticsearch :as elastic]
-            [containium.systems.cassandra.embedded12 :as cassandra]
+            [containium.systems.cassandra.embedded :as cassandra]
             [containium.systems.ring.http-kit :refer (test-http-kit)]
             [ring.middleware.session.memory :refer (memory-store)]
             [clojure.java.io :as io]))
@@ -23,7 +23,7 @@
                          :session-store (memory-store)
                          :ring (test-http-kit (-> ring :handler))
                          :elastic elastic/embedded
-                         :cassandra cassandra/embedded12]
+                         :cassandra cassandra/embedded]
     (start systems
            {:file (io/as-file ".")
             :profiles profiles


Require the namespace only if necessary

Require the namespace only if necessary

--- src/de/kotka/gorilla/util.clj
+++ src/de/kotka/gorilla/util.clj
@@ -215,5 +215,8 @@
   "Loads and returns the namespace named by the given string or symbol."
   [namespace]
   (let [namespace (if (symbol? namespace) namespace (symbol namespace))]
-    (require namespace)
-    (the-ns namespace)))
+    (try
+      (the-ns namespace)
+      (catch Exception _
+        (require namespace)
+        (the-ns namespace)))))


fixed normalizing of matching scores in match matrix

--- src/distillery/view/match.clj
+++ src/distillery/view/match.clj
@@ -43,7 +43,7 @@
                   (map render-match-matrix-head-cell categories)))})

 (defn- render-match-matrix-row
-  [matrix category-ids {:keys [id name] :as video}]
+  [matrix max-score category-ids {:keys [id name] :as video}]
   {:tag :tr
    :content
    (vec (cons {:tag :th
@@ -56,15 +56,16 @@
                (fn [category-id]
                  (let [match (get-in matrix [category-id id])
                        score (:score match)
-                       normalized-score (/ score (:max-score video))]
+                       normalized-score (/ score max-score)
+                       video-normalized-score (/ score (:max-score video))]
                    (if match
                      {:tag :td
                       :attrs {:class "match"
                               :data-video-id id
                               :data-category-id category-id
-                              :style (str "background-color: rgba(234,30,106," normalized-score ")")}
+                              :style (str "background-color: rgba(234,30,106," video-normalized-score ")")}
                       :content [(link (str "categories/" category-id "/index.html?match=" id)
-                                 (format "%.1f%%" (* 100 score)))]}
+                                 (format "%.1f%%" (* 100 normalized-score)))]}
                      {:tag :td :content []})))
                category-ids)))})

@@ -97,5 +98,5 @@
          [(render-match-matrix-head-row categories)]}
         {:tag :tbody
          :content
-         (vec (map (partial render-match-matrix-row matrix category-ids) videos))}]}]}))
+         (vec (map (partial render-match-matrix-row matrix max-score category-ids) videos))}]}]}))


Decrease address reload timeout

Decrease address reload timeout

--- src/district0x/ui/events.cljs
+++ src/district0x/ui/events.cljs
@@ -815,5 +815,5 @@
  interceptors
  (fn [{:keys [db]}]
    {:dispatch-interval {:dispatch [:district0x/reload-my-addresses]
-                        :ms 6000
+                        :ms 4000
                         :db-path [:district0x-reload-address-interval]}}))


try to compete

try to compete

--- src/tictactoe/core.cljs
+++ src/tictactoe/core.cljs
@@ -65,10 +65,18 @@
 (defn free-spot [board line-coords]
   (first (filter #(= "B" (get-in board %)) line-coords )))

+(defn occupied-line? [line]
+  (and (< 0 (count (filter #(= "X" %) line)))
+       (< 0 (count (filter #(= "B" %) line)))))
+
+(defn first-occupied-line [board]
+  (first (filter #(occupied-line? (get-coords board %)) (all-lines-coords))))
+
 (defn computer-move [board]
   (let [move (or
               (not-empty (free-spot board  (first (threat-lines "O" "X" board))))
               (not-empty (free-spot board  (first (threat-lines "X" "O" board))))
+              (not-empty (free-spot board (first-occupied-line board)))
               (rand-nth (free-spots board)))]
     (assoc-in board move "O")))


add try/catch in case transit-str fails

add try/catch in case transit-str fails

hard to track down error otherwise

--- src/main/shadow/cljs/devtools/server/common.clj
+++ src/main/shadow/cljs/devtools/server/common.clj
@@ -56,9 +56,12 @@
       (fn [data]
         (let [out (ByteArrayOutputStream. 4096)
               w (transit/writer out :json)]
-          (transit/write w data)
-          (.toString out)
-          )))
+          (try
+            (transit/write w data)
+            (.toString out)
+            (catch Exception e
+              (log/warn-ex e ::transit-str-failed {:data data})
+              (throw e))))))

     :stop (fn [x])}


Refactor collection name

Refactor collection name

--- src/obb_api/gateways/mongodb/battle_gateway.clj
+++ src/obb_api/gateways/mongodb/battle_gateway.clj
@@ -7,6 +7,7 @@
            [com.mongodb DB WriteConcern]))

 (def mongodb-uri (or (env :mongosoup-url) "mongodb://127.0.0.1/obb"))
+(def collection-name "battles")

 (defn- db
   "Gets the current DB to handle"
@@ -26,11 +27,11 @@
   "Creates a battle"
   [args]
   (-> (db)
-      (mc/insert-and-return "battles" (build args))))
+      (mc/insert-and-return collection-name (build args))))

 (defn load-battle
   "Loads a persisted battle"
   [id]
   (when (ObjectId/isValid id)
     (-> (db)
-        (mc/find-one-as-map "battles" {:_id (ObjectId. id)}))))
+        (mc/find-one-as-map collection-name {:_id (ObjectId. id)}))))


dispatch fixes

dispatch fixes

--- src/useful/dispatch.clj
+++ src/useful/dispatch.clj
@@ -6,7 +6,8 @@
   "Returns a function that dispatches using the given dispatch function to determine the
   namespace and function to call."
   [dispatch-fn & options]
-  (let [{:keys [hierarchy wrap default] :or {wrap identity}} (into-map options)]
+  (let [{:keys [hierarchy wrap default]} (into-map options)
+        wrap (or wrap identity)]
     (fn [& args]
       (let [fname   (apply dispatch-fn args)
             default (or default
@@ -19,8 +20,10 @@
                             (ns-resolve ns method)
                             (catch java.io.FileNotFoundException e))
                        default)]
-            (let [wrap (if (not (:no-wrap (meta f))) wrap identity)]
-              (apply (wrap f) args))
+            (let [wrap (if (:no-wrap (meta f))
+                         identity
+                         wrap)]
+                  (apply (wrap f) args))
             (recur [(get hierarchy ns) method])))))))

 (defmacro defdispatch


more tests for right buffer

more tests for right buffer

--- clients/clojure/test/samsara/ring_buffer_test.clj
+++ clients/clojure/test/samsara/ring_buffer_test.clj
@@ -112,6 +112,56 @@
           (enqueue :d)
           (enqueue :e)
           (enqueue :f)
-          (dequeue [[1 :a] [2 :a]])
+          (dequeue [[1 :a] [2 :b]])
           (snapshot)) => [[4 :d] [5 :e] [6 :f]]
       )
+
+
+(fact "ring-buffer: dequeue can work with present ids and overran ones"
+
+      (-> (ring-buffer 3)
+          (enqueue :a)
+          (enqueue :b)
+          (enqueue :c)
+          (enqueue :d)
+          (enqueue :e)
+          (enqueue :f)
+          (dequeue [[1 :a] [2 :b] [3 :c] [4 :d] [5 :e] [6 :f]])
+          (snapshot)) => []
+      )
+
+
+
+(fact "ring-buffer: dequeue removes only consecutive ids"
+
+      (-> (ring-buffer 3)
+          (enqueue :a)
+          (enqueue :b)
+          (enqueue :c)
+          (enqueue :d)
+          (enqueue :e) ;; you can't remove :f if you don't remove :e
+          (enqueue :f)
+          (dequeue [[1 :a] [2 :b] [3 :c] [4 :d] [6 :f]])
+          (snapshot)) => [[5 :e] [6 :f]]
+      )
+
+
+
+(fact "ring-buffer: dequeue of one element in buffer of size 1"
+
+      (-> (ring-buffer 1)
+          (enqueue :a)
+          (enqueue :b)
+          (enqueue :c)
+          (enqueue :d)
+          (enqueue :e) ;; you can't remove :f if you don't remove :e
+          (enqueue :f)
+          (dequeue [[6 :f]])
+          (snapshot)) => []
+      )
+
+
+(fact "ring-buffer: you can't create a buffer of size 0"
+
+      (-> (ring-buffer 0)) =throws=> Exception
+      )


Problem: unnecessary imports.

Problem: unnecessary imports.

--- main/clojure/src/hydra.clj
+++ main/clojure/src/hydra.clj
@@ -1,8 +1,7 @@
 (ns hydra
   (:require [zeromq.zmq :as zmq])
   (:import [org.zproto HydraMsg]
-           [org.zeromq ZMsg]
-           [java.io StringWriter PrintWriter PrintStream OutputStreamWriter]))
+           [org.zeromq ZMsg]))

 (defprotocol HydraClient


Add note about operationId uniqueness

Add note about operationId uniqueness

--- src/io/aviso/rook/swagger.clj
+++ src/io/aviso/rook/swagger.clj
@@ -338,6 +338,8 @@
                                       :summary     summary
                                       ;; This is required inside a Operation object:
                                       :responses   (sorted-map)
+                                      ;; There are a couple of scnearious where the function name is not
+                                      ;; unique, alas. But that doesn't seem to cause problems.
                                       :operationId (:function endpoint-meta)}))
           (path-params-injector swagger-options % routing-entry params-key)
           (query-params-injector swagger-options % routing-entry params-key)


Code cleanup

Code cleanup

--- src/forces_assemble/handler.clj
+++ src/forces_assemble/handler.clj
@@ -47,8 +47,8 @@
                       :priority "high"
                       :collapse_key (:id event)
                       :data (or (:data event) {})
-                      :notification {:title (or (:title event) "")
-                                     :body (or (:body event) "")
+                      :notification {:title (or title "")
+                                     :body (or body "")
                                      :sound "default"}}]
     (if (every? cstr/blank? [title body])
       (dissoc notification :notification)


fix shortening issue body, also dont cut off non-whitespace

--- src/gh_waiting_room/service.clj
+++ src/gh_waiting_room/service.clj
@@ -36,15 +36,17 @@
   []
   (swap! db assoc :issues (my-issues (api-options))))

-(defn- ->issue [issue]
+(defn- ->issue [{body :body :as issue}]
   {:name (str
           (or (re-find #"[^/]+/[^/]+(?=/issues/\d+)" (:html_url issue))
               (throw (ex-info "Failed to parse name from an issue" {:issue issue})))
           "#"
           (:number issue))
    :url (:html_url issue)
-   :desc (str (re-find #".{0,100}\S" (:body issue))
-              (if (> (count (:body issue)) 100) "") " ...")
+   :desc (if (re-find #"^\s*$" body)
+           ""
+           (str (re-find #"^.{0,100}(?=\s|$)" body)
+                (if (> (count body) 100) " ..." "")))
    :user (or (get-in issue [:user :login])
              (throw (ex-info "No user found for issue" {:issue issue})))
    :created (or (re-find #"\d{4}-\d\d-\d\d"(:created_at issue))


removed SNAPSHOT from project

removed SNAPSHOT from project

--- storm-kafka/project.clj
+++ storm-kafka/project.clj
@@ -1,4 +1,4 @@
-(defproject storm/storm-kafka "0.7.4-dynamic-json-SNAPSHOT"
+(defproject storm/storm-kafka "0.7.5-dynamic-json"
   :source-path "src/clj"
   :java-source-path "src/jvm"
   :javac-options {:debug "true" :fork "true"}


exif parsing

exif parsing

--- iwaswhere-web/src/clj/iwaswhere_web/imports.clj
+++ iwaswhere-web/src/clj/iwaswhere_web/imports.clj
@@ -3,6 +3,7 @@
   (:require [clojure.pprint :as pp]
             [iwaswhere-web.files :as f]
             [clj-time.coerce :as c]
+            [matthiasn.systems-toolbox.component :as st]
             [me.raynes.fs :as fs]
             [clj-time.format :as tf]
             [clojure.tools.logging :as log])
@@ -13,16 +14,17 @@
   when not all 3 groups dm, m, and s are contained in coord string. Result negative
   when coord in Western or Southern Hemisphere according to ref argument."
   [coord ref]
-  (let [matcher (re-matcher #"(\d{1,3})° (\d{1,2})' (\d{1,2}\.?\d+?)" coord)
-        [_dms d m s] (re-find matcher)]
-    (when (and d m s)
-      (let [d (read-string d)
-            m (read-string m)
-            s (read-string s)
-            dd (float (+ d (/ m 60) (/ s 3600)))]
-        (if (contains? #{"W" "S"} ref)
-          (- dd)
-          dd)))))
+  (when coord
+    (let [matcher (re-matcher #"(\d{1,3})° (\d{1,2})' (\d{1,2}\.?\d+?)" coord)
+          [_dms d m s] (re-find matcher)]
+      (when (and d m s)
+        (let [d (read-string d)
+              m (read-string m)
+              s (read-string s)
+              dd (float (+ d (/ m 60) (/ s 3600)))]
+          (if (contains? #{"W" "S"} ref)
+            (- dd)
+            dd))))))

 (defn extract-ts
   "Converts concatenated GPS timestamp strings into milliseconds since epoch.
@@ -31,7 +33,9 @@
     'GPS Time-Stamp' '20:07:57.00 UTC'"
   [ts]
   (let [f (tf/formatter "yyyy:MM:dd HH:mm:ss.SS z")]
-    (c/to-long (tf/parse f ts))))
+    (when (and (seq ts)
+               (re-matches #"\d{4}:\d{2}:\d{2} \d{2}:\d{2}:\d{2}\.\d{2} [A-Z]{1,5}" ts))
+      (c/to-long (tf/parse f ts)))))

 (defn extract-from-tag
   "Creates map for a single Exif directory.
@@ -54,10 +58,10 @@
         gps-date (get raw-exif "GPS Date Stamp")
         gps-time (get raw-exif "GPS Time-Stamp")]
     {:raw-exif  raw-exif
-     :timestamp (if gps-date
-                  (extract-ts (str gps-date " " gps-time))
-                  ;; workaround since EXIF editor doesn't add timezone
-                  (extract-ts (str (get raw-exif "Date/Time") ".00 UTC")))
+     :timestamp (or (extract-ts (str gps-date " " gps-time))
+                    (extract-ts (str (get raw-exif "Date/Time") ".00 UTC"))
+                    (extract-ts (str (get raw-exif "Date/Time Original") ".00 UTC"))
+                    (st/now))
      :latitude  (dms-to-dd lat-dms lat-ref)
      :longitude (dms-to-dd lon-dms lon-ref)}))

@@ -65,8 +69,10 @@
   "Imports photos from respective directory."
   [{:keys [put-fn]}]
   (let [files (file-seq (clojure.java.io/file "data/image-import"))]
-    (doseq [img (f/filter-by-name files #"[A-Za-z0-9_]+.jpg")]
+    (log/info "importing photos")
+    (doseq [img (f/filter-by-name files #"[A-Za-z0-9_]+.(jpg|JPG|PNG|png)")]
       (let [filename (.getName img)]
+        (log/info "Trying to import " filename)
         (try (let [rel-path (.getPath img)
                    file-info (exif-for-file img)
                    target-filename (str (:timestamp file-info) "-" filename)


safe get-version-artifacet method

safe get-version-artifacet method

--- src/leiningen/leinsync/deps.clj
+++ src/leiningen/leinsync/deps.clj
@@ -5,13 +5,18 @@

 (def different-marker "==> ")

+(defn repositories-opt [repos]
+  (if (empty? repos)
+    {:repositories ancient/default-repositories}
+    {:repositories repos}))
+
 (defn last-version-of [repos artifact]
-  (if-let [last-version (ancient/latest-version-string!
-                         artifact
-                         {:repositories (if (empty? repos)
-                                          ancient/default-repositories
-                                          repos)})]
-    last-version :unknown))
+  (try
+    (if-let [last-version (ancient/latest-version-string!
+                           artifact
+                           (repositories-opt repos))]
+      last-version :unknown)
+    (catch Exception _ :unknown)))

 (defn flat-deps-list [p deps-list]
   (into {}


Add morph property accessors.

Add morph property accessors.

--- src-cljs/cljs_workspace/om_morph.cljs
+++ src-cljs/cljs_workspace/om_morph.cljs
@@ -66,6 +66,45 @@
     (apply dom/div nil
       (om/build-all morph (:submorphs app)))))

+; property accessors
+
+(defn find-morph-path
+  ([morph-model id] (find-morph-path morph-model id []))
+  ([morph-model id path]
+    (when-let [submorph (get-in morph-model path)]
+      (if (== id (submorph :id))
+        path
+        (if-let [submorphs (submorph :submorphs)]
+          (some #(find-morph-path morph-model id
+            (concat path [:submorphs %])) (range (count submorphs)))
+          nil)))))
+
+(defn get-prop-path [model id attrPath]
+  (into [] (concat (find-morph-path @model id) attrPath)))
+
+(defn set-position [model id pos]
+  (let [prop-path (get-prop-path model id [:morph :Position])]
+    (swap! model assoc-in prop-path pos)))
+
+(defn add-morph [model id morph]
+  (let [prop-path (get-prop-path model id [:submorphs])
+        submorphs (get-in @model prop-path)]
+    (swap! model assoc-in prop-path (conj submorphs morph))))
+
+(defn remove-morph [model id morph-id]
+  (let [prop-path (get-prop-path model id [:submorphs])
+        submorphs (get-in @model prop-path)]
+    (prn "after removal: " (filter #(not= (% :id) morph-id) submorphs))
+    (swap! model assoc-in prop-path (filter #(not= (% :id) morph-id) submorphs))))
+
+(defn set-fill [model id color]
+  (let [prop-path (get-prop-path model id [:shape :Fill])]
+    (swap! model assoc-in prop-path color)))
+
+(defn set-extent [model id extent]
+  (let [prop-path (get-prop-path model id [:shape :Extent])]
+    (swap! model assoc-in prop-path extent)))
+
 ; multimethod for morph

 (defmethod morph "Text" [app owner]


make pay wall use the plan-model/paid-containers rather than raw container count

--- src-cljs/frontend/models/project.cljs
+++ src-cljs/frontend/models/project.cljs
@@ -153,12 +153,15 @@
 (defn feature-enabled? [project feature]
   (get-in project [:feature_flags feature]))

-(defn show-build-timing? [project plan]
+(defn- show-premium-content? [project plan]
   (or (config/enterprise?)
       (:oss project)
-      (plan-model/paid? plan)
+      (> (plan-model/paid-containers plan) 0)
       (plan-model/trial? plan)
       (plan-model/osx? plan)))
+
+(defn show-build-timing? [project plan]
+  (show-premium-content? project plan))

 (defn add-show-insights? [project plans]
   (let [org-name (-> project
@@ -170,10 +173,6 @@
                                         (= org-name)))
                            (first)
                            (:plans)
-                           (apply max-key :containers))]
+                           (apply max-key plan-model/paid-containers))]

-    (assoc project :show-insights? (or (config/enterprise?)
-                                       (:oss project)
-                                       (plan-model/paid? org-best-plan)
-                                       (plan-model/trial? org-best-plan)
-                                       (plan-model/osx? org-best-plan)))))
+    (assoc project :show-insights? (show-premium-content? project org-best-plan))))


make alt tag lines fade in

make alt tag lines fade in

--- frontend/components/landing-b.cljs
+++ frontend/components/landing-b.cljs
@@ -31,9 +31,15 @@
                 [:div.intro-brand
                  (common/ico :logo)]
                 [:div.intro-slogan
-                 [:h1 "Your org needs a hero."]
-                 [:h3 "Testing is hard. Help your team focus on product, we'll handle your "]
-                 [:h3 "Continuous Integration & Deployment."]]
+                 [:h1.slogan-tagline {:title "Your org needs a hero."
+                                     :alt "We just need authorization first."}
+                  "Your org needs a hero."]
+                 [:h3.slogan-subline {:title "Testing is hard. Help your team focus on product, we'll handle your"
+                                      :alt "Why? Because signing up with your GitHub account lets Circle start your tests really fast."}
+                  "Testing is hard. Help your team focus on product, we'll handle your"]
+                 [:h3.slogan-subline {:title "Continuous Integration & Deployment."
+                                      :alt "Note, without fine-grained scopes, GitHub requires us to request them in bulk."}
+                  "Continuous Integration & Deployment."]]
                 ; [:a.intro-action-btn "Sign Up Free"]
                 ; [:div.intro-action-overlay]
                 [:div.intro-learn


bumping example deps

bumping example deps

--- example/project.clj
+++ example/project.clj
@@ -16,7 +16,7 @@

   :plugins [[lein-ring "0.8.13"]
             #_[lein-cljsbuild "1.1.1"]
-            [lein-figwheel "0.5.0-3"]
+            [lein-figwheel "0.5.0-4"]
             [lein-npm "0.4.0"]]

   :node-dependencies [[source-map-support "0.2.8"]
@@ -98,7 +98,7 @@
                                     }}]}

   :profiles { :dev { :dependencies [[com.cemerick/piggieback "0.2.1"]
-                                    [figwheel-sidecar "0.5.0-3"]
+                                    [figwheel-sidecar "0.5.0-4"]
                                     [org.clojure/tools.namespace "0.2.11"]
                                     [org.clojure/tools.nrepl "0.2.12"]]
                     :source-paths ["src" "dev"]


Document control-flow

Document control-flow

--- src/clj/lambdacd/steps/control_flow.clj
+++ src/clj/lambdacd/steps/control_flow.clj
@@ -1,5 +1,5 @@
 (ns lambdacd.steps.control-flow
-  "control flow elements for a pipeline: steps that control the way their child-steps are being run"
+  "Control-flow elements for a pipeline: steps that control the way their child-steps are being run."
   (:require [lambdacd.execution.core :as execution]
             [clojure.core.async :as async]
             [lambdacd.steps.support :as support]
@@ -42,7 +42,22 @@
     (add-watch source key #(reset! target %4))
     key))

-(defn ^{:display-type :parallel} either [& steps]
+(defn ^{:display-type :parallel} either
+  "Build step that executes its children in parallel and returns after the first child finished successfully.
+  Commonly used to wait for one of multiple triggers to return.
+
+  Example:
+  ```clojure
+  (def pipeline-structure
+    `((either
+        wait-for-git-commit
+        wait-for-manual-trigger)
+      build
+      test
+      deploy))
+  ```
+  "
+  [& steps]
   (fn [args ctx]
     (let [parent-kill-switch (:is-killed ctx)
           kill-switch        (atom false)
@@ -79,13 +94,44 @@
                            :retrigger-predicate parallel-retrigger-predicate
                            :is-killed (:is-killed ctx)))

-(defn ^{:display-type :parallel} in-parallel [& steps]
+(defn ^{:display-type :parallel} in-parallel
+  "Build step that executes its children in parallel and returns after all children finished successfully.
+  Commonly used to parallelize build independent build steps
+
+  Example:
+  ```clojure
+  (def pipeline-structure
+    `(; ...
+      build
+      (in-parallel
+        test-backend
+        test-frontend)
+      deploy))
+  ```
+  "
+  [& steps]
   (fn [args ctx]
     (post-process-container-results
       (execute-steps-in-parallel steps args ctx))))

-(defn ^{:display-type :container} in-cwd [cwd & steps]
+(defn ^{:display-type :container} in-cwd
+  "Build step that executes its children in sequence and passes the value of a given working directory to each of them.
+  Returns once the last step finished.
+
+  Example:
+  ```clojure
+  (defn some-step [args ctx]
+    (println \"The working directory:\" (:cwd args)))
+
+  (def pipeline-structure
+    `(; ...
+      (in-cwd \"/tmp/some-dir\"
+        some-step
+        some-other-step)))
+  ```
+  "
+  [cwd & steps]
   (fn [args ctx]
     (post-process-container-results
       (execution/execute-steps steps (assoc args :cwd cwd) ctx
@@ -98,7 +144,28 @@
                              :is-killed (:is-killed ctx))))

-(defn ^{:display-type :container} run [ & steps]
+(defn ^{:display-type :container} run
+  "Build step that executes its children in sequence and returns once the last step finished.
+  Commonly used to pass a chain of steps to into a control flow expecting only one (e.g. `either`, `junction`) or
+  to wrap related steps into a container and `alias` it to structure the pipeline.
+
+  Example:
+  ```clojure
+  (def pipeline-structure
+    `(; ...
+      (alias \"tests\"
+        (run
+          unit-test
+          acceptance-test))
+      (junction
+        should-deploy?
+        (run
+          deploy-ci
+          deploy-qa)
+        do-nothing)))
+  ```
+  "
+  [ & steps]
   (fn [args ctx]
     (run-steps-in-sequence args ctx steps)))

@@ -107,7 +174,20 @@
         child-step-id  (step-id/child-id parent-step-id child-number)]
     (assoc parent-ctx :step-id child-step-id)))

-(defn ^{:display-type :parallel} junction [condition-step success-step failure-step]
+(defn ^{:display-type :parallel} junction
+  "Build step that executes the first child and, depending on its success, the second or third child.
+  Commonly used for conditional, if-then-else logic in pipelines.
+
+  Example:
+  ```clojure
+  (def pipeline-structure
+    `(; ...
+      (junction
+        should-do-something?
+        step-to-run-if-success
+        step-to-run-if-not-success)))
+  ```"
+  [condition-step success-step failure-step]
   (fn [args ctx]
     (post-process-container-results
       (let [condition-step-result (execution/execute-step args (child-context ctx 1) condition-step)]
@@ -116,12 +196,38 @@
           (execution/execute-step args (child-context ctx 3) failure-step))))))

 (defn ^{:is-alias true} alias
-  "just runs child but child is displayed with the given alias in visualization"
+  "Just runs child but child is displayed with the given alias in visualization.
+
+  Example:
+  ```clojure
+  (def pipeline-structure
+    `(; ...
+      (alias \"tests\"
+        (run
+          unit-test
+          acceptance-test)))
+  ```"
   [alias child]
   (run child))

 (defn with-workspace
-  "runs given steps with a clean workspace given to child step as :cwd argument"
+  "Runs given steps with a clean workspace given to child step as :cwd argument.
+  Commonly used if a build step needs some temporary directory to run, e.g. clone repositories and run build tasks.
+  The given workspace is not persistent, it only exists for the runtime of the build step and is deleted afterwards.
+  Long-living artifacts should be stored in an external artifact repository or using additional libraries like [`lambdacd-artifacts`](https://github.com/flosell/lambdacd-artifacts).
+
+  Example:
+  ```clojure
+  (defn some-step [args ctx]
+    (println \"The working directory:\" (:cwd args)))
+
+  (def pipeline-structure
+    `(; ...
+      (with-workspace
+        some-step
+        some-other-step)))
+  ```
+  "
   [& steps]
   (fn [args ctx]
     (let [home-dir (:home-dir (:config ctx))


adding vector so string extension isn't treated as chars when adding to set

--- src/clj/tdd_trainer/routes/snapshot.clj
+++ src/clj/tdd_trainer/routes/snapshot.clj
@@ -28,7 +28,7 @@
   (POST "/session" [timestamp projectBase watchedFiles]
         (let [new-session (create-session timestamp projectBase watchedFiles)]
           (reset! d/session-data new-session)
-          (watch-project d/change-list projectBase (set watchedFiles))
+          (watch-project d/change-list projectBase (set [watchedFiles]))
           (response/created (format-session-data new-session))))

   (GET "/session" []


fix desc-periodic-seq error

fix desc-periodic-seq error

--- src/cljc/clj_money/x_platform/util.cljc
+++ src/cljc/clj_money/x_platform/util.cljc
@@ -99,8 +99,9 @@

 (defn desc-periodic-seq
   ([end period-like]
-   (lazy-seq (cons end (desc-periodic-seq (t/minus end period-like) period-like))))
+   (lazy-seq (cons end
+                   (desc-periodic-seq (t/minus end period-like)
+                                      period-like))))
   ([start end period-like]
-   (let [period (.toPeriod period-like)]
-     (take-while #(t/after? % start)
-                 (desc-periodic-seq end period-like)))))
+   (take-while #(t/after? % start)
+                 (desc-periodic-seq end period-like))))


rename funcs to avoid clash

rename funcs to avoid clash

--- src/cljs/infinitelives/pixi/canvas.cljs
+++ src/cljs/infinitelives/pixi/canvas.cljs
@@ -178,24 +178,24 @@
     (.render renderer stage)

     (let [
-          render (fn [] (.render renderer stage))
-          resize (fn [width height]
-                   (.resize renderer width height)
-                   (doall (map (partial center-container! canvas)
-                               (map second layer))))
-          expand (fn [] (resize (.-innerWidth js/window)
-                                (.-innerHeight js/window)))
+          render-fn (fn [] (.render renderer stage))
+          resize-fn (fn [width height]
+                      (.resize renderer width height)
+                      (doall (map (partial center-container! canvas)
+                                  (map second layer))))
+          expand-fn (fn [] (resize-fn (.-innerWidth js/window)
+                                      (.-innerHeight js/window)))

           resizer-loop
           (when (:expand opts) (let [c (events/new-resize-chan)]
-                                 (go (while true
-                                       (let [[width height] (<! c)]
-                                         (resize width height)
-                                         (render))))))]
+                           (go (while true
+                                 (let [[width height] (<! c)]
+                                   (resize-fn width height)
+                                   (render-fn))))))]

       (into
        world
        {
-        :render-fn render
-        :resize-fn resize
-        :expand-fn expand}))))
+        :render-fn render-fn
+        :resize-fn resize-fn
+        :expand-fn expand-fn}))))


Cosmetic changes on the default handler adapter.

--- src/clojure/catacumba/impl/handlers.clj
+++ src/clojure/catacumba/impl/handlers.clj
@@ -396,19 +396,20 @@

 (defmethod adapter :catacumba/default
   [handler]
-  (reify Handler
-    (^void handle [_ ^Context ctx]
-      (let [context (ctx/context ctx)
-            context-params (ctx/context-params context)
-            route-params (ctx/route-params context)
-            bodyp (.. ctx getRequest getBody)]
-        (ch/then bodyp (fn [^TypedData body]
-                         (let [context' (-> (merge context context-params)
-                                            (assoc :route-params route-params)
-                                            (assoc :body body))
-                               response (handler context')]
-                           (when (satisfies? IHandlerResponse response)
-                             (handle-response response context)))))))))
+  (letfn [(continuation [^Context ctx ^TypedData body]
+            (let [context (ctx/context ctx)
+                  context-params (ctx/context-params context)
+                  route-params (ctx/route-params context)
+                  context' (-> (merge context context-params)
+                               (assoc :route-params route-params)
+                               (assoc :body body))
+                  response (handler context')]
+              (when (satisfies? IHandlerResponse response)
+                (handle-response response context))))]
+    (reify Handler
+      (^void handle [_ ^Context ctx]
+        (let [bodyp (.. ctx getRequest getBody)]
+          (ch/then bodyp (partial continuation ctx)))))))

 (defmethod adapter :catacumba/blocking
   [handler]


remove old metrics namespace

remove old metrics namespace

--- src/clj/ceres_analytics/metrics.clj
+++ src/clj/ceres_analytics/metrics.clj
@@ -1,134 +0,0 @@
-(ns ceres-analytics.metrics
-  (:refer-clojure :exclude [find sort])
-  (:require [monger.collection :as mc]
-            [ceres-analytics.core :refer [db news-accounts links nodes]]
-            [clojure.data.priority-map :refer [priority-map]]
-            [clj-time.core :as t]
-            [clj-time.periodic :as p]
-            [incanter.stats :refer [mean]]
-            [clj-time.format :as f]
-            [monger.core :as mg]
-            [monger.joda-time]
-            [monger.operators :refer :all]
-            [aprint.core :refer [aprint]]
-            [monger.query :refer :all]))
-
-(def refs ["mentions" "shares" "replies" "retweets" "urlrefs" "tagrefs" "unknown" "pubs"])
-
-(defn in-degree
-  "doc-string"
-  [{:keys [_id]}]
-  (into {} (map (fn [c] [c (mc/count @db c {:target _id})]) refs)))
-
-
-(defn out-degree
-  "doc-string"
-  [{:keys [_id]}]
-  (into {} (map (fn [c] [c (mc/count @db c {:source _id})]) refs)))
-
-
-(defn normalized-degree
-  [v coll]
-  ((comp float /)
-   (merge + (in-degree v) (out-degree v))
-   (reduce + (map #(mc/count @db %) ["users" "tags" "urls" "messages"]))))
-
-
-(defn find-neighbors [[id t]]
-  (if (=  t "pub")
-    (map
-     (fn [{:keys [source type]}] [source type])
-     (mc/find-maps @db "refs" {:source id :type "pub"}))
-    (map
-     (fn [{:keys [source type]}] [source type])
-     (mc/find-maps @db "refs" {:target id :type {$in ["retweet" "reply" "share" "pub"]}}))))
-
-
-(defn dijkstra
-  "Dijkstra on social news graph"
-  [start]
-  (loop [q (priority-map [start "source"] 0)
-         r {}]
-    (if-let [[v d] (peek q)]
-      (let [n (remove #(contains? r (first %)) (find-neighbors v))
-            dist (zipmap n (repeat (count n) (inc d)))]
-        (recur
-         (merge-with min (pop q) dist)
-         (assoc r (first v) [(second v) d])))
-      r)))
-
-
-
-
-
-(comment
-
-  (def users  (mc/find-maps @db "users" {:name {$in news-accounts}}))
-
-
-  (aprint (apply merge (map (fn [{:keys [_id name]}] {name (mc/count @db "pubs" {:source _id})}) users)))
-
-  (->> nodes (map (fn [d] [d (mc/count @db d)])) (into {}) aprint)
-
-  (->> links (map (fn [d] [d (mc/count @db d)])) (into {}) aprint)
-
-  (let [messages (mc/find-maps @db "messages")]
-    (->> messages
-         (pmap in-degree)
-         #_(reduce (fn [[id1 od1] [id2 od2]] [(+ id1 id2) (+ od1 od2)]))))
-
-
-
-  ;; avg avg out degree
-  (->> refs
-       (pmap (fn [d] [d
-                     (->> (mc/find-maps @db d)
-                          (map :source)
-                          frequencies
-                          vals
-                          mean)]))
-       vec
-       aprint
-       time)
-
-  ;; avg in degree
-  (->> refs
-       (pmap (fn [d]
-               [d
-                (->> (mc/find-maps @db d)
-                     (map :target)
-                     frequencies
-                     vals
-                     mean)]))
-       vec
-       aprint
-       time)
-
-
-  (->> (map
-        (fn [h] [h (mc/find-maps @db "pubs" {:ts {$gt (t/date-time 2015 3 13 h)
-                                                 $lt (t/date-time 2015 3 13 h 59 59 999)}})])
-        (range 0 24))
-       (into {})
-       (pmap (fn [[k v]] [k]))
-       aprint)
-
-  (->> {:ts {$gt (t/date-time 2015 3 13 8)
-             $lt (t/date-time 2015 3 13 8 59 59 999)}}
-       (mc/find-maps @db "pubs")
-       (pmap (fn [{:keys [target]}] (reduce + (pmap #(mc/count @db % {:target target
-                                                                     :ts {$gt (t/date-time 2015 3 13 8)
-                                                                          $lt (t/date-time 2015 3 13 8 59 59 999)}}) ["retweets" "replies" "shares"])) ))
-       frequencies
-       (sort-by val >)
-       aprint
-       time)
-
-
-
-  (map (fn [r] [r (mc/count @db r)]) refs)
-
-
-  (->> (mc/find-maps @db "shares" {:ts {$gt (t/date-time 2015 3 31)}}))
-
-  )


Point live browser clojure to repl.it

Point live browser clojure to repl.it

--- src/clj/clojuredocs/pages/intro.clj
+++ src/clj/clojuredocs/pages/intro.clj
@@ -168,9 +168,9 @@
        [:li [:a {:href "http://www.braveclojure.com"} "Clojure for the Brave and True"]]
        [:li [:a {:href "http://aphyr.com/posts/301-clojure-from-the-ground-up-welcome"}
              "Clojure from the Ground Up"]]
-       [:li [:a {:href "http://tryclj.com"} "Try Clojure (in your browser)"]]
+       [:li [:a {:href "http://4clojure.org"} "4Clojure (learn Clojure interactively)"]]
        [:li [:a {:href "http://clojurescriptkoans.com/"} "ClojureScript Koans"]]
-       [:li [:a {:href "http://4clojure.org"} "4Clojure (learn Clojure interactively)"]]]
+       [:li [:a {:href "https://repl.it/languages/clojure"} "Run Clojure code live in your browser"]]]
       [:p "There's no denying that Clojure is just so "
        " *different* "
        " from what most of us are used to (what is up with all those parentheses?!), "


a lot of docs

a lot of docs

--- src/clj/forma/classify/logistic.clj
+++ src/clj/forma/classify/logistic.clj
@@ -17,41 +17,82 @@
 ;; and feature sequences are consistently positioned in the label and
 ;; feature collections.

-(defn
-  ^DoubleMatrix
+(defn ^DoubleMatrix
+  to-double-matrix
+  "converts a clojure matrix representation to a DoubleMatrix instance
+  for use with jBLAS functions
+
+  Argument:
+    vector of vectors; clojure representation of a matrix
+
+  Example:
+    (to-double-matrix [0]) => #<DoubleMatrix []>
+    (to-double-matrix [[0]]) => #<DoubleMatrix [0.0]>
+    (to-double-matrix [[0] [1]]) => #<DoubleMatrix [0.0; 1.0]>
+
+  Reference:
+    http://jblas.org/javadoc/org/jblas/DoubleMatrix.html"
+  [mat]
+  (DoubleMatrix.
+   (into-array (map double-array mat))))
+
+(defn ^DoubleMatrix
+  to-double-rowmat
+  "converts a clojure vector to a DoubleMatrix row vector
+
+  Argument:
+    persistent vector
+
+  Example:
+    (to-double-rowmat [1 2 3]) => #<DoubleMatrix [1.0, 2.0, 3.0]>
+
+  Reference:
+    http://jblas.org/javadoc/org/jblas/DoubleMatrix.html"
+  [coll]
+  (to-double-matrix [(vec coll)]))
+
+(defn ^DoubleMatrix
   logistic-fn
+  "returns the value of the logistic curve at supplied `x` value;
+  output is a DoubleMatrix (org.jblas.DoubleMatrix).
+
+  Argument:
+    DoubleMatrix instance (org.jblas.DoubleMatrix) with only one
+    value
+
+  Example:
+    (logistic-fn (to-double-rowmat [0])) => #<DoubleMatrix [0.5]>
+
+  Reference:
+    http://en.wikipedia.org/wiki/Logistic_function"
   [x]
   (let [exp-x (MatrixFunctions/exp x)
         one (DoubleMatrix/ones 1)]
     (.divi exp-x (.add exp-x one))))

-(defn ^DoubleMatrix
-  to-double-matrix
-  "returns a DoubleMatrix instance for use with jBLAS functions"
-  [mat]
-  (DoubleMatrix.
-   (into-array (map double-array mat))))
-
-(defn ^DoubleMatrix
-  to-double-rowmat
-  [coll]
-  (to-double-matrix [(vec coll)]))
-
-(defn ^DoubleMatrix
-  copy-row
-  [row]
-  (.copy (to-double-matrix [[]]) row))

 (defn ^DoubleMatrix
   logistic-prob
-  ".dot returns a double, which needs to be converted to a
-  DoubleMatrix for logistic-fn"
-  [beta-mat features-mat]
+  "returns the DoubleMatrix value of the logistic curve at the value
+  given by the dot product of the parameter vector and the feature
+  vector. Both arguments and return values are DoubleMatrix instances.
+
+  Arguments:
+    beta-rowmat: DoubleMatrix row vector
+    features-rowmat: DoubleMatrix row vector, of equal length as
+                     beta-rowmat
+
+  Example:
+    (def beta (to-double-rowmat [0 0]))
+    (def features (to-double-rowmat [1 2]))
+    (logistic-prob beta features) => #<DoubleMatrix [0.5]>"
+  [beta-rowmat features-rowmat]
   (logistic-fn
-   (to-double-rowmat [(.dot beta-mat features-mat)])))
+   (to-double-rowmat [(.dot beta-rowmat features-rowmat)])))

 ;; TODO: convert the functions that are useful but not actually used
-;; in estimation, like `log-likelihood` and `total-log-likelihood`.
+;; in this version of estimation, including `log-likelihood` and
+;; `total-log-likelihood`.

 (defn log-likelihood
   "returns the log likelihood of a given pixel, conditional on its
@@ -72,31 +113,72 @@

 (defn ^DoubleMatrix
   probability-calc
-  [beta feature-mat]
-  (let [prob-row (.mmul beta (.transpose feature-mat))]
+  "returns a DoubleMatrix row vector of probabilities given by the
+  in-place dot product (read: matrix multiplication) of the beta
+  vector and the feature vectors collected in the feature matrix. Both
+  arguments and return values are DoubleMatrix instances.
+
+  Example:
+    (def beta (to-double-rowmat [0 0]))
+    (def feat (to-double-matrix [[1 2] [4 5]]))
+    (probability-calc beta feat) => #<DoubleMatrix [0.5, 0.5]>"
+  [beta-rowmat feature-mat]
+  (let [prob-row (.mmul beta-rowmat (.transpose feature-mat))]
     (logistic-fn prob-row)))

 (defn ^DoubleMatrix
   score-seq
-  "returns the score for each parameter "
+  "returns the score for each parameter at the current iteration,
+  based on the estimated probabilities and the true labels. Both
+  arguments and return values are DoubleMatrix instances.
+
+  Example:
+    (def beta (to-double-rowmat [0 0]))
+    (def feat (to-double-matrix [[1 2] [4 5]]))
+    (def label (to-double-rowmat [1 0]))
+    (score-seq beta label feat) => #<DoubleMatrix [-1.5; -1.5]>
+
+  Reference:
+    http://en.wikipedia.org/wiki/Scoring_algorithm"
   [beta labels feature-mat]
     (let [prob-seq (probability-calc beta feature-mat)]
     (.mmul (.transpose feature-mat)
            (.transpose (.sub labels prob-seq)))))

 (defn ^DoubleMatrix
-  mult-fn
-  [x]
-  (let [ones (DoubleMatrix/ones (.rows x) (.columns x))
-        new-mat (.add ones (.neg x))]
-    (.mul x new-mat)))
+  bernoulli-var
+  "returns the variance of a bernoulli random variable, given a row
+  matrix of probabilities `row-prob`.  Both arguments and return
+  values are DoubleMatrix instances.
+
+  Example:
+    (def row-prob (to-double-rowmat [0.5 0.5]))
+    (bernoulli-var row-prob) => #<DoubleMatrix [0.25, 0.25]>
+
+  Reference:
+    http://en.wikipedia.org/wiki/Bernoulli_distribution"
+  [row-prob]
+  (let [ones (DoubleMatrix/ones (.rows row-prob) (.columns row-prob))
+        new-mat (.add ones (.neg row-prob))]
+    (.mul row-prob new-mat)))

 (defn ^DoubleMatrix
   info-matrix
+  "returns the (symmetric) information matrix at the current iteration
+  of the scoring algorithm (specifically the Newton-Raphson method.
+
+  Example:
+    (def beta (to-double-rowmat [0 0]))
+    (def feat (to-double-matrix [[1 2] [4 5]]))
+    (info-matrix beta feat) => #<DoubleMatrix [4.25, 5.5; 5.5, 7.25]>
+
+  Reference:
+    http://en.wikipedia.org/wiki/Scoring_algorithm
+    http://en.wikipedia.org/wiki/Fisher_information"
   [beta-row feature-mat]
   {:pre [(= (.columns beta-row) (.columns feature-mat))]}
   (let [prob-row (probability-calc beta-row feature-mat)
-        transformed-row (mult-fn prob-row)]
+        transformed-row (bernoulli-var prob-row)]
     (.mmul (.muliRowVector (.transpose feature-mat) transformed-row)
            feature-mat)))


Make next-frames returning lazy seq

Make next-frames returning lazy seq

--- src/cljs/asciinema_player/core.cljs
+++ src/cljs/asciinema_player/core.cljs
@@ -47,12 +47,13 @@
         (recur (rest frames) (- seconds delay) (merge-with merge candidate changes))))))

 (defn next-frames [frames seconds]
-  (if (seq frames)
-    (let [[delay changes] (first frames)]
-      (if (<= delay seconds)
-        (recur (rest frames) (- seconds delay))
-        (cons [(- delay seconds) changes] (rest frames))))
-    frames))
+  (lazy-seq
+    (if (seq frames)
+      (let [[delay changes] (first frames)]
+        (if (<= delay seconds)
+          (next-frames (rest frames) (- seconds delay))
+          (cons [(- delay seconds) changes] (rest frames))))
+      frames)))

 (defn elapsed-time-since [then]
   (/ (- (.getTime (js/Date.)) (.getTime then)) 1000))


change influence limit symbols to other UTF-8 signs

--- src/cljs/netrunner/deckbuilder.cljs
+++ src/cljs/netrunner/deckbuilder.cljs
@@ -411,8 +411,8 @@
                                 [:span.influence
                                  {:class (-> card :faction .toLowerCase (.replace " " "-"))
                                   :dangerouslySetInnerHTML
-                                  #js {:__html (str (if-not infaction (apply str (for [_ (range influence)] "•")))
-                                                    (if wanted (apply str (for [_ (range (:qty line))] "◦"))))}}]))])
+                                  #js {:__html (str (if-not infaction (apply str (for [_ (range influence)] "●")))
+                                                    (if wanted (apply str (for [_ (range (:qty line))] "○"))))}}]))])
                          (:card line))])])]]))]

           [:div.deckedit


Disable format

Disable format

--- src/clojure/paredit_widget/core.clj
+++ src/clojure/paredit_widget/core.clj
@@ -3,7 +3,6 @@
             [paredit.loc-utils]
             [paredit.parser]
             [paredit.text-utils]
-            [paredit-widget.format :as format]
             [seesaw.core :as s])
   (:import [java.awt.event InputMethodListener KeyEvent KeyListener]))

@@ -124,7 +123,7 @@
       (when-not (.isConsumed e)
         (let [k (convert-key-event e)
               p (exec-paredit k w buffer enable-default? enable-advanced?)]
-          (if p (.consume e) (format/exec-format k w)))))))
+          (when p (.consume e)))))))

 (defn input-method-event-handler
   [w buffer enable-default? enable-advanced?]


Prevent exception when prettifying without a selection

--- src/clojure/paredit_widget/core.clj
+++ src/clojure/paredit_widget/core.clj
@@ -74,9 +74,9 @@
   {["M" "f"] :fmt-pprint})

 (defn exec-pprint [k widget]
-  (let [cmd (formatting-keymap k)]
-    (if cmd
-      (let [fs (with-out-str (clojure.pprint/pprint (read-string (.getSelectedText widget))))]
+  (when (formatting-keymap k)
+    (when-let [text (.getSelectedText widget)]
+      (let [fs (with-out-str (clojure.pprint/pprint (read-string text)))]
         (if *debug* (println "replacement: " fs " at: " (.getSelectionStart widget)))
         (if fs (.replaceRange widget fs (.getSelectionStart widget) (.getSelectionEnd widget)))))))


fixed the right crawl

fixed the right crawl

--- src/crawler/rich_char_extractor.clj
+++ src/crawler/rich_char_extractor.clj
@@ -21,15 +21,12 @@
      (state-action page-src url template-removed []))

   ([page-src url template-removed blacklist]
-     (let [processed-pg         (dom/html->xml-doc page-src)
+     (let [proc-pg              (dom/html->xml-doc page-src)

            ; xpaths nodes and associated anchor-text
-           xpaths-hrefs-text    (try
-                                  (dom/xpaths-hrefs-tokens
-                                   processed-pg
-                                   url
-                                   blacklist)
-                                  (catch Exception e nil))
+           xpaths-hrefs-text    (dom/xpaths-hrefs-tokens-no-position proc-pg
+                                                                     url
+                                                                     blacklist)

            template-removed     (map
                                  (fn [[xpath infos]]
@@ -38,7 +35,8 @@
                                                             set)]
                                      [xpath (filter
                                              (fn [{_ :node href :href _1 :text}]
-                                               (not (some #{href} template-links)))
+                                               (not
+                                                (some #{href} template-links)))
                                              infos)]))
                                  xpaths-hrefs-text)

@@ -78,7 +76,9 @@
                                     (let [potential-xpath xpath
                                           potential-score (reduce
                                                            (fn [acc an-info]
-                                                             (+ acc (:num-chars an-info)))
+                                                             (+
+                                                              acc
+                                                              (:num-chars an-info)))
                                                            0
                                                            info)
                                           potential-hrefs (reduce


Fix graphql typo (#724)

Fix graphql typo (#724)

--- src/ctia/schemas/graphql/common.clj
+++ src/ctia/schemas/graphql/common.clj
@@ -4,5 +4,5 @@
 (def lucene-query-arguments
   {:query {:type Scalars/GraphQLString
            :description (str "A Lucene query string, will only "
-                             "return Relationships matching it.")
+                             "return nodes matching it.")
            :default "*"}})


Store already-rendered references and avoid double-rendering

--- src/discuss/references/integration.cljs
+++ src/discuss/references/integration.cljs
@@ -2,6 +2,7 @@
   "Listen for mouse clicks, get references and highlight them in the article."
   (:require [om.next :as om :refer-macros [defui]]
             [clojure.string :refer [split lower-case]]
+            [clojure.set :refer [difference]]
             [discuss.utils.common :as lib]
             [discuss.utils.views :as vlib]
             [discuss.references.lib :as rlib]
@@ -53,11 +54,14 @@
                         parent)
           (rlib/highlight! ref-text))))))

-(defn process-references
+(defn- process-references!
   "Receives references through the API and prepares them for the next steps."
   [refs]
-  (doseq [ref refs]
-    (convert-reference ref)))
+  (let [refs-on-webpage (lib/load-from-app-state :references/on-webpage)
+        refs-to-be-rendered (difference (set refs) (set refs-on-webpage))]
+    (doseq [ref refs-to-be-rendered]
+      (lib/store-to-app-state! 'references/on-webpage (conj refs-on-webpage ref))
+      (convert-reference ref))))

 (defn- references-handler
   "Called when received a response on the reference-query."
@@ -65,13 +69,14 @@
   (let [res (lib/process-response response)
         refs (:references res)]
     (lib/store-to-app-state! 'references/all refs)
-    (process-references refs)))
+    (process-references! refs)))

 (defn request-references
-  "When this app is loaded, request all available references from the external discussion system."
+  "When this app is loaded, request all available references from the external
+  discussion system."
   []
   (let [url (get-in config/api [:get :references])
         params {:host js/location.host
                 :path js/location.pathname}]
-    (log/info "[request-references] Requesting references for " url ", " params)
+    (log/info "[request-references] Requesting references for %s, %s " url params)
     (comlib/ajax-get url nil references-handler params)))


+(deftest generate-from-vocab-items)

+(deftest generate-from-vocab-items)

--- test/babel/test/en.cljc
+++ test/babel/test/en.cljc
@@ -702,6 +702,22 @@
          (= "the woman that she sees"
             (morph result))))))

+(deftest generate-from-vocab-items
+  (let [vocab-items [{:surface "acre", :pred "acre", :vocab_cat "noun1"}
+                     {:surface "county", :pred "county", :vocab_cat "noun1"}
+                     {:surface "damage", :pred "damage", :vocab_cat "noun1"}
+                     {:surface "fire", :pred "fire", :vocab_cat "noun1"}
+                     {:surface "flame", :pred "flame", :vocab_cat "noun1"}
+                     {:surface "industry", :pred "industry", :vocab_cat "noun1"}
+                     {:surface "wine", :pred "wine", :vocab_cat "noun1"}]
+        filter-lexicon-fn #(= :det (get-in % [:synsem :cat]))
+        original-model @@(get babel.directory/models :en)
+        new-model ((:vocab2model original-model) vocab-items filter-lexicon-fn)]
+    (let [expression (generate/generate {:synsem {:subcat []
+                                                  :cat :noun}}
+                                        new-model)]
+      (is (not (nil? expression))))))
+
 (def spec
   {:synsem {:cat :verb
             :sem {:pred :sleep