Propert docstrings for condition types.

Propert docstrings for condition types.

--- src/active/clojure/condition.cljc
+++ src/active/clojure/condition.cljc
@@ -267,65 +267,104 @@
         ?constructor-params (concat (map (fn [[?field-name _]]
                                            (gensym ?field-name))
                                          ?field-pairs)
-                                    (map gensym (:field-names (eval ?supertype))))]
+                                    (map gensym (:field-names (eval ?supertype))))
+        document (fn [n doc]
+                   (vary-meta n
+                              (fn [m]
+                                (if (contains? m :doc)
+                                  m
+                                  (assoc m :doc doc)))))
+        document-with-arglist (fn [n arglist doc]
+                                (vary-meta n
+                                           (fn [m]
+                                             (let [m (if (contains? m :doc)
+                                                       m
+                                                       (assoc m :doc doc))]
+                                               (if (contains? m :arglists)
+                                                 m
+                                                 (assoc m :arglists `'(~arglist)))))))
+        name-doc (fn [field]
+                    (if-let [doc (:doc (meta field))]
+                      (str " (" doc ")")
+                      ""))
+        reference (fn [name]
+                    (str "[[" (ns-name *ns*) "/" name "]]"))
+        ?docref (str "See " (reference ?condition-type) ".")]
     `(do
        (let [total-field-count# (+ ~(count ?field-pairs) (:total-field-count ~?supertype))]
-         (def ~?condition-type
+         (def ~(vary-meta ?condition-type
+                          (fn [m]
+                            (assoc m :doc
+                                   (str (or (get m :doc)
+                                            "Condition type.")
+                                        "\n"
+                                        (apply str
+                                               (map (fn [[?field ?accessor]]
+                                                      (str "\n`" ?field "`" (name-doc ?field) ": access via " (reference ?accessor)))
+                                                    ?field-pairs))))))
            (->ConditionType '~?condition-type ~?supertype
                             '[~@(map first ?field-pairs)] total-field-count#))
-         (defn ~?constructor
-           [~@?constructor-params]
-           (make-condition [(->ConditionComponent ~?condition-type (vector ~@?constructor-params))]))
-         (def ~?predicate (condition-predicate ~?condition-type))
+         (def ~(document-with-arglist ?constructor
+                                      (vec (map first ?field-pairs))
+                                      (str "Construct a " (reference ?condition-type) " condition."))
+           (fn [~@?constructor-params]
+             (make-condition [(->ConditionComponent ~?condition-type (vector ~@?constructor-params))])))
+         (def ~(document-with-arglist ?predicate '[thing]
+                                      (str "Is object a " (reference ?condition-type) " condition?"))
+           (condition-predicate ~?condition-type))
          ~@(map (fn [[?field-name ?accessor]]
-                  `(def ~?accessor (condition-accessor ~?condition-type '~?field-name)))
+                  `(def ~(document-with-arglist ?accessor
+                                                (vector ?condition-type)
+                                                (str "Access the `" ?field-name "`" (name-doc ?field-name)
+                                                     " field from a " (reference ?condition-type) " condition."))
+                     (condition-accessor ~?condition-type '~?field-name)))
                 ?field-pairs))))))

 ; These standard condition types correspond directly to R6RS Scheme

-(define-condition-type &message &condition
+(define-condition-type ^{:doc "Human-reaable message."} &message &condition
   make-message-condition message-condition?
-  [message condition-message])
-
-(define-condition-type &warning &condition
+  [^{:doc "message text"} message condition-message])
+
+(define-condition-type ^{:doc "Non-fatal warning."} &warning &condition
   make-warning warning?
   [])

-(define-condition-type &serious &condition
+(define-condition-type ^{:doc "Serious condition that should not be ignored."} &serious &condition
   make-serious-condition serious-condition?
   [])

-(define-condition-type &error &serious
+(define-condition-type ^{:doc "Error from environment, not preventable by the program."} &error &serious
   make-error error?
   [])

-(define-condition-type &violation &serious
+(define-condition-type ^{:doc "Bug in the program."} &violation &serious
   make-violation violation?
   [])

-(define-condition-type &assertion &violation
+(define-condition-type ^{:doc "Violation of a specific assertion."}  &assertion &violation
   make-assertion-violation assertion-violation?
   [])

-(define-condition-type &irritants &condition
+(define-condition-type ^{:doc "Condition with objects providing more information about an exceptional situation."} &irritants &condition
   make-irritants-condition irritants-condition?
-  [irritants condition-irritants])
-
-(define-condition-type &who &condition
+  [^{:doc "objects providing more information"} irritants condition-irritants])
+
+(define-condition-type ^{:doc "Information about in what entity an exceptional situation occurred."} &who &condition
   make-who-condition who-condition?
-  [who condition-who])
-
-(define-condition-type &location &condition
+  [^{:doc "name of the entity"} who condition-who])
+
+(define-condition-type ^{:doc "Location information about an exceptional situation"} &location &condition
   make-location-condition location-condition?
   ;; any of these can be nil
-  [namespace location-condition-namespace
-   file location-condition-file
-   line location-condition-line])
+  [^{:doc "namespace of the location"} namespace location-condition-namespace
+   ^{:doc "file name of the location"} file location-condition-file
+   ^{:doc "line number of the loocation"} line location-condition-line])

 (define-condition-type
   ^{:doc "Throwable value that's not a condition."} &throwable &serious
   make-throwable throwable?
-  [value throwable-value])
+  [^{:doc "Throwable object"} value throwable-value])

 #?(:clj
 (defmacro throw-condition


Just look for starting position to find period

--- src/advent_2017/day_16.cljc
+++ src/advent_2017/day_16.cljc
@@ -43,9 +43,9 @@

 (defn part-2 []
   (let [final-positions (iterate #(reduce apply-dance-move % data) starting-position)
-        period          (loop [final-positions final-positions seen #{} counter 0]
-                          (if (seen (first final-positions))
+        period          (loop [final-positions (rest final-positions) counter 1]
+                          (if (= starting-position (first final-positions))
                             (* counter (count data))
-                            (recur (rest final-positions) (conj seen (first final-positions)) (inc counter))))
+                            (recur (rest final-positions) (inc counter))))
         [start offset] ((juxt quot rem) (rem 1000000000 period) (count data))]
     (apply str (reduce apply-dance-move (nth final-positions start) (take offset data)))))


Allow only pipes at the top-level. Dont allow pipes inside pipes. Separate values from refs.

--- src/aurora/interpreter.cljs
+++ src/aurora/interpreter.cljs
@@ -1,17 +1,4 @@
 (ns aurora.interpreter)
-
-(defn run-node [program node inputs actions]
-  (prn node inputs)
-  (case (:type node)
-    :match (run-match program node inputs actions)
-    :ref (run-ref program node inputs actions)
-    :pipe (run-pipe program node inputs actions)))
-
-(defn run-ref [program node inputs actions]
-  (case (:kind node)
-    :value (:value node)
-    :cljs (apply (:fn node) inputs)
-    :aurora (run-node program (get program (:id node)) inputs actions)))

 (defn run-pipe [program node inputs actions]
   (let [vars #js {}]
@@ -22,6 +9,21 @@
       (aset vars id (run-node program node (map #(aget vars %) inputs) actions))
       (prn vars))
     (aget vars (-> node :nodes last :id))))
+
+(defn run-node [program node inputs actions]
+  (prn node inputs)
+  (case (:type node)
+    :value (run-value program node inputs actions)
+    :match (run-match program node inputs actions)
+    :ref (run-ref program node inputs actions)))
+
+(defn run-value [program node inputs actions]
+  (:value node))
+
+(defn run-ref [program node inputs actions]
+  (case (:kind node)
+    :cljs (apply (:fn node) inputs)
+    :aurora (run-node program (get program (:id node)) inputs actions)))

 (defrecord MatchFailure [])

@@ -68,49 +70,61 @@
   {"root" {:type :pipe
            :inputs ["a" "b" "c"]
            :nodes [{:id "b-squared" :inputs ["b" "b"] :node {:type :ref :kind :cljs :name *}}
-                   {:id "four" :inputs [] :node {:type :ref :kind :value :value 4}}
+                   {:id "four" :inputs [] :node {:type :value :value 4}}
                    {:id "four-a-c" :inputs ["four" "a" "c"] :node {:type :ref :kind :cljs :fn *}}
                    {:id "result" :inputs ["b-squared" "four-a-c"] :node {:type :ref :kind :cljs :fn -}}]}})

 (def example-b
-  {"root" {:type :match
-           :branches [{:pattern {"a" (bind "a" {:type :ref :kind :cljs :fn number?}) "b" (bind "b" {:type :ref :kind :cljs :fn number?})}
-                       :inputs ["a" "b"]
-                       :node {:type :ref :kind :cljs :fn -}}
-                      {:pattern [(bind "x" {:type :ref :kind :value :value true}) "foo"]
-                       :inputs ["x" "y"]
-                       :node {:type :ref :kind :cljs :fn identity}}]}})
+  {"root" {:type :pipe
+           :inputs ["x"]
+           :nodes [{:id "result"
+                    :inputs ["x"]
+                    :node {:type :match
+                           :branches [{:pattern {"a" (bind "a" {:type :ref :kind :cljs :fn number?}) "b" (bind "b" {:type :ref :kind :cljs :fn number?})}
+                                       :inputs ["a" "b"]
+                                       :node {:type :ref :kind :cljs :fn -}}
+                                      {:pattern [(bind "x" {:type :value :value true}) "foo"]
+                                       :inputs ["x" "y"]
+                                       :node {:type :ref :kind :cljs :fn identity}}]}}]}})

 (def example-c
   {"root" {:type :ref :kind :aurora :id "even?"}
-   "even?" {:type :match
-            :branches [{:pattern 0
-                        :inputs []
-                        :node {:type :ref :kind :value :value true}}
-                       {:pattern (bind "x" {:type :ref :kind :value :value true})
-                        :inputs ["x"]
-                        :node {:type :ref :kind :aurora :id "even?not-0"}}]}
+   "even?" {:type :pipe
+            :inputs ["x"]
+            :nodes [{:id "result"
+                     :inputs ["x"]
+                     :node {:type :match
+                            :branches [{:pattern 0
+                                        :inputs []
+                                        :node {:type :value :value true}}
+                                       {:pattern (bind "x" {:type :value :value true})
+                                        :inputs ["x"]
+                                        :node {:type :ref :kind :aurora :id "even?not-0"}}]}}]}
    "even?not-0" {:type :pipe
                  :inputs ["x"]
-                 :nodes [{:id "one" :inputs [] :node {:type :ref :kind :value :value 1}}
+                 :nodes [{:id "one" :inputs [] :node {:type :value :value 1}}
                          {:id "x-1" :inputs ["x" "one"] :node {:type :ref :kind :cljs :fn -}}
                          {:id "result" :inputs ["x-1"] :node {:type :ref :kind :aurora :id "odd?"}}]}
-   "odd?" {:type :match
-           :branches [{:pattern 0
-                       :inputs []
-                       :node {:type :ref :kind :value :value false}}
-                      {:pattern (bind "x" {:type :ref :kind :value :value true})
-                       :inputs ["x"]
-                       :node {:type :ref :kind :aurora :id "odd?not-0"}}]}
+   "odd?" {:type :pipe
+           :inputs ["x"]
+           :nodes [{:id "result"
+                    :inputs ["x"]
+                    :node {:type :match
+                           :branches [{:pattern 0
+                                       :inputs []
+                                       :node {:type :value :value false}}
+                                      {:pattern (bind "x" {:type :value :value true})
+                                       :inputs ["x"]
+                                       :node {:type :ref :kind :aurora :id "odd?not-0"}}]}}]}
    "odd?not-0" {:type :pipe
                 :inputs ["x"]
-                :nodes [{:id "one" :inputs [] :node {:type :ref :kind :value :value 1}}
+                :nodes [{:id "one" :inputs [] :node {:type :value :value 1}}
                         {:id "x-1" :inputs ["x" "one"] :node {:type :ref :kind :cljs :fn -}}
                         {:id "result" :inputs ["x-1"] :node {:type :ref :kind :aurora :id "even?"}}]}})

 (defn run-example [example inputs]
   (try
-    (run-node example (get example "root") inputs nil)
+    (run-pipe example (get example "root") inputs nil)
     (catch MatchFailure e e)))

 (run-example example-a [1 4 2])


Add /categories page.

Add /categories page.

--- src/beebster_clj/routes.clj
+++ src/beebster_clj/routes.clj
@@ -9,7 +9,8 @@
 (defroutes app-routes
   (route/resources "/")
   (GET "/" [] (index-page))
-  (GET "/about" [] (about-page)))
+  (GET "/about" [] (about-page))
+  (GET "/categories" [category] (category-page category)))

 (def app


increase size of bot token

increase size of bot token

--- src/braid/server/db/bot.clj
+++ src/braid/server/db/bot.clj
@@ -10,7 +10,7 @@
         :bot/name name
         :bot/avatar avatar
         :bot/webhook-url webhook-url
-        :bot/token (random-nonce 20)
+        :bot/token (random-nonce 30)
         :bot/group [:group/id group-id]}
        (create-entity! conn)
        db->bot))


Parsing job info

Parsing job info

--- src/branch_handler/core.clj
+++ src/branch_handler/core.clj
@@ -102,14 +102,26 @@
     (-> (jenkins-api/read-list-of-all-jobs jenkins-url job-list-command)
         (filter-branch-jobs branch-job-prefix)))

+(defn parse-job-name
+    [branch-job-prefix job-name]
+    {:name job-name
+    })
+
+(defn parse-job-names
+    [branch-job-prefix job-names]
+    (for [job-name job-names]
+        (parse-job-name branch-job-prefix job-name)))
+
 (defn create-or-delete-jenkins-job
     [jenkins-url job-list-command branch-job-prefix action]
     (log/info "Create-or-delete-jenkins-job")
     (let [reponame       (:name action)
           group          (:group action)
-          jobs-for-branches (read-jobs-for-branches jenkins-url job-list-command branch-job-prefix)
+          jobs-for-branches   (read-jobs-for-branches jenkins-url job-list-command branch-job-prefix)
+          jobs-info      (parse-job-names branch-job-prefix jobs-for-branches)
           branch-list-in-repo (read-branch-list-from-repo workdir group reponame)]
-          branch-list-in-repo))
+          jobs-info))
+

 (defn create-action-queue
     []


Refactor, simplify

Refactor, simplify

--- src/buildviz/testsuites.clj
+++ src/buildviz/testsuites.clj
@@ -5,16 +5,19 @@
              [math :as math]
              [testsuite-transform :as transform]]))

-(defn- average-runtime-for-testcase-runs [testcases]
-  (when-let [runtimes (seq (remove nil? (map :runtime testcases)))]
-    (math/avg runtimes)))
+(defn- avg-with-nil [values]
+  (when-let [non-nil-values (seq (remove nil? values))]
+    (math/avg non-nil-values)))
+
+(defn average-runtime [testclasses]
+  (if-let [average-runtime (avg-with-nil (map :runtime testclasses))]
+    {:averageRuntime average-runtime}
+    {}))

 (defn aggregate-testcase-runs [testcases]
-  (let [failed-count (count (remove junit-xml/is-ok? testcases))
-        aggregated {:failedCount failed-count}]
-    (if-let [average-runtime (average-runtime-for-testcase-runs testcases)]
-      (assoc aggregated :averageRuntime average-runtime)
-      aggregated)))
+  (let [failed-count (count (remove junit-xml/is-ok? testcases))]
+    (assoc (average-runtime testcases)
+           :failedCount failed-count)))

 (defn- aggregate-runs [unrolled-testcases]
   (->> unrolled-testcases
@@ -40,18 +43,13 @@
                                                                     :failed-count failed-count}])))))

-(defn average-testclass-runs [testclasses]
-  (if-let [average-runtime (average-runtime-for-testcase-runs testclasses)]
-    {:averageRuntime average-runtime}
-    {}))
-
 (defn- average-runs [unrolled-testcases]
   (->> unrolled-testcases
        (group-by first)
        (map (fn [[testcase-id group]]
               [testcase-id (->> group
                                 (map last)
-                                average-testclass-runs)]))
+                                average-runtime)]))
        (into {})))

 (defn- accumulated-runtime [testcases]


Drop the use of non-blank?

Drop the use of non-blank?

--- src/catalog/layout/text.clj
+++ src/catalog/layout/text.clj
@@ -1,15 +1,11 @@
 (ns catalog.layout.text
   "Render catalog items as plain textx"
-  (:require [catalog.layout.common :as layout :refer [empty-or-blank? non-blank? wrap]]
-            [clj-time
-             [coerce :as time.coerce]
-             [core :as time.core]
-             [format :as time.format]]
+  (:require [catalog.layout.common :as layout :refer [empty-or-blank? wrap]]
+            [clj-time.core :as time.core]
             [clojure
              [set :as set]
              [string :as string]
              [walk :as walk]]
-            [clojure.data.xml :as xml]
             [endophile.core :as endophile]))

 (defmulti to-text (fn [{:keys [tag attrs content]}] tag))
@@ -221,8 +217,8 @@
         date (time.core/now)
         language "de"
         items (cond-> items
-                (layout/non-blank? editorial) (assoc :editorial editorial)
-                (layout/non-blank? recommendation) (assoc :recommendation recommendation))
+                (not (string/blank? editorial)) (assoc :editorial editorial)
+                (not (string/blank? recommendation)) (assoc :recommendation recommendation))
         path-to-numbers (layout/path-to-number items)]
     (str
      title


Naively handle file uploads

Naively handle file uploads

--- domain/src/domain/core.clj
+++ domain/src/domain/core.clj
@@ -3,8 +3,11 @@
             [compojure.route :as route]
             [ring.middleware.defaults :refer [wrap-defaults api-defaults]]
             [ring.middleware.json :refer [wrap-json-body wrap-json-response]]
-            [ring.util.response :refer [response]])
+            [ring.util.response :refer [response]]
+            [clojure.java.io :as io])
   (:gen-class))
