fix ArrayOfMaps annotation.

fix ArrayOfMaps annotation.

--- src/metabase/api/common.clj
+++ src/metabase/api/common.clj
@@ -340,19 +340,17 @@
   [symb value :nillable]
   (checkp-with map? symb value "value must be a dictionary."))

-;; TODO - this doesn't work
 (defannotation ArrayOfIntegers
   "Param must be an array of integers (this does *not* cast the param)."
   [symb value :nillable]
   (checkp-with vector? symb value "value must be an array.")
-  (map (fn [v] (checkp-with integer? symb v "array value must be an integer.")) value))
-
-;; TODO - this doesn't work
+  (mapv (fn [v] (checkp-with integer? symb v "array value must be an integer.")) value))
+
 (defannotation ArrayOfMaps
   "Param must be an array of maps (this does *not* cast the param)."
   [symb value :nillable]
   (checkp-with vector? symb value "value must be an array.")
-  (map (fn [v] (checkp-with map? symb v "array value must be a map.")) value))
+  (mapv (fn [v] (checkp-with map? symb v "array value must be a map.")) value))

 (defannotation NonEmptyString
   "Param must be a non-empty string (strings that only contain whitespace are considered empty)."


Switch back to high restart latency

Switch back to high restart latency

--- src/onyx_benchmark/peer.clj
+++ src/onyx_benchmark/peer.clj
@@ -90,8 +90,8 @@
                      :onyx/id id
                      :onyx.messaging/bind-addr (slurp "http://169.254.169.254/latest/meta-data/local-ipv4")
                      :onyx.messaging/peer-ports (vec (range 40000 40200))
-                     :onyx.messaging.aeron/offer-idle-strategy :low-restart-latency
-                     :onyx.messaging.aeron/poll-idle-strategy :low-restart-latency
+                     :onyx.messaging.aeron/offer-idle-strategy :high-restart-latency
+                     :onyx.messaging.aeron/poll-idle-strategy :high-restart-latency
                      :onyx.messaging.aeron/subscriber-count 2
                      :onyx.peer/join-failure-back-off 500
                      :onyx.peer/job-scheduler :onyx.job-scheduler/greedy


whitespace change

whitespace change

--- contrib/mr-kluj/src/main/clj/com/linkedin/mr_kluj/voldemort_serialization.clj
+++ contrib/mr-kluj/src/main/clj/com/linkedin/mr_kluj/voldemort_serialization.clj
@@ -247,4 +247,4 @@
   "Composes a reducer (ala com.linkedin.mr_kluj.job/create-reducer) and a join, allowing you to specify functionality
   on the joined group that can see all the values as if it was grouped by the join key"
   [join-wrapper reduce-fn]
-  (job/compose-wrappers join-wrapper (job/create-reducer reduce-fn)))+  (job/compose-wrappers join-wrapper (job/create-reducer reduce-fn)))


Fix bug

Fix bug

--- src/antlion_clojure/bot.clj
+++ src/antlion_clojure/bot.clj
@@ -433,12 +433,12 @@
   [{:keys [slack dynamodb res] :as opt} co2]
   (let [channel-id (some-> (dynamodb/get-lemming-channel dynamodb) :channel-id)
         last-state (some-> (dynamodb/get-lemming-last-state dynamodb) :state)]
+    (dynamodb/set-lemming-last-state co2)
     (when (and
             channel-id
             last-state
             (> max-ppm last-state)
             (> (:value co2) max-ppm))
-      (dynamodb/set-lemming-last-state co2)
       (slack/reaction! slack
         (map->Payload
           {:type :message


GAWB-2475: fix issues with discoverable by list (#912)

* when discoverable-by is the empty list, it still needs to be sent in the metadata command
code to convert the discoverable by group from a non list value to a list was doing the wrong thing when the data contained an empty list
* simplify empty check

--- src/cljs/main/broadfcui/page/workspace/summary/catalog/wizard.cljs
+++ src/cljs/main/broadfcui/page/workspace/summary/catalog/wizard.cljs
@@ -38,7 +38,7 @@
 (defn- ensure-sequence [input]
   ;;input may or maynot be a sequence, make it a sequence
   (cond (sequential? input) input
-        (nil? input) []
+        (empty? input) []
         :else [input]))

 (react/defc- DiscoverabilityPage
@@ -237,9 +237,14 @@
      (if (and (:published? @state) (not-empty (:invalid-properties @state)))
        (swap! state assoc :validation-error "You will need to complete all required metadata attributes to be able to re-publish the workspace in the Data Library")
        (let [attributes-seen (apply merge (vals (select-keys (:page-attributes @locals) (:pages-stack @state))))
+             discoverable-by (:library:discoverableByGroups attributes-seen)
              invoke-args (if (and set-discoverable? (not editable?))
-                           {:name endpoints/save-discoverable-by-groups :data (:library:discoverableByGroups attributes-seen)}
-                           {:name endpoints/save-library-metadata :data (library-utils/remove-empty-values (merge attributes-seen (:version-attributes @state)))})]
+                           {:name endpoints/save-discoverable-by-groups :data discoverable-by}
+                           {:name endpoints/save-library-metadata :data (merge
+                                                                         (library-utils/remove-empty-values (merge attributes-seen (:version-attributes @state)))
+                                                                         ; ensure discoverable by is being sent. when it is reset to all users, it is the empty list
+                                                                         ; and therefore removed by the call above
+                                                                         {:library:discoverableByGroups discoverable-by})})]
          (swap! state assoc :submitting? true :submit-error nil)
          (endpoints/call-ajax-orch
           {:endpoint ((:name invoke-args) (:workspace-id props))


Refactoring: fetch-mirror-repo should use the 'sh' function

--- src/branch_handler/core.clj
+++ src/branch_handler/core.clj
@@ -69,7 +69,7 @@
     [workdir group reponame repository-url]
     (log/info "Fetching mirror repository" repository-url)
     ; TODO test --prune
-    (exec "git" "--git-dir" (repo-workdir workdir group reponame) "fetch"))
+    (clojure.java.shell/sh "git" "--git-dir" (repo-workdir workdir group reponame) "fetch"))

 (defn clone-mirror-repo
     [workdir group reponame repository-url]


don't need file after resource

don't need file after resource

--- src/chat/server/handler.clj
+++ src/chat/server/handler.clj
@@ -20,7 +20,6 @@
   (GET "/" []
     (-> "chat.html"
         clojure.java.io/resource
-        clojure.java.io/file
         slurp))
   (GET "/92ddKI0spxFCkzmVkgOuMH80zhYikCvD7OVaFqy1l1YkN6N" req
     (let [user-id (db/with-conn (db/authenticate-user "test@ycombinator.com" (env :tester-password)))]


add note from Incanter docs on incanter.charts/add-lines

--- src/r_incantations/core.clj
+++ src/r_incantations/core.clj
@@ -392,6 +392,12 @@
         p (incanter.charts/xy-plot (map first coords) (map second coords))
         p (incanter.charts/add-polygon p coords)]
     (incanter.core/view p))
+
+  ;; from incanter docs for add-lines
+  (doto (incanter.charts/histogram (incanter.stats/sample-normal 1000) :density true)
+    (incanter.charts/add-lines (range -3 3 0.05) (incanter.stats/pdf-normal (range -3 3 0.05)))
+    incanter.core/view)
+

   )


Patch bodhi basic-merge

Patch bodhi basic-merge

--- src-cljs/frontend/core.cljs
+++ src-cljs/frontend/core.cljs
@@ -193,6 +193,39 @@
     (-> (next-merge env)
         (update :keys conj :compassus.core/route-data))))

+(defn- patched-basic-merge
+  "A patched version of bodhi/basic-merge. This should be swapped out
+  for bodhi/basic-merge when its handling of unnormalized data is
+  fixed."
+  [{:keys [merge merger state path novelty ast] :as env}]
+  (let [{:keys [key type]} ast]
+    (case type
+      :prop {:keys #{}
+             :next (assoc-in state path novelty)}
+      :join (if (vector? novelty)
+              ;; Note that we use `:merge` here and not `merger`, which would go
+              ;; one level deeper into the query/ast. This is analogous to
+              ;; `basic-read` using `:read` instead of `:parser` when processing
+              ;; vectors.
+              (reduce-kv
+               (fn [result idx novelty']
+                 (bodhi/update-merge-result result
+                                            (merge (-> env
+                                                       (update :path conj idx)
+                                                       (assoc :novelty novelty'
+                                                              :state (:next result))))))
+               {:keys #{}
+                :next (update-in state
+                                 path
+                                 (fn [old-vals]
+                                   (subvec (vec old-vals)
+                                           0
+                                           (min (count novelty)
+                                                ;; `(count nil)` is 0
+                                                (count old-vals)))))}
+               novelty)
+              (merger env)))))
+
 (defn ^:export setup! []
   (let [legacy-state (initial-state)
         comms {:controls (chan)
@@ -239,7 +272,12 @@
                           :merge-tree #(utils/deep-merge %1 %2)

                           :merge (bodhi/merge-fn
-                                  (-> bodhi/basic-merge
+                                  (-> patched-basic-merge
+
+                                      ;; bodhi/basic-merge
+                                      ;; see docstring for patched-basic-merge
+
+
                                       ;; TODO: re-enable normalization
                                       ;; by uncommenting
                                       ;; `default-db/merge` when bodhi


add first part of status pipeline

add first part of status pipeline

--- src/clj/ceres/collector.clj
+++ src/clj/ceres/collector.clj
@@ -230,7 +230,7 @@

 (defn store-hashtag [text]
-  (mc/insert
+  (mc/insert-and-return
    @db
    "hashtags"
    {:text text}))
@@ -241,6 +241,48 @@
   [pub-id source-id]
   (mc/insert @db "reactions" {:publication pub-id :source source-id}))

+
+(defn get-user-id [{:keys [user] :as status}]
+  (if-let [uid (:_id (mc/find-one-as-map @db "users" {:id (:id user)}))]
+    uid
+    (:_id (store-user status))))
+
+(defn get-hashtag-id [text]
+  (if-let [hid (:_id (mc/find-one-as-map @db "hashtags" {:text text}))]
+    hid
+    (:_id (store-hashtag text))))
+
+(defn get-url-id
+  "Get url id if exists otherwise store url"
+  [url]
+  (if-let [url-id (:_id (mc/find-one-as-map @db "urls" {:url url}))]
+    url-id
+    (if-let [expanded-url (:url (expand-url url))]
+      (if-let [x-url-id (:_id (mc/find-one-as-map @db "urls" {:url expanded-url}))]
+        x-url-id
+        (:_id (store-url expanded-url)))
+      nil)))
+
+
+(defn get-type [{:keys [in_reply_to_status_id retweeted_status entities]}]
+  (if in_reply_to_status_id
+    :reply
+    (if retweeted_status
+      :retweet
+      (if-not (empty? (:urls entities))
+        :source-or-share
+        :unrelated))))
+
+
+(defn store-raw-tweet [status]
+  (let [oid (ObjectId.)
+        doc (update-in status [:created_at] (fn [x] (f/parse custom-formatter x)))
+        {:keys [user entities retweeted_status in_reply_to_status_id created_at]
+         :as record} (from-db-object (mc/insert-and-return @db "tweets" (merge doc {:_id oid})) true)
+        uid (get-user-id status)
+        hids (map (fn [{:keys [text]}] (get-hashtag-id text)) (:hashtags entities))
+        type (get-type status)]
+    ))

 (comment
@@ -374,7 +416,7 @@
               (if retweeted_status
                 :retweet
                 (if-not (empty? (:urls entities))
-                  :source
+                  :source-or-share
                   :unrelated))))
           (transact-publications [{:keys [user _id entities created_at] :as tweet}]
             (let [uid (:_id (mc/find-one-as-map @db "users" {:id (:id user)}))


remove debug code

remove debug code

--- src/cljs/dato/lib/core.cljs
+++ src/cljs/dato/lib/core.cljs
@@ -265,7 +265,6 @@
         (loop []
           (alt!
             dato-ch ([{:keys [sender event data] :as payload}]
-                     (js/console.log "payload" (clj->js payload))
                      (cond
                        ;; Special-case waiting on https://github.com/tonsky/datascript/issues/76
                        ;; Can eliminate this branch afterwards


Added convenience function to mock-monad.

--- src/active/clojure/mock_monad.cljc
+++ src/active/clojure/mock_monad.cljc
@@ -79,20 +79,36 @@
   ^{:doc "Replace the next (unhandled) command by `(return nil)`, no matter what it is."}
   (mock (constantly nil) (constantly (monad/return nil))))

+;; FIXME This should be renamed to `mock-run-monad`
+(defn mock-execute-monad
+  ([mocks m]
+   (mock-execute-monad (monad/null-monad-command-config {} {}) mocks m))
+  ([command-config mocks m]
+   (try (monad/run-free-reader-state-exception
+         (monad/combine-monad-command-configs command-config
+                                              (mock-commands mocks))
+         (monad/monadic
+          [res m]
+          ;; check that mock stack is empty at 'end'
+          check-mocks-empty
+          (monad/return res)))
+        #?(:clj (catch Exception e
+                  (println "e =" e))
+           :cljs (catch js/Error e
+                   (println "e =" e))))))
+
+;; FIXME This should be renamed to `mock-execute-monad`
 (defn mock-run-monad
   "Run m under the given monad command configs, and the given mocked commands, returning the result of m.
    `mocks` should be a sequence, whose values can be created by the
   `mock`, `mock-result` or `mock-effect` and other functions above, and are
   expected to appear in that order while executing `m`."
   ([command-config mocks m]
-   (first (monad/execute-free-reader-state-exception
-           (monad/combine-monad-command-configs command-config
-                                                (mock-commands mocks))
-           (monad/monadic
-            [res m]
-            ;; check that mock stack is empty at 'end'
-            check-mocks-empty
-            (monad/return res)))))
+   (try (first (mock-execute-monad command-config mocks m))
+        #?(:clj (catch Exception e
+                  (println "e =" e))
+           :cljs (catch js/Error e
+                   (println "e =" e)))))
   ([mocks m]
    (mock-run-monad (monad/null-monad-command-config {} {}) mocks m)))

@@ -115,3 +131,10 @@
                                 (monad/return [r st2])))]
            (reset! state st2)
            [r st2])))))
+
+(defn is-mocked-state
+  "Takes an `expectation` and the `monad-command-config-state` after running a mock.
+  Applies `is` to the `=` of both, dissocing the ::mocks from the returned state."
+  [expectation mock-result-state]
+  (#?(:clj clojure.test/is :cljs cljs.test/is)
+   (= expectation (dissoc mock-result-state ::mocks))))


Fix h2

Fix h2

--- src/cljs/demtools/core.cljs
+++ src/cljs/demtools/core.cljs
@@ -363,7 +363,7 @@
           (str "Packet repl output: " (with-out-str (pprint repl-output))))
         (when packet
           (dom/div nil
-            (dom/h2 "Packet")
+            (dom/h2 nil "Packet")
             (js/JSON.stringify packet)))))))


