Allow Maya to target a previously-accessed card to return to R&D to fix interaction with Quantum Predictive Model and News Team. Fixes #1172.

--- src/clj/game/cards-hardware.clj
+++ src/clj/game/cards-hardware.clj
@@ -330,6 +330,7 @@
    "Maya"
    {:in-play [:memory 2]
     :abilities [{:once :per-turn
+                 :label "Move this accessed card to bottom of R&D"
                  :req (req (when-let [c (:card (first (get-in @state [:runner :prompt])))]
                              (in-deck? c)))
                  :msg "move the card just accessed to the bottom of R&D"
@@ -341,7 +342,20 @@
                                 (swap! state update-in [side :prompt] rest)
                                 (when-let [run (:run @state)]
                                   (when (and (:ended run) (empty? (get-in @state [:runner :prompt])) )
-                                    (handle-end-run state :runner)))))}]}
+                                    (handle-end-run state :runner)))))}
+                {:once :per-turn
+                 :label "Move a previously accessed card to bottom of R&D"
+                 :effect (effect (resolve-ability
+                                   {; only allow targeting cards that were accessed this turn -- not perfect, but good enough?
+                                    :choices {:req #(some (fn [c] (= (:cid %) (:cid c)))
+                                                          (map first (turn-events state side :access)))}
+                                    :msg (msg "move " (:title target) " to the bottom of R&D")
+                                    :effect (req (move state :corp target :deck)
+                                                 (tag-runner state :runner 1)
+                                                 (swap! state update-in [side :prompt] rest)
+                                                 (when-let [run (:run @state)]
+                                                   (when (and (:ended run) (empty? (get-in @state [:runner :prompt])))
+                                                     (handle-end-run state :runner))))} card nil))}]}

    "MemStrips"
    {:in-play [:memory 3]}


Docstring of hellhound.component ns added