+
+(def ads->features (atom {}))

 (def features
   "A map that holds features and their possible values"
@@ -88,6 +91,9 @@

 (defroutes app-routes
   (GET "/" [] "OMG HI!")
+  (POST "/auction/new"
+    {{{tempfile :tempfile filename :filename} :img} :params :as params}
+      (io/copy tempfile (io/file filename)))
   (route/not-found "Not Found"))

 (def app


Simplify data model to reflect winner more clearly

--- domain/src/domain/core.clj
+++ domain/src/domain/core.clj
@@ -21,23 +21,27 @@

 (def ads->features-example
   "An example of a map that holds each ad and its preferred features"
-  {:ad1 {:ethnicity :asian
-         :weather   :rainy
-         :location  :prime
-         :age       :mid
-         :gender    :male
-         :url       "http://example.com/1.jpg"}
-   :ad2 {:age       :mid
-         :gender    :female
-         :location  :average
-         :url       "http://example.com/2.jpg"}
-   :ad3 {:weather   :sunny
-         :gender    :male
-         :url       "http://example.com/3.jpg"}
-   :ad4 {:gender    :male
-         :age       :old
-         :location  :prime
-         :url       "http://example.com/4.jpg"}})
+  [{:id :one
+    :ethnicity :asian
+    :weather   :rainy
+    :location  :prime
+    :age       :mid
+    :gender    :male
+    :url       "http://example.com/1.jpg"}
+   {:id        :two
+    :age       :mid
+    :gender    :female
+    :location  :average
+    :url       "http://example.com/2.jpg"}
+   {:id        :three
+    :weather   :sunny
+    :gender    :male
+    :url       "http://example.com/3.jpg"}
+   {:id        :four
+    :gender    :male
+    :age       :old
+    :location  :prime
+    :url       "http://example.com/4.jpg"}])

 (def result-features-example
   "An example of a resulting map obtained from Tobiaz' UI and CV"
@@ -65,17 +69,15 @@
 (defn get-scored-ads [current-ad->features resulting-features]
   "Given a map of resulting features, computes the score for each ad feature"
   (let [result-set (set resulting-features)] ; convert to set for easy operation
-    (reduce (fn [scored-ad-features [ad ad-features]]
-              (let [scored-features (score-feature-set (set ad-features) result-set)]
-                (assoc scored-ad-features ad scored-features)))
-            {}
-            current-ad->features)))
+    (map #(score-feature-set (set %) result-set)
+         current-ad->features)))

 (defn get-winning-ad [current-features resulting-features]
   (let [results (get-scored-ads current-features resulting-features)]
     (->> results
-         (sort-by (comp :score second))
+         (sort-by :score)
          (last)
+         (assoc {} :winner)
          (merge {:features resulting-features}))))

 (defn run-auction [image env-features]


Remove enter keybind.

Remove enter keybind.

--- src/app/cljs/one/sample/view.cljs
+++ src/app/cljs/one/sample/view.cljs
@@ -93,12 +93,7 @@
                   #(dispatch/fire [:editing-field field-id]))
     (event/listen field
                   "keyup"
-                  #(dispatch/fire [:field-changed field-id] (value field)))
-    (event/listen keyboard
-                  "key"
-                  (fn [e] (when (= (.-keyCode e) key-codes/ENTER)
-                           (do (.blur (by-id "text-input") ())
-                               (dispatch/fire :form-submit)))))))
+                  #(dispatch/fire [:field-changed field-id] (value field)))))

 (defmulti render
   "Accepts a map which represents the current state of the application
@@ -133,6 +128,8 @@
   (add-input-event-listeners "text-input")

   (one.logging/start-display (one.logging/console-output))
+
+  (set-value! (by-id "text-input") "The quick brown fox jumped over the lazy dog.")

   (let [text-box (by-id "text-dvorak-input")]
       (event/listen (goog.events.KeyHandler. text-box)


Add destroyed logic

Add destroyed logic

Add logic that supports updating a players position when moving into
a destroyed item's space.

--- src/clj/battlebots/game.clj
+++ src/clj/battlebots/game.clj
@@ -36,8 +36,8 @@

 (defn- total-rounds
   "Calculates the total number of rounds that have elapsed"
-  [rounds segments]
-  (+ (* segments segment-length) rounds))
+  [num-rounds num-segments]
+  (+ (* num-segments segment-length) num-rounds))

 (defn- get-player
   "Grabs a player by id from the private player collection"
@@ -47,7 +47,7 @@
 (defn- sanitize-player
   "Sanitizes the full player object returning the partial used on the game map"
   [player]
-  (select-keys player [:_id :login]))
+  (select-keys player [:_id :login :energy]))

 (defn- save-segment
   [{:keys [_id players rounds segment-count] :as game-state}]
@@ -167,10 +167,12 @@
   Bots that run into item spaces that cannot be occupied will receive damage. If the item that is
   collided with has energy, it to will receive damage. If the item collided with has an energy level
   of 0 or less after the collision, that item will disappear and the bot will occupy its space."
-  [player-id collision-item collision-coords]
+  [player-id player-coords collision-item collision-coords]
   (fn [{:keys [players dirty-arena] :as game-state}]
     (if (is-player? collision-item)
-      (let [])
+      (let []
+        ;; TODO https://github.com/willowtreeapps/battlebots/issues/57
+        game-state)
       (let [player (get-player player-id players)
             updated-player (apply-damage player collision-damage-amount false)
             updated-players (update-player-with player-id players updated-player)
@@ -178,9 +180,11 @@
             collision-item-now-open? (= (:type updated-collision-item) "open")]
         (if collision-item-now-open?
           (merge game-state {:players updated-players
-                             :dirty-arena (au/update-cell dirty-arena
-                                                          collision-coords
-                                                          updated-player)})
+                             :dirty-arena (au/update-cell (au/update-cell dirty-arena
+                                                                          collision-coords
+                                                                          updated-player)
+                                                          player-coords
+                                                          (:open arena-key))})
           (merge game-state {:players updated-players
                              :dirty-arena (au/update-cell dirty-arena
                                                           collision-coords
@@ -206,6 +210,7 @@
       (reduce #(%2 %1) game-state [(clear-space player-coords)
                                    (player-occupy-space desired-coords player-id)])
       (reduce #(%2 %1) game-state [(apply-collision-damage player-id
+                                                           player-coords
                                                            desired-space-contents
                                                            desired-coords)]))))


getting much warmer - needed to associate the correct state w/ prev-info. when we round trip the only thing that seems to be off is :gline.

--- src/clj/cljs/source_map.clj
+++ src/clj/cljs/source_map.clj
@@ -89,8 +89,9 @@
         [(conj segv idx) state])
       [segv state])))