amazon/google/azure icons #236

amazon/google/azure icons
#236


Optimize: avoid recomputing the max-key project over and over

--- src/cljs/triboard/core.cljs
+++ src/cljs/triboard/core.cljs
@@ -173,6 +173,11 @@
 ;; ARTIFICIAL INTELLIGENCE
 ;; -----------------------------------------

+(defn fast-max-key
+  "Fast max key that avoids recomputing things several times"
+  [key-fn coll]
+  (apply max-key (memoize key-fn) coll))
+
 (defn move-strength ;; TODO - Count taken is bad: select a better evaluation
   "Compute the strength value of a move"
   [move]
@@ -183,7 +188,7 @@
    * For the provided player
    * And with move scope limitation"
   [moves move-filter]
-  (apply max-key ;; TODO - max key is slow: it will recompute the same stuff over and over
+  (fast-max-key
     #(transduce
        (comp
          (filter move-filter)
@@ -211,7 +216,7 @@
         others (remove #{player} players)
         outcomes (map (fn [[m _]] [m (play-move game m)]) moves)]
     (first
-      (apply max-key
+      (fast-max-key
         (fn [[m outcome]]
           (let [score (get-in outcome [:scores player])
                 losses (map #(worst-immediate-loss outcome % player) others)]


Add non-improvement meta-error

Add non-improvement meta-error

--- src/clojush/meta_errors.clj
+++ src/clojush/meta_errors.clj
@@ -184,6 +184,21 @@
         (if (some (fn [[new-err old-err]]
                     (and (not (zero? old-err))
                          (not= new-err old-err)))
+                  (map vector (first hist) (second hist)))
+          0
+          1)))))
+
+(defn non-improvement-meta-error
+  [ind evaluated-population argmap]
+  (if (not (:print-history argmap))
+    (throw
+     (Exception.
+      ":print-history must be true for :stasis"))
+    (let [hist (:history ind)]
+      (if (< (count hist) 2)
+        0
+        (if (some (fn [[new-err old-err]]
+                    (< new-err older-error))
                   (map vector (first hist) (second hist)))
           0
           1)))))


Added riemann.time as requirement

Added riemann.time as requirement

--- src/riemann/stackdriver.clj
+++ src/riemann/stackdriver.clj
@@ -1,6 +1,7 @@
 (ns riemann.stackdriver
   "Forwards events to Stackdriver."
-  (:require [clj-http.client :as client]
+  (:require riemann.time
+            [clj-http.client :as client]
             [cheshire.core :refer [generate-string]])
   (:use [clojure.string :only [replace]]))


Add npc temperment

Add npc temperment

--- src/robinson/monstergen.clj
+++ src/robinson/monstergen.clj
@@ -37,45 +37,45 @@
   ;;                                                               speed size (kg)
   ;;                                                                           strength
   ;;                                                                               toughness
-  ;;                                                                                body-parts                                  attacks                       movement policy                       range-threshold
-  ;;                                                                                status
-  (Monster. :rat            "rat"            "rats"            5 0 1.1   0.2   1    5 #{:face :head :neck :body :leg :tail}       #{:bite :claw}                :hostile-after-attacked               5 #{:docile})
-  (Monster. :spider         "spider"         "spiders"         2 0 0.9   0.01  0.1  1 #{:face :leg :abdomen}                      #{:bite-venom}                :hide-from-player-in-range-or-random  5 #{:hostile})
-  (Monster. :scorpion       "scorpion"       "scorpions"       3 0 1.1   0.01  0.1  1 #{:head :claw :leg :abdomen :tail}          #{:bite :claw :sting-venom}   :hide-from-player-in-range-or-random  4 #{:hostile})
-  (Monster. :snake          "snake"          "snakes"          5 0 0.8   1     1    8 #{:head :body :tail}                        #{:bite :bite-venom}          :hide-from-player-in-range-or-random  5 #{:hostile})
-  (Monster. :bat            "bat"            "bats"            5 0 1.6   1     0.5  4 #{:head :body :wing :leg :face}             #{:bite}                      :hide-from-player-in-range-or-random  7 #{:hostile})
-  (Monster. :boar           "boar"           "boars"          18 0 1.2  70    20    8 #{:head :body :tail :snout :face :eye :leg} #{:bite :gore}                :hide-from-player-in-range-or-random  7 #{:hostile})
-  (Monster. :gecko          "gecko"          "geckos"          2 0 0.9   0.1   0.5  5 #{:head :face :body :tail :leg}             #{:bite}                      :hide-from-player-in-range-or-random  4 #{:hostile})
-  (Monster. :monkey         "monkey"         "monkies"        13 0 1.2  50    10    5 #{:head :neck :body :tail :leg :face :arm}  #{:bite :punch}               :hide-from-player-in-range-or-random 10 #{:hostile})
-  (Monster. :bird           "bird"           "birds"           4 0 2.1   1     0.3  4 #{:head :body :tail :leg :beak :wing}       #{:bite :claw}                :hide-from-player-in-range-or-random  8 #{:hostile})
-  (Monster. :centipede      "centipede"      "centipedes"      1 0 0.5   0.1   0.1  1 #{:head :body :leg}                         #{:bite}                      :hide-from-player-in-range-or-random  3 #{:hostile})
-  (Monster. :turtle         "turtle"         "turtles"         4 0 0.5  10     1.5 20 #{:head :neck :body :leg :face :shell}      #{:bite}                      :hide-from-player-in-range-or-random  5 #{:hostile})
-  (Monster. :red-frog       "red frog"       "red frogs"       2 0 0.9   1     0.7  3 #{:head :body :leg :face}                   #{:claw}                      :hide-from-player-in-range-or-random  4 #{:hostile})
-  (Monster. :orange-frog    "orange frog"    "orange frogs"    2 0 0.9   1     0.7  3 #{:head :body :leg :face}                   #{:claw}                      :hide-from-player-in-range-or-random  4 #{:hostile})
-  (Monster. :yellow-frog    "yellow frog"    "yellow frogs"    2 0 0.9   1     0.7  3 #{:head :body :leg :face}                   #{:claw}                      :hide-from-player-in-range-or-random  4 #{:hostile})
-  (Monster. :green-frog     "green frog"     "green frogs"     2 0 0.9   1     0.7  3 #{:head :body :leg :face}                   #{:claw}                      :hide-from-player-in-range-or-random  4 #{:hostile})
-  (Monster. :blue-frog      "blue frog"      "blue frogs"      2 0 0.9   1     0.7  3 #{:head :body :leg :face}                   #{:claw}                      :hide-from-player-in-range-or-random  4 #{:hostile})
-  (Monster. :purple-frog    "purple frog"    "purple frogs"    2 0 0.9   1     0.7  3 #{:head :body :leg :face}                   #{:claw}                      :hide-from-player-in-range-or-random  4 #{:hostile})
-  (Monster. :parrot         "parrot"         "parrots"         5 0 2.1   1     1    3 #{:head :body :leg :face :wing :tail}       #{:claw :bite}                :hide-from-player-in-range-or-random 10 #{:hostile})
-  (Monster. :shark          "shark"          "sharks"         16 0 1.4 800    30   15 #{:head :body :fin :nose :tail}             #{:bite}                      :hide-from-player-in-range-or-random 10 #{:hostile})
-  (Monster. :fish           "fish"           "fish"            4 0 1.2   4     1    8 #{:head :body :fin :tail}                   #{:bite}                      :hide-from-player-in-range-or-random  4 #{:hostile})
-  (Monster. :octopus        "octopus"        "octopodes"       4 0 1.5  15     5    4 #{:head :body :tentacle}                    #{:bite :bite-venom :squeeze} :hide-from-player-in-range-or-random  2 #{:hostile})
-  (Monster. :sea-snake      "sea snake"      "sea snakes"      4 0 1.5   2     1    7 #{:head :body}                              #{:bite :bite-venom}          :hide-from-player-in-range-or-random  2 #{:hostile})
-  (Monster. :clam           "clam"           "clams"           2 0 0.1   0.2   0.2 25 #{:shell}                                   #{:clamp}                     :constant                             1 #{:hostile})
-  (Monster. :urchin         "urchin"         "urchins"         2 0 0.1   0.1  10   10 #{:body}                                    #{:spike}                     :constant                             1 #{:hostile})
-  (Monster. :squid          "squid"          "squids"          4 0 1.5  10     6    4 #{:head :body :tentacle}                    #{:bite :squeeze}             :hide-from-player-in-range-or-random  2 #{:hostile})
-  (Monster. :crocodile      "crocodile"      "crocodiles"     10 0 0.8 150    15    9 #{:head :body :arm :leg :tail :snout}       #{:bite :claw}                :hide-from-player-in-range-or-random  2 #{:hostile})
-  (Monster. :mosquito       "mosquito"       "mosquitoes"      1 0 1.4   0.01  0.1  1 #{:head :body :leg :wing}                   #{:bite}                      :hide-from-player-in-range-or-random  3 #{:hostile})
-  (Monster. :mongoose       "mongoose"       "mongeese"        4 0 1.4   5     4    6 #{:head :body :leg :tail}                   #{:bite :claw}                :hide-from-player-in-range-or-random  2 #{:hostile})
-  (Monster. :tarantula      "tarantula"      "tarantulas"      2 0 1.4   0.1   0.2  2 #{:head :body :leg}                         #{:bite}                      :hide-from-player-in-range-or-random  2 #{:hostile})
-  (Monster. :monitor-lizard "monitor lizard" "monitor lizards" 7 0 1.1  10     5   10 #{:head :body :leg :tail}                   #{:bite :claw}                :hide-from-player-in-range-or-random  2 #{:hostile})
-  (Monster. :komodo-dragon  "komodo dragon"  "komodo dragons" 12 0 0.8  60    10   14 #{:head :body :leg :tail}                   #{:bite :claw}                :hide-from-player-in-range-or-random  2 #{:hostile})
-  (Monster. :cobra          "cobra"          "cobras"          5 0 0.8   6     3    7 #{:head :body :tail}                        #{:bite :bite-venom}          :hide-from-player-in-range-or-random  2 #{:hostile})
-  (Monster. :puffer-fish    "puffer fish"    "puffer fish"     3 0 1.1   1     0.6  7 #{:head :body :tail}                        #{:sting-venom}               :hide-from-player-in-range-or-random  2 #{:hostile})
-  (Monster. :crab           "crab"           "crabs"           4 0 0.8   2     1.5  9 #{:head :body}                              #{:claw}                      :hide-from-player-in-range-or-random  2 #{:hostile})
-  (Monster. :hermit-crab    "hermit crab"    "hermit crabs"    3 0 0.6   1     1   15 #{:head :shell :leg}                        #{:claw}                      :hide-from-player-in-range-or-random  1 #{:hostile})
-  (Monster. :electric-eel   "electric eel"   "electric eels"   5 0 0.6  10     5    8 #{:head :body}                              #{:bite}                      :hide-from-player-in-range-or-random  2 #{:hostile})
-  (Monster. :jellyfish      "jellyfish"      "jellyfish"       3 0 0.6   1     0.1  4 #{:body}                                    #{:sting-venom}               :hide-from-player-in-range-or-random  1 #{:hostile})])
+  ;;                                                                                body-parts                                  attacks                       temperment                            movement policy                       range-threshold
+  ;;                                                                                status
+  (Monster. :rat            "rat"            "rats"            5 0 1.1   0.2   1    5 #{:face :head :neck :body :leg :tail}       #{:bite :claw}                :hostile-after-attacked               :hide-from-player-in-range-or-random  5 #{:docile})
+  (Monster. :spider         "spider"         "spiders"         2 0 0.9   0.01  0.1  1 #{:face :leg :abdomen}                      #{:bite-venom}                :retreat-after-attacked               :random                               5 #{:docile})
+  (Monster. :scorpion       "scorpion"       "scorpions"       3 0 1.1   0.01  0.1  1 #{:head :claw :leg :abdomen :tail}          #{:bite :claw :sting-venom}   :hostile-after-attacked               :random                               4 #{:hostile})
+  (Monster. :snake          "snake"          "snakes"          5 0 0.8   1     1    8 #{:head :body :tail}                        #{:bite :bite-venom}          :retreat-after-attackd                :random                               5 #{:hostile})
+  (Monster. :bat            "bat"            "bats"            5 0 1.6   1     0.5  4 #{:head :body :wing :leg :face}             #{:bite}                      :hostile-after-attacked               :random                               7 #{:hostile})
+  (Monster. :boar           "boar"           "boars"          18 0 1.2  70    20    8 #{:head :body :tail :snout :face :eye :leg} #{:bite :gore}                :hostile                              :random                               7 #{:hostile})
+  (Monster. :gecko          "gecko"          "geckos"          2 0 0.9   0.1   0.5  5 #{:head :face :body :tail :leg}             #{:bite}                      :hostile-after-sound                  :random                               4 #{:hostile})
+  (Monster. :monkey         "monkey"         "monkies"        13 0 1.2  50    10    5 #{:head :neck :body :tail :leg :face :arm}  #{:bite :punch}               :hostile-after-attacked               :follow-player-in-range-or-random    10 #{:hostile})
+  (Monster. :bird           "bird"           "birds"           4 0 2.1   1     0.3  4 #{:head :body :tail :leg :beak :wing}       #{:bite :claw}                :retreat-after-sound                  :random                               8 #{:docile})
+  (Monster. :centipede      "centipede"      "centipedes"      1 0 0.5   0.1   0.1  1 #{:head :body :leg}                         #{:bite}                      :hostile-after-attacked               :random                               3 #{:hostile})
+  (Monster. :turtle         "turtle"         "turtles"         4 0 0.5  10     1.5 20 #{:head :neck :body :leg :face :shell}      #{:bite}                      :retreat-after-attacked               :random                               5 #{:hostile})
+  (Monster. :red-frog       "red frog"       "red frogs"       2 0 0.9   1     0.7  3 #{:head :body :leg :face}                   #{:claw}                      :hostile-after-attacked               :random                               4 #{:docile})
+  (Monster. :orange-frog    "orange frog"    "orange frogs"    2 0 0.9   1     0.7  3 #{:head :body :leg :face}                   #{:claw}                      :hostile-after-attacked               :random                               4 #{:docile})
+  (Monster. :yellow-frog    "yellow frog"    "yellow frogs"    2 0 0.9   1     0.7  3 #{:head :body :leg :face}                   #{:claw}                      :hostile-after-attacked               :random                               4 #{:docile})
+  (Monster. :green-frog     "green frog"     "green frogs"     2 0 0.9   1     0.7  3 #{:head :body :leg :face}                   #{:claw}                      :hostile-after-attacked               :random                               4 #{:docile})
+  (Monster. :blue-frog      "blue frog"      "blue frogs"      2 0 0.9   1     0.7  3 #{:head :body :leg :face}                   #{:claw}                      :hostile-after-attacked               :random                               4 #{:docile})
+  (Monster. :purple-frog    "purple frog"    "purple frogs"    2 0 0.9   1     0.7  3 #{:head :body :leg :face}                   #{:claw}                      :hostile-after-attacked               :random                               4 #{:docile})
+  (Monster. :parrot         "parrot"         "parrots"         5 0 2.1   1     1    3 #{:head :body :leg :face :wing :tail}       #{:claw :bite}                :hostile-during-day                   :random                              10 #{:hostile})
+  (Monster. :shark          "shark"          "sharks"         16 0 1.4 800    30   15 #{:head :body :fin :nose :tail}             #{:bite}                      :hostile                              :follow-player-in-range-or-random    10 #{:hostile})
+  (Monster. :fish           "fish"           "fish"            4 0 1.2   4     1    8 #{:head :body :fin :tail}                   #{:bite}                      :hide-from-player-in-range-or-random  :hide-from-player-in-range-or-random  1 #{:hostile})
+  (Monster. :octopus        "octopus"        "octopodes"       4 0 1.5  15     5    4 #{:head :body :tentacle}                    #{:bite :bite-venom :squeeze} :hide-from-player-in-range-or-random  :hide-from-player-in-range-or-random  2 #{:hostile})
+  (Monster. :sea-snake      "sea snake"      "sea snakes"      4 0 1.5   2     1    7 #{:head :body}                              #{:bite :bite-venom}          :hostile-at-night                     :follow-player-in-range-or-random     2 #{:hostile})
+  (Monster. :clam           "clam"           "clams"           2 0 0.1   0.2   0.2 25 #{:shell}                                   #{:clamp}                     :hostile                              :constant                             1 #{:hostile})
+  (Monster. :urchin         "urchin"         "urchins"         2 0 0.1   0.1  10   10 #{:body}                                    #{:spike}                     :hostile                              :constant                             1 #{:hostile})
+  (Monster. :squid          "squid"          "squids"          4 0 1.5  10     6    4 #{:head :body :tentacle}                    #{:bite :squeeze}             :hide-from-player-in-range-or-random  :hide-from-player-in-range-or-random  2 #{:hostile})
+  (Monster. :crocodile      "crocodile"      "crocodiles"     10 0 0.8 150    15    9 #{:head :body :arm :leg :tail :snout}       #{:bite :claw}                :hostile-after-attacked               :follow-player-in-range-or-random     2 #{:hostile})
+  (Monster. :mosquito       "mosquito"       "mosquitoes"      1 0 1.4   0.01  0.1  1 #{:head :body :leg :wing}                   #{:bite}                      :hostile-after-attacked               :follow-player-in-range-or-random     3 #{:hostile})
+  (Monster. :mongoose       "mongoose"       "mongeese"        4 0 1.4   5     4    6 #{:head :body :leg :tail}                   #{:bite :claw}                :hostile-during-day                   :follow-player-in-range-or-random     2 #{:hostile})
+  (Monster. :tarantula      "tarantula"      "tarantulas"      2 0 1.4   0.1   0.2  2 #{:head :body :leg}                         #{:bite}                      :retreat-after-attacked               :hide-from-player-in-range-or-random  2 #{:hostile})
+  (Monster. :monitor-lizard "monitor lizard" "monitor lizards" 7 0 1.1  10     5   10 #{:head :body :leg :tail}                   #{:bite :claw}                :hostile-after-sound                  :random                               2 #{:hostile})
+  (Monster. :komodo-dragon  "komodo dragon"  "komodo dragons" 12 0 0.8  60    10   14 #{:head :body :leg :tail}                   #{:bite :claw}                :hostile-after-attacked               :random                               2 #{:hostile})
+  (Monster. :cobra          "cobra"          "cobras"          5 0 0.8   6     3    7 #{:head :body :tail}                        #{:bite :bite-venom}          :hostile-after-attacked               :random                               2 #{:hostile})
+  (Monster. :puffer-fish    "puffer fish"    "puffer fish"     3 0 1.1   1     0.6  7 #{:head :body :tail}                        #{:sting-venom}               :hostile-during-day                   :random                               2 #{:hostile})
+  (Monster. :crab           "crab"           "crabs"           4 0 0.8   2     1.5  9 #{:head :body}                              #{:claw}                      :hostile-after-sound                  2 #{:hostile})
+  (Monster. :hermit-crab    "hermit crab"    "hermit crabs"    3 0 0.6   1     1   15 #{:head :shell :leg}                        #{:claw}                      :hostile-during-day                   1 #{:hostile})
+  (Monster. :electric-eel   "electric eel"   "electric eels"   5 0 0.6  10     5    8 #{:head :body}                              #{:bite}                      :follow-player-in-range-or-random     2 #{:hostile})
+  (Monster. :jellyfish      "jellyfish"      "jellyfish"       3 0 0.6   1     0.1  4 #{:body}                                    #{:sting-venom}               :retreat-after-attacked               1 #{:hostile})])

 (def ^:private race->monster-map
   (apply hash-map (mapcat (fn [[k v]] [k (first v)])


Snapshot version

Snapshot version

--- scheduler/project.clj
+++ scheduler/project.clj
@@ -13,7 +13,7 @@
 ;; See the License for the specific language governing permissions and
 ;; limitations under the License.
 ;;
-(defproject cook "1.17.0"
+(defproject cook "1.17.1-SNAPSHOT"
   :description "This launches jobs on a Mesos cluster with fair sharing and preemption"
   :license {:name "Apache License, Version 2.0"}
   :dependencies [[org.clojure/clojure "1.8.0"]


constrain complement of vp-pronoun-phrasal to be {:case :acc}

--- src/babel/francais/grammar.cljc
+++ src/babel/francais/grammar.cljc
@@ -389,6 +389,7 @@
                                    :infl {:not :past-p}}
                             :comp {:phrasal false
                                    :synsem {:cat :noun
+                                            :case :acc
                                             :pronoun true}}
                             :rule "vp-pronoun-phrasal"
                             :synsem {:cat :verb}})


improve comment

improve comment

--- src/babel/italiano/lexicon.cljc
+++ src/babel/italiano/lexicon.cljc
@@ -2154,7 +2154,7 @@
                            vals))))

                  ;; If a verb is not specifically marked as reflexive, it
-                 ;; is reflexive:false, to prevent generation of reflexive
+                 ;; is {:reflexive false}, to prevent generation of reflexive
                  ;; sentences using nonreflexive verbs.
                  ;; TODO: move this to within intransitivize and transitivize:
                  ;; that is, within babel.italiano.pos, mark certain parts of speech


fix namespace issues due to recent clojurescript attempts

--- src/babel/italiano/workbook.clj
+++ src/babel/italiano/workbook.clj
@@ -10,11 +10,11 @@
    [babel.pos :as pos]
    [babel.reader :as reader]
    [clojail.core :refer [sandbox]]
+   [clojail.testers :refer :all]
    [clojure.repl :refer [doc]]
    [clojure.set :as set]
    [clojure.string :as string]
    [clojure.tools.logging :as log]
-   [babel.logjs :as log]
    [compojure.core :as compojure :refer [GET PUT POST DELETE ANY]]
    [dag_unify.core :refer [fail? fail-path-between get-in remove-false strip-refs unify]]
    [hiccup.core :refer [html]]))


Style header buttons to look more like buttons

--- src/braid/ui/styles/header.cljs
+++ src/braid/ui/styles/header.cljs
@@ -1,5 +1,5 @@
 (ns braid.ui.styles.header
-  (:require [garden.units :refer [em]]
+  (:require [garden.units :refer [em px]]
             [braid.ui.styles.vars :as vars]
             [braid.ui.styles.mixins :as mixins]))

@@ -34,12 +34,30 @@
        :margin-right vars/pad}

       [:.title
-       {:text-decoration "none"
-        :color vars/grey-text}]
+       {:display "inline-block"
+        :text-decoration "none"
+        :background "#FFF"
+        :width "2rem"
+        :height "2rem"
+        :text-align "center"
+        :line-height "2rem"
+        :border-radius "50%"
+        :box-shadow [[0 (px 1) (px 4) 0 "#ccc"]]
+        :color "#AAA"
+        :transition [["all" "0.2s" "ease-in-out"]]
+        :position "relative"
+        :bottom "0"}]

-      [:&.active :&:hover
+      [:&:hover
        [:.title
-        {:color "#000"}]]
+        {:box-shadow [[0 (px 4) (px 4) 0 "#ccc"]]
+         :bottom "1px"}]]
+
+      [:&.active
+       [:.title
+        {:background "#AAA"
+         :color "#fff"
+         :-webkit-font-smoothing "antialiased"}]]

       [:&:hover
        [:.modal


Show Reply... as a textarea placeholder

Show Reply... as a textarea placeholder

--- src/braid/client/mobile/views.cljs
+++ src/braid/client/mobile/views.cljs
@@ -20,6 +20,7 @@
        [upload-button-view {:thread-id thread-id
                             :group-id @group-id}]
        [:textarea {:value @message
+                   :placeholder "Reply..."
                    :on-change
                    (fn [e]
                      (reset! message (.. e -target -value)))


Add /points endpoint that accepts 'n' param (num points)

Returns JSON echoing number of points for now

--- src/clj/cljs_leaflet/server.clj
+++ src/clj/cljs_leaflet/server.clj
@@ -8,15 +8,26 @@
             [ring.middleware.logger :refer [wrap-with-logger]]
             [ring.util.response :refer [response]]
             [environ.core :refer [env]]
-            [ring.adapter.jetty :refer [run-jetty]])
+            [ring.adapter.jetty :refer [run-jetty]]
+
+            ;; application imports
+            ;; TODO:
+            )
   (:gen-class))
+
+(defn random-points-response [params]
+  (let [num-points (if (nil? (:n params)) 0 (:n params))]
+    (response {:msg (str "You requested " num-points " random points")}) ))

 (defroutes routes
   (GET "/" _
     {:status 200
      :headers {"Content-Type" "text/html; charset=utf-8"}
      :body (io/input-stream (io/resource "public/index.html"))})
-  (GET "/json" [] (response {:foo "bar"}))
+  (GET "/json" _
+       (response {:foo "bar"}))
+  (GET "/points" {params :params}
+       (random-points-response params))
   (resources "/"))

 (def http-handler


fix hosting of installed cards on Progenior

fixes #1470

--- src/clj/game/cards-programs.clj
+++ src/clj/game/cards-programs.clj
@@ -542,7 +542,10 @@
                                       (has-subtype? % "Virus")
                                       (installed? %))}
                  :msg (msg "host " (:title target))
-                 :effect (effect (host card target))}]
+                 :effect (effect (host card target)
+                                 (gain :memory (:memoryunits target))
+                                 (update! (assoc (get-card state card)
+                                                 :hosted-programs (cons (:cid target) (:hosted-programs card)))))}]
     :events {:pre-purge {:effect (req (when-let [c (first (:hosted card))]
                                         (update! state side (assoc-in card [:special :numpurged] (:counter c)))))}
              :purge {:req (req (pos? (or (get-in card [:special :numpurged]) 0)))


reduce number of swaps

reduce number of swaps

--- src/clj_money/authorization.clj
+++ src/clj_money/authorization.clj
@@ -46,9 +46,10 @@

 (defn allow
   [resource actions auth-fn]
-  ; TODO Maybe change this so there is only one swap per call
-  (doseq [action actions]
-    (swap! auth-fns #(assoc % [action resource] auth-fn))))
+  (swap! auth-fns #(reduce (fn [result action]
+                             (assoc result [action resource] auth-fn))
+                           %
+                           actions)))

 (defn user-owns-entity?
   [user entity-id]


Connect to firebase

Connect to firebase

--- src/cljs/hacker_agent/core.cljs
+++ src/cljs/hacker_agent/core.cljs
@@ -1,48 +1,67 @@
 (ns hacker-agent.core
-    (:require [reagent.core :as reagent :refer [atom]]
-              [secretary.core :as secretary :include-macros true]
-              [goog.events :as events]
-              [goog.history.EventType :as EventType])
-    (:import goog.History))
+  (:require-macros [cljs.core.async.macros :refer [go]])
+  (:require [reagent.core :as reagent :refer [atom]]
+            [secretary.core :as secretary :include-macros true]
+            [goog.events :as events]
+            [goog.history.EventType :as EventType]
+            [weasel.repl :as ws-repl]
+            [cljs.core.async :as async :refer [put! chan <! >! close!]]
+            [hacker-agent.session :as session :refer [global-state global-put!]])
+  (:import goog.History))

 ;; -------------------------
 ;; State
 (defonce app-state (atom {:text "Hello, this is: "}))

-(defn get-state [k & [default]]
-  (clojure.core/get @app-state k default))
+(defonce firebase
+  (let [fb (js/Firebase. "https://hacker-news.firebaseio.com/v0")]
+    (.on (.child fb "topstories") "value"
+         (fn [snapshot]
+           (let [db (js->clj (.val snapshot))]
+             (global-put! :stories db))))
+    (.on (.child fb "maxitem") "value"
+         (fn [snapshot]
+           (let [db (js->clj (.val snapshot))]
+             (global-put! :max-item db))))
+    fb))

-(defn put! [k v]
-  (swap! app-state assoc k v))
+;; -------------------------
+;; Components
+
+(defn hacker []
+  (let [fb (js/Firebase. "https://hacker-news.firebaseio.com/v0/topstories")]
+    [:div
+     [:h2 "Home Page"]
+     [:div
+      [:h3 "Latest Item"]
+      [:div
+       (global-state :max-item)]]
+     [:div
+      [:h3 "Top Stories"]
+      [:ul
+       (for [item (global-state :stories)]
+         ^{:key item} [:li item])]]]))

 ;; -------------------------
 ;; Views

 (defmulti page identity)

-(defmethod page :page1 [_]
-  [:div [:h2 (get-state :text) "Page 1"]
-   [:div [:a {:href "#/page2"} "go to page 2"]]])
-
-(defmethod page :page2 [_]
-  [:div [:h2 (get-state :text) "Page 2"]
-   [:div [:a {:href "#/"} "go to page 1"]]])
-
 (defmethod page :default [_]
   [:div "Invalid/Unknown route"])

+(defmethod page :hacker [_]
+  [hacker])
+
 (defn main-page []
-  [:div [page (get-state :current-page)]])
+  [:div [page :hacker]])

 ;; -------------------------
 ;; Routes
 (secretary/set-config! :prefix "#")

 (secretary/defroute "/" []
-  (put! :current-page :page1))
-
-(secretary/defroute "/page2" []
-  (put! :current-page :page2))
+  (swap! app-state assoc :current-page :hacker))

 ;; -------------------------
 ;; Initialize app


Fix recursive file deletion

Fix recursive file deletion

--- src/clojure/nightcode/utils.clj
+++ src/clojure/nightcode/utils.clj
@@ -36,13 +36,15 @@
     (get-relative-path project-path selected-dir)))

 (defn delete-file-recursively [project-path path]
-  (when (and (= 0 (count (.listFiles (java.io/file path))))
-             (not= project-path path))
-    (.delete (java.io/file path))
-    (delete-file-recursively project-path
-                             (-> (java.io/file path)
-                                 .getParentFile
-                                 .getCanonicalPath))))
+  (let [file (java.io/file path)]
+    (when (and (= 0 (count (.listFiles file)))
+               (not= project-path path))
+      (when (.isDirectory file)
+        (.delete file))
+      (->> file
+           .getParentFile
+           .getCanonicalPath
+           (delete-file-recursively project-path)))))

 (defn format-name
   [name-str project-type]


Further adjustments

Further adjustments

--- src/clojurefx/controllergen.clj
+++ src/clojurefx/controllergen.clj
@@ -42,10 +42,12 @@
   (first (filter #(= class-str (last (str/split (pr-str %) #"\."))) imports)))

 (defn init-class [pkg classname import-classes]
+  (debug (str (str/replace pkg #"\." "/") "/" classname))
+
   (let [cw (new org.objectweb.asm.ClassWriter 0)
         clazz (.visit cw Opcodes/V1_8
                       (+ Opcodes/ACC_PUBLIC Opcodes/ACC_SUPER)
-                      (str pkg "/" classname)
+                      (str (str/replace pkg #"\." "/") "/" classname)
                       nil
                       "java/lang/Object"
                       nil)
@@ -159,13 +161,14 @@
 ;;          (gen-initializer clj-ns clj-fn)
 ;;          "\n}")))

-(defn gen-fx-controller [fxmlzip fxmlpath [clj-ns clj-fn] [pkg classname]]
+(defn gen-fx-controller #^Byte [fxmlzip fxmlpath [clj-ns clj-fn] [pkg classname]]
   (let [fxid-elems (get-fxid-elems fxmlzip)
         handler-fns (get-handler-fns fxmlzip)
         import-classes (build-imports fxmlpath)]
     (-> (init-class pkg classname import-classes)
         (gen-props fxid-elems import-classes)
-        (gen-handlers handler-fns clj-ns))))
+        (gen-handlers handler-fns clj-ns)
+        .toByteArray)))

 ;; ;; Plumber

@@ -180,11 +183,16 @@
 ;;     (makeclass pkg classname (gen-fx-controller fxmlzip fxmlpath cljvec))))

 (defn gen-fx-controller-class [fxmlpath clj-fn]
-  (let [clj-fn (if (symbol? clj-fn)
-                 (str (namespace clj-fn) "/" (name clj-fn))
-                 clj-fn)
+  (let [clj-fn ^String (if (symbol? clj-fn)
+                         (str (namespace clj-fn) "/" (name clj-fn))
+                         clj-fn)
         fxmlzip (zip-tree-seq (xml/parse (io/input-stream fxmlpath)))
         clazz (get-controller-class fxmlzip)
-        [pkg classname] (reverse (map str/reverse (str/split (str/reverse clazz) #"\." 2)))
-        cljvec (str/split clj-fn #"/")]
-    (gen-fx-controller fxmlzip fxmlpath cljvec [pkg classname])))
+        [pkg classname] (reverse (map str/reverse (str/split (str/reverse clazz) #"\." 2)))
+        cljvec (str/split clj-fn #"/")
+        controllerclass #^Byte (gen-fx-controller fxmlzip fxmlpath cljvec [pkg classname])
+        classloader (.getContextClassLoader (Thread/currentThread))]
+    (debug "Controllerclass array size is" (count controllerclass) "Byte")
+    (debug "Controllerclass of class" (str pkg "." classname) "has an array size of" (count controllerclass) "Byte")
+    (debug (type controllerclass))
+    (.defineClass classloader (str pkg "." classname) controllerclass 0 (count controllerclass))))


Seems alright, only remaining thing is cleanup

--- src/com/hypirion/clj_xchart.clj
+++ src/com/hypirion/clj_xchart.clj
@@ -1,7 +1,9 @@
 (ns com.hypirion.clj-xchart
-  (:import (org.knowm.xchart XYChart
+  (:import (org.knowm.xchart BubbleChart
+                             XYChart
                              PieChart
                              CategoryChart
+                             BubbleSeries$BubbleSeriesRenderStyle
                              CategorySeries$CategorySeriesRenderStyle
                              PieSeries$PieSeriesRenderStyle
                              XYSeries$XYSeriesRenderStyle
@@ -70,6 +72,8 @@
    :scatter CategorySeries$CategorySeriesRenderStyle/Scatter
    :stick CategorySeries$CategorySeriesRenderStyle/Stick})

+(def bubble-render-styles
+  {:round BubbleSeries$BubbleSeriesRenderStyle/Round})

 (def text-alignments
   {:centre Styler$TextAlignment/Centre
@@ -378,6 +382,47 @@
       chart
       title (.setTitle title)))))

+(defn add-bubble-series
+  [chart s-name data]
+  (if (sequential? data)
+    (apply add-raw-series chart s-name data)
+    (let [{:keys [x y bubble style]} data
+          {:keys [marker-color marker-type
+                  line-color line-style line-width
+                  fill-color show-in-legend]} style]
+      (doto-cond
+       (add-raw-series chart s-name x y bubble)
+       line-color (.setLineColor (colors line-color line-color))
+       line-style (.setLineStyle line-style)
+       line-width (.setLineWidth (float line-width))
+       fill-color (.setFillColor (colors fill-color fill-color))
+       (not (nil? show-in-legend)) (.setShowInLegend (boolean show-in-legend))))))
+
+(defn bubble-chart
+  "Returns a bubble chart"
+  ([series]
+   (bubble-chart series {}))
+  ([series
+    {:keys [width height title theme render-style]
+     :or {width 640 height 500}
+     :as styling}]
+   {:pre [series]}
+   (let [chart (BubbleChart. width height)]
+     (doseq [[s-name data] series]
+       (let [render-style (-> data :style :render-style)]
+         (doto-cond (add-series chart s-name data)
+          render-style (.setBubbleSeriesRenderStyle (bubble-render-styles render-style)))))
+     (doto-cond
+      (.getStyler chart)
+      theme (.setTheme (themes theme theme))
+      render-style (.setDefaultSeriesRenderStyle (bubble-render-styles render-style)))
+     (doto (.getStyler chart)
+       (set-default-style! styling)
+       (set-axes-style! styling))
+     (doto-cond
+      chart
+      title (.setTitle title)))))
+
 (defn pie-chart
   "Returns a pie chart"
   ([series]


Strip guard from :path-info in addition to :uri

If :path-info is present, Compojure gives it precedence over :uri for
routing, so it needs to be stripped as well.

--- src/spiral/experimental.clj
+++ src/spiral/experimental.clj
@@ -1,8 +1,8 @@
 (ns spiral.experimental
   "This namespace contains experimental spiral functionality.
-
+
    work-shed is an async middle that automatically returns short, precomputed responses to clients when the server gets overloaded.
-
+
    route-concurrently is a simple async routing macro that provides a way to expose concurrency between different routes. Beauty will probably replace it wholesale.
    "
   (:require [clojure.core.async :as async]))
@@ -31,6 +31,11 @@
             (async/>! (:async-response req) shed-response)))))
     req-chan))

+(defn- strip-guard-prefix [path guard]
+  (when path
+    (let [suffix (.substring ^String path (count guard))]
+      (when-not (empty? suffix) suffix))))
+
 (defn route-concurrently-
   [pairs]
   (let [req-chan (async/chan)]
@@ -40,12 +45,10 @@
               [guard fwd] (some (fn [[^String guard :as pair]]
                                   (when (.startsWith (:uri req "") guard)
                                     pair))
-                                pairs)
-              uri-suffix (.substring ^String (:uri req) (count guard))
-              uri-suffix (if (= uri-suffix "")
-                           "/"
-                           uri-suffix)]
-          (async/>! fwd (assoc req :uri uri-suffix)))))
+                                pairs)]
+          (async/>! fwd (assoc req
+                          :uri (or (strip-guard-prefix (:uri req) guard) "/")
+                          :path-info (strip-guard-prefix (:path-info req) guard))))))
     req-chan))

 (defmacro route-concurrently


Allow random units and chosen units

Allow random units and chosen units

--- src/test_utils/sandbox.cljc
+++ src/test_utils/sandbox.cljc
@@ -405,9 +405,9 @@
 (defn rand-length-unit []
   (rand-nth [:ft :m]))

-(defn typical-fracture-geometry []
-  (let [unit (rand-length-unit)]
-    [(map #(vector unit %) (typical-fracture-size unit)) (typical-fracture-azimuth)]))
+(defn typical-fracture-geometry
+  ([unit] [(map #(vector unit %) (typical-fracture-size unit)) (typical-fracture-azimuth)])
+  ([] (typical-fracture-geometry (rand-length-unit))))

 (defn typical-subsurface-location
   ([] (typical-subsurface-location (rand-length-unit)))


Make public token generation function.

Make public token generation function.

--- src/uxbox/services/auth.clj
+++ src/uxbox/services/auth.clj
@@ -80,7 +80,7 @@
   [user password]
   (hashers/check password (:password user)))

-(defn- generate-token
+(defn generate-token
   [user]
   (let [data {:id (:id user)}]
     (jwe/encrypt data secret +auth-opts+)))


Only associate parameters when not nil

Only associate parameters when not nil

--- src/yada/resources/misc.clj
+++ src/yada/resources/misc.clj
@@ -10,7 +10,9 @@
   (resource-properties [this]
     {:allowed-methods (keys this)
      :parameters (reduce-kv (fn [acc k v]
-                              (assoc acc k (:parameters v))) {} this)
+                              (cond-> acc (:parameters v)
+                                      (assoc k (:parameters v))))
+                            {} this)
      :representations [{:media-type #{"text/plain"}}]})
   (resource-properties [_ ctx]
     {:last-modified (to-date (now))})


Add eval feature

Add eval feature

--- src/antlion_clojure/bot.clj
+++ src/antlion_clojure/bot.clj
@@ -94,6 +94,14 @@
                    :channel channel
                    :text "ｹｼﾀﾖ!"})))

+(defn- eval
+  [{:keys [user channel] :as res} txt]
+  (let [parse-result (parse-form txt)]
+    (map->Payload {:type :message
+                   :user user
+                   :channel channel
+                   :text (format-result parse-result)})))
+
 (defn- channel-leave-handler
   [{:keys [user channel]
     :as res}]
@@ -125,13 +133,17 @@
                      :text "ﾊﾞｶｼﾞｬﾈｰﾉ"}))))

 (defn- default-message-handler
-  [{:keys [user channel]
+  [{:keys [user channel text]
     :as res}]
-  (let [self (redis/get-self)]
+  (let [self (redis/get-self)
+        txt (-> (split text #" " 2) second)]
+    (println txt)
     (when (slack/message-for-me? res self)
       (cond
         (redis/get-checking-question? user)
         (check-question res)
+        (= (-> txt first) \()
+        (eval res txt)
         :else (command-message-handler res)))))

 (defn message-handler


adding roles and clearing / in couple of users routes

--- src/celestial/users_api.clj
+++ src/celestial/users_api.clj
@@ -25,15 +25,18 @@
   (GET- "/users" [] {:nickname "getUsers" :summary "Get all users"}
         (success (map #(dissoc (p/get-user %) :password) (p/all-users))))

+  (GET- "/users/roles" [] {:nickname "getRoles" :summary "Get all existing user roles"}
+        (success {:roles roles-m}))
+
   (GET- "/users/:name" [^:string name] {:nickname "getUser" :summary "Get User"}
         (success (p/get-user name)))

-  (POST- "/users/" [& ^:user user] {:nickname "addUser" :summary "Adds a new user"}
+  (POST- "/users" [& ^:user user] {:nickname "addUser" :summary "Adds a new user"}
          (wrap-errors
            (p/add-user (-> user convert-roles hash-pass))
            (success {:msg "added user"})))

-  (PUT- "/users/" [& ^:user user] {:nickname "updateUser" :summary "Updates an existing user"}
+  (PUT- "/users" [& ^:user user] {:nickname "updateUser" :summary "Updates an existing user"}
         (wrap-errors (p/update-user (-> user convert-roles hash-pass))
                      (success {:msg "user updated"})))


CMR-203: Added tests with sort key for keyword scoring.

--- test/cmr/system_int_test/search/collection_keyword_search_test.clj
+++ test/cmr/system_int_test/search/collection_keyword_search_test.clj
@@ -71,4 +71,13 @@
            "Laser platform_SnA" [coll14 coll11 coll9 coll5 coll7]
            "La?er platform_SnA" [coll14 coll11 coll9 coll5 coll7]
            "L*er platfor*_SnA" [coll14 coll11 coll9 coll5 coll7]
-           "L?s* plat?o*_SnA" [coll14 coll11 coll9 coll5 coll7]))))+           "L?s* plat?o*_SnA" [coll14 coll11 coll9 coll5 coll7]))
+    (testing "sorted search by keywords with sort keys."
+      (are [keyword-str sort-key items] (d/refs-match-order? items
+                                                              (search/find-refs
+                                                                :collection {:keyword keyword-str
+                                                                             :sort-key sort-key}))
+           "Laser platform_SnA" "-entry-title" [coll14 coll11 coll9 coll7 coll5]
+           "La?er platform_SnA" "score" [coll14 coll11 coll9 coll5 coll7]
+           "Laser platfor*_SnA" "+score" [coll5 coll7 coll9 coll11 coll14]
+           "L?s* plat?o*_SnA" "-score" [coll14 coll11 coll9 coll5 coll7]))))


Hide unimplemented buttons.

Hide unimplemented buttons.

--- src/sqls/ui/seesaw/worksheet.clj
+++ src/sqls/ui/seesaw/worksheet.clj
@@ -350,16 +350,16 @@
                                                     {:title "Log" :content log-panel}])
         menu-panel (seesaw.core/horizontal-panel :id :menu-panel
                                                  :items [
-                                                         (seesaw.core/button :id :new
-                                                                             :icon (seesaw.icon/icon "new.png"))
-                                                         (seesaw.core/button :id :save
-                                                                             :icon (seesaw.icon/icon "floppy.png"))
-                                                         (seesaw.core/button :id :open
-                                                                             :icon (seesaw.icon/icon "open.png"))
+                                                         ; (seesaw.core/button :id :new
+                                                         ;                     :icon (seesaw.icon/icon "new.png"))
+                                                         ; (seesaw.core/button :id :save
+                                                         ;                     :icon (seesaw.icon/icon "floppy.png"))
+                                                         ; (seesaw.core/button :id :open
+                                                         ;                     :icon (seesaw.icon/icon "open.png"))
                                                          ; (seesaw.core/button :id :explain
                                                          ;                     :text "Explain plan")
-                                                         (seesaw.core/button :id :execute
-                                                                             :text "Execute")
+                                                         ; (seesaw.core/button :id :execute
+                                                         ;                     :text "Execute")
                                                          (seesaw.core/button :id :commit
                                                                              :text "Commit")
                                                          (seesaw.core/button :id :rollback


refer router state in handler

refer router state in handler

--- src/chat/server/handler.clj
+++ src/chat/server/handler.clj
@@ -10,7 +10,7 @@
             [ring.util.response :refer [get-header]]
             [taoensso.timbre :as timbre]
             [clojure.tools.nrepl.server :as nrepl]
-            [chat.server.sync :as sync :refer [sync-routes]]
+            [chat.server.sync :as sync :refer [sync-routes router]]
             [chat.server.routes :as routes
              :refer [desktop-client-routes
                      mobile-client-routes
@@ -157,6 +157,4 @@
   (let [port (Integer/parseInt (first args))
         repl-port (Integer/parseInt (second args))]
     (mount/start-with-args {:port port
-                            :repl-port repl-port})
-    (chat.server.sync/start-router!)
-    ))
+                            :repl-port repl-port})))


fix typos in docstrings

fix typos in docstrings

--- src/clj/com/rpl/specter/macros.clj
+++ src/clj/com/rpl/specter/macros.clj
@@ -536,7 +536,7 @@
 (defmacro select
   "Navigates to and returns a sequence of all the elements specified by the path.
    This macro will attempt to do inline factoring and caching of the path, falling
-   back to compiling the path on every invocation it it's not possible to
+   back to compiling the path on every invocation if it's not possible to
    factor/cache the path."
   [apath structure]
   `(i/compiled-select* (path ~apath) ~structure))
@@ -544,7 +544,7 @@
 (defmacro select-one!
   "Returns exactly one element, throws exception if zero or multiple elements found.
    This macro will attempt to do inline factoring and caching of the path, falling
-   back to compiling the path on every invocation it it's not possible to
+   back to compiling the path on every invocation if it's not possible to
    factor/cache the path."
   [apath structure]
   `(i/compiled-select-one!* (path ~apath) ~structure))
@@ -552,7 +552,7 @@
 (defmacro select-one
   "Like select, but returns either one element or nil. Throws exception if multiple elements found.
    This macro will attempt to do inline factoring and caching of the path, falling
-   back to compiling the path on every invocation it it's not possible to
+   back to compiling the path on every invocation if it's not possible to
    factor/cache the path."
   [apath structure]
   `(i/compiled-select-one* (path ~apath) ~structure))
@@ -560,7 +560,7 @@
 (defmacro select-first
   "Returns first element found.
    This macro will attempt to do inline factoring and caching of the path, falling
-   back to compiling the path on every invocation it it's not possible to
+   back to compiling the path on every invocation if it's not possible to
    factor/cache the path."
   [apath structure]
   `(i/compiled-select-first* (path ~apath) ~structure))
@@ -569,7 +569,7 @@
   "Returns any element found or [[NONE]] if nothing selected. This is the most
    efficient of the various selection operations.
    This macro will attempt to do inline factoring and caching of the path, falling
-   back to compiling the path on every invocation it it's not possible to
+   back to compiling the path on every invocation if it's not possible to
    factor/cache the path."
   [apath structure]
   `(i/compiled-select-any* (path ~apath) ~structure))
@@ -577,7 +577,7 @@
 (defmacro selected-any?
   "Returns true if any element was selected, false otherwise.
    This macro will attempt to do inline factoring and caching of the path, falling
-   back to compiling the path on every invocation it it's not possible to
+   back to compiling the path on every invocation if it's not possible to
    factor/cache the path."
   [apath structure]
   `(i/compiled-selected-any?* (path ~apath) ~structure))
@@ -586,7 +586,7 @@
   "Navigates to each value specified by the path and replaces it by the result of running
    the transform-fn on it.
    This macro will attempt to do inline factoring and caching of the path, falling
-   back to compiling the path on every invocation it it's not possible to
+   back to compiling the path on every invocation if it's not possible to
    factor/cache the path."
   [apath transform-fn structure]
   `(i/compiled-transform* (path ~apath) ~transform-fn ~structure))
@@ -594,7 +594,7 @@
 (defmacro setval
   "Navigates to each value specified by the path and replaces it by `aval`.
    This macro will attempt to do inline factoring and caching of the path, falling
-   back to compiling the path on every invocation it it's not possible to
+   back to compiling the path on every invocation if it's not possible to
    factor/cache the path."
   [apath aval structure]
   `(i/compiled-setval* (path ~apath) ~aval ~structure))
@@ -606,7 +606,7 @@
    in the final return. replace-in is useful for situations where you need to know the specific values
    of what was transformed in the data structure.
    This macro will attempt to do inline factoring and caching of the path, falling
-   back to compiling the path on every invocation it it's not possible to
+   back to compiling the path on every invocation if it's not possible to
    factor/cache the path."
   [apath transform-fn structure & args]
   `(i/compiled-replace-in* (path ~apath) ~transform-fn ~structure ~@args))


But fix and code cleanup (from Alex B.)

But fix and code cleanup (from Alex B.)

--- src/cia/auth/middleware.clj
+++ src/cia/auth/middleware.clj
@@ -30,11 +30,11 @@
 ;; https://github.com/metosin/compojure-api/wiki/Creating-your-own-metadata-handlers
 (defmethod meta/restructure-param :capabilities
   [_ capabilities acc]
-  (update-in acc
-             [:lets]
-             into
-             ['_ `(require-capability! ~capabilities
-                                       (:identity ~'+compojure-api-request+))]))
+  (update acc :lets into
+          ['_ `(require-capability! ~capabilities
+                                    (:identity ~'+compojure-api-request+))]))

 (defmethod meta/restructure-param :login [_ bind-to acc]
-  (update-in acc [:lets] into [bind-to `(get-in  ~'+compojure-api-request+ [:identity :login])]))
+  (update acc :lets into
+          [bind-to `(-> (:identity ~'+compojure-api-request+)
+                        auth/login)]))


add shell function for budget monitors

add shell function for budget monitors

--- src/clj_money/web/money_shared.clj
+++ src/clj_money/web/money_shared.clj
@@ -23,3 +23,7 @@
      true (map #(rename-keys % {:id :value
                                 :name :caption}))
      (contains? options :include-none?) (concat [{:value "" :caption "None"}]))))
+
+(defn budget-monitors
+  [entity-id]
+  [:h3 "Budget monitors"])


fix date filtering

fix date filtering

--- src/cljs/ceres_analytics/core.cljs
+++ src/cljs/ceres_analytics/core.cljs
@@ -132,9 +132,10 @@

 (defn start-vis [state]
   (let [nodes (get-in @state [:data :new-nodes])
-        links (get-in @state [:data :new-links])]
-    (go-loop [k 10]
-      (if (= k 11)
+        links (get-in @state [:data :new-links])
+        day (get-in @state [:day])]
+    (go-loop [k day]
+      (if (= k (inc day))
         (set! (.-innerHTML (.getElementById js/document "current-time")) "DONE")
         (do
           (loop [i 0]
@@ -164,6 +165,7 @@
           broadcaster (rand-nth (keys broadcasters))
           random-day (rand-int 31)]
       (swap! state assoc-in [:ws-channel] ws-channel)
+      (swap! state assoc-in [:day] random-day)
       (>! ws-channel {:topic :user-tree :data {:broadcaster broadcaster :day random-day}})
       (set! (.-innerHTML (.getElementById js/document "graph-title")) (get broadcasters broadcaster))
       (set! (.-innerHTML (.getElementById js/document "current-day")) (str random-day " April 2015"))


Use hash-tag regexp consistently.

Use hash-tag regexp consistently.

--- src/cljs/link_collective/core.cljs
+++ src/cljs/link_collective/core.cljs
@@ -54,6 +54,9 @@

 (def hashtag-regexp #"(^|\s|\.|;|,|!|-)(#[\w\d\u00a1-\uffff_-]+)")

+(defn extract-hashtags [text]
+  (map #(nth % 2) (re-seq hashtag-regexp text)))
+

 (defn add-post
   "Transacts a new topiq to the stage"
@@ -61,7 +64,7 @@
   (let [post-id (uuid)
         ts (js/Date.)
         text (dom/value (dom/by-id "general-input-form"))
-        hash-tags (map #(nth % 2) (re-seq hashtag-regexp text))
+        hash-tags (extract-hashtags text)
         urls (->> text
                   (re-seq url-regexp)
                   (map first))]
@@ -91,7 +94,7 @@
   (let [comment-id (uuid)
         ts (js/Date.)
         text (dom/value (dom/by-id "general-input-form"))
-        hash-tags (re-seq #"#[\w\d-_]+" text)
+        hash-tags (extract-hashtags text)
         urls (->> text
                   (re-seq url-regexp)
                   (map first))]


Minor: remove println

Minor: remove println

--- src/cljs/mandelbrot_cljs/core.cljs
+++ src/cljs/mandelbrot_cljs/core.cljs
@@ -114,7 +114,6 @@
   []
   (let [{:keys [query] :as full-url} (url (aget (aget js/window "location")"href"))
         query                        (into {} (map (fn [[k v]] [(keyword k) v]) query))]
-    (println full-url)
     (when (and (:x0 query) (:y0 query) (:width query) (:height query))
       query)))


ship radius-limited arena view to bots

ship radius-limited arena view to bots

--- src/clj/battlebots/game.clj
+++ src/clj/battlebots/game.clj
@@ -4,6 +4,7 @@
             [battlebots.services.github :as github]
             [battlebots.constants.arena :refer [arena-key]]
             [battlebots.constants.game :refer [segment-length game-length]]
+            [battlebots.utils.arena :refer :all]
             [battlebots.utils.arena :refer :all]))

 ;;
@@ -177,7 +178,8 @@
   their bots and an identical clean version of the arena"
   [players clean-arena]
   (map (fn [{:keys [_id bot saved-state energy] :as player}]
-         {:decision ((load-string bot) {:arena clean-arena
+         {:decision ((load-string bot)
+                     {:arena (get-arena-area clean-arena (get-player-coords _id) 10)
                                         :state saved-state
                                         :bot_id _id
                                         :energy energy


add title to head

add title to head

--- src/clj/easynxc/handler.clj
+++ src/clj/easynxc/handler.clj
@@ -14,6 +14,7 @@
            :content "width=device-width, initial-scale=1"}]
    [:link {:rel "stylesheet" :href "https://cdnjs.cloudflare.com/ajax/libs/normalize/4.2.0/normalize.min.css"}]
    [:link {:rel "icon" :type "image/png" :href "/images/icon-512.png"}]
+   [:title "easynxc"]
    (include-css (if (env :dev) "/css/site.css" "/css/site.min.css"))])

 (def home-page


display tag toasts only to the runner

display tag toasts only to the runner

--- src/clj/game/core-rules.clj
+++ src/clj/game/core-rules.clj
@@ -150,7 +150,7 @@
 (defn resolve-tag [state side n args]
   (when (pos? n)
     (gain state :runner :tag n)
-    (toast state side (str "Took " n " tag" (when (> n 1) "s") "!") "info")
+    (toast state :runner (str "Took " n " tag" (when (> n 1) "s") "!") "info")
     (trigger-event state side :runner-gain-tag n)))

 (defn tag-runner


Fail example requests randomly

Fail example requests randomly

--- src/clj_gatling/example.clj
+++ src/clj_gatling/example.clj
@@ -3,7 +3,7 @@
 (defn run-request [id]
   ;(println (str "Simulating request for " id))
   (Thread/sleep (rand 1000))
-  "OK")
+  (> 0.7 (rand 1)))

 (def test-scenario
   {:name "Test scenario"


Removed unused binding: descriptions

Removed unused binding: descriptions

--- src/clj_mrazik/importer.clj
+++ src/clj_mrazik/importer.clj
@@ -54,7 +54,6 @@
 (defn import-data
     [file-name]
     (let [parsed-csv (read-csv file-name)
-          descriptions (first parsed-csv)
           entries      (rest  parsed-csv)]
          (doseq [entry entries]
              (let [word-class (get-word-class (nth entry 3))


Fix-up district and supporters imports

Fix-up district and supporters imports

--- src/cljs/geoforms/tasks.clj
+++ src/cljs/geoforms/tasks.clj
@@ -23,6 +23,11 @@
             s
             mungings)))

+(defn ->set-map
+  "Convert a set into a map of {element true}"
+  [set]
+  (zipmap (map munge- set) (repeat true)))
+
 (def ref (m/connect "https://geoforms.firebaseio.com/community-app"))

 ;; upsert
@@ -47,7 +52,7 @@
 (def header-lookup
   {;; idea
    "Timestamp"       :created-at
-   "Quartier"        :district
+   "Quartier"        :districts
    "Idee"            :title
    "Categorie"       :category
    "Desc"            :desc
@@ -85,7 +90,8 @@
            (map #(zipmap headers %))
            ;; idea?
            (map #(update % :urls split-list))
-           (map #(update % :supporters split-list))
+           (map #(update % :supporters (comp ->set-map split-list)))
+           (map #(update % :districts split-list))
            ;; user?
            (map #(update % :age parse-age))
            (map #(update % :alert-districts? parse-bool))


Cache invalidate is an "update" not a "delete"

--- src/cljs/herder/getter.cljs
+++ src/cljs/herder/getter.cljs
@@ -77,6 +77,6 @@
     (let [[type data] data]
       (if (= type :herder.web.notifications/cache-invalidate)
         (doseq [key data]
-          (js/console.log "delete" (pr-str key))
+          (js/console.log "update" (pr-str key))
           (get-data key :refresh true))
         (js/console.log "something else" type)))))


Basic Hiccup formatting

Basic Hiccup formatting

--- src/cljs/tohiccup/core.cljs
+++ src/cljs/tohiccup/core.cljs
@@ -4,6 +4,7 @@
             [om.dom :as dom :include-macros true]
             [om-tools.core :refer-macros [defcomponentk]]
             [om-tools.dom :include-macros true]
+            [clojure.string :refer [join trim blank?]]
             [cljs.core.async :refer [put! chan <!]]
             [hickory.core :as hickory]
             [sablono.core :as html :refer-macros [html]]))
@@ -12,12 +13,28 @@
                     {:html-text ""
                      :hiccup-text ""}))

+(declare beautify-hiccup)
+
+(defn beautify-hiccup-coll [hiccup-expression indent]
+  (join (str "\n" indent)
+        (filter #(not= % "")
+                (map #(beautify-hiccup % (str " " indent))
+                     hiccup-expression))))
+
+(defn beautify-hiccup [hiccup-expression indent]
+  (cond
+   (seq? hiccup-expression) (beautify-hiccup-coll hiccup-expression indent)
+   (vector? hiccup-expression) (str "[" (beautify-hiccup-coll hiccup-expression indent) "]")
+   (map? hiccup-expression) ""
+   (blank? hiccup-expression) ""
+   :else (pr-str hiccup-expression)))
+
 (defn process-action [[action-name action-data]]
   (case action-name
     :update-hiccup
     (let [html-text action-data
           nodes (hickory/parse-fragment html-text)
-          new-hiccup-text (map hickory/as-hiccup nodes)]
+          new-hiccup-text (beautify-hiccup (map hickory/as-hiccup nodes) "")]
       (swap! app-state assoc :hiccup-text new-hiccup-text))))

 (defcomponentk html-input-view


cljs.stacktrace, remove reliance on util ns if used from CLJS

--- src/main/cljs/cljs/stacktrace.cljc
+++ src/main/cljs/cljs/stacktrace.cljc
@@ -33,6 +33,10 @@
 (defn string->regex [s]
   #?(:clj  (Pattern/compile s)
      :cljs (RegExp. s)))
+
+(defn output-directory [opts]
+  #?(:clj  (util/output-directory opts)
+     :cljs (or (:output-dir opts) "out")))

 (defmethod parse-stacktrace :default
   [repl-env st err opts] st)
@@ -68,7 +72,7 @@
           (string->regex
             ;; if :asset-path specified drop leading slash
             (str "^" (or (and asset-path (string/replace asset-path #"^/" ""))
-                         (util/output-directory opts)) "/"))
+                         (output-directory opts)) "/"))
           ""))
       (if-let [asset-root (:asset-root opts)]
         (string/replace file asset-root "")


looks like clojure does not like us nesting ModelImpl inside org.dada.core

--- src/main/clojure/org/dada/core.clj
+++ src/main/clojure/org/dada/core.clj
@@ -211,8 +211,8 @@
   ([#^String model-name #^Keyword key #^Keyword version #^Metadata metadata]
    (let [id-getter (.getAttributeGetter metadata (name key))
 	 version-getter (.getAttributeGetter metadata (name version))]
-     ;;(new VersionedModelView model-name metadata id-getter version-getter)
-     (org.dada.core.ModelImpl. model-name metadata #(.get id-getter %) #(.get version-getter %))
+     (new VersionedModelView model-name metadata id-getter version-getter)
+     ;;(org.dada.core.ModelImpl. model-name metadata #(.get id-getter %) #(.get version-getter %))
      )))

 ;; this should really be collapsed into (model) above - but arity overloading is not sufficient...
@@ -221,8 +221,8 @@
 	keys (.getKeyAttributeKeys metadata)
 	key-getter (.getAttributeGetter metadata (first keys))
 	version-getter (.getAttributeGetter metadata (second keys))]
-    ;;(VersionedModelView. name metadata key-getter version-getter)
-    (org.dada.core.ModelImpl. name metadata #(.get key-getter %) #(.get version-getter %))
+    (VersionedModelView. name metadata key-getter version-getter)
+    ;;(org.dada.core.ModelImpl. name metadata #(.get key-getter %) #(.get version-getter %))
     ))

 (defn apply-getters [#^ISeq getters value]


formatting

formatting

--- src/desdemona/ui/table.cljs
+++ src/desdemona/ui/table.cljs
@@ -1,7 +1,8 @@
 (ns desdemona.ui.table
   (:require [wilson.dom :as wd]
             [reagent.session :as session]
-            [dommy.core :as d :refer-macros [sel sel1]]))
+            [dommy.core :as d :refer-macros [sel sel1]]
+            [desdemona.ui.dom :refer [get-el-height get-el-width]]))

 (def sort-order-id :table-sort-order)
 (def sort-key-id :table-sort-key)
@@ -19,7 +20,8 @@
   (let [state-deref @session/state
         active? #(some #{%} (session-entry state-deref))
         toggler-class (str "columns-toggler drawer drawer--left"
-                           (when (:columns-toggler-open? state-deref) " open"))]
+                           (when (:columns-toggler-open? state-deref)
+                             " open"))]
     [:div {:class toggler-class}
      [:button {:class "drawer-toggler btn brad-0"
                :on-click


Add some specs

Add some specs

--- src/docker_clojure/core.clj
+++ src/docker_clojure/core.clj
@@ -2,8 +2,29 @@
   (:require
    [clojure.java.shell :refer [sh]]
    [clojure.math.combinatorics :as combo]
+   [clojure.spec.alpha :as s]
    [clojure.string :as str]
    [docker-clojure.dockerfile :as df]))
+
+(s/def ::non-blank-string
+  (s/and string? #(not (str/blank? %))))
+
+(s/def ::base-image ::non-blank-string)
+(s/def ::base-images (s/coll-of ::base-image :distinct true :into #{}))
+
+(s/def ::distro ::non-blank-string)
+(s/def ::distros (s/coll-of ::distro :distinct true :into #{}))
+
+(s/def ::build-tool ::non-blank-string)
+(s/def ::build-tool-version
+  (s/and ::non-blank-string #(re-matches #"[\d\.]+" %)))
+(s/def ::build-tools (s/map-of ::build-tool ::build-tool-version))
+
+(s/def ::exclusions
+  (s/keys :opt-un [::base-image ::distro ::build-tool ::build-tool-version]))
+
+(s/def ::maintainers
+  (s/map-of keyword? ::non-blank-string))

 (def base-images
   #{"openjdk:8" "openjdk:11"})
@@ -58,6 +79,10 @@
     (str/join "-" (remove nil? [jdk-label build-tool build-tool-version
                                 distro-label]))))

+(s/def ::variant
+  (s/keys :req-un [::base-image ::distro ::build-tool ::build-tool-version
+                   ::maintainer ::docker-tag]))
+
 (defn variant-map [[base-image distro build-tool]]
   (let [base {:base-image base-image
               :distro     distro
@@ -84,6 +109,7 @@
 (defn image-variants [base-images distros build-tools]
   (->> (combo/cartesian-product base-images distros build-tools)
        (map variant-map)
+       (remove #(= ::s/invalid (s/conform ::variant %)))
        set))

 (defn build-images [variants]


Make JDK 17 the new default

Make JDK 17 the new default

It's the new LTS release

--- src/docker_clojure/core.clj
+++ src/docker_clojure/core.clj
@@ -36,7 +36,7 @@
 (def jdk-versions #{8 11 17 18})

 ;; The default JDK version to use for tags that don't specify one; usually the latest LTS release
-(def default-jdk-version 11)
+(def default-jdk-version 17)

 (def distros
   #{:debian/buster :debian-slim/slim-buster :debian/bullseye :debian-slim/slim-bullseye :alpine/alpine})


Remove html because we are already in one

--- src-cljs/frontend/components/account.cljs
+++ src-cljs/frontend/components/account.cljs
@@ -95,32 +95,31 @@
                                                 :kind :primary
                                                 :size :medium}
                                                "Create New Token")}
-            (html
-              [:div
-               [:div.api-item
-                [:p
-                 "Tokens you have generated that can be used to access the CircleCI API. Apps using these tokens can act as you and have full read- and write-permissions!"]
-                [:div.api-item
-                 (when (seq tokens)
-                   (om/build table/table
-                             {:rows tokens
-                              :key-fn :token
-                              :columns [{:header "Label"
-                                         :cell-fn :label}
-                                        {:header "Token"
-                                         :type :shrink
-                                         :cell-fn :token}
-                                        {:header "Created"
-                                         :type :shrink
-                                         :cell-fn (comp datetime/medium-datetime js/Date.parse :time)}
-                                        {:header "Remove"
-                                         :type :shrink
-                                         :cell-fn
-                                         (fn [token]
-                                           (table/action-button
-                                            "Remove"
-                                            (icon/cancel-circle)
-                                            #(raise! owner [:api-token-revocation-attempted {:token token}])))}]}))]]]))])))))
+                       [:div
+                        [:div.api-item
+                         [:p
+                          "Tokens you have generated that can be used to access the CircleCI API. Apps using these tokens can act as you and have full read- and write-permissions!"]
+                         [:div.api-item
+                          (when (seq tokens)
+                            (om/build table/table
+                                      {:rows tokens
+                                       :key-fn :token
+                                       :columns [{:header "Label"
+                                                  :cell-fn :label}
+                                                 {:header "Token"
+                                                  :type :shrink
+                                                  :cell-fn :token}
+                                                 {:header "Created"
+                                                  :type :shrink
+                                                  :cell-fn (comp datetime/medium-datetime js/Date.parse :time)}
+                                                 {:header "Remove"
+                                                  :type :shrink
+                                                  :cell-fn
+                                                  (fn [token]
+                                                    (table/action-button
+                                                     "Remove"
+                                                     (icon/cancel-circle)
+                                                     #(raise! owner [:api-token-revocation-attempted {:token token}])))}]}))]]])])))))

 (def available-betas
   [{:id "project-cache-clear-buttons"


Invite URL is based on actual page domain.

--- src-cljs/frontend/components/invites.cljs
+++ src-cljs/frontend/components/invites.cljs
@@ -8,7 +8,8 @@
             [frontend.utils.github :as gh-utils]
             [frontend.utils.vcs-url :as vcs-url]
             [om.core :as om :include-macros true])
-  (:require-macros [frontend.utils :refer [html]]))
+  (:require-macros [frontend.utils :refer [html]])
+  (:import [goog Uri]))

 (defn invitees
   "Filters users to invite and returns only fields needed by invitation API"
@@ -129,8 +130,9 @@
                         (remove :circle_member (:github-users invite-data))
                         {:opts {:org-name (:org invite-data)}}) ]
              [:div.org-invites
-               [:h3 "Invite your teammates"]
-               [:p "Select one of your organizations on the left to select teammates to invite.  Or send them this link:"]
-               [:p [:input {:value "https://circleci.com/?join=dont-test-alone", :type "text"}]]
-               [:p "We use GitHub permissions for every user, so if your teammates have access to your project on GitHub, they will automatically have access to the same project on Circle."]]
-             )])))))
+              [:h3 "Invite your teammates"]
+              [:p "Select one of your organizations on the left to select teammates to invite.  Or send them this link:"]
+              (let [current-uri (Uri. js/location.href)
+                    root-uri (.resolve current-uri (Uri. "/"))]
+                [:p [:input {:value root-uri :type "text"}]])
+              [:p "We use GitHub permissions for every user, so if your teammates have access to your project on GitHub, they will automatically have access to the same project on Circle."]])])))))


Update reserved board slugs to avoid conflicts with clients static paths.

--- src/oc/storage/resources/board.clj
+++ src/oc/storage/resources/board.clj
@@ -72,7 +72,7 @@

 ;; ----- Board Slug -----

-(def reserved-slugs #{"create-board" "settings" "boards" "all-posts" "drafts" "must-see" "bookmarks" "inbox" "new" "following" "unfollowing" "home" "threads" "topics"})
+(def reserved-slugs #{"create-board" "settings" "boards" "all-posts" "drafts" "must-see" "bookmarks" "inbox" "new" "following" "unfollowing" "home" "topics" "for-you"})

 (declare list-boards-by-org)
 (defn taken-slugs


Fix comment typo.

Fix comment typo.

--- src/oc/storage/resources/entry.clj
+++ src/oc/storage/resources/entry.clj
@@ -475,7 +475,7 @@
    {:pre [(db-common/conn? conn)]}
    (let [old-follow-ups (:follow-ups original-entry)
          ;; List the user-ids of the assignees that can't be replaced
-         cant-replace-follow-ups (remove nil? (map #(when ;; Cant' replace tje follow-ups that
+         cant-replace-follow-ups (remove nil? (map #(when ;; Cant' replace the follow-ups that
                                                           (and ;; are not assigned to current user
                                                                (not= (-> % :assignee :user-id) (:user-id user))
                                                                ;; and


Add rudimentary GZIP compression to netchan

--- src/engulf/comm/netchan.clj
+++ src/engulf/comm/netchan.clj
@@ -2,25 +2,51 @@
   (:require
    [clojure.tools.logging :as log]
    [cheshire.core :as chesh])
-  (:use aleph.tcp
-        lamina.core
-        gloss.core
-        gloss.io
-        [clojure.walk :only [keywordize-keys]])
-  (:import java.nio.ByteBuffer
-           java.util.Arrays))
+  (:use
+   aleph.tcp
+   lamina.core
+   gloss.core
+   gloss.io
+   [clojure.walk :only [keywordize-keys]])
+  (:import
+   java.util.zip.GZIPOutputStream
+   java.util.zip.GZIPInputStream
+   java.io.ByteArrayOutputStream
+   java.io.ByteArrayInputStream
+   java.nio.ByteBuffer
+   java.util.Arrays))
+
+(defn compress-byte-array
+  [^bytes ba]
+  (let [baos (ByteArrayOutputStream.)
+        gzos (GZIPOutputStream. baos)]
+    (doto gzos (.write ba) (.close))
+    (.toByteArray baos)))
+
+(defn decompress-byte-array
+  [^bytes ba]
+  ;; It's late, gonna be lazy and read in 2MB only
+  (let [bais (ByteArrayInputStream. ba)
+        gzis (GZIPInputStream. bais)
+        buf-size (* 2 1024 1024)
+        buf (byte-array buf-size)
+        read-len (.read gzis buf 0 buf-size)]
+    (.close gzis)
+    (when (>= read-len buf-size)
+      (throw ( Exception. "Hit max buf size! Fix my lazy work!")))
+    (Arrays/copyOfRange buf 0 read-len)))

 (defn encode-msg
-  "Encodes a message using SMILE"
-  [type body]
-  (chesh/encode-smile {:type type :body body}))
+    "Encodes a message using SMILE and GZIP"
+    [type body]
+    (compress-byte-array (chesh/encode-smile {:type type :body body})))

 (defn decode-msg
-  "Parses a SIMLE msg, ensures it's properly formatted as well"
+  "Parses a GZIPed SIMLE msg, ensures it's properly formatted as well"
   [msg]
   {:post [(not= nil (first %))]}
-  (let [{:strs [type body]} (chesh/parse-smile msg)]
-    [type (keywordize-keys body)]))
+  (let [{:strs [type body]} (chesh/parse-smile (decompress-byte-array msg))]
+    [type body]))

 ;; Simple int32 prefixed frames
 (def wire-protocol


usertype-metadata query

usertype-metadata query

--- src/er_cassandra/schema.clj
+++ src/er_cassandra/schema.clj
@@ -16,6 +16,17 @@
   (d/chain (session/execute session (table-metadata-query keyspace table))
            first))

+(defn ^:private usertype-metadata-query
+  [keyspace type]
+  (h/select :system.schema_usertypes
+            (h/where {:keyspace_name keyspace
+                      :type_name type})))
+
+(defn usertype-metadata
+  [session keyspace type]
+  (d/chain (session/execute session (usertype-metadata-query keyspace type))
+           first))
+
 (defn ^:private column-metadata-query
   [keyspace table]
   (h/select :system.schema_columns


flatten the key for update

flatten the key for update

--- src/er_cassandra/record.clj
+++ src/er_cassandra/record.clj
@@ -94,7 +94,7 @@
    (let [key-clause (extract-key-equality-clause key record opts)
          set-cols (if (not-empty set-columns)
                     (select-keys record set-columns)
-                    (apply dissoc record (make-sequential key)))]
+                    (apply dissoc record (make-sequential (flatten key))))]
      (h/update table
                (h/set-columns set-cols)
                (h/where key-clause)


(PCP-701) Only schedule purge when broker is running

When the broker is not running, there are guaranteed to be no clients
connected. Scheduling a purge every time the broker is HUPed could lead
to many extraneous threads. Only schedule a client purge if the broker
is already running.

--- src/puppetlabs/pcp/broker/core.clj
+++ src/puppetlabs/pcp/broker/core.clj
@@ -587,7 +587,7 @@
   (let [timestamp (now)]
     (swap! (:database broker) update :subscriptions dissoc uri)
     (swap! (:database broker) update :warning-bin assoc uri timestamp)
-    (when (all-controllers-disconnected? broker)
+    (when (and (= :running @(:state broker)) (all-controllers-disconnected? broker))
       (schedule-client-purge! broker timestamp controller-disconnection-graceperiod uri))))

 (s/defn start-client


Added type check to validity check.

Added type check to validity check.

--- src/fm/simrunner/config.clj
+++ src/fm/simrunner/config.clj
@@ -108,11 +108,16 @@
   ([config validate?]
     (-> (if validate? (validate config) config) meta ::invalid-ids)))

+(defn config? [config]
+  (= ::config (type config)))
+
 (defn valid?
   ([config]
     (valid? config false))
   ([config validate?]
-    (-> (if validate? (validate config) config) invalid-ids seq not)))
+    (let [config (if validate? (validate config) config)]
+      (and (config? config)
+           (-> config invalid-ids seq not)))))

 (defn read-config-lines [lines]
   (let [values (-> lines


Remove docs stuff from precompile-assets

--- src/frontend/tasks/http.clj
+++ src/frontend/tasks/http.clj
@@ -27,15 +27,7 @@
                       (throw (ex-info "Couldn't update hosted script" script e)))))
         (recur (dec tries))))))

-(defn generate-doc-manifest []
-  (let [doc-root "resources/assets/docs"
-        json (-> doc-root
-                 doc-utils/read-doc-manifest
-                 (json/generate-string {:pretty true}))]
-    (spit (fs/join doc-root "manifest.json") json)))
-
 (defn precompile-assets []
-  (generate-doc-manifest)
   (update-hosted-scripts frontend.stefon/hosted-scripts)
   (less/compile! :minify true)
   (println (format "Stefon options: %s" stefon-options))


basic task dispatcher added to basilisk.core

--- src/basilisk/core.clj
+++ src/basilisk/core.clj
@@ -1,8 +1,38 @@
 (ns basilisk.core
-  (:require [monger.core :as mg])
+  ;(:require [clojure.tools.cli :refer [parse-opts]])
   (:gen-class))
+
+
+(defn- task-name-to-function
+  "Convert a string to function path."
+  [string]
+  (let [tokens (clojure.string/split string #":")]
+    (case (count tokens)
+      0 nil
+      1 (str "basilisk.tasks.core/" (first tokens))
+      (do
+        (str "basilisk.tasks."
+             (clojure.string/join
+              "."
+              (subvec tokens 0 (- (count tokens) 1))) "/" (last tokens))))))
+
+(defn- print-usage
+  [task]
+  (println (str "Can't find task '" task "'.")))
+
+
+(defn- run-task
+  [task args]
+  (let [func (resolve task)]
+    (if (nil? func)
+      (print-usage task)
+      (apply (resolve task) args))))

 (defn -main
   "I don't do a whole lot ... yet."
-  [& args]
-  (println "Hello, World!"))
+  [command & args]
+  (let [task (task-name-to-function command)]
+
+    (if (nil? task)
+      (print-usage command)
+      (run-task (symbol task) args))))


improve image extension detection

improve image extension detection

--- src/blogiseq/core.clj
+++ src/blogiseq/core.clj
@@ -105,7 +105,7 @@
       (copy-path-if-not-exists path mini-name))))

 (defn is-image? [path]
-  (not (nil? (re-find #"jpg|png|gif" (clojure.string/lower-case path)))))
+  (not (nil? (re-find #"jpg$|png$|gif$" (clojure.string/lower-case path)))))

 (is-image? "resources/photowalls/usa")


Remove some superfluous brackets in a thread last pipeline

--- src/catalog/vubis.clj
+++ src/catalog/vubis.clj
@@ -279,8 +279,8 @@
    [producer-long producer-place]
    (remove nil?)
    (remove string/blank?)
-   (seq) ; short-circuit if both producer-long and producer-place are
-         ; nil or blank
+   seq ; short-circuit if both producer-long and producer-place are
+       ; nil or blank
    (string/join ", ")))

 (defn get-producer-brief


moving back to simpler output model

moving back to simpler output model

--- src/celestial/ssh.clj
+++ src/celestial/ssh.clj
@@ -45,11 +45,10 @@
   (with-session host port
     (fn [session]
       (doseq [b batches]
-        (let [{:keys [channel out-stream] :as res} (ssh session {:in  (join "\n" b)  :out :stream})]
-          (log-output out-stream)
-          (let [exit (.getExitStatus channel)]
-            (when-not (= exit 0)
-              (throw+ (merge res {:type ::execute-failed :exit exit} (meta b))))))))))
+        (let [{:keys [exit out] :as res} (ssh session {:in  (join "\n" b)})]
+            (if (= exit 0)
+              (debug out)
+              (throw+ (merge res {:type ::execute-failed :exit exit} (meta b)))))))))

 (defn fname [uri] (-> uri (split '#"/") last))


CLJS-752: implement specify!

CLJS-752: implement specify!

redefine specify in terms of specify! which directly modifies instances.

--- src/clj/cljs/core.clj
+++ src/clj/cljs/core.clj
@@ -607,11 +607,15 @@
            ~@impls))
        (new ~t ~@locals nil))))

-(defmacro specify [expr & impls]
+(defmacro specify! [expr & impls]
   (let [x (with-meta (gensym "x") {:extend :instance})]
-    `(let [~x (cljs.core/clone ~expr)]
+    `(let [~x ~expr]
        (extend-type ~x ~@impls)
        ~x)))
+
+(defmacro specify [expr & impls]
+  `(cljs.core/specify! (cljs.core/clone ~expr)
+     ~@impls))

 (defmacro ^:private js-this []
   (core/list 'js* "this"))


Add run credits for corp's bad publicity

--- src/clj/game/core.clj
+++ src/clj/game/core.clj
@@ -738,6 +738,10 @@
       "New remote" [:servers :remote (count (get-in @state [:corp :servers :remote]))]
       [:servers :remote (-> (split server #" ") last Integer/parseInt)])))

+(defn add-bad-publicity-credit [state]
+  (swap! state update-in [:runner :run-credit] + (get-in @state [:corp :bad-publicity]))
+  (swap! state update-in [:runner :credit] + (get-in @state [:corp :bad-publicity])))
+
 (defn run
   ([state side server] (run state side server nil nil))
   ([state side server run-effect card]
@@ -752,6 +756,7 @@
          (swap! state assoc :per-run nil
                 :run {:server s :position (count ices) :ices ices :access-bonus 0
                       :run-effect (assoc run-effect :card card)})
+         (add-bad-publicity-credit state)
          (swap! state update-in [:runner :register :made-run] #(conj % (first s)))
          (trigger-event state :runner :run s)))))


Removing unused functionality.

Removing unused functionality.

--- src/clj/game/core.clj
+++ src/clj/game/core.clj
@@ -627,11 +627,6 @@

 (defn damage-prevent [state side dtype n]
   (swap! state update-in [:damage :damage-prevent dtype] (fnil #(+ % n) 0)))
-
-(defn save-last-damage-info [state side dtype n card]
-  (swap! state assoc-in [:first-damage dtype :amount] n )
-  (swap! state assoc-in [:first-damage dtype :card] card )
-)

 (defn damage-defer [state side dtype n]
   (swap! state assoc-in [:damage :defer-damage dtype] n )
@@ -1325,7 +1320,7 @@

 (defn start-turn [state side args]
   (turn-message state side true)
-  (swap! state assoc :active-player side :per-turn nil :end-turn false :first-damage nil)
+  (swap! state assoc :active-player side :per-turn nil :end-turn false)
   (swap! state assoc-in [side :register] nil)
   (swap! state assoc-in [side :click] (get-in @state [side :click-per-turn]))
   (trigger-event state side (if (= side :corp) :corp-turn-begins :runner-turn-begins))


heroku go-loop check

heroku go-loop check

--- src/cljs/ts/core.cljs
+++ src/cljs/ts/core.cljs
@@ -43,6 +43,12 @@
             (if (= t js/undefined)
               (.log js/console "t is undefined:" (.-data msg))
               (swap! tweets add-tweet t)))))))
+
+;; checking on heroku?
+(go-loop []
+  (when-let [msg (<! receive)]
+    (.log js/console "we have msg")
+    (recur)))

 (defn make-receiver []
   (.log js/console "make recevier")