--- src/clj/hellhound/component.clj
+++ src/clj/hellhound/component.clj
@@ -1,12 +1,57 @@
 (ns hellhound.component
+  "Components are the main parts of HellHound systems. Basically
+  each components should be an implementation of `IComponent`. The
+  protocol which defines a component functionality. By default HellHound
+  implements `IComponent` protocols for hashmaps only. So we can define
+  components in form of maps.
+
+  In order to define a component a map should should contains following
+  keys (All the keys should be namespaced keyword under `hellhound.component`):
+
+  * `name`: The name of the component. It should be a namespaced keyword.
+  This key is **mandatory**.
+
+  * `start-fn`: A function which takes the component map as the only argument
+  and return the component with the necessary keys attached to it. This
+  function is responsible for **starting** the component.
+  This key is **mandatory**.
+
+  * `stop-fn`: A function which takes the component map as the only argument
+  and return the component with the necessary keys attached to it. This
+  function is responsible for **stoping** the component.
+  This key is **mandatory**.
+
+  * `depends-on`: This key specifies all the components which are the
+   dependencies of the current component. A collection  of components
+  name.
+  This key is optional.
+
+  * `input-stream-fn`: A function which returns a `manifold` as the input
+  of the component. You rarely need to use this key for a component.
+  This key optional.
+
+  * `output-stream-fn`: A function which returns a `manifold` as the output
+  of the component. You rarely need to use this key for a component.
+  This key optional.
+
+  So as an example:
+
+  ```clojure
+  (def sample-component
+    {:hellhound.component/name :sample.core/component-A
+     :hellhound.component/start-fn (fn [component] component)
+     :hellhound.component/stop-fn (fn [component] component)
+     :hellhound.component/depends-on [:sample.core/component-B]})
+  ```
+
+  In this example `start-fn` and `stop-fn` don't do anything.
+  "
+  {:added 1.0}
   (:require [clojure.spec.alpha     :as s]
             [clojure.spec.gen.alpha :as gen]
             [manifold.stream        :as stream]
             [hellhound.core :as core]
-            [hellhound.logger :as log])
-  (:import (clojure.lang PersistentArrayMap
-                         PersistentHashMap)))
-
+            [hellhound.logger :as log]))

 ;; Protocols -----------------------------------------------
 (defprotocol IComponent


thread name

thread name

--- src/clj/neb/durability/core.clj
+++ src/clj/neb/durability/core.clj
@@ -19,8 +19,8 @@
 (defn sync-trunk [^Trunk trunk]
   (try
     (let [dirty-segments (.getDirtySegments trunk)
-          sync-pool (cp/threadpool (* 2 (count @server-sids)) :name "Range-Remote-Sync")
-          seg-pool (cp/threadpool 2)
+          sync-pool (cp/threadpool (* 2 (count @server-sids)) :name "Backup-Remote-Sync")
+          seg-pool (cp/threadpool 2 "Backup-Segment")
           trunk-id (.getId trunk)]
       (cp/pdoseq
         seg-pool [^Segment seg dirty-segments]


Improve documentation in `quil.snippets.macro`.

--- src/clj/quil/snippets/macro.clj
+++ src/clj/quil/snippets/macro.clj
@@ -5,14 +5,17 @@
   "Defines a snippet. A snippet is a small example showing how to use a specific
   Quil function. Snippets are used in Quil docs and for release testing.

-  If a snippet is intended for a clj-only or cljs-only function, use reader conditionals
-  (https://clojure.org/reference/reader#_reader_conditionals) to define the snippet only in
-  clj or cljs. You can also use reader conditionals inside the snippet itself if needed.
+  If a snippet is intended for a clj-only or cljs-only function, use
+  [reader
+  conditionals](https://clojure.org/reference/reader#_reader_conditionals)
+  to define the snippet only in clj or cljs. You can also use reader
+  conditionals inside the snippet itself if needed.

-  If the snippet is not trivial and has multiple parts it should have comments. These
-  comments will help Quil users to understand better what the snippet does when they read
-  the Quil API. Since standard clojure comments (the one that start with ;) are stripped in
-  macros, comments should be added using (comment) macro like this:
+  If the snippet is not trivial and has multiple parts it should have
+  comments. These comments will help Quil users to better understand what the
+  snippet does when they read the Quil API. Since standard Clojure comments (the
+  ones that start with `;`) are stripped in macros, comments should be added
+  using the `(comment)` macro like this:

   ```
   (comment \"Do foo bar\")
@@ -22,20 +25,22 @@
   All `(comment)` forms will be converted into `;` comments when generating the
   documentation.

-  Snippets are stored in https://github.com/quil/quil/tree/master/src/cljc/quil/snippets
+  Snippets are stored in
+  https://github.com/quil/quil/tree/master/src/cljc/quil/snippets

   More info about snippets: https://github.com/quil/quil/wiki/Snippets

-  This macro works by storing its parts in a list [[quil.snippets.all-snippets/all-snippets]]
-  that is later used to generate tests for release testing or generate documentation.
+  This macro works by storing its parts in a
+  list [[quil.snippets.all-snippets/all-snippets]] that is later used to
+  generate tests for release testing or generate documentation.

   Parameters:
     * `name` - Name of snippet. Usually the same as the function
                the snippet tests. Needs to be unique in the current file.
     * `fns`  - Name of the Quil function that the snippet tests. Used to
-               to find all snippets for each function when generating documentation.
-               Supports a collection of names if snippet tests few related Quil
-               functions at the same time.
+               to find all snippets for each function when generating
+               documentation. Supports a collection of names if the
+               snippet tests a few related Quil functions at the same time.
     * `opts` - Map of extra options. Supported options:
       - `:renderer` - Renderer to use for the snippet, if not default.
       - `:setup`    - Setup function to use. Default is empty.


add test for Titanium Ribs

add test for Titanium Ribs

--- src/clj/test/cards-hardware.clj
+++ src/clj/test/cards-hardware.clj
@@ -213,6 +213,36 @@
       (is (= 1 (count (:hosted (refresh fae)))) "TPT hosted on Faerie")
       (is (= 3 (:current-strength (refresh fae))) "Faerie receiving +1 strength from TPT"))))

+(deftest titanium-ribs
+  "Titanium Ribs - Choose cards lost to damage, but not on Corp turn against Chronos Protocol"
+  (do-game
+    (new-game (make-deck "Chronos Protocol: Selective Mind-mapping" [(qty "Pup" 1) (qty "Viktor 1.0" 1)
+                                                                     (qty "Neural EMP" 1)])
+              (default-runner [(qty "Titanium Ribs" 2) (qty "Sure Gamble" 1)
+                               (qty "Fall Guy" 1) (qty "Kati Jones" 1)]))
+    (play-from-hand state :corp "Pup" "HQ")
+    (play-from-hand state :corp "Viktor 1.0" "R&D")
+    (take-credits state :corp)
+    (play-from-hand state :runner "Fall Guy")
+    (play-from-hand state :runner "Titanium Ribs")
+    (prompt-select :runner (find-card "Titanium Ribs" (:hand (get-runner))))
+    (prompt-select :runner (find-card "Kati Jones" (:hand (get-runner))))
+    (is (empty? (:prompt (get-runner))) "Fall Guy didn't try to prevent trashing of Kati")
+    (is (= 2 (count (:discard (get-runner)))) "2 cards trashed for Ribs installation meat damage")
+    (run-on state "HQ")
+    (let [pup (get-ice state :hq 0)]
+      (core/rez state :corp pup)
+      (card-ability state :corp pup 0)
+      (prompt-select :runner (find-card "Sure Gamble" (:hand (get-runner)))) ; Ribs takes precedence over CP on Runner turn
+      (is (= 3 (count (:discard (get-runner)))) "Chose card lost from 1 net damage")
+      (run-jack-out state)
+      (take-credits state :runner)
+      (core/move state :runner (find-card "Sure Gamble" (:discard (get-runner))) :hand)
+      (core/move state :runner (find-card "Kati Jones" (:discard (get-runner))) :hand)
+      (play-from-hand state :corp "Neural EMP")
+      (prompt-choice :corp "Kati Jones") ; Chronos Protocol takes precedence over Ribs on Corp turn
+      (is (= 2 (count (:discard (get-runner)))) "Card chosen by Corp for first net damage"))))
+
 (deftest turntable-swap
   "Turntable - Swap a stolen agenda for a scored agenda"
   (do-game


suggest no-cache of latest image svgs

suggest no-cache of latest image svgs

--- src/clojars/routes/artifact.clj
+++ src/clojars/routes/artifact.clj
@@ -57,11 +57,13 @@
   (GET ["/:artifact-id/latest-version.svg" :artifact-id #"[^/]+"]
        [artifact-id]
        (-> (response/response (view/make-latest-version-svg artifact-id artifact-id))
+           (response/header "Cache-Control" "no-cache")
            (response/content-type "image/svg+xml")))
   (GET ["/:group-id/:artifact-id/latest-version.svg"
         :group-id #"[^/]+" :artifact-id #"[^/]+"]
        [group-id artifact-id]
        (-> (response/response (view/make-latest-version-svg group-id artifact-id))
+           (response/header "Cache-Control" "no-cache")
            (response/content-type "image/svg+xml")))

   (POST ["/:group-id/:artifact-id/promote/:version"


Minor docstring updates

Minor docstring updates

--- src/clojure/alfresco/behave.clj
+++ src/clojure/alfresco/behave.clj
@@ -52,7 +52,7 @@

 (def ^:private policies
   "A list of all of the Alfresco policies supported by lambdalf (note: doesn't include all of the available policies).
-  This list is used by the gen-policy-registration-fns macro to generate the various registration methods and Alfresco
+  This list is used by the gen-policy-registration-fns macro to generate the various registration functions and Alfresco
   Java API interop boilerplate."
   [
     ;clojure-fn-name         alfresco-policy-class                                                      policy-method             policy-method-parameters


Changing expected delete status code from the indexer.

--- src/cmr/ingest/data/indexer.clj
+++ src/cmr/ingest/data/indexer.clj
@@ -59,6 +59,6 @@
                                  :headers (get-headers context)
                                  :connection-manager (transmit-conn/conn-mgr conn)})
         status (:status response)]
-    (when-not (some #{200, 201} [status])
+    (when-not (some #{200, 204} [status])
       (errors/internal-error! (str "Delete concept operation failed. Indexer app response status code: "  status " " response)))))


Adding back in the original SMAP_ISO string Metadata DB originally used.

--- metadata-db-app/src/cmr/metadata_db/data/oracle/concepts.clj
+++ metadata-db-app/src/cmr/metadata_db/data/oracle/concepts.clj
@@ -51,7 +51,10 @@
   ;; CMR bootstrap-app simply copies this format into CMR database, we could have "ISO-SMAP" as
   ;; a format in CMR database.
   (assoc (set/map-invert mime-type->db-format)
-         "ISO-SMAP" "application/iso:smap+xml"))
+         "ISO-SMAP" "application/iso:smap+xml"
+         ;; We also have to support whatever the original version of the the string Metadata DB originally used.
+         "SMAP_ISO"  "application/iso:smap+xml"))
+

 (defn safe-max
   "Return the maximimum of two numbers, treating nil as the lowest possible number"


Rendering for sign-up forms: EmailVerifiedRenderer

--- modules/bootstrap/src/modular/bootstrap/cylon/user_forms.clj
+++ modules/bootstrap/src/modular/bootstrap/cylon/user_forms.clj
@@ -5,7 +5,7 @@
    [clojure.tools.logging :refer :all]
    [modular.bootstrap :refer (ContentBoilerplate wrap-content-in-boilerplate)]
    [cylon.impl.authentication :refer (LoginFormRenderer)]
-   [cylon.impl.signup :refer (SignupFormRenderer)]
+   [cylon.impl.signup :refer (SignupFormRenderer EmailVerifiedRenderer)]
    [hiccup.core :refer (html h)]
    [garden.core :refer (css)]
    [garden.units :refer (pt em px)]
@@ -111,7 +111,19 @@

         [:button.btn.btn-lg.btn-primary.btn-block {:type "submit"} "Sign up"]

-        ]]))))
+        ]])))
+   EmailVerifiedRenderer
+   (render-email-verified [this req model]
+     (boilerplate
+      this req
+      (html
+       [:div
+        [:style (styles)]
+        (:message model)
+        ]))
+     )
+
+  )

 (def new-bootstrap-user-form-renderer-schema
   {(s/optional-key :boilerplate) (s/protocol ContentBoilerplate)


Updated variable name

Updated variable name

--- kabob-build/src/main/resources/edu/ucdenver/ccp/kabob/build/rules/bio_to_ice/ontology_ice_gen_rules.clj
+++ kabob-build/src/main/resources/edu/ucdenver/ccp/kabob/build/rules/bio_to_ice/ontology_ice_gen_rules.clj
@@ -10,7 +10,7 @@
 								  minus{?root rdfs:subClassOf ?class}
 								  minus{?root owl:deprecated true}
 								         }"
-  :reify ([?/id {:ln (:localname ?/subclass)
+  :reify ([?/id {:ln (:localname ?/root)
                  :ns "ccp" :prefix "" :suffix ""}])}


Keep ruler active until an other click.

Keep ruler active until an other click.

--- src/uxbox/ui/workspace/canvas/ruler.cljs
+++ src/uxbox/ui/workspace/canvas/ruler.cljs
@@ -39,7 +39,7 @@
 (defn- on-mouse-up
   [own local event]
   (dom/stop-propagation event)
-  (reset! local {:active false}))
+  (swap! local assoc :active false))

 (defn- overlay-render
   [own local]
@@ -53,7 +53,7 @@
       [:rect {:style {:fill "transparent" :stroke "transparent" :cursor "cell"}
               :width wb/viewport-width
               :height wb/viewport-height}]
-      (if (and (:active @local) x1 x2)
+      (if (and x1 x2)
           [:g
            [:line {:x1 x1 :y1 y1 :x2 x2 :y2 y2
                    :style {:cursor "cell"}


Force turn to belong to p1

Force turn to belong to p1

--- test/obb_api/handlers/play_game_test.clj
+++ test/obb_api/handlers/play_game_test.clj
@@ -3,13 +3,18 @@
             [obb-api.service-test :as service]
             [obb-rules.stash :as stash]
             [obb-api.handlers.deploy-game-test :as deploy-game-test]
+            [obb-api.gateways.battle-gateway :as battle-gateway]
             [io.pedestal.test :refer :all]
             [io.pedestal.http :as bootstrap]))

 (defn- create-game
   "Creates a game where p1 is the first to play"
   []
-  (-> (deploy-game-test/create-deployed-game)))
+  (let [[game status] (deploy-game-test/create-deployed-game)]
+    (-> game
+        (assoc-in [:board :state] "p1")
+        (battle-gateway/update-battle))
+    game))

 (defn- make-move
   "Makes a move on a game"
@@ -21,12 +26,12 @@
                      data)))

 (deftest play-game-smoke
-  (let [[game _] (create-game)
+  (let [game (create-game)
         [response status] (make-move game nil)]
     (is (not= 404 status))))

 (deftest error-if-no-actions-test
-  (let [[game _] (create-game)
+  (let [game (create-game)
         [response status] (make-move game nil)]
     (is (= "EmptyJSON" (response :error)))
     (is (= 412 status))))
@@ -38,7 +43,7 @@
     (is (= 404 status))))

 (deftest error-if-invalid-player-test
-  (let [[game _] (create-game)
+  (let [game (create-game)
         [response status] (make-move game {} "ShadowKnight")]
     (is (= "InvalidPlayer" (response :error)))
     (is (= 401 status))))
@@ -51,7 +56,7 @@
     (get-in game [(keyword other-code) :name])))

 (deftest error-if-not-player-turn-test
-  (let [[game _] (create-game)
+  (let [game (create-game)
         other-player (get-waiting-player game)
         [response status] (make-move game {} other-player)]
     (is (= "InvalidPlayer" (response :error)))


fix how args are destructured in routes

fix how args are destructured in routes

--- src-cljs/frontend/routes.cljs
+++ src-cljs/frontend/routes.cljs
@@ -14,29 +14,34 @@
     (put! nav-ch [:error {:status 404}])))

 (defn define-user-routes! [nav-ch]
-  (defroute root "/" [{:keys [query-params]}]
+  (defroute root "/" {:keys [query-params]}
     (put! nav-ch [:landing {:query-params query-params}]))
-  (defroute home "/home" [{:keys [query-params]}]
+
+  (defroute home "/home" {:keys [query-params]}
     (put! nav-ch [:landing {:query-params query-params}]))
-  (defroute pricing "/pricing" [{:keys [query-params]}]
+
+  (defroute pricing "/pricing" {:keys [query-params]}
     (put! nav-ch [:pricing {:query-params query-params}]))

   ;; TODO: remove these when backend deploys, only here for backwards compatibility
-  (defroute early-access "/early-access" [{:keys [query-params]}]
+  (defroute early-access "/early-access" {:keys [query-params]}
     (put! nav-ch [:navigate! {:path "/trial/team"
                               :replace-token? true}]))
-  (defroute early-access-type "/early-access/:type" [type {:keys [query-params]}]
+
+  (defroute early-access-type "/early-access/:type" {:keys [type query-params]}
     (put! nav-ch [:navigate! {:path (str "/trial/" type)
                               :replace-token? true}]))

-  (defroute trial "/trial/:type" [type {:keys [query-params]}]
+
+  (defroute trial "/trial/:type" {:keys [type query-params]}
     (put! nav-ch [:trial {:query-params query-params
                           :trial-type type}]))

-  (defroute new-doc "/new" [{:keys [query-params]}]
+
+  (defroute new-doc "/new" {:keys [query-params]}
     (put! nav-ch [:new {:query-params query-params}]))

-  (defroute document #"/document/(\d+)" [doc-id {:keys [query-params]}]
+  (defroute document ["/document/:doc-id" :doc-id #"\d+"] {:keys [doc-id query-params]}
     (put! nav-ch [:document {:document/id (long doc-id)
                              :query-params query-params}])))


Work around bizarre compilation failure

Work around bizarre compilation failure

Somehow it produced javascript that had a space in the middle of what
should've been one token

--- src-cljs/frontend/routes.cljs
+++ src-cljs/frontend/routes.cljs
@@ -77,12 +77,14 @@
     [org repo branch args]
     (open-to-inner! nav-ch :dashboard (merge args {:org org :repo repo :branch branch})))
   (defroute v1-build #"/gh/([^/]+)/([^/]+)/(\d+)"
-    [org repo build-num _ {:keys [_fragment]}]
-    (open-to-inner! nav-ch :build {:project-name (str org "/" repo)
-                                   :build-num (js/parseInt build-num)
-                                   :org org
-                                   :repo repo
-                                   :tab (keyword _fragment)}))
+    [org repo build-num _ maybe-fragment]
+    ;; normal destructuring for this broke the closure compiler
+    (let [_fragment (:_fragment maybe-fragment)]
+      (open-to-inner! nav-ch :build {:project-name (str org "/" repo)
+                                    :build-num (js/parseInt build-num)
+                                    :org org
+                                    :repo repo
+                                    :tab (keyword _fragment)})))
   (defroute v1-project-settings "/gh/:org/:repo/edit"
     [org repo _fragment]
     (open-to-inner! nav-ch :project-settings {:project-name (str org "/" repo)


Bogus values for :page turn into 1

Bogus values for :page turn into 1

--- src-cljs/frontend/routes.cljs
+++ src-cljs/frontend/routes.cljs
@@ -246,9 +246,10 @@
             {:organization/vcs-type (vcs/short-to-long-vcs short-vcs-type)
              :organization/name org-name
              :project/name project-name
-             :page/number (if-let [page (get-in params [:query-params :page])]
-                            (js/parseInt page)
-                            1)}}))
+             :page/number (let [page (get-in params [:query-params :page])]
+                            (if (re-matches #"\d+" page)
+                              (js/parseInt page)
+                              1))}}))

   (defroute v1-project-branch-workflows #"/(gh|bb)/([^/]+)/workflows/([^/]+)/tree/([^/]+)"
     [short-vcs-type org-name project-name branch]


Updated text to be less awkward

Updated text to be less awkward

--- src-cljs/frontend/experiments/nux_bootstrap.cljs
+++ src-cljs/frontend/experiments/nux_bootstrap.cljs
@@ -120,7 +120,7 @@
                    :subheading (html
                                  [:div
                                   [:div "Build and follow projects to populate your dashboard and receive build status emails."]
-                                  [:div "To get started, here are the projects that you have access to."]])}))
+                                  [:div "To get started, here is a list of projects you have access to."]])}))

               (if projects-loaded?
                 (om/build nux-bootstrap-content data)


CLJS-1272: :include-macros description inaccurate in require

Update description to clarifty that `true`
causes macros to be required.

--- src/main/clojure/cljs/repl.cljc
+++ src/main/clojure/cljs/repl.cljc
@@ -1017,7 +1017,7 @@
     lib's namespace in the current namespace.
   :refer takes a list of symbols to refer from the namespace..
   :refer-macros takes a list of macro symbols to refer from the namespace.
-  :include-macros takes a list of macro symbols to refer from the namespace.
+  :include-macros true causes macros from the namespace to be required.

   Flags


Fix message-from-me?

Fix message-from-me?

--- src/antlion_clojure/slack.clj
+++ src/antlion_clojure/slack.clj
@@ -49,7 +49,7 @@
 (defn message-from-me?
   [{:keys [slack res] :as opt}]
   (= (-> slack :rtm-connection :start :self :id)
-     (:id res)))
+     (:user res)))

 (defn post
   [{:keys [connection]} {:keys [channel text optionals]}]


Adding demos for finding a group by name and by member. Also fixing issue when curling without an accept header.

--- access-control-app/src/cmr/access_control/api/routes.clj
+++ access-control-app/src/cmr/access_control/api/routes.clj
@@ -125,7 +125,7 @@

 (defn search-for-groups
   [context headers params]
-  (mt/extract-header-mime-type #{mt/json} headers "accept" true)
+  (mt/extract-header-mime-type #{mt/json mt/any} headers "accept" true)
   (-> (group-service/search-for-groups context params)
       cr/search-response))


added taken and shown

added taken and shown

--- src/babel/english/lexicon.clj
+++ src/babel/english/lexicon.clj
@@ -864,7 +864,8 @@
              :subcat '()}}

    "show" {:synsem {:cat :verb
-                    :sem {:pred :show}}}
+                    :sem {:pred :show
+                          :past-participle "shown"}}}

    "sigh" {:synsem {:cat :verb
                 :sem {:pred :sigh}}}
@@ -930,7 +931,8 @@

    "take"  {:synsem {:cat :verb
                      :sem {:pred :take}}
-            :english {:past "took"}}
+            :english {:past "took"
+                      :past-participle "taken"}}

    "take advantage of" {:english {:past "took advantage of"
                                   :participle "taking advantage of"


Open-file -> clean workspace

Open-file -> clean workspace

--- src/blocks_editor/events.cljs
+++ src/blocks_editor/events.cljs
@@ -33,6 +33,7 @@
             (let [wdom (bx/textToDom content)
                   rname (some-> wdom .-children (aget 0)
                                 .-innerHTML)]
+              (.clear c/workspace)
               (bx/domToWorkspace wdom c/workspace)
               (rf/dispatch [:update-robot-name rname]))
             (do (js/alert (str


Don't sync ongoing builds and handle cancellations of an ongoing sync gracefully. We just pick up where we left off

--- src/buildviz/jenkins/sync.clj
+++ src/buildviz/jenkins/sync.clj
@@ -56,15 +56,23 @@
 (defn- jenkins-build->start-time [{timestamp :timestamp}]
   (tc/from-long timestamp))

+(defn- ignore-ongoing-builds [builds]
+  (filter :result builds))
+
 (defn- all-builds-for-job [jenkins-url sync-start-time job-name]
   (let [safe-build-start-time (t/minus sync-start-time (t/millis 1))]
     (->> (api/get-builds jenkins-url job-name)
-         (take-while #(t/after? (jenkins-build->start-time %) safe-build-start-time)))))
+         (take-while #(t/after? (jenkins-build->start-time %) safe-build-start-time))
+         ignore-ongoing-builds)))
+
+(defn- sync-oldest-first-to-deal-with-cancellation [builds]
+  (sort-by :timestamp builds))

 (defn- sync-jobs [jenkins-url buildviz-url sync-start-time]
   (->> (api/get-jobs jenkins-url)
        (mapcat #(all-builds-for-job jenkins-url sync-start-time %))
        (progress/init "Syncing")
+       sync-oldest-first-to-deal-with-cancellation
        (map (partial add-test-results jenkins-url))
        (map transform/jenkins-build->buildviz-build)
        (map (partial put-to-buildviz buildviz-url))


Fix benchmark macro

Fix benchmark macro

--- benchmarks/caesium/crypto/secretbox_benchmark.clj
+++ benchmarks/caesium/crypto/secretbox_benchmark.clj
@@ -66,7 +66,7 @@
              nonce# (~rand-buf s/noncebytes)
              out# (~rand-buf (+ s/macbytes size#))]
          (println f# (fmt-bytes size#) (mapv type [out# msg# nonce# key#]))
-         (bench (f out# msg# nonce# key#))))))
+         (bench (f# out# msg# nonce# key#))))))

 (deftest ^:benchmark to-buf!-benchmarks
   (println "secretbox to-buf! with direct bufs, pre-allocation")


Log also the cause of a failure when logging

--- src/clj/mdr2/repair/async.clj
+++ src/clj/mdr2/repair/async.clj
@@ -11,9 +11,8 @@
 (defstate repair-consumer
   :start (go-loop []
            (when-let [production (<! queues/repair)]
-             (let [p (repair/repair production)]
-               (when (fail/failed? p)
-                 (log/errorf "Failed to repair %s" production)))
+             (fail/when-let-failed? [cause (repair/repair production)]
+               (log/errorf "Failed to repair %s because %s" production cause))
              (recur)))

   :stop (when repair-consumer


Use the new archive.mozilla.org URL, as ftp.mozilla.org is being phased out.

--- src/clj/medusa/changesets.clj
+++ src/clj/medusa/changesets.clj
@@ -53,7 +53,7 @@
   "Finds the hg revision of associated with the buildid `buildid` on channel `channel`."
   [buildid channel]
   (let [p (split-buildid buildid)
-        build-dir-url (format "http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/%02d/%02d/%02d-%02d-%02d-%02d-%02d-%02d-%s/"
+        build-dir-url (format "https://archive.mozilla.org/pub/mozilla.org/firefox/nightly/%02d/%02d/%02d-%02d-%02d-%02d-%02d-%02d-%s/"
                     (:y p) (:m p) (:y p) (:m p) (:d p) (:hour p) (:min p) (:sec p) channel)]
     (find-build-dir-revision build-dir-url)))

@@ -63,7 +63,7 @@
   (let [p (split-buildid buildid)

         ;; Obtain a list of links to build directories in the desired channel
-        build-dirs-url (format "https://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/%02d/%02d/" (:y p) (:m p))
+        build-dirs-url (format "https://archive.mozilla.org/pub/mozilla.org/firefox/nightly/%02d/%02d/" (:y p) (:m p))
         target (format "%02d-%02d-%02d-%02d-%02d-%02d-%s/" (:y p) (:m p) (:d p) (:hour p) (:min p) (:sec p) channel)
         response (tagsoup/parse build-dirs-url)
         links (elements-by-tag-name response :a)
@@ -77,7 +77,7 @@
               month (if (= (:m p) 0) 12 (dec (:m p)))

               ;; Obtain the last link to build directories in the desired channel in the previous month's folder, which is the build dir of the last build in the previous month
-              prev-build-dirs-url (format "https://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/%02d/%02d/" year month)
+              prev-build-dirs-url (format "https://archive.mozilla.org/pub/mozilla.org/firefox/nightly/%02d/%02d/" year month)
               response (tagsoup/parse prev-build-dirs-url)
               links (elements-by-tag-name response :a)
               target-link (last (filter #(.endsWith (get % 2) build-dirs-suffix) links))
@@ -100,7 +100,7 @@
   [date channel]
   (let [[_ year month day] (re-find #"^(\d{4})-(\d{2})-(\d{2})$" date)
         build-dirs-suffix (format "-%s/" channel)
-        build-dirs-url (format "https://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/%s/%s/" year month)
+        build-dirs-url (format "https://archive.mozilla.org/pub/mozilla.org/firefox/nightly/%s/%s/" year month)
         response (tagsoup/parse build-dirs-url)
         links (elements-by-tag-name response :a)
         build-dirs-links (filter #(.endsWith (get % 2) build-dirs-suffix) links)


Refactor tally to use reductions

Refactor tally to use reductions

--- src/clj/quil/helpers/seqs.clj
+++ src/clj/quil/helpers/seqs.clj
@@ -118,19 +118,16 @@
         (first old)))))

 (defn tally
-  "Cumulative tally. Takes a sequence of numbers and returns a new
-  sequence which is a cumulative tally of the successive additions of
-  each element in the original seq.
+  "Cumulative tally. Returns a lazy sequence of the successive sums
+  of coll, starting with init plus the first element.

-  (take 5 (tally (range))) ;=> [0 1 3 6 10]"
-  ([s] (tally s 0))
-  ([s amount]
-     (lazy-seq
-      (let [nxt-amount (+ (first s) amount)
-            nxt-s (next s)]
-        (cons nxt-amount (if nxt-s
-                           (tally nxt-s nxt-amount)
-                           []))))))
+  (take 5 (tally (range)))   ;=> (0 1 3 6 10)
+  (take 5 (tally 3 (range))) ;=> (3 4 6 9 13)
+  (tally [])                 ;=> ()
+  (tally 100 [])             ;=> ()"
+  ([coll] (tally 0 coll))
+  ([init coll]
+     (rest (reductions + init coll))))

 (defn perlin-noise-seq
   "Generate a lazy infinite sequence of perlin noise values starting from


Fix highscores alignment

Fix highscores alignment

--- src/cljc/robinson/render.cljc
+++ src/cljc/robinson/render.cljc
@@ -1944,7 +1944,7 @@
 ;;                                                                                "days"
 ;;                                                                                "day")
 ;;                                                                                points)))
-          (put-string (state :screen) 1 (+ idx 3) (format "%d. %-20s (%d points)" (inc idx) player-name points) (if (and (= player-name (get-in state [:world :player :name]))
+          (put-string (state :screen) 1 (+ idx 3) (format "%2d.%-20s (%d points)" (inc idx) player-name points) (if (and (= player-name (get-in state [:world :player :name]))
                                                                                (= points (get state :points)))
                                                                                :highlight
                                                                                :white)


Don't send request to server when query is blank

--- src/cljs/subman/handlers.cljs
+++ src/cljs/subman/handlers.cljs
@@ -27,9 +27,11 @@
                (swap! state assoc
                       :in-progress true)
                (swap! state assoc
-                      :results (<! (m/get-search-result val 0
+                      :results (if (is-filled? val)
+                                 (<! (m/get-search-result val 0
                                                         (:language @options)
                                                         (:source @options)))
+                                 [])
                       :offset 0
                       :in-progress false)
                (apply r/change-url!


Added dynamic fields from DB

Added dynamic fields from DB

--- src/cljs/t5pmobile/leave.cljs
+++ src/cljs/t5pmobile/leave.cljs
@@ -9,6 +9,8 @@
             [ajax.core :refer [GET POST]]
             [clojure.string :as str]
             [om-bootstrap.button :as b]
+            [om-bootstrap.panel :as p]
+
   )
   (:import goog.History)
 )
@@ -17,12 +19,36 @@
 (def jquery (js* "$"))
 (defonce app-state (atom  {:leavetypes [] :leavecode "请选择"} ))

+(defn leaves-to-map [leave]
+  (let [
+      newdata {(keyword (get leave "leavecode")) leave }
+    ]
+    newdata
+  )
+)
+
+(defn leaves-to-leavecodes [leave]
+  (let [
+      newdata {:leavecode (get leave "leavecode") :name (get leave "name") }
+    ]
+    newdata
+  )
+
+)

 (defn OnGetLeaveTypes [response]
-
-   (swap! app-state assoc :leavetypes  response)
-
-   (.log js/console (:leavetypes @app-state))
+  ( let [
+    newdata (map leaves-to-map response)
+    leavecodes (map leaves-to-leavecodes response)
+  ]
+
+
+     (swap! app-state assoc :leavetypes  (into {} newdata) )
+     (swap! app-state assoc :leavecodes leavecodes)
+  )
+
+
+   ;(.log js/console (:leavetypes @app-state))

 )

@@ -33,11 +59,16 @@
 )

+
+
+
+
+
 (defn getLeaveTypes [data]
  (.log js/console (str "token: " " " (:token  (first (:token @t5pcore/app-state)))       ))

-  (GET "http://localhost/T5PWebAPI/api/leavetype" {:handler OnGetLeaveTypes
+  (GET "http://localhost/T5PWebAPI/api/leavetype/leavetype2?type=0" {:handler OnGetLeaveTypes
                                             :error-handler error-handler
                                             :headers {:content-type "application/json" :Authorization (str "Bearer "  (:token  (first (:token @t5pcore/app-state)))) }
                                             })
@@ -66,9 +97,22 @@
   )
 )

+(defn setdatepickers []
+  (map (fn [text]
+    (jquery
+     (fn []
+       (-> (jquery (str "#" (get text "fieldcode")) )
+         (.datepicker {})
+       )
+     )
+    )
+    (.log js/console (str "#" (get text "fieldcode") ))
+    )  (get ((keyword (:leavecode @app-state)) (:leavetypes @app-state)) "fields" )
+  )
+)

 (defn alertselected [event]
-   ;(js/alert (str event  "ClojureScript says 'Boo!'" ))
+  ;(js/alert (str event  "ClojureScript says 'Boo!'" ))
   (swap! app-state assoc :leavecode  event)

   (jquery
@@ -78,18 +122,29 @@
      )
    )
   )
-
+
+   ;(.log js/console (str "#" "leavefromdate" ))
+
+    (jquery
+     (fn []
+       (-> (jquery (str "#" "leavefromdate") )
+         (.datepicker {})
+       )
+     )
+    )
 )

 (defcomponent leave-page-view [data owner]
   (did-mount [_]
     (onMount data)
   )
+  (did-update [this prev-props prev-state]
+    ;(.log js/console "did updated!!!!!!!!!!!!!" )
+    (setdatepickers)
+  )
   (render [_]
-    (dom/div {:className "panel panel-primary"}
-      (dom/div {:className "panel-heading"}
-        (dom/h3 {:className "panel-title"} "休假申请"
-        )
+    (p/panel (merge {:header (dom/h3 "休假申请" )} {:bs-style "primary"}
+
       )

       (dom/div {:className "panel-body"}
@@ -103,24 +158,38 @@
                 {:id "leavebtngroup" }
                 (b/dropdown {:title (:leavecode @app-state) }
                   (map (fn [item]
-                    (b/menu-item {:key (get item "leavecode")  :on-select (fn [e](alertselected e))   } (get item "chinese"))
-                    )(:leavetypes data)
+                    (b/menu-item {:key (:leavecode item)  :on-select (fn [e](alertselected e))   } (:name item))
+                    )(:leavecodes data)
                   )
                 )
               )
             )
           )

-
-          (dom/div {:className "form-group"}
-            (dom/label {:className "col-sm-2 control-label"}
-              (dom/span {:className "glyphicon glyphicon-time green"} "开始日期")
-              (dom/span {:style {:color "Red"}} "*")
-            )
-            (dom/div {:className "col-sm-10"}
-              (dom/input {:type "text" :id "datepicker"})
-            )
+          (map (fn [text]
+            (dom/div {:className "form-group"}
+              (dom/label {:className "col-sm-2 control-label"}
+                (dom/span {} (get text "name"))
+                (if ( = (get text "required") true )
+                  (dom/span {:style {:color "Red"}} "*")
+                )
+              )
+              (dom/div {:className "col-sm-10"}
+                (cond
+                  (= (get text "fieldtype") 1)
+                    (dom/input {:type "text" :id (get text "fieldcode")})
+                  (= (get text "fieldtype") 0)
+                    (dom/input {:type "text" :id (get text "fieldcode")})
+                )
+
+
+              )
+            )
+            )  (get ((keyword (:leavecode data)) (:leavetypes @app-state)) "fields" )
           )
+
+
+
         )
       )
     )


[#797] WIP Analizing splitable chars in text values

--- backend/src/akvo/lumen/import.clj
+++ backend/src/akvo/lumen/import.clj
@@ -71,6 +71,56 @@
   (sql-value [v] (val->geometry-pgobj v)))

+(defn l [t o]
+  (log/error t o)
+  o)
+
+
+(frequencies (re-seq (re-pattern "[^a-zA-Z0-9\\s]") "lkjasd f&8(/&"))
+
+
+(def regex "[^a-zA-Z0-9\\s]")
+
+(let [data ["uss/" "a·bc1&&&&???????23de?f" "lk&&&&&&&jasdf& 8"]
+      res (->>
+           data
+           (reduce
+            (fn [c v]
+              (let [f (frequencies (re-seq (re-pattern regex) v))]
+                (reduce (fn [c2 [k v2]]
+                          (assoc c2 k {:max-by-row (max v2 (get-in c2 [k :by-row] 0))
+                                       :row-coincidences (inc (get-in c2 [k :row-coincidences] 0))
+                                       :total (+ v2 (get-in c2 [k :total] 0))}))
+                        c f)))
+            {}))]
+  {:total-count (count data)
+   :max-by-row  (seq (into (sorted-map-by >) (group-by (fn [c] (:max-by-row (val c))) res)))
+   :row-coincidences  (seq (into (sorted-map-by >) (group-by (fn [c] (:row-coincidences (val c))) res)))
+   :total-rows (seq (into (sorted-map-by >) (group-by (fn [c] (:total (val c))) res)))})
+
+
+{:max-by-row
+ [[8
+   [["&" {:max-by-row 8, :row-coincidences 2, :total 12}]
+    ["?" {:max-by-row 8, :row-coincidences 1, :total 8}]]]
+  [1
+   [["/" {:max-by-row 1, :row-coincidences 1, :total 1}]
+    ["·" {:max-by-row 1, :row-coincidences 1, :total 1}]]]],
+ :row-coincidences
+ [[2 [["&" {:max-by-row 8, :row-coincidences 2, :total 12}]]]
+  [1
+   [["/" {:max-by-row 1, :row-coincidences 1, :total 1}]
+    ["·" {:max-by-row 1, :row-coincidences 1, :total 1}]
+    ["?" {:max-by-row 8, :row-coincidences 1, :total 8}]]]],
+ :total-count 3,
+ :total-rows
+ [[12 [["&" {:max-by-row 8, :row-coincidences 2, :total 12}]]]
+  [8 [["?" {:max-by-row 8, :row-coincidences 1, :total 8}]]]
+  [1
+   [["/" {:max-by-row 1, :row-coincidences 1, :total 1}]
+    ["·" {:max-by-row 1, :row-coincidences 1, :total 1}]]]]}
+
+

 (defn do-import
   "Import runs within a future and since this is not taking part of ring
@@ -80,10 +130,12 @@
     (try
       (let [spec (:spec (data-source-spec-by-job-execution-id conn {:job-execution-id job-execution-id}))]
         (with-open [importer (import/dataset-importer (get spec "source") config)]
-          (let [columns (import/columns importer)]
+          (let [columns (import/columns importer)
+                records (import/records importer)]
             (import/create-dataset-table conn table-name columns)
             (import/add-key-constraints conn table-name columns)
-            (doseq [record (map import/coerce-to-sql (import/records importer))]
+            (doseq [record (map (comp import/coerce-to-sql (partial l :raw-row)) records)]
+              (l :coerced record)
               (jdbc/insert! conn table-name record))
             (successful-import conn job-execution-id table-name columns spec claims data-source))))
       (catch Throwable e


Remove unused type attr from import entry spec.

--- backend/src/uxbox/cli/collimp.clj
+++ backend/src/uxbox/cli/collimp.clj
@@ -31,12 +31,11 @@
 (def ^:const +imates-uuid-ns+ #uuid "3642a582-565f-4070-beba-af797ab27a6e")

 (s/def ::name string?)
-(s/def ::type keyword?)
 (s/def ::path string?)
 (s/def ::regex us/regex?)

 (s/def ::import-entry
-  (s/keys :req-un [::name ::type ::path ::regex]))
+  (s/keys :req-un [::name ::path ::regex]))

 ;; --- CLI Helpers


Increases address reload timeout

Increases 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 4000
+                        :ms 6000
                         :db-path [:district0x-reload-address-interval]}}))


Add memoization for schema and statement validation

--- src/graphql_clj/validator.clj
+++ src/graphql_clj/validator.clj
@@ -83,9 +83,9 @@
     schema
     (update schema :type-system-definitions concat (:type-system-definitions intro/introspection-schema))))

-(defn- validate-schema*
+(defn- validate-schema**
   "Inject the introspection schema to form a complete schema definition.
-   Then, do a 2 pass validation:
+   Then, do a 2 pass validation (without error handling):
    - 1) Add specs and validate that all types resolve.
    - 2) Apply validation rules and final transformations."
   [schema rules1 rules2]
@@ -96,8 +96,8 @@
         second-pass (visitor/visit-document document state rules2)]
     (assoc-in second-pass [:state :schema] (ts/mapify-schema (:document second-pass)))))

-(defn validate-statement*
-  "Do a 2 pass validation of a statement"
+(defn validate-statement**
+  "Do a 2 pass validation of a statement (without error handling)"
   [document' state rules1 rules2]
   (guard-parsed "schema" state)
   (guard-parsed "statement" document')
@@ -107,16 +107,22 @@

 ;; Public API

-(defn validate-schema
+(defn validate-schema*
+  "Validate a schema with error handling, but without memoization"
   ([schema]
-   (validate-schema schema second-pass-rules-schema))
+   (validate-schema* schema second-pass-rules-schema))
   ([schema rules2]
-   (:state (validate #(validate-schema* schema first-pass-rules rules2))))) ;; Unwrap state - it now encompasses the original schema
+   (:state (validate #(validate-schema** schema first-pass-rules rules2))))) ;; Unwrap state - it now encompasses the original schema

-(defn validate-statement
+(def validate-schema (memoize validate-schema*))
+
+(defn validate-statement*
+  "Validate a statement with error handling, but without memoization"
   ([document state]
-   (validate-statement document state second-pass-rules-statement))
+   (validate-statement* document state second-pass-rules-statement))
   ([document state rules2]
    (if (:errors state) ;; Don't try to validate a statement if the schema is invalid
      state
-     (validate #(validate-statement* document state first-pass-rules rules2)))))
+     (validate #(validate-statement** document state first-pass-rules rules2)))))
+
+(def validate-statement (memoize validate-statement*))


[QuickFix] Basic 404 page added.

[QuickFix] Basic 404 page added.

--- src/hellhound/routes/core.clj
+++ src/hellhound/routes/core.clj
@@ -8,6 +8,7 @@
   (:require [bidi.bidi        :refer [match-route path-for] :as bidi]
             [hellhound.system :refer [get-system]]
             [bidi.ring        :as biring]
+            [clojure.pprint   :refer [pprint]]
             [taoensso.timbre  :as log]))

@@ -20,7 +21,8 @@
 (defn route-table
   "Return the current route table. Use this function for debuggin purposes."
   []
-  @__routes__)
+
+   @__routes__)

 (defn not-found
   "Default route for bidi. This means that a route that does not
@@ -29,7 +31,11 @@
   ;; TODO: We should provide a better view of routes here
   {:status 404
    :headers {"Content-Type" "text/html"}
-   :body (clojure.string/replace (route-table) "\n" "
")})
+   :body (str "
"
+              (clojure.string/replace (with-out-str
+                                        (pprint (route-table)))
+                                      "\n" "
")
+              "
")})

 (defn hellhound-routes
@@ -55,15 +61,3 @@
 (defn redirect-to-not-found
   []
   [true not-found])
-
-(defn make-route
-  "Create data sctructure that represents a `bidi` route."
-  ([method url func]
-   (make-route method url func {}))
-
-  ([method url func options]
-   (let [{:keys [tag]} options
-         handler (if (nil? tag)
-                   func
-                   (bidi/tag func tag))]
-     {method [url handler]})))


Use latest cider.

Use latest cider.

No need to specify cider-nrepl in both `:plugins` *and* `:dependencies`.
(Should only be in `:plugins`)

--- lein/.lein/profiles.d/cider.clj
+++ lein/.lein/profiles.d/cider.clj
@@ -1,7 +1,6 @@
-{:plugins [[cider/cider-nrepl "0.15.0"]
-           [refactor-nrepl "2.3.1"]]
- :dependencies [[cider/cider-nrepl "0.15.0"]
-                [acyclic/squiggly-clojure "0.1.6"]]
+{:plugins [[cider/cider-nrepl "0.15.1-SNAPSHOT"]
+           [refactor-nrepl "2.4.0-SNAPSHOT"]]
+ :dependencies [[acyclic/squiggly-clojure "0.1.8"]]
  :env {:squiggly
        ;; Quote options to avoid warnings
        ;; introduced with `lein-environ 1.1.0` plugin


Remove contrib dependencies from r.m.lint.

--- ring-devel/src/ring/middleware/lint.clj
+++ ring-devel/src/ring/middleware/lint.clj
@@ -1,6 +1,5 @@
 (ns ring.middleware.lint
   "Lint Ring requests and responses."
-  (:use [clojure.contrib.except :only (throwf)])
   (:require [clojure.set :as set])
   (:import (java.io File InputStream)))

@@ -11,12 +10,12 @@
   [val spec message]
   (try
     (if-not (spec val)
-      (throwf "Ring lint error: specified %s, but %s was not" message (pr-str val)))
+      (throw (Exception. (format "Ring lint error: specified %s, but %s was not" message (pr-str val)))))
     (catch Exception e
       (if-not (re-find #"^Ring lint error: " (.getMessage e))
-        (throwf
+        (throw (Exception. (format
           "Ring lint error: exception occured when checking that %s on %s: %s"
-          message (pr-str val) (.getMessage e))
+          message (pr-str val) (.getMessage e))))
         (throw e)))))

 (defn- check-req


Fix atlasdb.clj

Fix atlasdb.clj

--- atlasdb-jepsen-tests/src/jepsen/atlasdb.clj
+++ atlasdb-jepsen-tests/src/jepsen/atlasdb.clj
@@ -31,7 +31,7 @@
         (c/upload "resources/atlasdb/timelock.yml" "/atlasdb-timelock-server/var/conf")
         (c/exec :sed :-i (format "s/<HOSTNAME>/%s/" (name node)) "/atlasdb-timelock-server/var/conf/timelock.yml")
         (info node "Starting timelock server")
-        (c/exec :env "/usr/lib/jvm/java-8-oracle" "/atlasdb-timelock-server/service/bin/init.sh" "start")
+        (c/exec :env "JAVA_HOME=/usr/lib/jvm/java-8-oracle" "/atlasdb-timelock-server/service/bin/init.sh" "start")
         (info node "Waiting until timelock cluster is ready")
         (TimestampClient/waitUntilHostReady (name node))
         (TimestampClient/waitUntilTimestampClusterReady '("n1" "n2" "n3" "n4" "n5"))))


Mention :keep-non-project-classes in sample.project.clj.

--- sample.project.clj
+++ sample.project.clj
@@ -44,6 +44,10 @@
   ;; Before fetching dependencies, the contents of the lib/ directory
   ;; will get deleted unless this is set to true.
   :disable-implicit-clean false
+  ;; Normally .class files will be deleted if they are do not have a
+  ;; correspoinding package in the src/ directory. This flag disables
+  ;; that behaviour.
+  :keep-non-project-classes false
   ;; Load these namespaces on startup to pick up hooks from
   ;; them. Hooks are generally included in plugins.
   :hooks [leiningen.hooks.difftest]


Update Neko dependency

Update Neko dependency

--- sample/project.clj
+++ sample/project.clj
@@ -17,7 +17,7 @@
   ;; :java-only true

   :dependencies [[org.clojure-android/clojure "1.7.0-alpha5" :use-resources true]
-                 [neko/neko "3.2.0-preview2"]]
+                 [neko/neko "3.2.0-preview3"]]

   :profiles {:default [:dev]


slightly more concise impl :sob:

slightly more concise impl :sob:

--- src/metabase/api/meta/table.clj
+++ src/metabase/api/meta/table.clj
@@ -26,9 +26,8 @@
     (-> (sel :many Table :active true :db_id [in db-ids] (order :name :ASC))
         (hydrate :db)
         ;; if for some reason a Table doesn't have rows set then set it to 0 so UI doesn't barf
-        (#(map (fn [{:keys [rows] :as table}]
-                 (cond-> table
-                   (not rows) (assoc :rows 0)))
+        (#(map #(cond-> %
+                  (not (:rows %)) (assoc :rows 0))
                %)))))


Add Torrent figure 8 cue.

Add Torrent figure 8 cue.

--- src/afterglow/examples.clj
+++ src/afterglow/examples.clj
@@ -1175,6 +1175,42 @@
                (move/pan-tilt-effect "can can element" direction (show/fixtures-named (:key head)))))]
     (apply fx/scene "Can Can" fx)))

+;; TODO: It looks like this and the can-can chase are just lissajous genrators with different
+;;       values for A and B and delta. So consider pulling that part into a function both can
+;;       use.
+(defn torrent-8
+  "A effect that moves the torrents in a figure 8."
+  [& {:keys [bars cycles stagger spread pan-min pan-max tilt-min tilt-max]
+      :or {bars 1 cycles 1 stagger 0 spread 0 pan-min -45 pan-max 45 tilt-min 0 tilt-max 45}}]
+  (let [bars (params/bind-keyword-param bars Number 1)
+        cycles (params/bind-keyword-param cycles Number 1)
+        stagger (params/bind-keyword-param stagger Number 0)
+        spread (params/bind-keyword-param spread Number 0)
+        pan-min (params/bind-keyword-param pan-min Number -45)
+        pan-max (params/bind-keyword-param pan-max Number 45)
+        tilt-min (params/bind-keyword-param tilt-min Number 0)
+        tilt-max (params/bind-keyword-param tilt-max Number 45)
+        pan-ratio (params/build-param-formula Number #(/ (* 2 %1) %2) bars cycles)
+        tilt-ratio (params/build-param-formula Number #(/ %1 %2) bars cycles)
+        fx (for [head [{:key :torrent-1 :phase 0.0 :pan-offset 1}
+                       {:key :torrent-2 :phase 0.5 :pan-offset -1}]]
+             (let [head-phase (params/build-param-formula Number #(+ 0.25 (* % (:phase head 0))) stagger)
+                   tilt-osc (oscillators/sine :interval :bar :interval-ratio tilt-ratio :phase head-phase)
+                   tilt-param (oscillators/build-oscillated-param tilt-osc :min tilt-min :max tilt-max)
+                   pan-osc (oscillators/sine :interval :bar :interval-ratio pan-ratio :phase head-phase)
+                   head-pan-min (params/build-param-formula Number #(+ (if (zero? (:phase head)) %1 (- %2))
+                                                                       (* (:pan-offset head 0) %3))
+                                                            pan-min pan-max spread)
+                   head-pan-max (params/build-param-formula Number #(+ (if (zero? (:phase head)) %1 (- %2))
+                                                                       (* (:pan-offset head 0) %3))
+                                                            pan-max pan-min spread)
+                   pan-param (oscillators/build-oscillated-param pan-osc
+                                                                 :min head-pan-min
+                                                                 :max head-pan-max)
+                   direction (params/build-pan-tilt-param :pan pan-param :tilt tilt-param)]
+               (move/pan-tilt-effect "t8 element" direction (show/fixtures-named (:key head)))))]
+    (apply fx/scene "Torrent 8" fx)))
+
 (defn make-movement-cues
   "Create a page of with some large scale and layered movement
   effects. And miscellany which I'm not totally sure what to do with
@@ -1231,9 +1267,27 @@
                                          {:key "pan-max" :name "Pan max" :min -180 :max 180
                                           :centered true :resolution 0.5 :start 0}
                                          {:key "tilt-min" :name "Tilt min" :min -180 :max 180
-                                          :centered true :resolution 0.5 :start -100}
+                                          :centered true :resolution 0.5 :start -60}
                                          {:key "tilt-max" :name "Tilt max" :min -180 :max 180
                                           :centered true :resolution 0.5 :start 100}]
+                             :color :yellow :end-keys [:movement]))
+
+    (show/set-cue! (+ x-base 3) (+ y-base 3)
+                   (cues/cue :move-torrents
+                             (fn [var-map] (cues/apply-merging-var-map var-map torrent-8))
+                             :variables [{:key "bars" :name "Bars" :min 1 :max 8 :type :integer :start 2}
+                                         {:key "cycles" :name "Cycles" :min 1 :max 8 :type :integer :start 1}
+                                         {:key "stagger" :name "Stagger" :min 0 :max 4 :start 0}
+                                         {:key "spread" :name "Spread" :min -45 :max 45
+                                          :centered true :resolution 0.25 :start 0}
+                                         {:key "pan-min" :name "Pan min" :min -180 :max 180
+                                          :centered true :resolution 0.5 :start -75}
+                                         {:key "pan-max" :name "Pan max" :min -180 :max 180
+                                          :centered true :resolution 0.5 :start 90}
+                                         {:key "tilt-min" :name "Tilt min" :min -180 :max 180
+                                          :centered true :resolution 0.5 :start -10}
+                                         {:key "tilt-max" :name "Tilt max" :min -180 :max 180
+                                          :centered true :resolution 0.5 :start 75}]
                              :color :yellow :end-keys [:movement]))

     ;; A chase which overlays on other movement cues, gradually taking over the lights


Be more flexible about predicate names

Be more flexible about predicate names

--- src/aurora/compiler/datalog.cljs
+++ src/aurora/compiler/datalog.cljs
@@ -67,28 +67,33 @@
       #{}
       (match/vars clause))))

+(defn pred-name [clause]
+  (or (and (map? clause) (:name clause))
+      (and (vector? clause) (first clause))
+      ::any))
+
 (defn preds-in [clause]
   ;; TODO check not nil
   (condp op? clause
-    '+ed #{(:name (second clause))}
-    '-ed #{(:name (second clause))}
+    '+ed #{(pred-name (second clause))}
+    '-ed #{(pred-name (second clause))}
     'set (apply clojure.set/union (map preds-in (nthnext clause 3)))
     (if (seq? clause)
       #{}
-      #{(:name clause)})))
+      #{(pred-name clause)})))

 (defn preds-out [clause]
   ;; TODO check not nil
   (condp op? clause
-    '+ #{(:name (second clause))}
-    '- #{(:name (second clause))}
+    '+ #{(pred-name (second clause))}
+    '- #{(pred-name (second clause))}
     '+s #{::any}
     '-s #{::any}
-    '> (let [from-name (:name (nth clause 1))
-             to-name (:name (nth clause 2))]
+    '> (let [from-name (pred-name (nth clause 1))
+             to-name (pred-name (nth clause 2))]
          (check from-name)
-         (check (or (nil? to-name) (= from-name to-name)))
-         #{(:name (nth clause 1))})
+         (check (or (= ::any to-name) (= from-name to-name)))
+         #{(pred-name (nth clause 1))})
     #{}))

 (defn negs-in [clause]
@@ -100,13 +105,13 @@
 (defn negs-out [clause]
   ;; TODO check not nil
   (condp op? clause
-    '- #{(:name (second clause))}
+    '- #{(pred-name (second clause))}
     '-s #{::any}
-    '> (let [from-name (:name (nth clause 1))
-             to-name (:name (nth clause 2))]
+    '> (let [from-name (pred-name (nth clause 1))
+             to-name (pred-name (nth clause 2))]
          (check from-name)
-         (check (or (nil? to-name) (= from-name to-name)))
-         #{(:name (nth clause 1))})
+         (check (or (= ::any to-name) (= from-name to-name)))
+         #{(pred-name (nth clause 1))})
     #{}))

 (def empty-q
@@ -277,6 +282,8 @@
 ;; tests

 (comment
+  (enable-console-print!)
+
   ((query [a b _]
           [_ a b]
           (? (integer? a))


Adjustments to previous gathering

Adjustments to previous gathering

--- src/clj/chili_dog_night/data.clj
+++ src/clj/chili_dog_night/data.clj
@@ -50,6 +50,8 @@
                           " "
                           (el/link-to "https://news.vice.com/article/how-us-immigrant-detention-facilities-get-away-with-being-complete-hellholes" "detention centers")
                           [:br]
+                          (el/link-to "https://bfi.org/about-fuller/big-ideas/geodesic-domes" "Fuller's House")
+                          [:br]
                           (el/link-to "http://www.pablopicasso.org/cubism.jsp" "Picasso's")
                           " "
                           (el/link-to "https://en.wikipedia.org/wiki/Cubism" "Cubism")


implement Guru Davinder; more informative Councilman toast

--- src/clj/game/cards-resources.clj
+++ src/clj/game/cards-resources.clj
@@ -108,7 +108,8 @@
    "Councilman"
    {:events {:rez {:req (req (and (#{"Asset" "Upgrade"} (:type target))
                                   (can-pay? state :runner nil [:credit (rez-cost state :corp target)])))
-                   :effect (req (toast state :runner "Click Councilman to derez the asset or upgrade that was just rezzed" "info"))}}
+                   :effect (req (toast state :runner (str "Click Councilman to derez " (:title target)
+                                                          " just rezzed in " (zone->name (second (:zone target)))) "info"))}}
     :abilities [{:prompt "Choose an asset or upgrade that was just rezzed"
                  :choices {:req #(and (rezzed? %)
                                       (or (is-type? % "Asset") (is-type? % "Upgrade")))}
@@ -311,6 +312,25 @@
                                       {:effect (effect (gain :credit 1)) :msg "gain 1 [Credits]"}
                                       {:effect (effect (trash card)) :msg "trash Grifter"})]
                              (resolve-ability state side ab card targets)))}}}
+
+   "Guru Davinder"
+   {:events {:pre-damage
+             {:req (req (or (= target :meat) (= target :net)))
+              :msg (msg "prevent all " (if (= target :meat) "meat" "net") " damage")
+              :effect (req (damage-prevent state side :meat Integer/MAX_VALUE)
+                           (damage-prevent state side :net Integer/MAX_VALUE)
+                           (if (< (:credit runner) 4)
+                             (trash state side card)
+                             (resolve-ability
+                               state :runner
+                               {:optional
+                                {:prompt "Pay 4 [Credits] to prevent trashing Guru Davinder?"
+                                 :player :runner
+                                 :yes-ability {:effect (effect (lose :runner :credit 4)
+                                                               (system-msg (str "pays 4 [Credits] to prevent Guru Davinder "
+                                                                                "from being trashed")))}
+                                 :no-ability {:effect (effect (trash card))}}}
+                              card nil)))}}}

    "Hades Shard"
    {:abilities [{:msg "access all cards in Archives"


make Jak Sinclair ask for runnable servers

--- src/clj/game/cards-resources.clj
+++ src/clj/game/cards-resources.clj
@@ -392,7 +392,7 @@
    "Jak Sinclair"
    (let [ability {:label "Make a run (start of turn)"
                   :prompt "Choose a server"
-                  :choices (req servers)
+                  :choices (req runnable-servers)
                   :msg (msg "make a run on " target " during which no programs can be used")
                   :effect (effect (run target))}]
    {:install-cost-bonus (req [:credit (* -1 (:link runner))])


fix typo

fix typo

--- src/cljs/bulldog/components.cljs
+++ src/cljs/bulldog/components.cljs
@@ -6,7 +6,7 @@

 (defn onChange
-  "Creates input callpack"
+  "Creates input callback"
   [value component]
   (fn [event]
     (om/set-state!


import badge button description

import badge button description

--- src/cljs/salava/badge/ui/my.cljs
+++ src/cljs/salava/badge/ui/my.cljs
@@ -6,7 +6,7 @@
     [clojure.set :as set :refer [intersection]]
     [clojure.string :refer [upper-case]]
     [salava.core.ui.ajax-utils :as ajax]
-    [salava.core.ui.helper :as h :refer [unique-values navigate-to path-for  not-activated? private? js-navigate-to current-path current-route-path]]
+    [salava.core.ui.helper :as h :refer [unique-values navigate-to path-for  not-activated? private? js-navigate-to current-path current-route-path plugin-fun]]
     [salava.core.ui.notactivated :refer [not-activated-banner]]
     [salava.core.ui.layout :as layout]
     [salava.core.ui.grid :as g]
@@ -74,6 +74,12 @@
     true false))

+(defn import-button-description []
+  (let [func (first (plugin-fun (session/get :plugins) "block" "importbadgetext"))
+        user-lang (session/get-in [:user :language] "en")
+        block (func user-lang)]
+    (if block [block] [:div ""])))
+
 (defn badge-grid [state]
   (let [badges (:badges @state)
         order (keyword (:order @state))
@@ -96,7 +102,8 @@
                   [:div {:id "add-element-icon"}
                    [:i {:class "fa fa-plus"}]]
                   [:div {:id "add-element-link"}
-                   (t :badge/Import)]]]]]])]
+                   (t :badge/Import)
+                   [import-button-description]]]]]]])]
           (doall
             (for [element-data badges]
               (if (badge-visible? element-data state)


Make labels partially transparent when rolled over

--- src/clojure/nightmod/screens.clj
+++ src/clojure/nightmod/screens.clj
@@ -298,8 +298,15 @@
           :background (shape e :rect 0 0 width height c1 c1 c2 c2)
           e))))

+  :on-ui-enter
+  (fn [screen entities]
+    (when (some-> (:actor screen) (actor! :get-parent) image-text-button?)
+      (actor! (:actor screen) :set-color (color :white))))
+
   :on-ui-exit
   (fn [screen entities]
+    (when (some-> (:actor screen) (actor! :get-parent) image-text-button?)
+      (actor! (:actor screen) :set-color 1 1 1 0.5))
     (if (or (some-> (:actor screen) image-text-button?)
             (some-> (:actor screen) (actor! :get-parent) image-text-button?))
       (set-cursor-image! (:cursor-image screen))


Implement event go loop

Implement event go loop

--- src/clojure_fabric/event_hub.clj
+++ src/clojure_fabric/event_hub.clj
@@ -15,8 +15,11 @@
 (ns clojure-fabric.event-hub
   (:require [clojure-fabric.proto :as proto]
             [clojure-fabric.crypto-suite :as crypto]
-            [clojure.core.async :as async])
+            [clojure-fabric.utils :as utils]
+            [clojure.core.async :as async]
+            [clojure-fabric.core :as core])
   (:import io.grpc.stub.StreamObserver
+           [clojure_fabric.proto Block ChaincodeEvent]
            [com.google.protobuf ByteString]
            io.grpc.ManagedChannel
            org.hyperledger.fabric.protos.msp.Identities$SerializedIdentity
@@ -94,9 +97,6 @@
 ;; disconnect
 ;; get-peer-address
 ;; connected?
-;; register-block-event
-;; register-chaincode-event
-;; register-tx-event
 ;; set-peer-address
 ;; unregister-block-event
 ;; unregister-chaincode-event
@@ -107,21 +107,6 @@
 ;; remove-chaincode-interest
 ;; get-interested-events
 ;; receive (i/f - block or chaincode)
-
-#_
-(defonce event-type {:register
-                     :block
-                     :chaincode
-                     :rejection
-                     :filtered-block})
-
-(defonce default-sliding-buffer-size 32)
-;; Block event - any block events
-(defonce event-channels (atom []))
-;; Transaction event - matching tx-id
-(defonce tx-id-event-channels (atom {}))
-;; Chaincode event - matching chaincode-id
-(defonce chaincode-channels (atom {}))

 (defonce block-metadata-index-map
   (zipmap [:signatures :last-config :transactions-filter :orderer]
@@ -180,33 +165,132 @@
            :illegal-writeset
            :invalid-other-reason]))

+#_
+(defonce event-type {:register
+                     :block
+                     :chaincode
+                     :rejection
+                     :filtered-block})
+
+(defonce default-sliding-buffer-size 32)
+(defonce command-ch (chan))
+;; Block event - any block events
+(defonce block-event-chan (async/sliding-buffer default-sliding-buffer-size))
+(defonce block-event-handlers (atom {}))
+;; Transaction event - matching tx-id
+(defonce tx-id->chan-fn-map (atom {}))
+;; Chaincode event - matching chaincode-id
+(defonce chaincode-id->chan-fn-map (atom {}))
+
+(defrecord ChanFun [ch fn])
+(defn make-chan-fun
+  [fn]
+  (->ChanFun (async/chan) fn))
+
+(defn register-block-event
+  [fn-name fn]
+  (swap! block-event-handlers assoc fn-name fn))
+
+(defn unregister-block-event
+  [fn-name]
+  (swap! block-event-handlers dissoc fn-name))
+
+(defn- %unregister-event
+  [id ref]
+  (when-let [existing (get (deref ref) id)]
+    (async/close! (:ch existing))
+    (swap! ref dissoc id))
+  (async/put! command-ch :refresh))
+
+(defn- %register-event
+  [id fn ref]
+  (when-let [existing (get (deref ref) id)]
+    (async/close! (:ch existing)))
+  (swap! ref assoc id (make-chan-fun fn))
+  (async/put! command-ch :refresh))
+
+(defn register-tx-event
+  [tx-id fn]
+  (%register-event tx-id fn tx-id->chan-fn-map))
+
+(defn unregister-tx-event
+  [tx-id]
+  (%unregister-event tx-id tx-id->chan-fn-map))
+
+(defn register-chaincode-event
+  [chaincode-id fn]
+  (%register-event chaincode-id fn chaincode-id->chan-fn-map))
+
+(defn unregister-chaincode-event
+  [chaincode-id]
+  (%unregister-event chaincode-id chaincode-id->chan-fn-map))
+
+(defn get-all-event-chans
+  []
+  (letfn [(%get-all-chans [ref]
+            (map :ch (vals (deref ref))))]
+    `[~command-ch
+      ~block-event-chans
+      ~@(%get-all-chans tx-id->chan-fn-map)
+      ~@(%get-all-chans chaincode-id->chan-fn-map)]))
+
 ;; Block event is proto/Block
+;; Chaincode event is proto/ChaincodeEvent
 (defrecord TxEvent [tx-id status])

-(defn tx-id->channel [tx-id]
-  :fixme)
+(defonce event-go-loop
+  (async/go-loop []
+    (let [[v ch] (async/alts! (get-all-event-chans))]
+      (cond (and (= ch command-ch) (= v :refresh))
+            :renew-get-all-event-chans
+
+            (instance? Block v)
+            (doseq [f @block-event-handlers]
+                  (utils/ignore-errors
+                   (f v)))
+
+            (instance? TxEvent v)
+            (utils/ignore-errors
+             ((:fn (get @tx-id->chan-fn-map (:tx-id v))) v))
+
+            (instance? ChaincodeEvent v)
+            (utils/ignore-errors
+             ((:fn (get @chaincode-id->chan-fn-map (:chaincode-id v))) v)))
+      (recur))))
+
+(defn- %id->ch
+  [id ref]
+  (-> (deref ref) (get id) (:ch)))
+
+(defn tx-id->chan
+  [tx-id]
+  (%id->ch tx-id tx-id->chan-fn-map))
+
+(defn chaincode-id->chan
+  [chaincode-id]
+  (%id->ch chaincode-id chaincode-id->chan-fn-map))

 (defn deliver-block-events-to-channels
   [^Common$Block proto-block]
   (let [clj-block (proto/proto->clj proto-block (proto/parse-trees :block))]
     ;; 1. Block Event on all channels
-    (async/put! block-channel clj-block)
+    (async/put! block-event-channel clj-block)
     (doseq [[data code] (map list
                              (:data clj-block)
                              (-> (:metadata clj-block)
                                  (:metadata)
                                  (nth (block-metadata-index-map :transactions-filter))
                                  (.toByteArray)))]
-      (let [payload (get data :payload)
+      (let [payload (:payload data)
             channel-header (get-in payload [:header :channel-header])]
         ;; 2. Transaction Event with tx-id
-        (when-let [ch (tx-id->channel tx-id)]
+        (when-let [ch (tx-id->chan tx-id)]
           (async/put! ch (make-TxEvent (:tx-id channel-header) code)))
         ;; 3. Chaincode event
         (when (= (:type channel-header) (proto/header-types :endorser-transaction))
           (let [chaincode-event (get-in payload [:data :actions 0 :payload :action
                                                  :proposal-response-payload :extension :events])]
-            (when-let [ch (chaincode-id->channel (:chaincode-id chaincode-event))]
+            (when-let [ch (chaincode-id->chan (:chaincode-id chaincode-event))]
               (async/put! ch chaincode-event))))))))

 (defn transaction-observer


Highlight correctly in Insufficient/Extra input cases

--- src/pinpointer/formatter.cljc
+++ src/pinpointer/formatter.cljc
@@ -16,11 +16,12 @@
   [:span [:escaped *highlighting-mark*] x [:escaped *highlighting-mark*]])

 (defn- wrap [f {:keys [trace] :as printer} x]
-  (if (= x (:val (first trace)))
-    (if (= (count trace) 1)
-      (highlight (f (:base-printer printer) x))
-      (render (first trace) f printer x))
-    (f (:base-printer printer) x)))
+  (let [frame (first trace)]
+    (if (= x (:val frame))
+      (if (and (= (count trace) 1) (not (:reason frame)))
+        (highlight (f (:base-printer printer) x))
+        (render frame f printer x))
+      (f (:base-printer printer) x))))

 (defn pop-trace [printer]
   (update printer :trace rest))
@@ -162,23 +163,40 @@
 (defmethod render `s/merge [frame _ printer x]
   (render-next printer x))

+(defn- render-regex [{:keys [reason steps] :as frame} printer x]
+  (cond (= reason "Extra input")
+        (let [printer (:base-printer printer)]
+          (render-coll frame printer x
+            (fn [i v]
+              (cond-> (visit/visit printer v)
+                (>= i (first steps)) highlight))))
+
+        (let [next-frame (second (:trace printer))]
+          (and next-frame (= (:reason next-frame) "Insufficient input")))
+        (highlight (visit/visit (:base-printer printer) x))
+
+        (empty? steps)
+        (render-next printer x)
+
+        :else (render-coll frame printer x)))
+
 (defmethod render `s/cat [frame _ printer x]
-  (render-coll frame printer x))
+  (render-regex frame printer x))

 (defmethod render `s/& [frame _ printer x]
-  (render-coll frame printer x))
+  (render-regex frame printer x))

 (defmethod render `s/alt [frame _ printer x]
-  (render-coll frame printer x))
+  (render-regex frame printer x))

 (defmethod render `s/? [frame _ printer x]
-  (render-coll frame printer x))
+  (render-regex frame printer x))

 (defmethod render `s/* [frame _ printer x]
-  (render-coll frame printer x))
+  (render-regex frame printer x))

 (defmethod render `s/+ [frame _ printer x]
-  (render-coll frame printer x))
+  (render-regex frame printer x))

 (defmethod render `s/multi-spec [frame _ printer x]
   (render-next printer x))


start work in issuer search

start work in issuer search

--- src/cljs/salava/extra/application/ui/issuer.cljs
+++ src/cljs/salava/extra/application/ui/issuer.cljs
@@ -18,11 +18,14 @@
     (subs text 1)
     text))

-(defn all-connections [state]
+(defn create-favourite-list [favourites all]
+ (sort-by :issuer_content_name (distinct-by :issuer_content_id (filter (fn [app] (some #(= (:id %) (:issuer_content_id app)) favourites)) all))))
+
+(defn get-favourites [state]
   (ajax/GET
     (path-for (str "/obpv1/social/connections_issuer"))
     {:handler (fn [data]
-                (swap! state assoc :all-connections data)
+                (swap! state assoc :favourites (create-favourite-list data (:all-applications @state)))
                 )}))

 (defn init-issuer-applications [state]
@@ -36,8 +39,9 @@
                 :order (trim order)
                 :followed show-followed-only}
        :handler (fn [data]
-                  (swap! state assoc :all-issuer-applications (:applications data) )
-                  (all-connections state))})))
+                  (swap! state assoc :all-issuer-applications (:applications data)
+                                     :show-favourite-issuers false)
+                  (get-favourites state))})))

 (defn fetch-badge-adverts [state]
   (let [{:keys [user-id country-selected name recipient-name issuer-name order tags show-followed-only]} @state]
@@ -84,6 +88,30 @@
     [:img.profile-picture
      {:src (if (re-find #"^file/" path) (str "/" path) path)
       :style {:width "50px" :padding-right "10px"}}]))
+
+
+
+(defn text-field [key label placeholder state]
+  (let [applications (cursor state [:all-applications])
+        search-atom (cursor state [key])
+        favourites (cursor state [:favourites])
+        show-favourites-atom (cursor state [:show-favourite-issuers])
+        current-application-list (if @show-favourites-atom favourites applications)]
+    [:div.form-group
+     ;[:label {:class "control-label col-sm-2" :for field-id} (str label ":")]
+     [:div.col-sm-10
+      [:input {:class       (str "form-control")
+               :type        "text"
+               :placeholder placeholder
+               :value       @search-atom
+               :on-change   #(do
+                               (reset! search-atom (.-target.value %))
+                               (reset! current-application-list (filter (fn [s]
+                                         (->> s (:issuer_content_name) (re-find (re-pattern (str "(?i)" @search-atom))))) @current-application-list))
+                               (when (blank? @search-atom) (issuer-applications "" state)))
+
+               #_(search-timer state)}]]]))
+

 (defn issuer-info-grid [state]
   (let [show-issuer-info-atom (cursor state [:show-issuer-info])
@@ -113,10 +141,80 @@
               [:a {:href "#" :on-click #(remove-issuer-from-favourites id state nil)} [:i {:class "fa fa-bookmark"}] (str " " (t :badge/Removefromfavourites))]
               )]]]]])))

+(defn issuer-filter-grid [show-favourites-atom state]
+  [:div#grid-filter {:class "form-horizontal" :style {:margin-bottom "10px"}}
+   [:div {:class "form-group wishlist-buttons"}
+       #_[:label {:for   "input-email-notifications"
+            :class "col-md-2"}
+    (str (t :core/Show) ":")]
+    [:div.col-md-10
+    [:div.buttons
+     [:button {:class (str "btn btn-default " (if-not @show-favourites-atom "btn-active"))
+               :id "btn-all"
+               :on-click #(reset! show-favourites-atom (if @show-favourites-atom false true))}
+      (t :core/All)]
+     [:button {:class (str "btn btn-default " (if @show-favourites-atom "btn-active"))
+               :id "btn-all"
+               :on-click #(reset! show-favourites-atom (if @show-favourites-atom false true))}
+      [:i {:class "fa fa-bookmark"}] (str " " (t :extra-application/Favourites))]]]]
+   [:div {:style {:margin-top "5px"}}
+    [text-field :issuer  nil "search issuer" state]]])
+
+(defn favourites-block [favourites state]
+  (if-not (empty? @favourites)
+    [:div
+     (doall
+       (for [app @favourites
+             :let [{:keys [issuer_content_name issuer_image issuer_content_url issuer_content_id]} app
+                   applications-count (issuer-applications-count issuer_content_name state)
+                   ;testing
+                   banner (if (even? (count issuer_content_name)) true false)]]
+         [:a { :key issuer_content_id
+               :data-dismiss "modal"
+               :on-click #(do
+                            (.preventDefault %)
+                            (init-issuer-connection issuer_content_id state)
+                            (swap! state assoc :show-issuer-info true
+                                   :issuer-content {:id issuer_content_id :name issuer_content_name :image issuer_image :url issuer_content_url :banner banner})
+                            (issuer-applications issuer_content_name state))}
+
+          [:div {:style {:padding "5px"}} (if issuer_image
+                                            [:img.badge-icon {:style {:width "30px" :padding-right "10px"} :src (str "/" issuer_image)}])
+           (str issuer_content_name "  ("  applications-count ")")]]
+
+         ))]
+    [:div]))
+
+(defn issuer-block [applications state]
+  (into
+    [:div
+     [:a {:data-dismiss "modal"
+          :on-click #(do
+                       (swap! state assoc :show-issuer-info false :issuer-content {:name (t :core/All)})
+                       (issuer-applications "" state))} [:div.all (t :core/All)]]]
+    (doall
+      (for [app (sort-by :issuer_content_name (distinct-by :issuer_content_name @applications))
+            :let [{:keys [issuer_content_name issuer_image issuer_content_url issuer_content_id]} app
+                  applications-count (issuer-applications-count issuer_content_name state)
+                  ;testing
+                  banner (if (even? (count issuer_content_name)) true false)]]
+        ^{:key app}[:a { :data-dismiss "modal"
+              :on-click #(do
+                           (.preventDefault %)
+                           (init-issuer-connection issuer_content_id state)
+                           (swap! state assoc :show-issuer-info true
+                                  :issuer-content {:id issuer_content_id :name issuer_content_name :image issuer_image :url issuer_content_url :banner banner})
+                           (issuer-applications issuer_content_name state))}
+
+         [:div {:style {:padding "5px"}} (if issuer_image
+                                           [:img.badge-icon {:style {:width "30px" :padding-right "10px"} :src (str "/" issuer_image)}])
+          (str issuer_content_name "  ("  applications-count ")")]]))))
+
 (defn issuer-content-modal [state]
   (let [applications (cursor state [:all-applications])
         issuer-name (cursor state [:issuer-content :name])
-        favourites (cursor state [:all-connections])]
+        favourites (cursor state [:favourites])
+        show-favourites-atom (cursor state [:show-favourite-issuers])]
     (fn []
       [:div#badge-content
        [:div.modal-body
@@ -131,32 +229,8 @@
             [:span {:aria-hidden             "true"
                     :dangerouslySetInnerHTML {:__html "×"}}]]]]]
         [:div.issuer-list
-         (into
-           [:div
-            [:a {:data-dismiss "modal"
-                 :on-click #(do
-                              (swap! state assoc :show-issuer-info false
-                                     :issuer-content {:name (t :core/All) #_(t :badge/Issuers)})
-                              (issuer-applications "" state))}
-             [:div.all (t :core/All)]]
-            (doall
-              (for [app (sort-by :issuer_content_name (distinct-by :issuer_content_name @applications))
-                    :let [{:keys [issuer_content_name issuer_image issuer_content_url issuer_content_id]} app
-                          applications-count (issuer-applications-count issuer_content_name state)
-                          ;testing
-                          banner (if (even? (count issuer_content_name)) true false)]]
-                [:a { :key issuer_content_id
-                      :data-dismiss "modal"
-                      :on-click #(do
-                                   (.preventDefault %)
-                                   (init-issuer-connection issuer_content_id state)
-                                   (swap! state assoc :show-issuer-info true
-                                          :issuer-content {:id issuer_content_id :name issuer_content_name :image issuer_image :url issuer_content_url :banner banner})
-                                   (issuer-applications issuer_content_name state))}
-
-                 [:div {:style {:padding "5px"}} (if issuer_image
-                                                   [:img.badge-icon {:style {:width "30px" :padding-right "10px"} :src (str "/" issuer_image)}])
-                  (str issuer_content_name "  ("  applications-count ")")]]))])]]
+         [issuer-filter-grid show-favourites-atom state]
+         (if @show-favourites-atom [favourites-block favourites state] [issuer-block applications state])]]
        [:div.modal-footer]])))

@@ -174,4 +248,4 @@
       [:button.issuer-button {:class (str "btn form-control btn-active")
                               :id "btn-all"
                               :on-click #(do
-                                           (m/modal! [open-issuer-modal state] {:size :md :shown (fn [] (init-issuer-applications state)) }))} (str @issuer-name)]]]))
+                                           (m/modal! [open-issuer-modal state] {:size :md :shown (fn []  (init-issuer-applications state)) }))} (str @issuer-name)]]]))


registry form -> public support

registry form -> public support

--- src/cljs/swarmpit/component/registry/create.cljs
+++ src/cljs/swarmpit/component/registry/create.cljs
@@ -68,6 +68,14 @@
        :onChange (fn [_ v]
                    (state/update-value [:password] v cursor))})))

+(defn- form-public [value]
+  (comp/form-comp
+    "PUBLIC"
+    (comp/form-checkbox
+      {:checked value
+       :onCheck (fn [_ v]
+                  (state/update-value [:public] v cursor))})))
+
 (defn- create-registry-handler
   []
   (handler/post
@@ -86,6 +94,7 @@
   []
   (state/set-value {:name     ""
                     :url      ""
+                    :public   false
                     :withAuth false
                     :username ""
                     :password ""
@@ -100,6 +109,7 @@
                  init-state-mixin []
   (let [{:keys [name
                 url
+                public
                 withAuth
                 username
                 password
@@ -121,6 +131,7 @@
          :onInvalid #(state/update-value [:isValid] false cursor)}
         (form-name name)
         (form-url url)
+        (form-public public)
         (form-auth withAuth)
         (if withAuth
           (comp/form-comps


Add devcards for `button/link`s

Add devcards for `button/link`s


Split long lines.

Split long lines.

--- src/cbfg/net-test.cljs
+++ src/cbfg/net-test.cljs
@@ -15,27 +15,31 @@
          (if (and (let [listen-ch (achan tn)
                         connect-ch (achan tn)
                         net (make-net tn listen-ch connect-ch)]
-                    (aclose tn listen-ch) ; Closing listen-ch should shutdown net.
+                    ; Closing listen-ch should shutdown net.
+                    (aclose tn listen-ch)
                     (e n (atake tn net) :done (atake tn net)))
                   (let [listen-ch (achan tn)
                         connect-ch (achan tn)
                         net (make-net tn listen-ch connect-ch)]
-                    (aclose tn connect-ch) ; Closing connect-ch should shutdown net.
+                    ; Closing connect-ch should shutdown net.
+                    (aclose tn connect-ch)
                     (e n (atake tn net) :done (atake tn net)))
                   (let [listen-ch (achan tn)
                         connect-ch (achan tn)
                         net (make-net tn listen-ch connect-ch)
                         accept-ch (achan tn)]
+                    ; Closing listen-ch should shutdown net and accept-ch's.
                     (aput tn listen-ch [:addr-a 1000 accept-ch])
-                    (aclose tn listen-ch) ; Closing listen-ch should shutdown net and accept-ch's.
+                    (aclose tn listen-ch)
                     (and (e n (atake tn accept-ch) nil nil)
                          (e n (atake tn net) :done (atake tn net))))
                   (let [listen-ch (achan tn)
                         connect-ch (achan tn)
                         net (make-net tn listen-ch connect-ch)
                         accept-ch (achan tn)]
+                    ; Closing connect-ch should shutdown net and accept-ch's.
                     (aput tn listen-ch [:addr-a 1000 accept-ch])
-                    (aclose tn connect-ch) ; Closing connect-ch should shutdown net and accept-ch's.
+                    (aclose tn connect-ch)
                     (and (e n (atake tn accept-ch) nil nil)
                          (e n (atake tn net) :done (atake tn net))))
                   (let [listen-ch (achan tn)
@@ -43,8 +47,9 @@
                         net (make-net tn listen-ch connect-ch)
                         accept-ch (achan tn)
                         accept-ch2 (achan tn)]
+                    ; 2nd listen on same addr/port should fail.
                     (aput tn listen-ch [:addr-a 1000 accept-ch])
-                    (aput tn listen-ch [:addr-a 1000 accept-ch2]) ; 2nd listen on same addr/port should fail.
+                    (aput tn listen-ch [:addr-a 1000 accept-ch2])
                     (and (e n (atake tn accept-ch2) nil nil)
                          (do (aclose tn listen-ch)
                              (aclose tn connect-ch)
@@ -54,6 +59,7 @@
                         connect-ch (achan tn)
                         net (make-net tn listen-ch connect-ch)
                         connect-result-ch (achan tn)]
+                    ; Connecting to unlistened to port should fail.
                     (aput tn connect-ch [:addr-a 1000 :addr-x connect-result-ch])
                     (and (e n (atake tn connect-result-ch) nil nil)
                          (do (aclose tn listen-ch)


Shorter authenticate logic.

Shorter authenticate logic.

--- src/cbfg/world/t2.cljs
+++ src/cbfg/world/t2.cljs
@@ -34,10 +34,9 @@
   (case (:op m)
     :authenticate
     (if-let [{:keys [realm user pswd]} m]
-      (if (and realm user pswd)
-        (if (= pswd (get-in server-state [:realms realm :users user :pswd]))
-          [server-state (assoc (dissoc m :pswd) :status :ok)]
-          [server-state (assoc (dissoc m :pswd) :status :mismatch)])
+      (if (and realm user pswd
+               (= pswd (get-in server-state [:realms realm :users user :pswd])))
+        [server-state (assoc (dissoc m :pswd) :status :ok)]
         [server-state (assoc (dissoc m :pswd) :status :invalid)])
       [server-state (assoc (dissoc m :pswd) :status :invalid)])
     "realms-list"


minute multiplication

minute multiplication

--- src/celestial/jobs.clj
+++ src/celestial/jobs.clj
@@ -43,7 +43,7 @@
    "marks jobs as succesful"
    [spec status]
   (let [id (add-job-status (merge spec {:status status :end (System/currentTimeMillis)}))
-        status-exp (or (get* :celestial :job :status-exp) (* 5 60))]
+        status-exp (* 60 (or (get* :celestial :job :status-exp) 5))]
     (wcar (car/expire (job-status-id id) status-exp)) {:status status}))

 (defn job-exec [f  {:keys [message attempt]}]


Documentation for core.

Documentation for core.

--- src/clj/forma/core.clj
+++ src/clj/forma/core.clj
@@ -1,3 +1,8 @@
+;; This namespace is a hub for all others, and not really complete in
+;; its own right. We define various forma constants, and hold some of
+;; the test queries in here for now. Some of these bad boys need to
+;; get moved over to tests.
+
 (ns forma.core
   (:use cascalog.api
         (forma [hadoop :only (all-files)]))
@@ -6,30 +11,26 @@
             (forma [hdf :as h]
                    [rain :as r])))

-;; ## FORMA Constants
+;; ### FORMA Constants
+;;
 ;; Aside from our EC2 information, this is the only data we need to
 ;; supply for the first phase of operations. Everything else should be
 ;; able to remain local to individual modules.

-(def
-  ^{:doc "MODIS datasets required for FORMA processing."}
-  forma-subsets
-  #{:ndvi :evi :qual :reli})
+(def forma-subsets #{:ndvi :evi :qual :reli})

-(def forma-res "1000")
+;; Arbitrary number of pixels slurped at a time off of a MODIS raster
+;; band. For 1km data, each MODIS tile is 1200x1200 pixels; dealing
+;; with each pixel individually would incur unacceptable IO costs
+;; within hadoop. We currently fix the chunk size at 24,000, resulting
+;; in 60 chunks per 1km data. Sharper resolution -> more chunks!

-(def
-  ^{:doc "Arbitrary number of pixels slurped at a time off of a
-MODIS raster band. For 1km data, each MODIS tile is 1200x1200 pixels;
-dealing with each pixel individually would incur unacceptable IO costs
-within hadoop. We currently fix the chunk size at 24,000, resulting in
-60 chunks per 1km data. Sharper resolution -> more chunks!"}
-  chunk-size 24000)
+(def chunk-size 24000)

-;; ## Demonstration Queries
-;; MODIS data first, then rain data.
+;; ### Demonstration Queries
+
 (defn chunk-test
-  "Simple query that takes a directory containing MODIS HDF files, or
+  "Cascalog query that takes a directory containing MODIS HDF files, or
   a link directly to such a file, totals up the # of chunks per file,
   and displays the count alongside some other nice metadata. This
   method is a proof of concept for the hadoop chunking system; The
@@ -44,7 +45,7 @@
          (c/count ?count))))

 (defn rain-test
-  "Like chunk-test, but checks the same thing for the rain data."
+  "Like chunk-test, but works for NOAA PRECL data files."
   [m-res ll-res c-size tile-seq dir]
   (let [source (all-files dir)
         chunks (r/rain-chunks m-res ll-res c-size tile-seq dir)]


refine transaction generation

refine transaction generation

--- src/clj_money/seed.clj
+++ src/clj_money/seed.clj
@@ -4,6 +4,7 @@
             [clj-time.core :as t]
             [clj-time.periodic :refer [periodic-seq]]
             [clj-time.format :refer [parse-local-date]]
+            [clj-money.inflection :refer [keywordize]]
             [clj-money.serialization :refer [realize]]
             [clj-money.models.helpers :refer [with-storage
                                               with-transacted-storage]]
@@ -89,41 +90,25 @@
     (let [user (users/find-by-email s email)
           entity (entities/find-by-name s user entity-name)
           start-date (parse-local-date start-date)
-          accounts (accounts/select-by-entity-id s (:id entity))
-          [salary
-           fit
-           social-security
-           medicare
-           checking] (map (fn [account-name]
-                            (->> accounts
-                                 (filter #(= account-name (:name %)))
-                                 first))
-                          ["Salary"
-                           "FIT"
-                           "Social Security"
-                           "Medicare"
-                           "Checking"])]
+          all-accounts (accounts/select-by-entity-id s (:id entity))
+          accounts (->> ["Salary"
+                         "FIT"
+                         "Social Security"
+                         "Medicare"
+                         "Checking"]
+                        (map (fn [account-name]
+                               [(keywordize account-name)
+                                (->> all-accounts
+                                     (filter #(= account-name (:name %)))
+                                     first)]))
+                        (into {}))]
+
+      (when (some nil? (vals accounts))
+        (throw (RuntimeException. (str "At least one account could not be found. " accounts))))

       ; Salary
-      (->> Months/ONE
-           (periodic-seq start-date)
-           (take 12)
-           (map #(generate-salary-transaction s
-                                              entity
-                                              %
-                                              {:salary salary
-                                               :fit fit
-                                               :social-security social-security
-                                               :medicare medicare
-                                               :checking checking})))
-      (pprint (->> Months/ONE
-           (periodic-seq (t/plus start-date (Days/days 14)))
-           (take 12)
-           (map #(generate-salary-transaction s
-                                              entity
-                                              %
-                                              {:salary salary
-                                               :fit fit
-                                               :social-security social-security
-                                               :medicare medicare
-                                               :checking checking})))))))
+      (dorun (->> [start-date (t/plus start-date (Days/days 14))]
+                  (map #(periodic-seq % Months/ONE))
+                  (apply interleave)
+                  (take 24)
+                  (map #(generate-salary-transaction s entity % accounts)))))))


Fixed basestation tests.

Fixed basestation tests.

--- test/com/lemondronor/orbital_detector/basestationdb_test.clj
+++ test/com/lemondronor/orbital_detector/basestationdb_test.clj
@@ -32,22 +32,22 @@
   (testing "find N520PD in basestation-1.sqb"
     (is (records-equiv? N521PD
                         (basestationdb/find-aircraft
-                         (db/db-spec "dev-resources/basestation-1.sqb")
+                         (db/sqlite-db-spec "dev-resources/basestation-1.sqb")
                          "A68DEE"))))
   (testing "find N521PD in basestation-1.sqb"
     (is (records-equiv? N520PD
                         (basestationdb/find-aircraft
-                         (db/db-spec "dev-resources/basestation-1.sqb")
+                         (db/sqlite-db-spec "dev-resources/basestation-1.sqb")
                          "A68A37"))))
   (testing "find N520PD in basestation-planebase.sqb"
     (is (records-equiv? N521PD
                         (basestationdb/find-aircraft
-                         (db/db-spec "dev-resources/basestation-planebase.sqb")
+                         (db/sqlite-db-spec "dev-resources/basestation-planebase.sqb")
                          "A68DEE"))))
   (testing "find on non-existent aircraft"
     (is (= nil
            (basestationdb/find-aircraft
-            (db/db-spec "dev-resources/basestation-1.sqb")
+            (db/sqlite-db-spec "dev-resources/basestation-1.sqb")
             "XXXXXX")))))


sampling code committed

sampling code committed

--- src/crawler/sample.clj
+++ src/crawler/sample.clj
@@ -4,10 +4,23 @@
    A sample picks out some links. Visiting is left
    to the user")

+(defn sample-a-decision
+  [links blacklist]
+  (take 20 (filter (fn [a-link] (some blacklist)) links)))
+
 (defn sample
   "Given a set of decisions, we produce an instance of
    each decision. In URLspeak:
    a decision is an XPath
-   a sample is some links from an XPath"
-  [decisions]
-  '*)
+   a sample is some links from an XPath
+
+   We are hard-coding samples to 20
+
+   Args:
+    decisions: {Xpath -> URLs}
+    blacklist: [a set of URLs you don't want to follow]"
+  [decisions blacklist]
+  (map
+   (fn [[a-decision info]]
+     (sample-a-decision (map #(:href %) info) blacklist))
+   decisions))


Update generator documentation

Update generator documentation

--- src/simple_check/generators.clj
+++ src/simple_check/generators.clj
@@ -264,7 +264,7 @@

 (defn choose
   "Create a generator that returns numbers in the range
-  `min-range` to `max-range`."
+  `min-range` to `max-range`, inclusive."
   [lower upper]
   (make-gen
     (fn [^Random rnd _size]
@@ -340,15 +340,23 @@
           (recur rand-seed (inc size)))))))

 (def not-empty
-  "Modifies a generator so that it doesn't generate empty collections."
+  "Modifies a generator so that it doesn't generate empty collections.
+
+  Examples:
+
+      ;; generate a vector of booleans, but never the empty vector
+      (gen/not-empty (gen/vector gen/boolean))
+  "
   (partial such-that clojure.core/not-empty))

 (def boolean
+  "Generates one of `true` or `false`. Shrinks to `false`."
   (elements [false true]))

 (defn tuple
   "Create a generator that returns a vector, whose elements are chosen
-  from the generators in the same position.
+  from the generators in the same position. The individual elements shrink
+  according to their generator, but the value will never shrink in count.

   Examples:

@@ -369,6 +377,7 @@
   (sized (fn [size] (choose (- size) size))))

 (def nat
+  "Generates natural numbers, starting at zero. Shrinks to zero."
   (fmap #(Math/abs (long %)) int))

 (def pos-int
@@ -432,9 +441,13 @@
                           (gen-pure (shrink-rose clojure.core/list
                                                  roses)))))))

-(def byte (fmap clojure.core/byte (choose Byte/MIN_VALUE Byte/MAX_VALUE)))
-
-(def bytes (fmap clojure.core/byte-array (vector byte)))
+(def byte
+  "Generates `java.lang.Byte`s, using the full byte-range."
+  (fmap clojure.core/byte (choose Byte/MIN_VALUE Byte/MAX_VALUE)))
+
+(def bytes
+  "Generates byte-arrays."
+  (fmap clojure.core/byte-array (vector byte)))

 (defn map
   "Create a generator that generates maps, with keys chosen from
@@ -443,10 +456,15 @@
   (let [input (vector (tuple key-gen val-gen))]
     (fmap (partial into {}) input)))

-(defn hash-map
+(defn hash-map
   "Like clojure.core/hash-map, except the values are generators.
-   Returns a generator that makes maps with the supplied keys and
-   values generated using the supplied generators."
+   Returns a generator that makes maps with the supplied keys and
+   values generated using the supplied generators.
+
+  Examples:
+
+    (gen/hash-map :a gen/boolean :b gen/nat)
+  "
   [& kvs]
   (assert (even? (count kvs)))
   (let [ks (take-nth 2 kvs)
@@ -470,7 +488,7 @@
                  (choose 97 122)])))

 (def string
-  "Generate strings."
+  "Generate strings. May generate unprintable characters."
   (fmap clojure.string/join (vector char)))

 (def string-ascii
@@ -488,6 +506,8 @@
     (fmap clojure.core/keyword)))

 (def ratio
+  "Generates a `clojure.lang.Ratio`. Shrinks toward 0. Not all values generated
+  will be ratios, as many values returned by `/` are not ratios."
   (fmap
     (fn [[a b]] (/ a b))
     (tuple int