-(defn prev-info->segv [info state]
-  (let [segv [(:gcol info) (:source-idx state) (:line state) (:col state)]]
+(defn prev-info->segv [info]
+  (let [state (meta info)
+        segv [(:gcol info) (:source-idx state) (:line state) (:col state)]]
     (if-let [name (:name info)]
       (conj segv (get (:names->idx state) name))
       segv)))
@@ -102,9 +103,9 @@
             [segv state] (info->segv info state)
             prev-info (:prev-info state)
             relsegv (if prev-info
-                      (let [prev-segv (prev-info->segv prev-info state)]
+                      (let [prev-segv (prev-info->segv prev-info)]
                         (if (not= (:gline info) (:gline prev-info))
-                          (into [] (cons (first segv) (map - (rest segv) (rest prev-segv))))
+                          (into [(first segv)] (map - (rest segv) (rest prev-segv)))
                           (into [] (map - segv prev-segv))))
                       segv)]
         (recur (next infos)
@@ -115,7 +116,11 @@
             (-> state
                 (assoc :lines lines)
                 (assoc :prev-info
-                  (if (:name info) info (assoc info :name (:name prev-info))))))))
+                  (with-meta
+                    (if (:name info)
+                      info
+                      (assoc info :name (:name prev-info)))
+                    state))))))
       state)))

 (defn encode [m opts]


update home page text

update home page text

--- src/clj/easynxc/handler.clj
+++ src/clj/easynxc/handler.clj
@@ -15,16 +15,17 @@
    [:link {:rel "stylesheet" :href "https://cdnjs.cloudflare.com/ajax/libs/normalize/4.2.0/normalize.min.css"}]
    (include-css (if (env :dev) "/css/site.css" "/css/site.min.css"))])

+
 (def home-page
   (html5
    (head)
-   [:body {:class "body-container"}
+   [:body
     [:div#app
-     [:div {:class "main"}
-      [:p "hello and welcome to easynxc. to use this site find a video from youtube or soundcloud or something and add \"easynxc.com/\" to the beginning of the URL"]
-      [:p "so if for example you wanted to try it with " [:a {:href "https://www.youtube.com/watch?v=5GL9JoH4Sws"} "https://www.youtube.com/watch?v=5GL9JoH4Sws"] ", you'd go to " [:a {:href "/https://www.youtube.com/watch?v=5GL9JoH4Sws"} "easynxc.com/https://www.youtube.com/watch?v=5GL9JoH4Sws"]]
-      [:p "move the mouse to change speed, and click to lock/unlock your speed. when locked, your speed gets added to the URL so you can share with friends. i like the example at about 1.4x " [:a {:href "/https://www.youtube.com/watch?nxc=1.40&v=5GL9JoH4Sws"} "easynxc.com/https://www.youtube.com/watch?nxc=1.40&v=5GL9JoH4Sws"]]
-      [:p [:a {:href "https://github.com/parkeristyping/easynxc-clj"} "github"]]]]]))
+     [:p "this is a site for changing the speed of songs"]
+     [:p "find a song on youtube or soundcloud or something and add \"easynxc.com/\" to the beginning of the URL"]
+     [:p "example: " [:a {:href "/https://www.youtube.com/watch?v=5GL9JoH4Sws"} "easynxc.com/https://www.youtube.com/watch?v=5GL9JoH4Sws"]]
+     [:p [:a {:href "https://github.com/parkeristyping/easynxc-clj"} "github"]]]
+    (include-js "/js/google-analytics.js")]))

 (def loading-page
   (html5


source date is just a year, so it needs special parsing

--- src/clj/mdr2/production.clj
+++ src/clj/mdr2/production.clj
@@ -110,8 +110,9 @@
    (fn [m k v]
      (assoc m k
       (cond
-        (#{:date :source_date :produced_date :revision_date} k)
-        (time/local-date v)
+        (#{:date :produced_date :revision_date} k) (time/local-date v)
+        ;; source_date is just a year string
+        (#{:source_date} k) (time/local-date (time/year v))
         (#{:volumes :library_record_id} k) (Integer/parseInt v)
         :else v)))
    {} production))


Add a default state to a new production

Add a default state to a new production

--- src/clj/mdr2/production.clj
+++ src/clj/mdr2/production.clj
@@ -95,6 +95,7 @@
    :type "Sound"
    :revision 0
    :depth 1
+   :state "new"
    :format "Daisy 2.02"}) ; "ANSI/NISO Z39.86-2005" for DAISY3

 (defn add-default-meta-data


adjusting function doc string

adjusting function doc string

--- src/clj/ow/factum/facts.clj
+++ src/clj/ow/factum/facts.clj
@@ -10,7 +10,7 @@
                                 v #{:action :attribute :value}))))

 (defn get-facts [& {:keys [where-criteria]}]
-  "Retrieves all facts, potentially narrowed by specified criteria."
+  "Retrieves all raw facts, potentially narrowed by specified criteria."
   (let [query (-> (db/select* es_events)
                   (#(if where-criteria
                       (db/where % where-criteria)


Make 'em private

Make 'em private

--- src/cljs/drawer/canvas.cljs
+++ src/cljs/drawer/canvas.cljs
@@ -20,7 +20,7 @@
   obj)

 ;; Stub
-(defn mirror
+(defn- mirror
   "Mirrors an object."
   [obj objs]
   obj)
@@ -47,12 +47,12 @@
   [point]
   (pop point))

-(defn project-point
+(defn- project-point
   "Projects a 4D point onto the 2d plain."
   [point]
   (-> point P4->P3 P3->P2))

-(defn project-obj
+(defn- project-obj
   "Projects an object (4D) onto
   the screen plain (2D).
   Doesn't actually draw the object,


Extract surface/canvas out of draw functions

--- src/cljs/kindness/game.cljs
+++ src/cljs/kindness/game.cljs
@@ -284,59 +284,46 @@
     (set! (.-type source-mp3) "audio/mpeg; codecs=\"mp3\"")
 ))

-(defmulti draw (fn [e] (:shape (utils/find-component :renderable e))))
-(defmethod draw :circle [e]
-  (let [renderable (utils/find-component :renderable e)
-        color (:color renderable)
-        positionable (utils/find-component :positionable e)
-        [x y] (:position positionable)
-        boundable (utils/find-component :boundable e)
-        [w _] (:bounds boundable)
-        canvas (:canvas @game-state)
+(defmulti draw (fn [_ _ e] (:shape (utils/find-component :renderable e))))
+(defmethod draw :circle
+  [surface canvas e]
+  (let [color (:color (utils/find-component :renderable e))
+        [x y] (:position (utils/find-component :positionable e))
+        [w _] (:bounds (utils/find-component :boundable e))
         width (.-width canvas)
         height (.-height canvas)
-        radius (int (* height (/ (/ w 2) 100)))
-        surface (:surface @game-state)]
+        radius (int (* height (/ (/ w 2) 100)))]
     (set! (.-fillStyle surface) color)
     (.beginPath surface)
     (.arc surface x y radius 0 (* 2 Math/PI) true)
     (.closePath surface)
     (.fill surface)))
-(defmethod draw :rectangle [e]
-  (let [renderable (utils/find-component :renderable e)
-        color (:color renderable)
-        positionable (utils/find-component :positionable e)
-        [x y] (:position positionable)
-        boundable (utils/find-component :boundable e)
-        [width height] (:bounds boundable)
-        surface (:surface @game-state)]
+(defmethod draw :rectangle
+  [surface canvas e]
+  (let [color (:color (utils/find-component :renderable e))
+        [x y] (:position (utils/find-component :positionable e))
+        [width height] (:bounds (utils/find-component :boundable e))]
     ;;(println "name:" (:name e) "x,y:" [x y] "width, height:" [width height] "color:" color)
     (set! (.-fillStyle surface) color)
     (.fillRect surface x y width height)))
-(defmethod draw :background [e]
-  (let [renderable (utils/find-component :renderable e)
-        color (:color renderable)
-        canvas (:canvas @game-state)
+(defmethod draw :background
+  [surface canvas e]
+  (let [color (:color (utils/find-component :renderable e))
         width (.-width canvas)
-        height (.-height canvas)
-        surface (:surface @game-state)]
+        height (.-height canvas)]
     (set! (.-fillStyle surface) color)
     (.fillRect surface 0 0 width height)
     (.strokeRect surface 0 0 width height)))
-(defmethod draw :image [e]
-  (let [renderable (utils/find-component :renderable e)
-        positionable (utils/find-component :positionable e)
-        image (:image renderable)
+(defmethod draw :image
+  [surface canvas e]
+  (let [image (:image (utils/find-component :renderable e))
         img (utils/find-image image)
-        [x y] (:position positionable)
-        surface (:surface @game-state)]
+        [x y] (:position (utils/find-component :positionable e))]
     (.drawImage surface img x y)))
-(defmethod draw :text [e]
-  (let [renderable (utils/find-component :renderable e)
-        [x y] (:position (utils/find-component :positionable e))
-        surface (:surface @game-state)
-        canvas (:canvas @game-state)
-        text (:text renderable)]
+(defmethod draw :text
+  [surface canvas e]
+  (let [[x y] (:position (utils/find-component :positionable e))
+        text (:text (utils/find-component :renderable e))]
     (set! (.-textAlign surface) (:align text))
     (set! (.-textBaseline surface) (:baseline text))
     (set! (.-font surface) (:font text))
@@ -356,8 +343,10 @@

 (defn render-entities
   []
-  (doseq [entity (renderable-entities)]
-    (draw entity)))
+  (let [surface (:surface @game-state)
+        canvas (:canvas @game-state)]
+   (doseq [entity (renderable-entities)]
+     (draw surface canvas entity))))

 (defn tap-print
   [text val]


fixed bug with next call to threads-since

--- src/clueweb_disqus/core.clj
+++ src/clueweb_disqus/core.clj
@@ -158,6 +158,8 @@
         c/to-long
         (quot 1000))))

+(declare threads-since)
+
 (defn discover-iteration
   [start-epoch first-page-content]
   (let [next-pg-check (-> first-page-content
@@ -185,7 +187,13 @@
                             process-disqus-date
                             (str "\n"))
                         :append
-                        true))
+                        true)
+                  (threads-since (-> first-page-content
+                                     (get "response")
+                                     last
+                                     (get "createdAt")
+                                     process-disqus-date
+                                     str)))

               (not
                (stop-iteration? start-epoch (get next-pg-content "response")))


Version 0.1.4

Version 0.1.4


[Fix] default of *assert* is true

[Fix] default of *assert* is true


:art: Fix layout

:art: Fix layout


release 2.0.4

release 2.0.4


Extract session managment to bespoke meta wrapper

Add meta wrapper for braid universal middleware (which includes
request logging and session handling).

NB: By wrapping all handlers in the universal middleware, session
encoding/decoding now happens earlier in the middleware, as does
general cookie processing.

NB: Session handling is now present universally.  Previously it was
present in almost every handler's enclosing middleware _except_ the
`public-handler`.  There is no problem with attempting to decode a
session from an anonymous user making a request to this handler and it
has the additional benefit of allow greater insight into site usage.

--- src/braid/core/server/handler.clj
+++ src/braid/core/server/handler.clj
@@ -12,6 +12,7 @@
    [ring.middleware.defaults :refer [wrap-defaults api-defaults secure-site-defaults site-defaults]]
    [ring.middleware.format :refer [wrap-restful-format]]
    [ring.middleware.edn :refer [wrap-edn-params]]
+   [ring.middleware.session :refer [wrap-session]]
    [taoensso.timbre :as timbre]))

 (def session-max-age (* 60 60 24 365))
@@ -31,19 +32,6 @@
     (let [cookie-store (ns-resolve 'ring.middleware.session.cookie 'cookie-store)]
       (def session-store (cookie-store)))))

-(defn assoc-cookie-conf [defaults]
-  (-> defaults
-      (assoc-in [:session :cookie-name] "braid")
-      (assoc-in [:session :cookie-attrs :secure] (cond
-                                                   (env :http-only)
-                                                   false
-                                                   (= (env :environment) "prod")
-                                                   true
-                                                   :else
-                                                   false))
-      (assoc-in [:session :cookie-attrs :max-age] session-max-age)
-      (assoc-in [:session :store] session-store)))
-
 (defn assoc-csrf-conf [defaults]
   (-> defaults
       (assoc-in [:security :anti-forgery] true)))
@@ -58,6 +46,15 @@
                :content-types          true
                :default-charset        "utf-8"}})

+(def session-config
+  {:cookie-name "braid",
+   :cookie-attrs {:secure (cond
+                            (env :http-only) false
+                            (= (env :environment) "prod") true
+                            :else false)
+                  :max-age session-max-age},
+   :store session-store})
+
 (defn- wrap-log-requests
   [handler]
   (fn [{uri :uri method :request-method :as request}]
@@ -66,62 +63,57 @@
       (timbre/debugf "[%s +%4dms] %8.8s %s" status (- (System/currentTimeMillis) t0) method uri)
       response)))

-(def mobile-client-app
-  (-> (routes
-       resource-routes
-       mobile-client-routes)
-      (wrap-defaults (-> static-site-defaults
-                         assoc-cookie-conf))
+;; Here we define universal (as opposed to route-specific) middleware.
+(defn- wrap-universal-middleware
+  "Wrap the handler with middleware that is universally applicable across the site."
+  [handler options]
+  (-> handler
+      (wrap-session (options :session))
       wrap-log-requests))

+(def mobile-client-app
+  (-> (routes resource-routes mobile-client-routes)
+      (wrap-defaults static-site-defaults)
+      (wrap-universal-middleware {:session session-config})))
+
 (def desktop-client-app
-  (-> (routes
-       resource-routes
-       desktop-client-routes)
-      (wrap-defaults (-> static-site-defaults
-                         assoc-cookie-conf))
-      wrap-log-requests))
+  (-> (routes resource-routes desktop-client-routes)
+      (wrap-defaults static-site-defaults)
+      (wrap-universal-middleware {:session session-config})))

 (def api-server-app
   (-> (routes
-        modules/raw-handlers
+       modules/raw-handlers

-        (-> api-public-routes
-            (wrap-defaults (-> site-defaults
-                               (assoc-in [:security :anti-forgery] false)
-                               assoc-cookie-conf)))
+       (-> api-public-routes
+           (wrap-defaults (-> site-defaults
+                              (assoc-in [:security :anti-forgery] false))))

-        (-> modules/public-handler
-            (wrap-defaults (-> site-defaults
-                               (assoc-in [:security :anti-forgery] false)))
-            (wrap-restful-format :formats [:edn :transit-json]))
+       (-> modules/public-handler
+           (wrap-defaults (-> site-defaults
+                              (assoc-in [:security :anti-forgery] false)))
+           (wrap-restful-format :formats [:edn :transit-json]))

-        (-> sync-routes
-            (wrap-defaults (-> api-defaults
-                               assoc-cookie-conf
-                               assoc-csrf-conf)))
+       (-> sync-routes
+           (wrap-defaults (-> api-defaults assoc-csrf-conf)))

        (-> api-private-routes
-            (wrap-defaults (-> api-defaults
-                               assoc-cookie-conf
-                               assoc-csrf-conf)))
+           (wrap-defaults (-> api-defaults assoc-csrf-conf)))

        ;; this needs to be last, because the middleware will return
        ;; 401 if not authorized & hence not fall-through to other
        ;; routes
        (-> modules/private-handler
-           (wrap-defaults (-> site-defaults
-                              assoc-cookie-conf
-                              assoc-csrf-conf))
+           (wrap-defaults (-> site-defaults assoc-csrf-conf))
            (wrap-restful-format :formats [:edn :transit-json])))
       (wrap-cors :access-control-allow-origin (->>
-                                                [(when-let [site (env :site-url)]
-                                                   (re-pattern (java.util.regex.Pattern/quote site)))
-                                                 (when-let [mobile-site (env :mobile-site-url)]
-                                                   (re-pattern (java.util.regex.Pattern/quote mobile-site)))
-                                                 #"http://localhost:\d+"]
-                                                  (remove nil?))
+                                               [(when-let [site (env :site-url)]
+                                                  (re-pattern (java.util.regex.Pattern/quote site)))
+                                                (when-let [mobile-site (env :mobile-site-url)]
+                                                  (re-pattern (java.util.regex.Pattern/quote mobile-site)))
+                                                #"http://localhost:\d+"]
+                                               (remove nil?))
                  :access-control-allow-credentials true
                  :access-control-allow-methods [:get :put :post :delete])
       wrap-edn-params
-      wrap-log-requests))
+      (wrap-universal-middleware {:session session-config})))


Add type hints to fix reflection warnings

--- src/buddy/core/keys/jwk/eddsa.clj
+++ src/buddy/core/keys/jwk/eddsa.clj
@@ -23,15 +23,17 @@
                                            Ed448PrivateKeyParameters Ed448PublicKeyParameters
                                            AsymmetricKeyParameter)
            (org.bouncycastle.jcajce.provider.asymmetric.edec BCEdDSAPrivateKey BCEdDSAPublicKey)
+           (java.lang.reflect Constructor)
            (java.util Arrays)))

 (defn- construct
-  [cls params]
+  [^java.lang.Class cls params]
   ; HACK: These constructors are not public
   (let [cons (vec (.getDeclaredConstructors cls))
+        ^Constructor
         ctor (first (filter #(and
-                               (= 1 (.getParameterCount %))
-                               (= AsymmetricKeyParameter (aget (.getParameterTypes %) 0)))
+                               (= 1 (.getParameterCount ^Constructor %))
+                               (= AsymmetricKeyParameter (aget (.getParameterTypes ^Constructor %) 0)))
                       cons))]
     (when-not (some? ctor)
       (throw (UnsupportedOperationException. "Can not get key constructor")))
@@ -39,15 +41,15 @@
     (.newInstance ctor (to-array [params]))))

 (defn pkcs8-key
-  [encoded len]
+  [^bytes encoded len]
   (let [offset (if (and (= len 57)
                      (not= 73 (count encoded)))
                  17 16)]
-    (Arrays/copyOfRange encoded offset (+ offset len))))
+    (Arrays/copyOfRange encoded offset ^Integer (+ offset len))))

 (defn x509-key
-  [encoded len]
-  (Arrays/copyOfRange encoded 12 (+ 12 len)))
+  [^bytes encoded len]
+  (Arrays/copyOfRange encoded 12 ^Integer (+ 12 len)))

 (defn bc-ed-private-key
   [params]
@@ -72,7 +74,7 @@
     (bc-ed-public-key)))

 (defn- verify-public-key!
-  [priv pub]
+  [^BCEdDSAPrivateKey priv ^BCEdDSAPublicKey pub]
   ;; Check for incorrect public key
   (let [pub-buf (.getEncoded pub)
         pub2-buf (-> (.getPublicKey priv) (.getEncoded))]


Fixing name method on HttpMethod

Fixing name method on HttpMethod

--- src/clj/fortress/ring/request.clj
+++ src/clj/fortress/ring/request.clj
@@ -20,7 +20,7 @@
 (defn method [^HttpMethod method]
   (if-let [method-keyword (method-mapping method)]
     method-keyword
-    (-> method (.getName) (s/lower-case) (keyword))))
+    (-> method (.name) (s/lower-case) (keyword))))

 (defn url [request-uri]
   (let [regex #"([^?]+)[?]?([^?]+)?"


remove prompt when triggering Geist ability as draw is not optional

--- src/clj/game/cards-identities.clj
+++ src/clj/game/cards-identities.clj
@@ -33,10 +33,9 @@

    "Armand \"Geist\" Walker: Tech Lord"
    {:effect (effect (gain :link 1))
-    :events {:runner-trash {:optional {:req (req (and (= side :runner) (= (second targets) :ability-cost)))
-                                       :prompt "Draw a card?"
-                                       :yes-ability {:msg "draw a card"
-                                                     :effect (effect (draw 1))}}}}}
+    :events {:runner-trash {:req (req (and (= side :runner) (= (second targets) :ability-cost)))
+                            :msg "draw a card"
+                            :effect (effect (draw 1))}}}

    "Blue Sun: Powering the Future"
    {:abilities [{:choices {:req #(:rezzed %)}


no UI update for spotify entries

no UI update for spotify entries

--- src/clj/iwaswhere_web/imports.clj
+++ src/clj/iwaswhere_web/imports.clj
@@ -296,7 +296,7 @@
                            new-entries (map entry-mapper recently-played)]
                        (log/info "obtained response from spotify")
                        (doseq [entry new-entries]
-                         (put-fn [:entry/update entry]))))
+                         (put-fn [:entry/import entry]))))
         refresh-handler (fn [res]
                           (let [access-token (:access-token (parser res))
                                 url (str rp-url access-token)]


swapped Watch and Join buttons to avoid accidental Watch when Join disappears

--- src/cljs/netrunner/gamelobby.cljs
+++ src/cljs/netrunner/gamelobby.cljs
@@ -186,12 +186,12 @@
      [:h4 "No game"]
      (for [game games]
        [:div.gameline {:class (when (= gameid (:gameid game)) "active")}
+        (when (and (:allowspectator game) (not gameid))
+          (let [id (:gameid game)]
+            [:button {:on-click #(watch-game id owner)} "Watch"]))
         (when-not (or gameid (= (count (:players game)) 2) (:started game))
           (let [id (:gameid game)]
             [:button {:on-click #(join-game id owner)} "Join"]))
-        (when (and (:allowspectator game) (not gameid))
-          (let [id (:gameid game)]
-            [:button {:on-click #(watch-game id owner)} "Watch"]))
         (let [c (count (:spectators game))]
           [:h4 (str (:title game)
                     (when (pos? c)


Add clojure version of constant type equality check function for byte arrays.

--- src/clojure/buddy/core/codecs.clj
+++ src/clojure/buddy/core/codecs.clj
@@ -155,6 +155,16 @@
   ([^bytes input ^long offset ^long limit]
    (java.util.Arrays/copyOfRange input offset limit)))

+(defn equals?
+  "Test whether two sequences of characters or bytes are equal in a way that
+  protects against timing attacks. Note that this does not prevent an attacker
+  from discovering the *length* of the data being compared."
+  [a b]
+  (let [a (map int a), b (map int b)]
+    (if (and a b (= (count a) (count b)))
+      (zero? (reduce bit-or (map bit-xor a b)))
+      false)))
+
 (defprotocol ByteArray
   "Facility for convert input parameters
   to bytes array with default implementation


Correcting spelling in error message.

Correcting spelling in error message.

--- src/cmr/elastic_utils/connect.clj
+++ src/cmr/elastic_utils/connect.clj
@@ -41,7 +41,7 @@
   (try
     (admin/cluster-health conn :wait_for_status "yellow" :timeout "30s")
     (catch Exception e
-      {:status "Unaccessible"
+      {:status "Inaccessible"
        :problem (format "Unable to get elasticsearch cluster health, caught exception: %s"
                         (.getMessage e))})))


Fixed 404 content type.

Fixed 404 content type.

--- src/cmr/opendap/rest/response.clj
+++ src/cmr/opendap/rest/response.clj
@@ -30,7 +30,7 @@
   [_request]
   (response/content-type
    (response/not-found "Not Found")
-   "plain/text"))
+   "text/plain"))

 (defn cors
   [request response]


Performance and consistency tweaks

Performance and consistency tweaks

* Consistently define syllables (e.g. "00 1" does not have 3 syllables, and "0" is not a syllable)
* Avoid unnecessary reflection, collection wrapping, function wrapping and double negation
* Extract rhyming section in single pass

--- src/com/lemonodor/pronouncing.clj
+++ src/com/lemonodor/pronouncing.clj
@@ -11,14 +11,14 @@
     [(string/lower-case word) phones]))

-(defn is-cmudict-comment-line? [line]
-  (= (get line 0) \;))
+(defn is-cmudict-comment-line? [^String line]
+  (.startsWith line ";"))

 (defn parse-cmudict [rdr]
   (->> rdr
        line-seq
-       (filter #(not (is-cmudict-comment-line? %)))
+       (remove is-cmudict-comment-line?)
        (map parse-cmudict-line)))

@@ -34,7 +34,7 @@
    (fn []
      (reduce
       (fn [db [word phones]]
-        (assoc db word (concat (get db word []) (vector phones))))
+        (assoc db word (conj (get db word []) phones)))
       {}
       (default-pronouncing-db)))))

@@ -42,7 +42,7 @@
 (defn syllable-count
   "Counts the number of syllables in a string of phones."
   [phones]
-  (count (filter #(#{\0 \1 \2} %) phones)))
+  (count (re-seq #"\S+[0-2]\b" phones)))

 (defn phones-for-word
@@ -77,15 +77,17 @@
   (map stresses (phones-for-word word)))

-(defn take-while-inclusive
-  "Like take-while, but also includes the first item for which pred
-  returns false."
+(defn- take-from-last
+  "Return seq of elements in collection from the last item to pass
+  predicate until the end."
   [pred coll]
-  (lazy-seq
-   (when-let [s (seq coll)]
-     (if (pred (first s))
-       (cons (first s) (take-while-inclusive pred (rest s)))
-       (list (first s))))))
+  (loop [match nil
+         xs coll]
+    (if-not (seq xs)
+      match
+      (if (pred (first xs))
+        (recur xs (rest xs))
+        (recur match (rest xs))))))

 (defn rhyming-part
@@ -95,9 +97,7 @@
   syllable nearest the end of the word up to the end of the word."
   [phones-str]
   (->> (string/split phones-str #" ")
-       reverse
-       (take-while-inclusive #(not (re-matches #".+[12]$" %)))
-       reverse
+       (take-from-last #(re-matches #".+[12]$" %))
        (string/join " ")))

@@ -138,4 +138,4 @@
              rhyming-part
              (str "$")
              search))
-       (filter #(not (= % word)))))
+       (remove #{word})))


Update for compatibility with latest clojure-contrib.sql (with-query-results instead of with-results).

--- clj_record/core.clj
+++ clj_record/core.clj
@@ -11,7 +11,7 @@

 (defn find-record [model-name id]
   (sql/with-connection db
-    (sql/with-results rows (format "select * from %s where id = %s" (table-name model-name) id)
+    (sql/with-query-results rows [(format "select * from %s where id = ?" (table-name model-name)) id]
       (merge {} (first rows)))))

 (defn- to-condition [[attribute value]] ; XXX: should be using PreparedStatement for smarter quoting
@@ -27,7 +27,7 @@
 (defn find-records [model-name attributes]
   (let [select-query (format "select * from %s where %s" (table-name model-name) (to-conditions attributes))]
     (sql/with-connection db
-      (sql/with-results rows select-query
+      (sql/with-query-results rows [select-query]
         (doall (map #(merge {} %) rows))))))

 (defn create [model-name attributes]
@@ -37,7 +37,7 @@
        val-vector (map attributes key-vector)
        id (sql/transaction
             (sql/insert-values (table-name model-name) key-vector val-vector)
-            (sql/with-results rows "VALUES IDENTITY_VAL_LOCAL()" (:1 (first rows))))] ; XXX: db-vendor-specific
+            (sql/with-query-results rows ["VALUES IDENTITY_VAL_LOCAL()"] (:1 (first rows))))] ; XXX: db-vendor-specific
       (find-record model-name id))))

 (defn destroy-record [model-name record]


Adding «fuzzy-subsets»

Adding «fuzzy-subsets»

Signed-off-by: Daniel Borchmann <25857343a15bf1edafebc2912e82ecf775c585c1@mailbox.tu-dresden.de>

--- src/conexp/contrib/fuzzy/sets.clj
+++ src/conexp/contrib/fuzzy/sets.clj
@@ -8,7 +8,8 @@

 (ns conexp.contrib.fuzzy.sets
   (:use conexp.main
-        conexp.contrib.fuzzy.logics))
+        conexp.contrib.fuzzy.logics)
+  (:require [clojure.contrib.combinatorics :as comb]))

 (ns-doc "Basic definitions for fuzzy sets")

@@ -157,6 +158,18 @@
   (fn [first & rest]
     (max 0 (apply - first rest))))

+(defn fuzzy-subsets
+  "Returns all fuzzy subsets of the given fuzzy set base-set with given fuzzy values."
+  [values base-set]
+  (let [values     (sort values),
+        base-set   (seq (make-fuzzy-set base-set)),
+        max-values (vec (map second base-set)),
+        crisp-base (map first base-set)]
+    (map #(make-fuzzy-set (zipmap crisp-base %))
+         (apply comb/cartesian-product
+                (for [i (range (count base-set))]
+                  (take-while #(<= % (nth max-values i)) values))))))
+
 (defn fuzzy-subset?
   "Returns true iff fuzzy-set-1 is a subset of fuzzy-set-2."
   [fuzzy-set-1 fuzzy-set-2]


cli.clj/format-doc: a simpler format string supports better docstrings

--- boot/core/src/boot/cli.clj
+++ boot/core/src/boot/cli.clj
@@ -91,7 +91,7 @@
         docstring (cond
                     incr? (format "Increase %s" (decap doc))
                     flag? doc
-                    atom? (format "Set %s to %s." (depunc (decap doc)) optarg)
+                    atom? (format "%s sets %s." optarg (depunc (decap doc)))
                     :else (let [f "Conj %s onto %s"
                                 v ((parse-fn optarg) (str optarg))]
                             (format f (if (string? v) v (pr-str (mapv symbol v))) (decap doc))))]


Check :boot.util/omit-stacktrace? to hide stack trace

--- boot/pod/src/boot/util.clj
+++ boot/pod/src/boot/util.clj
@@ -251,13 +251,17 @@
      (binding [*err* s#] ~@body (str s#))))

 (defn print-ex
-  "Print exception to *err* as appropriate for the current *verbosity* level."
+  "Print exception to *err* as appropriate for the current *verbosity* level.
+
+  If ex-data contains truthy :boot.util/omit-stacktrace? value, only exception
+  message is shown."
   [ex]
-  (case @*verbosity*
-    0 nil
-    1 (pretty/write-exception *err* ex nil)
-    2 (pretty/write-exception *err* ex {:filter nil})
-    (binding [*out* *err*] (.printStackTrace ex))))
+  (cond
+    (= 0 @*verbosity*) nil
+    (::omit-stacktrace? (ex-data ex)) (fail (.getMessage ex))
+    (= 1 @*verbosity*) (pretty/write-exception *err* ex nil)
+    (= 2 @*verbosity*) (pretty/write-exception *err* ex {:filter nil})
+    :else (binding [*out* *err*] (.printStackTrace ex))))

 (defn print-tree
   "Pretty prints tree, with the optional prefixes prepended to each line. The


added truncated inverse gaussian sampling function

--- src/distributions/polya-gamma.clj
+++ src/distributions/polya-gamma.clj
@@ -1,4 +1,29 @@
 (in-ns 'distributions.core)
+
+
+
+(defn rand-tig [mu]
+  (let [t 0.64]
+    (cond
+      (> mu t) (let [z (/ 1 mu)
+                     E (repeatedly #(sample (exponential 1)))
+                     Ep (repeatedly #(sample (exponential 1)))
+                     E-acc (map first (filter (fn [[e ep]] (< (square e) (* 2 (/ ep t) ))) (map vector E Ep)))
+                     X (map (fn [e] (/ t (square (inc (* t e))))) E-acc)
+                     alpha (map (fn [x] (exp (negate (* 0.5 x (square z))))) X)
+                     U (repeatedly #(sample (uniform 0 1)))
+                     accepted (filter (fn [[x a u]] (<= u a)) (map vector X alpha U))]
+                 (first (first accepted)))
+      :else  (let [Y (repeatedly #(square (sample (normal 0 1))))
+                   X (map (fn [y] (+ mu
+                                     (* 0.5 (square mu) y)
+                                     (negate
+                                      (* 0.5
+                                         mu
+                                         (sqrt (+ (* 4 mu y)  (square (* mu y)))))))) Y)
+                   X-new (map (fn [x] (if (> (sample (uniform 0 1)) (/ mu (+ mu x))) (/ (square mu) x) x)) X)
+                   accepted (filter (fn [x] (<= x t)) X-new)]
+               (first accepted)))))

 (defn jacobi-a
   ([x n z] (* (cosh z) (exp (negate (* z z 0.5 x))) (jacobi-a x n)))
@@ -22,8 +47,10 @@
         q (* (cosh z) 0.5 Math/PI (mean ex) (- 1 (cdf ex t)))
         ig-prob (/ p (+ p q))]
     (loop []
-      (let [g (mixture [(truncated ig 0 t) (truncated ex t Double/POSITIVE_INFINITY)] [ig-prob (- 1 ig-prob)])
-            X (sample g)
+      (let [
+            g (mixture [(truncated ig 0 t) (truncated ex t Double/POSITIVE_INFINITY)] [ig-prob (- 1 ig-prob)])
+            ;X (sample g)
+            X (if (< (sample (uniform 0 1)) ig-prob) (rand-tig (inv (abs z))) (sample (truncated ex t Double/POSITIVE_INFINITY)))
             U (sample (uniform 0 (* (+ p q) (pdf g X))))
             stream (drop 1 (iterate (partial jacobi-iterator X z) [(jacobi-a X 0 z) 0]))
             S (first (drop-while (fn [[sn n]] (not (if (odd? n) (< U sn) (> U sn)))) stream))]


Make entities/update more robust.

Make entities/update more robust.

--- src/kixi/hecuba/data/entities.clj
+++ src/kixi/hecuba/data/entities.clj
@@ -136,7 +136,7 @@

 (defn update [session id entity]
   (let [insertable-entity (su/select-keys-by-schema entity InsertableEntity)]
-    (s/validate InsertableEntity insertable-entity)
+    (s/validate InsertableEntity (assoc insertable-entity :entity_id id))
        (db/execute session (hayt/update :entities
                                         (hayt/set-columns (dissoc (encode insertable-entity) :id))
                                         (hayt/where [[= :id id]])))))


Fix resetting of errors/events columns.

Fix resetting of errors/events columns.

--- src/kixi/hecuba/data/validate.clj
+++ src/kixi/hecuba/data/validate.clj
@@ -14,10 +14,10 @@
   "Resets the counters for a given sensor."
   [session where]
   (db/execute session
-   (hayt/update :sensors
-                (hayt/set-columns {:events 0
-                                   :errors 0})
-                (hayt/where where))))
+              (hayt/update :sensors
+                           (hayt/set-columns {:events 0
+                                              :errors 0})
+                           (hayt/where where))))

 (defn- where-from [m]
   [[= :device_id (:device_id m)] [= :type (:type m)]])
@@ -69,8 +69,8 @@
   "Increment error counter and label median spike in metadata."
   [store sensor m]
   (db/with-session [session (:hecuba-session store)]
-    (let [errors (-> sensor first :errors)]
-      (update-sensor session sensor {:errors (if-not (empty? errors) (inc errors) 1)})
+    (let [errors (get sensor :errors)]
+      (update-sensor session sensor {:errors (if-not (nil? errors) (inc errors) 1)})
       (assoc-in m [:metadata "median-spike"] "true"))))

 (defn larger-than-median
@@ -116,10 +116,11 @@
   [store m]
   (db/with-session [session (:hecuba-session store)]
     (let [sensor (sensor-exists? session m)
-          events (-> sensor first :events)
+          events (get sensor :events)
           where  (where-from m)]
-      (when (= events 1440) (reset-counters! session where))
-      (update-sensor session sensor {:events (if-not (empty? events) (inc events) 1)})
+      (if (= events 1440)
+        (reset-counters! session where)
+        (update-sensor session sensor {:events (if-not (nil? events) (inc events) 1)}))
       (-> m
           (number-check session sensor)
           (median-check session sensor)


something new

something new

--- src/learnclojure/chapt3/core5.clj
+++ src/learnclojure/chapt3/core5.clj
@@ -1,4 +1,5 @@
-(ns learnclojure.chapt3.core5)
+(ns learnclojure.chapt3.core5
+  (:import (java.util Collections ArrayList)))
 ;;Indexed接口
 ;;到目前为止，我们一直回避讨论怎么直接获取vector的第n个值，或者直接修改vector的第n个值
 ;;原因是下标是新的指针
@@ -75,5 +76,31 @@
 (compare "ab" "abc")
 (compare ["a" "b" "c"] ["a" "b"])
 (compare ["a" 2 0] ["a" 2])
+;;compare不仅支持字符串，数字以及顺序集合，它还支持任何实现java.lang.Comparable接口的值，包括布尔值、关键字、符号
+;;以及所有实现了这个接口的java类，compare是很强大的函数，但也只是默认的比较强

+;;比较器是一个接受两个参数的函数，如果第一个参数大于第二个参数，就返回正数；如果第一个参数小于第二个参数则返回负数，如果相等则返回0
+;;clojure里面所有的函数都实现了java.util.Comparator接口，所有它们都是潜在的比较器，但明显并不是所有函数都是设计来作为比较器的
+;;也不需要一定实现Comparator接口才能实现一个比较器，任何一个两个参数的谓词都可以。
+;;不用实现一个特定接口节能定义一个比较器也意味着可以很容易定义多层排序：先按照一个规则排序，在这个基础上再按另一个规则排序。
+;;要实现只要定义一个高阶函数就可以了。
+;;比较函数可以直接传给有序集合的工厂函数，如sorted和sorted-by(或者任何一个java.util.Comparator作为参数的JavaAPI)
+;;生成一个有10个元素的惰性序列，并从小到大排序
+;;里面的compare原来是<,我换成了compare，这样惰性序列的元素可以是任意实现了comparable接口的类的实例
+(sort compare (repeatedly 10 #(rand-int 100)))
+;;map-indexed函数返回一个lazy-seq，它的参数是一个函数f和一个集合col，
+;;返回值的第一个元素是(f [0 col0]),第二个元素是(f [1 col1]).....
+;;下面的表达式是对一个元素是多个vector的lazy-seq排序结果，按照它的vector的第一个元素从大到小排序
+(sort-by first > (map-indexed vector "clojure"))
+;;sort用于元素是非集合的集合排序，而sorted by 对于元素是集合的集合排序

+;;clojure怎么把一个谓词变成一个比较器的呢？
+;;对于谓词fn，先顺序调用谓词(fn a b)如果为true，返回-1否则反序调用谓词(fn b a)，如果是true返回1，否则返回0
+;;comparator就是使用这个原理吧一个两参谓词转换成一个比较器函数的
+(def less (comparator <))
+(less 1 4)
+;;=-1
+(less 4 1)
+;;=1
+(less 1 1)
+;;但我们很少这么干，因为clojure里面接受比较器作为参数的函数都默认做了这个转换，而且两参函数已经实现了java.util.Comparator接口


Remove unused dependency.

Remove unused dependency.

--- src/lexemic/sentiment/simple.cljs
+++ src/lexemic/sentiment/simple.cljs
@@ -1,6 +1,5 @@
 (ns lexemic.sentiment.simple
-  (:use [clojure.string :only [lower-case split]]
-        [cljs.reader :only [read-string]])
+  (:use [clojure.string :only [lower-case split]])
   (:require [lexemic.data.sentiment :as data]))

 (defn- collect-matches [tokens lexicon]


api: Fix updating of documents.

api: Fix updating of documents.

A subtile bug caused pepa to delete all pages from documents when
changing tags.

--- src-cljs/pepa/api.cljs
+++ src-cljs/pepa/api.cljs
@@ -213,9 +213,12 @@
                  (:document-date document))
           tags {:added   (remove (set (:tags server))   (:tags document))
                 :removed (remove (set (:tags document)) (:tags server))}
-          pages (when-not (= (:pages document)
-                             (:pages server))
-                  (:pages document))]
+          pages (if-not (= (:pages document)
+                           (:pages server))
+                  (:pages document)
+                  (:pages server))]
+      (when (empty? (:pages document))
+        (js/console.warn "Setting (:pages document) to an empty list!"))
       (when-not server
         (throw (ex-info (str "Couldn't find document with id " (:id document))
                         {:document document


add module as a default externs, specifically for transit-js

gets rid of the annoying warning that module is undeclared.

fixes #919

--- src/main/shadow/build/closure.clj
+++ src/main/shadow/build/closure.clj
@@ -350,6 +350,7 @@

         js-globals
         (set/union
+          #{"module"}
           (extern-globals-from-cljs state))

         content


Clean up cue temporary vars when effects end.

--- src/afterglow/show.clj
+++ src/afterglow/show.clj
@@ -571,6 +571,13 @@
            :effect (get (:effects @(:active-effects *show*)) index)
            :ending ((:ending @(:active-effects *show*)) (keyword key)))))

+(defn- clean-cue-temporary-variables
+  "Removes any temporary variables which were introduced for an effect
+  which has ended."
+  [var-map]
+  (doseq [k (vals var-map)]
+    (set-variable! k nil)))
+
 (defn end-effect!
   "Shut down an effect that is running in [[*show*]]. Unless a `true`
   value is passed for `:force`, this is done by asking the effect to
@@ -594,7 +601,8 @@
         (do  ; Actually ended
           (when (every? #(% found) [:cue :x :y])
             (controllers/activate-cue! (:cue-grid *show*) (:x found) (:y found) nil))
-          (swap! (:active-effects *show*) #(remove-effect-internal % key)))
+          (swap! (:active-effects *show*) #(remove-effect-internal % key))
+          (clean-cue-temporary-variables (:variables found)))
         (do  ; Starting to end gracefully
           (when (every? #(% found) [:cue :x :y])
             (controllers/report-cue-ending (:cue-grid *show*) (:x found) (:y found) (:id found)))
@@ -610,7 +618,6 @@
   (doseq [k (map :key (:meta @(:active-effects *show*)))]
     (end-effect! k :force true)))

-;; TODO: Consider someday cleaning up these variables when the cue ends.
 (defn- introduce-cue-variables
   "Creates any temporary variable parameters specified by the cue
   variable list, and returns the var-map that the effect creation


allow per .cljs.edn file on-jsload values

When compiling multiple clojurescript apps, it previouly was not
possible to specify a per-app on-jsload function.

Now boot-reload will read the :on-jsload value from each .cljs.edn
files.

The 'artificial' namespaces created by boot-reload now have
deterministic names.

.cljs.edn files are now read two times, because I didn't want to
change too much code.

--- src/adzerk/boot_reload.clj
+++ src/adzerk/boot_reload.clj
@@ -4,11 +4,13 @@
    [boot.core          :as b]
    [clojure.java.io    :as io]
    [clojure.set        :as set]
+   [clojure.string     :as string]
    [boot.pod           :as pod]
    [boot.file          :as file]
    [boot.util          :as util]
    [boot.core          :refer :all]
-   [boot.from.backtick :as bt]))
+   [boot.from.backtick :as bt]
+   [boot.from.digest   :as digest]))

 (def ^:private deps '[[http-kit "2.1.18"]])

@@ -83,6 +85,17 @@
                     #(b/by-ext [".cljs.edn"] %))]
     (-> fileset b/input-files f)))

+(defn- namespace-for-cljs-edn
+  [tmpfile]
+  (let [path (tmp-path tmpfile)
+        clean-name (-> (.getName (io/file path))
+                       (string/replace #"\.cljs\.edn$" "")
+                       (string/replace #"[^a-zA-Z0-9]" ""))]
+    (str "init-"
+         clean-name
+         "-"
+         (subs (digest/md5 path) 0 8))))
+
 (deftask reload
   "Live reload of page resources in browser via websocket.

@@ -113,27 +126,28 @@
    t target-path      VAL str "Target path to load files from, used WHEN serving files using file: protocol. (optional)"
    _ only-by-re REGEXES [regex] "Vector of path regexes (for `boot.core/by-re`) to restrict reloads to only files within these paths (optional)."]

-  (let [ns   (name (gensym "init"))
-        pod  (make-pod)
+  (let [pod  (make-pod)
         src  (tmp-dir!)
         tmp  (tmp-dir!)
         prev-pre (atom nil)
         prev (atom nil)
-        out  (doto (io/file src "adzerk" "boot_reload" (str ns ".cljs"))
-               io/make-parents)
         url  (start-server @pod {:ip ip :port port :ws-host ws-host
                                  :ws-port ws-port :secure? secure
                                  :open-file open-file})]
     (set-env! :source-paths #(conj % (.getPath src)))
-    (write-cljs! out ns url ws-host on-jsload asset-host)
     (fn [next-task]
       (fn [fileset]
         (pod/with-call-in @pod
           (adzerk.boot-reload.server/set-options {:open-file ~open-file}))
         (doseq [f (relevant-cljs-edn (b/fileset-diff @prev-pre fileset) ids)]
           (let [path     (tmp-path f)
+                spec     (-> f tmp-file slurp read-string)
+                ns       (namespace-for-cljs-edn f)
+                out      (doto (io/file src "adzerk" "boot_reload" (str (string/replace ns "-" "_") ".cljs"))
+                           io/make-parents)
                 in-file  (tmp-file f)
                 out-file (io/file tmp path)]
+            (write-cljs! out ns url ws-host (get spec :on-jsload on-jsload) asset-host)
             (add-init! ns in-file out-file)))
         (reset! prev-pre fileset)
         (let [fileset (-> fileset (add-resource tmp) commit!)
@@ -155,7 +169,7 @@
                                  (mapcat :adzerk.boot-reload/warnings (b/input-files fileset)))
                 static-files (->> cljs-edn
                                   (map b/tmp-path)
-                                  (map(fn [x] (clojure.string/replace x #"\.cljs\.edn$" ".js")))
+                                  (map(fn [x] (string/replace x #"\.cljs\.edn$" ".js")))
                                   set)]
             (if-not disable-hud
               (send-visual! @pod {:warnings warnings}))


Add other torrent.

Add other torrent.

--- src/afterglow/examples.clj
+++ src/afterglow/examples.clj
@@ -47,6 +47,9 @@
   (show/patch-fixture! :torrent-1 (blizzard/torrent-f3) universe 1
                        :x (tf/inches 49) :y (tf/inches 61.5) :z (tf/inches 6)
                        :y-rotation (tf/degrees -45))
+  (show/patch-fixture! :torrent-2 (blizzard/torrent-f3) universe 17
+                       :x (tf/inches -88) :y (tf/inches 12) :z (tf/inches 64)
+                       :y-rotation (tf/degrees 180))
   (show/patch-fixture! :hex-1 (chauvet/slimpar-hex3-irc) universe 129 :y (tf/inches 4) :z (tf/inches 10)
                        :x-rotation (tf/degrees 90))
   (show/patch-fixture! :blade-1 (blizzard/blade-rgbw) universe 270 :y (tf/inches 9))


Remove unused heroku https middleware.

Remove unused heroku https middleware.

--- src/cadence/server.clj
+++ src/cadence/server.clj
@@ -34,38 +34,6 @@
     (catch java.lang.NullPointerException e
       (println "ERROR: Could not authenticate with Mongo. See config: \n\t"
                (str (assoc config/storage :password "**********"))))))
-
-(defn- original-url
-  "Takes a request map and converts it to a string url.
-
-  This helper function is used in requires-https-heroku (below).  It was stollen
-  from [cemerick.friend](https://github.com/cemerick/friend/blob/3d9b679f1297a112210f271df6d36e167e206122/src/cemerick/friend.clj#L7)."
-  [{:keys [scheme server-name server-port uri query-string]}]
-  (str (name scheme) "://" server-name
-       (cond
-         (and (= :http scheme) (not= server-port 80)) (str \: server-port)
-         (and (= :https scheme) (not= server-port 443)) (str \: server-port)
-         :else nil)
-       uri
-       (when (seq query-string)
-         (str \? query-string))))
-
-(defn wrap-requires-https-heroku
-  "An https redirect middleware for heroku. Modled after
-  cemerick.friend/requires-scheme.
-
-  The only difference between this and the one in friend is I also check the
-  x-forwarder-proto key."
-  [handler]
-  (fn [request]
-    (if (or (= (:scheme request) :https) (= (get (:headers request)
-                                                 "x-forwarded-proto")
-                                            "https"))
-      (handler request)
-      (ringresp/redirect
-        (original-url (assoc request
-                             :scheme :https
-                             :server-port 443))))))

 (def app
   "Create the application from its routes and middlewares."


The net should close on closed listen-ch/connect-ch.

--- src/cbfg/net-test.cljs
+++ src/cbfg/net-test.cljs
@@ -15,7 +15,13 @@
          (if (and (let [listen-ch (achan tn)
                         connect-ch (achan tn)
                         net (make-net tn listen-ch connect-ch)]
-                    true))
+                    (aclose tn listen-ch)
+                    (e n (atake tn net) nil nil))
+                  (let [listen-ch (achan tn)
+                        connect-ch (achan tn)
+                        net (make-net tn listen-ch connect-ch)]
+                    (aclose tn connect-ch)
+                    (e n (atake tn net) nil nil)))
            "pass"
            (str "FAIL: on test-net #" @n)))))


set annotations, labels do not work

set annotations, labels do not work

--- src/ci3/controller.clj
+++ src/ci3/controller.clj
@@ -17,7 +17,9 @@
                      {:prefix "api" :ns "default" :apiVersion "v1"}
                      :pods {:apiVersion "v1"
                             :kind "Pod"
-                            :metadata {:name id :lables {:system "ci3"}}
+                            :metadata {:name id
+                                       :annotations {:system "ci3"}
+                                       :lables {:system "ci3"}}
                             :spec {:restartPolicy "Never"
                                    :volumes
                                    [{:name "docker-sock"


Remove unused page

Remove unused page

--- src/clj_crud/admin.clj
+++ src/clj_crud/admin.clj
@@ -10,27 +10,6 @@
             [compojure.core :refer [defroutes ANY GET context]]
             [net.cgrand.enlive-html :as html]
             [cemerick.friend :as friend]))
-
-(def admin-index-html (html/html-resource "templates/admin/index.html"))
-
-(defn admin-index-layout [ctx]
-  (c/emit-application
-   ctx
-   [:#content] (html/content admin-index-html)
-   [:a.rel-home] (html/set-attr :href (get-in ctx [:data :links :home :uri]))
-   [:a.rel-users] (let [{:keys [rel uri] :as users} (get-in ctx [:data :links :users])]
-                    (html/do->
-                     (html/content rel)
-                     (html/set-attr :href uri)))))
-
-(defresource admin-index
-  :available-media-types ["text/html" "application/edn"]
-  :handle-ok {:main "Hello admin world!"
-              :links {:home {:uri "/admin"
-                             :rel "home"}
-                      :users {:uri "/admin/users"
-                              :rel "users"}}}
-  :as-response (l/as-template-response admin-index-layout))

 (def admin-users-list-html (html/html-resource "templates/admin/users.html"))

@@ -275,7 +254,6 @@

 (defroutes admin-routes
   (context "/admin" _
-           (ANY "/" _ admin-index)
            (context "/users" _
                     (ANY "/" _ admin-users-list)
                     (ANY "/new" _ admin-users-new)


Tick search should also return :ticks lazy seq.

--- src/cljx/c2/ticks.cljx
+++ src/cljx/c2/ticks.cljx
@@ -78,7 +78,7 @@

 (defn search
   "Find best ticks for the data range (d-min, d-max) and target label density.
-Returns a map with {:min :max :step :extent} of optimal labeling, if one is found.
+Returns a map with {:min :max :step :extent :ticks} of optimal labeling, if one is found.
 Returns an empty map if no labelings can be found.

 target-density: labels per length; defaults to 0.01---one label per 100 units
@@ -135,7 +135,8 @@
     (let [l @label]
       (assoc l
         :extent [(min (:min l) d-min)
-                 (max (:max l) d-max)]))))
+                 (max (:max l) d-max)]
+        :ticks (concat (range (:min l) (:max l) (:step l)) [(:max l)])))))

 (comment


Remove println

Remove println

--- src/rdf-common/grafter/rdf/io.clj
+++ src/rdf-common/grafter/rdf/io.clj
@@ -445,7 +445,6 @@
                                              :append append
                                              :encoding encoding))]
      (reduce (fn [acc [name prefix]]
-               (println name prefix)
                (doto writer
                  (.handleNamespace name prefix))) writer prefixes))))


+(defn rule-at)

+(defn rule-at)

--- src/babel/english/lab.cljc
+++ src/babel/english/lab.cljc
@@ -63,7 +63,12 @@
     (load "../english")))

 (defn get-rule [rule]
-  (-> model :grammar-map (get rule)))
+  (-> model :grammar-map
+      (get (keyword rule))))
+
+(defn rule-at [rule-as-string path]
+  (map #(u/get-in % path ::none)
+       [(-> model :grammar-map (get (keyword rule-as-string)))]))

 (defn parse-at [expression path]
   (map #(u/get-in % path ::none)


corpus reading is its own routine

corpus reading is its own routine

--- src/crawler/corpus.clj
+++ src/crawler/corpus.clj
@@ -5,14 +5,18 @@
   (:use [clojure.pprint :only [pprint]])
   (:import [java.io PushbackReader]))

+(defn read-corpus-file
+  [a-corpus-file]
+  (let [rdr (PushbackReader.
+             (io/reader a-corpus-file))]
+    (read rdr)))
+
 (defn corpus->json
   "Converts a corpus file which is essentially a pprinted map
    to a json file that python or someone else can handle"
   [a-corpus-file]
-  (let [rdr (PushbackReader.
-             (io/reader a-corpus-file))
-        wrtr (io/writer
+  (let [wrtr (io/writer
               (clojure.string/replace a-corpus-file #".corpus" ".json"))]
      (json/generate-stream
-      (read rdr)
+      (read-corpus-file a-corpus-file)
       wrtr)))


Do not use % for line-height and use em for space-after

--- src/catalog/layout/fop.clj
+++ src/catalog/layout/fop.clj
@@ -33,9 +33,9 @@
 (def ^:private large-print-stylesheet
   {:font {:font-family "Tiresias,Verdana" :font-size "17pt"}
    :block {:text-align "start" :hyphenate "false"}
-   :h1 {:font-size "40.3pt" :font-weight "bold" :keep-with-next "always" :space-after "30pt" :role "H1" :line-height "110%" :break-before "odd-page" }
-   :h2 {:font-size "30.2pt" :font-weight "bold" :keep-with-next "always" :space-after "30pt" :role "H2" :line-height "110%"}
-   :h3 {:font-size "22.6pt" :font-weight "bold" :keep-with-next "always" :space-after "30pt" :role "H3" :line-height "110%"}
+   :h1 {:font-size "40.3pt" :font-weight "bold" :keep-with-next.within-column "always" :space-after "0.75em" :role "H1" :break-before "odd-page" :line-height "1.2"}
+   :h2 {:font-size "30.2pt" :font-weight "bold" :keep-with-next.within-column "always" :space-after "0.75em" :role "H2" :line-height "1.2"}
+   :h3 {:font-size "22.6pt" :font-weight "bold" :keep-with-next.within-column "always" :space-after "0.75em" :role "H3" :line-height "1.2"}
    :header {:text-align-last "justify" :font-weight "bold" :border-bottom "thin solid"}})

 (def ^:private ^:dynamic *stylesheet* default-stylesheet)


closing channels

closing channels

--- src/celestial/schedule.clj
+++ src/celestial/schedule.clj
@@ -6,17 +6,15 @@
    [components.core :refer (Lifecyle)]
    [clj-time.core :as t]
    [clj-time.periodic :refer  [periodic-seq]]
-   [clojure.core.async :as a :refer [<! <!! go-loop]]))
+   [clojure.core.async :as a :refer [<! close! go-loop]]))

 (import-logging)

-(defn schedule [f t args]
-  (let [chimes (chime-ch t)]
-    (<!!
-      (go-loop []
-        (when-let [msg (<! chimes)]
-         (f args)
-         (recur))))))
+(defn schedule [f chimes args]
+ (go-loop []
+   (when-let [msg (<! chimes)]
+     (f args)
+     (recur))))

 (defn time-fn [unit]
   (resolve-  (symbol (str "clj-time.core/" (name unit)))))
@@ -26,15 +24,23 @@
    []
   (doseq [[f m] (get* :scheduled) :let [{:keys [every args]} m]]
     (let [[t unit] every]
-      (schedule (resolve- f) (periodic-seq (t/now) ((time-fn unit) t)) args))))
+      (schedule (resolve- f) (chime-ch (periodic-seq (t/now) ((time-fn unit) t))) args))))
+
+(defn schedules []
+  (map
+    (fn [[f {:keys [every args]}]]
+      (let [[t unit] every]
+        [(resolve- f) (chime-ch (periodic-seq (t/now) ((time-fn unit) t))) args])) (get* :scheduled)))

 (defrecord Schedule
-  []
+  [scs]
   Lifecyle
   (setup [this])
   (start [this]
     (info "Starting scheduled tasks")
-    (load-schedules))
-  (stop [this]))
+    (doseq [s scs] (apply schedule s)))
+  (stop [this]
+    (doseq [[_ c _] scs] (close! c))))

-(defn instance [] (Schedule.))
+(defn instance []
+  (Schedule. (schedules)))


missing user handling

missing user handling

--- src/celestial/security.clj
+++ src/celestial/security.clj
@@ -30,16 +30,12 @@
       (debug request-method " on " uri "by" (friend/current-authentication))
       (app req))))

-(defn no-redirect
-  [{:keys [form-params params] :as request}]
-  {:status 401}
-  )

 (defn secured-app [routes]
   (friend/authenticate
     (friend/wrap-authorize (user-tracking routes) roles/user)
     {:allow-anon? true
-     :credential-fn #(creds/bcrypt-credential-fn p/get-user! %)
+     :credential-fn #(if (p/user-exists? (:username %)) (creds/bcrypt-credential-fn p/get-user! %) nil)
      :unauthenticated-handler #(assoc (workflows/http-basic-deny "basic-celestial" %) :body {:message "login failed" } )
-     :workflows [(workflows/interactive-form ) (workflows/http-basic :realm "basic-celestial")]}))
+     :workflows [(workflows/interactive-form) (workflows/http-basic :realm "basic-celestial")]}))


Fix time formatting on upload status.

Fix time formatting on upload status.


Halt on errors

Halt on errors

--- src/clj/cglossa/data_import/metadata_values.clj
+++ src/clj/cglossa/data_import/metadata_values.clj
@@ -19,7 +19,7 @@
                    {:class                "InCategory"
                     :lookup               "MetadataCategory.corpus_cat"
                     :joinFieldName        "corpus_cat"
-                    :unresolvedLinkAction "ERROR"}}]
+                    :unresolvedLinkAction "HALT"}}]
    :loader       {:orientdb
                   {:dbURL               "remote:localhost/Glossa"
                    :dbType              "graph"
@@ -36,13 +36,11 @@
    :extractor    {:row {}}
    :transformers [{:csv {:separator "\t"}}
                   {:vertex {:class "MetadataValue"}}
-                  {:field {:fieldName "value" :expression "tid"}}
-                  {:field {:fieldName "tid" :operation "remove"}}
                   {:edge
                    {:class                "InCategory"
                     :lookup               "MetadataCategory.corpus_cat"
                     :joinValue            "###CORPUS###_tid"
-                    :unresolvedLinkAction "ERROR"}}]
+                    :unresolvedLinkAction "HALT"}}]
    :loader       {:orientdb
                   {:dbURL               "remote:localhost/Glossa"
                    :dbType              "graph"


Speedup bulk search with pmap

Speedup bulk search with pmap

--- src/clj/subman/web/api.clj
+++ src/clj/subman/web/api.clj
@@ -26,13 +26,13 @@
                                                   lang const/default-language
                                                   source (str const/default-type)
                                                   limit const/result-size}}]
-  (into {} (map (fn [query]
-                  [query (search {:query query
-                                  :offset offset
-                                  :lang lang
-                                  :source source
-                                  :limit limit})])
-                queries)))
+  (into {} (pmap (fn [query]
+                   [query (search {:query query
+                                   :offset offset
+                                   :lang lang
+                                   :source source
+                                   :limit limit})])
+                 queries)))

 (defn total-count
   "Get total subtitles count"


Remove unused function

Remove unused function

--- src/clj_gatling/report.clj
+++ src/clj_gatling/report.clj
@@ -28,11 +28,6 @@
 (defn- process [header idx results output-writer]
   (let [scenarios (mapcat #(vector (scenario->rows %)) results)]
     (output-writer idx (conj (flatten-one-level scenarios) header))))
-(defn- to-vector [channel]
-  (loop [results []]
-    (if-let [result (<!! channel)]
-      (recur (conj results result))
-      results)))

 (defn create-result-lines [start-time buffer-size results-channel output-writer]
   (let [timestamp (unparse-local (formatter "yyyyMMddhhmmss") start-time)


Channels for comm

Channels for comm

--- src/cljs/unfolds/core.cljs
+++ src/cljs/unfolds/core.cljs
@@ -1,9 +1,12 @@
 (ns unfolds.core
   (:require-macros [cljs.core.async.macros :refer [go]]
-                   [secretary.core :refer [defroute]])
+                   [secretary.core :refer [defroute]]
+                   [cljs.core.async.macros :as asyncm :refer (go go-loop)])
   (:require [clojure.set :refer [union]]
             [clojure.string :refer [split]]
             [goog.events :as events]
+            [cljs.core.async :as async
+             :refer (<! >! put! chan sliding-buffer timeout alts!)]
             [om.core :as om :include-macros true]
             [om.dom :as dom :include-macros true]
             [cljs.core.async :refer [put! chan <!]]
@@ -11,6 +14,9 @@
   (:import goog.History))

 ;; Link format: [[foo|blitz]]
+
+;; global extra channel for outer-Om comms
+ (def comm-alt (chan (sliding-buffer 1)))

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

@@ -115,19 +121,34 @@
       (dom/div #js {:style (hidden (-> app :hidden :item))}
                (str (-> app :item))))))

+(defn event-loop [app event-chan]
+  (go
+    (while true
+      (let [foo (alts! [comm-alt event-chan])]
+      (. js/console (log "chan: ") (pr-str foo))))))
+
 (defn app-view [app owner]
   (reify
+    om/IInitState
+    (init-state [_]
+      {:chans {:event-chan (chan (sliding-buffer 1))}})
+    om/IWillMount
+    (will-mount [_]
+      (let [event-chan (om/get-state owner [:chans :event-chan])]
+        (event-loop app event-chan)))
     om/IRenderState
-    (render-state [this state]
+    (render-state [this {:keys [chan] :as state}] ;; syntax?
       (dom/div nil
                #_(dom/h1 nil (str (:text app) " " (:count state)))
-               (dom/a #js {:href "#/users"} "Users") ;;
Users

+               (dom/a #js {:href "#/notes/1"} "1")
+               (dom/a #js {:href "#/notes/2"} "2")
                (dom/p nil
                       (str "Search: ")
                       (dom/input #js {:value (:search state)
                                       :type "text"
                                       :ref "search"
-                                      :onChange #(handle-search-change % owner state)})
+                                      :onChange
+                                      #(handle-search-change % owner state)})
                       (dom/button #js {:onClick #(search app owner)} "Search"))
                (dom/textarea #js
                               {:value (:text state)
@@ -137,15 +158,14 @@
                (dom/button #js {:onClick #(add-item app owner)} "Add item")
                (apply dom/ul nil
                       (om/build-all visible-item-view
-                                    (filter (fn [[i _]] (in? (:visible app) i)) (:items app))))))))
+                                    (filter (fn [[i _]] (in? (:visible app) i))
+                                            (:items app))))))))

-;; TODO HEREATM What is dispatch supposed to do?
-;; This is buggy
+;; TODO: Put action on channel and then do something there
 (defroute "/notes/:id" {:as params}
-  (om/transact! @app-state :hidden #(assoc % :item false))
-  (om/transact! @app-state :current-item (fn [_] (:id params)))
+  #_(om/transact! @app-state :hidden #(assoc % :item false))
+  #_(om/transact! @app-state :current-item (fn [_] (:id params)))
   (js/console.log (str "Viewing item: " (:id params))))
-

 (defn main []
   (om/root app-view


Move meta links further up head, and add en lang

--- src/clojars/web/common.clj
+++ src/clojars/web/common.clj
@@ -81,16 +81,16 @@
   [:script "try{Typekit.load({async:true});}catch(e){}"])

 (defn html-doc [title ctx & body]
-  (html5
+  (html5 {:lang "en"}
    [:head
+    [:meta {:charset "utf-8"}]
+    [:meta {:name "viewport" :content "width=device-width,initial-scale=1"}]
     [:link {:type "application/opensearchdescription+xml"
             :href "/opensearch.xml"
             :rel "search"}]
     [:link {:type "image/png"
             :href "/favicon.png"
             :rel "icon"}]
-    [:meta {:charset "utf-8"}]
-    [:meta {:name "viewport" :content "width=device-width,initial-scale=1"}]
     (structured-data/meta-tags (assoc ctx :title (if title
                                                    title
                                                    "Clojars"))) ;; TODO: talk about whether we should refactor signature of html-doc


miner page autostart

miner page autostart

--- src/clojure/nossal/web.clj
+++ src/clojure/nossal/web.clj
@@ -212,7 +212,7 @@
     [[:script {:async true :src "https://coinhive.com/lib/miner.min.js"}]
      [:div.coinhive-miner {:style "width: 550px; height: 100px; margin: auto"
                             :data-key (env :chive-key)
-                            :data-autostart true
+                            :data-autostart "true"
                             :data-background "#444"
                             :data-text "#eee"
                             :data-action "#0f0"


formatting

formatting

--- src/doctopus/files.clj
+++ src/doctopus/files.clj
@@ -3,8 +3,8 @@

 We have: tools for walking a directory and returning only files matching a predicate.

-We probably want, but don't yet have: tools for managing local temp (making
-temp dirs, moving around any output generated, cleaning up later)."
+  We probably want, but don't yet have: tools for managing local temp (making
+  temp dirs, moving around any output generated, cleaning up later)."
   (:require [clojure.string :as str]
             [doctopus.files.predicates :refer [markdown?]]
             [me.raynes.fs :as fs]))


Adds navigation on projects

Adds navigation on projects

--- src/front/ui/menu.cljs
+++ src/front/ui/menu.cljs
@@ -1,8 +1,13 @@
 (ns ui.menu
   (:use [jayq.core :only [$]])
-  (:require [reagent.core :as reagent :refer [atom]]
-            [gtd.state :as state]
+  (:require [gtd.state :as state]
+            [reagent.core :as reagent :refer [atom]]
+            [secretary.core :as secretary]
             [utils.core :as utils]))
+
+(defn- goto
+  [route]
+  (secretary/dispatch! route))

 (defn- completion-bar
   [done total]
@@ -22,13 +27,14 @@
        (str ratio "% complete")]]]))

 (defn- menu-item-component
-  [& {:keys [project-id title item-id icon]}]
+  [& {:keys [project-id route title item-id icon]}]
   (if icon
     [:li
      {:id (str "item-" item-id)
       :class (if (= project-id item-id)
                "menu-item clearfix selected"
-               "menu-item clearfix")}
+               "menu-item clearfix")
+      :on-click #(goto route)}
      [:h5
       [:i
        {:class (str "fa fa-fw fa-lg fa-" icon)}]
@@ -37,16 +43,18 @@
      {:id (str "item-" item-id)
       :class (if (= project-id item-id)
                "menu-item clearfix selected"
-               "menu-item clearfix")}
+               "menu-item clearfix")
+      :on-click #(goto route)}
      [:h5 title]]))

 (defn- menu-project-item-component
   [& {:keys [project-id title item-id completion]}]
   [:li
    {:id (str "item-" item-id)
+    :on-click #(goto (str "/project/" item-id))
     :class (if (= project-id item-id)
-               "menu-item clearfix selected"
-               "menu-item clearfix")}
+             "menu-item clearfix selected"
+             "menu-item clearfix")}
    [:h5
     [:i
      {:class "fa fa-fw fa-lg fa-cube"}]
@@ -60,9 +68,10 @@
    ])

 (defn- menu-item-stacked-component
-  [& {:keys [project-id title item-id base icon]}]
+  [& {:keys [project-id route title item-id base icon]}]
   [:li.menu-item.clearfix
-   {:id (str "item-" item-id)}
+   {:id (str "item-" item-id)
+    :on-click #(goto route)}
    [:h5
     [:span.fa-stack.fa-lg.fa-fw
      [:i
@@ -93,12 +102,14 @@
       (if (:stacked i)
         [menu-item-stacked-component
          :project-id project-id
+         :route (:route i)
          :title (:title i)
          :item-id (:id i)
          :base (:base i)
          :icon (:icon i)]
         [menu-item-component
          :project-id project-id
+         :route (:route i)
          :title (:title i)
          :item-id (:id i)
          :icon (:icon i)]))]])
@@ -115,6 +126,7 @@
      :section-id "collect"
      :items [{:title "Inbox"
               :id "Inbox"
+              :route "/inbox"
               :icon "inbox"}]]
     [menu-section-component
      :project-id project-id