[#3081] WIP Implement undo with data-groups

- Still needs some love to cover merge-dataset new-data-groups generated

--- backend/src/akvo/lumen/lib/transformation/engine.clj
+++ backend/src/akvo/lumen/lib/transformation/engine.clj
@@ -11,7 +11,8 @@
             [clojure.string :as str]
             [clojure.tools.logging :as log]
             [clojure.walk :as w])
-  (:import [java.time Instant]))
+  (:import [java.time Instant]
+           [clojure.lang ExceptionInfo]))

 (defmulti columns-used
   (fn [applied-transformation columns]
@@ -346,14 +347,86 @@
               (throw (ex-info (str "Failed to undo transformation index:" tx-index ". Tx message:" message) {:transformation-result transformation-result
                                                                                :transformation transformation})))))))))

+;; TODO: merge-datasets tables should be cloned and setted to :imported-table-name
+(defn copy-tables-2 [tenant-conn data-groups]
+  (doall (map (fn [data-group]
+          (let [imported-table-name (:imported-table-name data-group)
+                table-name (util/gen-table-name "ds")]
+            (db.transformation/copy-table tenant-conn
+                                          {:source-table imported-table-name
+                                           :dest-table   table-name}
+                                          {}
+                                          {:transaction? false})
+
+            (assoc data-group :table-name table-name :previous-table-name (:table-name data-group)))
+          ) data-groups)))
+
+(defn- apply-undo-2 [{:keys [tenant-conn claims] :as deps} dataset-id job-execution-id current-dataset-version]
+  (let [initial-dataset-version (db.transformation/initial-dataset-version-2-to-update-by-dataset-id
+                                 tenant-conn
+                                 {:dataset-id dataset-id})
+        initial-data-groups     (->> (db.data-group/list-data-groups-by-dataset-version-id tenant-conn {:dataset-version-id (:id initial-dataset-version)})
+                                     (copy-tables-2 tenant-conn ))] ;; TODO: initial-data-groups or current-data-groups???
+
+    (loop [data-groups     initial-data-groups
+           transformations (butlast (:transformations current-dataset-version))
+           tx-index        0]
+      (if (empty? transformations)
+        (let [new-dataset-version-id (str (util/squuid))]
+          (db.dataset-version/new-dataset-version-2 tenant-conn {:id               new-dataset-version-id
+                                                                 :dataset-id       dataset-id
+                                                                 :job-execution-id job-execution-id
+                                                                 :version          (inc (:version current-dataset-version))
+                                                                 :author           claims
+                                                                 :transformations  (w/keywordize-keys (vec (butlast (:transformations current-dataset-version))))})
+          (doseq [data-group data-groups]
+            (let [new-data-group-id (str (util/squuid))]
+              ;;  TODO: now we have a database constriction  NOT NULL           (db.transformation/clear-data-group-data-table tenant-conn {:id (:id data-group)})
+              (db.data-group/new-data-group tenant-conn (assoc data-group
+                                                               :id                  new-data-group-id
+                                                               :dataset-version-id  new-dataset-version-id
+                                                               :version             (inc (:version current-dataset-version))
+                                                               :columns             (vec (w/keywordize-keys (:columns data-group)))))
+              (db.transformation/drop-table tenant-conn {:table-name (:previous-table-name data-group)})))
+          (db.transformation/touch-dataset tenant-conn {:id dataset-id}))
+        (let [transformation (assoc (first transformations) :dataset-id dataset-id)
+              {:keys [data-groups-to-be-created data-group columns]}
+              (try
+                (try-apply-operation-2 deps {:transformation transformation
+                                             :data-groups data-groups})
+                (catch ExceptionInfo e
+                  (do
+                    (log/info (str "Unsuccessful undo of dataset: " dataset-id))
+                    (log/debug (->  (ex-data e) :transformation-result :message))
+                    (log/debug "Job executionid: " job-execution-id)
+                    (throw (ex-info (str "Failed to undo transformation index:" tx-index ". Tx message:" (.getMessage e))
+                                    {:transformation-result (:transformation-result (ex-data e))
+                                     :transformation        transformation})))))]
+          (log/error :data-group data-group)
+          (log/error :data-groups data-groups)
+          (log/error :data-groups-to-be-created data-groups-to-be-created)
+          (recur (reduce (fn [c dg]
+                           (if (= (:id dg) (:id data-group ))
+                             (conj c (assoc dg :columns columns))
+                             (conj c dg)
+                             )) data-groups-to-be-created data-groups) (rest transformations) (inc tx-index)))))))
+
 (defn execute-undo [{:keys [tenant-conn] :as deps} dataset-id job-execution-id]
-  (let [current-dataset-version (db.transformation/latest-dataset-version-by-dataset-id tenant-conn
-                                                                      {:dataset-id dataset-id})]
-    (when (not= (:version current-dataset-version) 1)
-      (apply-undo deps
-                  dataset-id
-                  job-execution-id
-                  current-dataset-version))))
+  (if (get (env/all tenant-conn) "data-groups")
+    (let [current-dataset-version (db.dataset-version/latest-dataset-version-2-by-dataset-id tenant-conn
+                                                                                {:dataset-id dataset-id})]
+      (when (not= (:version current-dataset-version) 1)
+        (apply-undo-2 deps
+                      dataset-id
+                      job-execution-id
+                      current-dataset-version)))
+   (let [current-dataset-version (db.transformation/latest-dataset-version-by-dataset-id tenant-conn
+                                                                                {:dataset-id dataset-id})]
+     (when (not= (:version current-dataset-version) 1)
+       (apply-undo deps
+                   dataset-id
+                   job-execution-id
+                   current-dataset-version)))))

 (defmulti adapt-transformation
   (fn [op-spec older-columns new-columns]


add dom until fns (this stuff should all end up being replaced by a decent external lib soon)

--- src-cljs/defpi/dom.cljs
+++ src-cljs/defpi/dom.cljs
@@ -15,5 +15,15 @@
   [el s]
   (set! (.-innerHTML el) s))

+(defn append-child!
+  "Append the dom element c to element el as a child."
+  [el c]
+  (.appendChild el c))
+
+(defn insert-before!
+  "Incert the dom element c to before element el"
+  [el c]
+  (.insertBefore el c))
+
 (defn get-html [el]
   (.-innerHTML el))


Add all tests back in.

Add all tests back in.

--- test/onyx/peer/single_peer_test.clj
+++ test/onyx/peer/single_peer_test.clj
@@ -72,11 +72,8 @@
       (fact results => (conj (vec (map (fn [x] {:n (inc x)}) (range n-messages))) :done)))))

  (run-job (str (java.util.UUID/randomUUID)) (str (java.util.UUID/randomUUID)) 10 1 1)
-; (run-job (str (java.util.UUID/randomUUID)) (str (java.util.UUID/randomUUID)) 100 10 10)
+ (run-job (str (java.util.UUID/randomUUID)) (str (java.util.UUID/randomUUID)) 100 10 10)
+ (run-job (str (java.util.UUID/randomUUID)) (str (java.util.UUID/randomUUID)) 1000 100 100)
+ (run-job (str (java.util.UUID/randomUUID)) (str (java.util.UUID/randomUUID)) 15000 1320 1000)
+ (run-job (str (java.util.UUID/randomUUID)) (str (java.util.UUID/randomUUID)) 100000 3000 10000)

-;; (run-job (str (java.util.UUID/randomUUID)) (str (java.util.UUID/randomUUID)) 1000 100 100)
-;; (run-job (str (java.util.UUID/randomUUID)) (str (java.util.UUID/randomUUID)) 15000 1320 1000)
-;; (run-job (str (java.util.UUID/randomUUID)) (str (java.util.UUID/randomUUID)) 100000 3000 10000)
-
-
-


Fix functions to take no args

Fix functions to take no args

--- src/cljam/io/bigwig.clj
+++ src/cljam/io/bigwig.clj
@@ -190,7 +190,7 @@
   "Returns the Chrom data of leafs."
   [^RandomAccessFile r key-size child-count]
   (repeatedly child-count
-              (fn [_]
+              (fn []
                 (let [name (->> (lsb/read-bytes r key-size)
                                 (map char)
                                 (apply str))
@@ -203,7 +203,7 @@
   "Skips offsets and returns the file offsets of children."
   [^RandomAccessFile r key-size child-count]
   (repeatedly child-count
-              (fn [_]
+              (fn []
                 (lsb/skip r key-size)
                 (lsb/read-long r))))


remove runtime constructed char-escapes ObjMap

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -6439,19 +6439,21 @@
   [fmt & args]
   (print (apply format fmt args)))

-(def ^:private char-escapes {"\"" "\\\""
-                             "\\" "\\\\"
-                             "\b" "\\b"
-                             "\f" "\\f"
-                             "\n" "\\n"
-                             "\r" "\\r"
-                             "\t" "\\t"})
+(def ^:private char-escapes
+  (js-obj
+    "\"" "\\\""
+    "\\" "\\\\"
+    "\b" "\\b"
+    "\f" "\\f"
+    "\n" "\\n"
+    "\r" "\\r"
+    "\t" "\\t"))

 (defn ^:private quote-string
   [s]
   (str \"
        (.replace s (js/RegExp "[\\\\\"\b\f\n\r\t]" "g")
-         (fn [match] (get char-escapes match)))
+         (fn [match] (aget char-escapes match)))
        \"))

 (extend-protocol IPrintWithWriter


Add missing docstrings

Add missing docstrings

--- src/clojure/neko/ui.clj
+++ src/clojure/neko/ui.clj
@@ -58,6 +58,8 @@
 ;; ## Widget creation

 (defn construct-element
+  "Constructs a UI widget by a given keyword. Infers a correct
+  constructor for the types of arguments being passed to it."
   ([kw context constructor-args]
      (let [element-class (kw/classname kw)]
        (.newInstance (reflect-constructor element-class
@@ -66,6 +68,9 @@
                      (to-array (cons context constructor-args))))))

 (defn make-ui-element
+  "Creates a UI widget based on its keyword name, applies attributes
+  to it, then recursively create its subelements and add them to the
+  widget."
   [context tree options]
   (let [[widget-kw attributes & inside-elements] tree
         _ (assert (and (keyword? widget-kw) (map? attributes)))


PR Changes

PR Changes

--- src/clojurebot/core.clj
+++ src/clojurebot/core.clj
@@ -41,10 +41,14 @@
   [name handler]
   (swap! commands assoc name handler))

-(defn replace-nl
+(defn replace-ws
   "Replace occurences of \n from s with whitespace, so it doesn't trim the IRC output."
   [s]
-  (clojure.string/replace s "\n " " "))
+  (clojure.string/replace s #"\s+" " "))
+
+(defn doc->string
+  [s]
+  (format "%s ::: %s" (:arglists s) (:doc s)))

 (defn handle-message [chan msg]
   (let [[cmd msg] (parse-message msg)
@@ -87,19 +91,27 @@
  (fn [msg]
    (str "=> " (pr-str (eval-string msg)))))

+; (reg-command
+;   "doc"
+;   (fn [sym-name]
+;     (if (not (clojure.string/blank? sym-name))
+;         (->> (symbol sym-name)
+;              (resolve)
+;              (meta)
+;              (doc->string)
+;              (replace-ws))
+;         "ERROR: No arguments provided")))
+
 (reg-command
   "doc"
   (fn [sym-name]
-    (if (not (empty? sym-name))
-      (->> (symbol sym-name)
-           (resolve)
-           ;; TODO: If sym-name is not a valid symbol resolve returns nil
-           ;; find a way to skip the forms below and show an error like
-           ;; Error: symbol is not valid
-           (meta)
-           (#(format "::: %s ::: \"%s\" " (:arglists %1) (:doc %1)))
-           (replace-nl))
-      "ERROR: No arguments provided")))
+    (if (not (clojure.string/blank? sym-name))
+        (->> (if-let [sym (symbol sym-name)]
+          (resolve)
+          (meta)
+          (doc->string)
+          (replace-ws)))
+        "Error: Symbol is not valid")))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Entry point


Cleaned up real-path duplication.

Cleaned up real-path duplication.

--- test/vignette/storage/core_test.clj
+++ test/vignette/storage/core_test.clj
@@ -59,14 +59,14 @@
                     (sh "mkdir" "-p" local-path)))]

   (facts :save-thumbnail :integration
-    (let [local (create-local-object-storage "/tmp/vignette-local-storage")
+    (let [local (create-local-object-storage local-path)
           image-store (create-local-image-storage local "originals" "thumbs")]
       local => truthy
       image-store => truthy
       (save-thumbnail image-store (io/file "image-samples/ropes.jpg") sample-thumbnail-hash) => truthy))

   (facts :get-thumbnail :integration
-    (let [local (create-local-object-storage "/tmp/vignette-local-storage")
+    (let [local (create-local-object-storage local-path)
           image-store (create-local-image-storage local "originals" "thumbs")]
       (get-thumbnail image-store sample-thumbnail-hash) => falsey
       (save-thumbnail image-store (io/file "image-samples/ropes.jpg") sample-thumbnail-hash) => truthy
@@ -74,12 +74,12 @@

   (facts :save-original :integration
-    (let [local (create-local-object-storage "/tmp/vignette-local-storage")
+    (let [local (create-local-object-storage local-path)
           image-store (create-local-image-storage local "originals" "thumbs")]
       (save-original image-store (io/file "image-samples/ropes.jpg") sample-media-hash) => truthy))

   (facts :get-original :integration
-    (let [local (create-local-object-storage "/tmp/vignette-local-storage")
+    (let [local (create-local-object-storage local-path)
           image-store (create-local-image-storage local "originals" "thumbs")]
       (save-original image-store (io/file "image-samples/ropes.jpg") sample-media-hash) => truthy
       (get-original image-store sample-media-hash) => truthy)))


Updated toolbar examples to reflect the new modifiers

--- src/css-guide/styles/components.cljs
+++ src/css-guide/styles/components.cljs
@@ -539,7 +539,7 @@
          (l/row {}
            (l/col {:width 9 :push 1}

-            (l/row {:density :collapse :valign :bottom :halign :center :className "u-trailer"}
+            (l/row {:density :collapse :className "u-trailer" :valign :bottom :halign :center}
               (l/col {:className "u-column has-xpipe has-start-pipe" :halign :center}
                 (icons/icon :sentiment_very_dissatisfied))
               (l/col {:className "u-column has-xpipe" :halign :center}
@@ -1548,10 +1548,10 @@
   "Fullscreen modal"
   (dom/div #js {:className "c-modal c-modal--fullscreen"}
     (dom/div #js {:className "c-modal__card"}
-      (dom/div #js {:className "o-toolbar o-toolbar--primary o-toolbar--raised"}
+      (dom/div #js {:className "c-toolbar c-toolbar--primary c-toolbar--raised"}
         (dom/button #js {:className "c-button c-button--icon"} (icons/icon :close))
         (dom/div #js {:className "c-modal__title"} "Modal title that is getting way too long")
-        (dom/div #js {:className "o-toolbar__actions"}
+        (dom/div #js {:className "c-toolbar__actions"}
           (dom/button #js {:className "c-button"} "Save")))
       (dom/div #js {:className "has-menu"}
           (dom/button #js {:className "c-button c-button--wide"} "untangler@untangled.io"))
@@ -1586,10 +1586,10 @@

     (dom/div #js {:className "c-modal c-modal--fullscreen"}
      (dom/div #js {:className "c-modal__card"}
-       (dom/div #js {:className "o-toolbar o-toolbar--primary o-toolbar--raised"}
+       (dom/div #js {:className "c-toolbar c-toolbar--primary c-toolbar--raised"}
          (dom/button #js {:className "c-button c-button--icon"} (icons/icon :close))
          (dom/div #js {:className "c-modal__title"} "Modal title that is getting way too long")
-         (dom/div #js {:className "o-toolbar__actions"}
+         (dom/div #js {:className "c-toolbar__actions"}
            (dom/button #js {:className "c-button"} "Save")))
        (dom/div #js {:className "has-menu"}
          (dom/button #js {:className "c-button c-button--wide"} "untangler@untangled.io"))
@@ -1616,30 +1616,19 @@
         lang-item-selected (or (if (= (:id changed-menu) :lang) (:selected-item changed-menu) nil) "English-US")
         menu-action (fn [menu opened item]
                       (om/update-state! this assoc :changed-menu {:id menu :open-state opened :selected-item item}))]
-    (dom/div #js {}
-      (dom/div #js {:className "o-toolbar"}
-        (dom/div #js {:className "o-toolbar__view"}
+    (dom/div #js {:className "c-toolbar" :style #js {:position "static"}}
+      (dom/div #js {:className "c-toolbar__row"}
+        (dom/div #js {:className "c-toolbar__view"}
           (dom/button #js {:className "c-button c-button--icon"}
-            (icons/icon :menu))
-          (dom/span #js {:className "o-toolbar__label"} "View Name"))
-
-        (dom/div #js {:className "o-toolbar__actions"}
-          (dom/div #js {:className "u-wrapper"}
-            (dom/button #js {:className "c-button c-button--icon u-hide@md-up"}
-              (icons/icon :language))
-
-            (dom/button #js {:className "c-button has-menu u-hide@sm"
-                             :onClick   #(menu-action :lang (not lang-menu-open) lang-item-selected)} lang-item-selected)
-            (dom/ul #js {:className lang-menu-class :tabIndex "-1"}
-              (dom/li #js {} (dom/button #js {:className "c-menu__item"
-                                              :onClick   #(menu-action :lang false "English-US")} "English-US"))
-              (dom/li #js {} (dom/button #js {:className "c-menu__item"
-                                              :onClick   #(menu-action :lang false "Español")} "Español"))))
+            (icons/icon :menu)))
+
+        (dom/div #js {:className "c-toolbar__actions"}
+
           (dom/button #js {:className "c-button c-button--icon"} (icons/icon :help))

-          (dom/span #js {:title "Kevin Mitnick"}
-            (dom/button #js {:className "c-button c-button--icon"}
-              (icons/icon :account_circle)))
+          (dom/button #js {:className "c-button c-button--icon"
+                           :title "Kevin Mitnick"}
+            (icons/icon :account_circle))
           )))))

@@ -1653,52 +1642,41 @@
         lang-item-selected (or (if (= (:id changed-menu) :lang) (:selected-item changed-menu) nil) "English-US")
         menu-action (fn [menu opened item]
                       (om/update-state! this assoc :changed-menu {:id menu :open-state opened :selected-item item}))]
-    (dom/div #js {}
-      (dom/div #js {:className "o-toolbar o-toolbar--primary o-toolbar--raised"}
-        (dom/div #js {:className "o-toolbar__view"}
-          (dom/button #js {:className "c-button c-button--icon"}
-            (icons/icon :menu))
-          (dom/span #js {:className "o-toolbar__label"} "Primary color"))
-
-        (dom/div #js {:className "o-toolbar__actions"}
-          (dom/button #js {:className "c-button c-button--icon"}
-            (icons/icon :help))
-
-          (dom/span #js {:title "Kevin Mitnick"}
+    (dom/div nil
+
+      (dom/div #js {:className "c-toolbar c-toolbar--primary c-toolbar--raised" :style #js {:position "static"}}
+        (dom/div #js {:className "c-toolbar__row"}
+          (dom/div #js {:className "c-toolbar__view"}
             (dom/button #js {:className "c-button c-button--icon"}
-              (icons/icon :account_circle)))
-          ))
+              (icons/icon :menu))
+            (dom/span #js {:className "c-toolbar__label"} "Primary toolbar"))
+
+          (dom/div #js {:className "c-toolbar__actions"}
+            (dom/button #js {:className "c-button c-button--icon"}
+              (icons/icon :help))
+
+            (dom/span #js {:title "Kevin Mitnick"}
+              (dom/button #js {:className "c-button c-button--icon"}
+                (icons/icon :account_circle)))
+            )))

       (dom/p nil " ")

-      (dom/div #js {:className "o-toolbar o-toolbar--accent o-toolbar--raised"}
-        (dom/div #js {:className "o-toolbar__view"}
-          (dom/button #js {:className "c-button c-button--icon"}
-            (icons/icon :close))
-          (dom/span #js {:className "o-toolbar__label"} "Accent color"))
-
-        (dom/div #js {:className "o-toolbar__actions"}
-          (dom/span #js {:title "Kevin Mitnick"}
-            (dom/button #js {:className "c-button"}
-              "Save"))
-          ))
-
-      (dom/p nil " ")
-
-      (dom/div #js {:className "o-toolbar o-toolbar--dark o-toolbar--raised"}
-        (dom/div #js {:className "o-toolbar__view"}
-          (dom/button #js {:className "c-button c-button--icon"}
-            (icons/icon :arrow_back))
-          (dom/span #js {:className "o-toolbar__label"} "Dark color"))
-
-        (dom/div #js {:className "o-toolbar__actions"}
-          (dom/button #js {:className "c-button c-button--icon"}
-            (icons/icon :filter_list))
-
-          (dom/span #js {:title "Kevin Mitnick"}
+      (dom/div #js {:className "c-toolbar c-toolbar--dark c-toolbar--raised" :style #js {:position "static"}}
+        (dom/div #js {:className "c-toolbar__row"}
+          (dom/div #js {:className "c-toolbar__view"}
             (dom/button #js {:className "c-button c-button--icon"}
-              (icons/icon :search)))
-          )))))
+              (icons/icon :arrow_back))
+            (dom/span #js {:className "c-toolbar__label"} "Dark toolbar"))
+
+          (dom/div #js {:className "c-toolbar__actions"}
+            (dom/button #js {:className "c-button c-button--icon"}
+              (icons/icon :filter_list))
+
+            (dom/span #js {:title "Kevin Mitnick"}
+              (dom/button #js {:className "c-button c-button--icon"}
+                (icons/icon :search)))
+            ))))))

 (defexample toolbar-dense
   "### Dense
@@ -1709,9 +1687,23 @@
         get-class (fn [item] (str "c-tab " (if (= item selected-item) " is-active" "")))
         select-item (fn [item] (om/update-state! this assoc :selected-item item))
         ]
-    (dom/div #js {}
-      (dom/div #js {:className "o-toolbar o-toolbar--dense u-center"}
-        (dom/ul #js {:className "u-wrapper"}
+      (dom/div #js {:className "c-toolbar c-toolbar--raised c-toolbar--primary u-center" :style #js {:position "static"}}
+        (dom/div #js {:className "c-toolbar__row"}
+          (dom/div #js {:className "c-toolbar__view"}
+            (dom/button #js {:className "c-button c-button--icon"}
+              (icons/icon :menu))
+            (dom/span #js {:className "c-toolbar__label"} "Second row is dense"))
+
+          (dom/div #js {:className "c-toolbar__actions"}
+            (dom/button #js {:className "c-button c-button--icon"}
+              (icons/icon :help))
+
+            (dom/span #js {:title "Kevin Mitnick"}
+              (dom/button #js {:className "c-button c-button--icon"}
+                (icons/icon :account_circle)))
+            ))
+        (dom/div #js {:className "c-toolbar__row c-toolbar__row--dense"}
+        (dom/ul #js {:className "c-tabs"}
           (dom/button #js {:className (get-class :widgets)
                            :onClick   #(select-item :widgets)} "Widgets")
           (dom/button #js {:className (get-class :doodads)
@@ -1720,50 +1712,6 @@
                            :onClick   #(select-item :apparatuses)} "Apparatuses")
           (dom/button #js {:className (get-class :things)
                            :onClick   #(select-item :things)} "Things"))))))
-
-
-(defexample toolbar-secondary
-  "### Secondary Toolbar Example
-
-  The secondary toolbar is intended to only provide operations for the current view of the app your in.
-  "
-  (let [example-class-modifier (str (if (om/get-state this :toolbar-secondary-visible) "" " u-hide"))]
-    (dom/div #js {:className (str "o-toolbar o-toolbar--secondary") :style #js {:position "static"}}
-      ;; View Info for Mobile
-      (dom/div #js {:className "o-toolbar__info u-hide@md-up"}
-        (dom/h1 #js {} "View Name"))
-
-      ;; View Actions for Mobile
-      (dom/div #js {:className "u-column u-hide@md-up u-end"}
-        (dom/button #js {:title "Filter by tag" :className "c-button c-button--icon u-hide@md-up"}
-          (icons/icon :filter_list))
-        (dom/button #js {:title "Search widgets" :className "c-button c-button--icon u-hide@md-up"}
-          (icons/icon :search))
-        (dom/button #js {:title "List view" :className "c-button c-button--icon u-hide@md-up"}
-          (icons/icon :list))
-        (dom/button #js {:title "Create widgets" :className "c-button c-button--icon u-hide@md-up"}
-          (icons/icon :create)))
-
-      ;; View Actions for Tablets and Computers
-      (dom/div #js {:className "u-column--bar u-hide@sm"}
-        (dom/div #js {:className "has-menu"}
-          (dom/button #js {:className "c-button"} "Filter by tag")
-          (dom/ul #js {:id "test-dropdown" :aria-hidden "true" :className "c-menu [is-active]" :tabIndex "-1"}
-            (dom/li #js {}
-              (dom/button #js {:className "c-menu__item"} "Water"))
-            (dom/li #js {}
-              (dom/button #js {:className "c-menu__item"} "Coffee"))
-            (dom/li #js {}
-              (dom/button #js {:className "c-menu__item"} "Tea"))))
-        (dom/div #js {:className "o-input"}
-          (dom/input #js {:type "text" :placeholder "Search your widgets" :autoCapitalize "off" :className "o-input__box" :spellCheck "false" :autoCorrect "off" :autoComplete "off"})
-          (icons/icon :search)))
-      (dom/div #js {:className "u-column--bar u-hide@sm"}
-        (dom/div #js {:className "o-button-group--toggle"}
-          (dom/button #js {:className "c-button c-button--raised c-button--primary"} "List")
-          (dom/button #js {:className "c-button"} "Detail"))
-        (dom/button #js {:className "c-button c-button--accent"} "Create a widget")))))
-

@@ -1961,6 +1909,5 @@
                       toolbar
                       toolbar-colors
                       toolbar-dense
-                      toolbar-secondary
                       ]}
           ])))


don't remove final -e, causes misspellings

--- src/babel/english/morphology.cljc
+++ src/babel/english/morphology.cljc
@@ -393,14 +393,9 @@
          last-stem-char-is-e (re-find #"e$" stem)]
      ;; remove final "e", if any, before adding "e": e.g. "write" => "writing"
      (let [root stem ;; save this since we don't remove final 'e' for "used to" form.
-           stem (if (and last-stem-char-is-e
-                         (> (.length stem) 2) ;; don't apply this to "be".
-                         (not penultimate-stem-char-is-vowel))
-                  stem-minus-one
-                  stem)

            ;; unless overridden by :participle or :participle-suffix below,
-           ;; ing-form or used-to-form (chosen randomly) will be used.
+           ;; ing-form or used-to-form (chosen randomly) will be used: see the (rand-int) below
            ing-form (present-participle-of stem)

            used-to-form


Improve observe docs

Improve observe docs

--- src/yetibot/core/commands/observe.clj
+++ src/yetibot/core/commands/observe.clj
@@ -57,7 +57,7 @@

    Examples:
    1. Generate a meme when appropriate
-   !observe y.+u.+no.* = meme y u no:
+   !observe y.?u.?no = meme y u no:

    2. Lookup the temperature any time someone mentions something that looks like a zip code:
    !observe \\b\\d{5}\\b = \"weather | head 2 | tail\"


Don't show tooltips for non-managed nodes

--- src/net/sekao/nightcode/shortcuts.clj
+++ src/net/sekao/nightcode/shortcuts.clj
@@ -65,27 +65,28 @@
    (doseq [id ids]
      (let [node (.lookup scene (keyword->fx-id id))
            text (get id->key-char id)]
-       (when (and node text (.isManaged node))
+       (when (and node text)
          (add-tooltip! node text))))))

 (defn show-tooltip!
   ([^Stage stage ^Node node]
    (show-tooltip! stage node nil))
   ([^Stage stage ^Node node ^Node relative-node]
-   (when-let [^Tooltip tooltip (.getTooltip node)]
-     (let [node (or relative-node node)
-           point (.localToScene node (double 0) (double 0))
-           scene (.getScene stage)
-           _ (.show tooltip stage (double 0) (double 0))
-           half-width (- (/ (.getWidth node) 2)
-                         (/ (.getWidth tooltip) 4))
-           half-height (- (/ (.getHeight node) 2)
-                          (/ (.getHeight tooltip) 4))]
-       (doto tooltip
-         (.setOpacity 1)
-         (.show stage
-           (double (+ (.getX point) (.getX scene) (-> scene .getWindow .getX) half-width))
-           (double (+ (.getY point) (.getY scene) (-> scene .getWindow .getY) half-height))))))))
+   (when (.isManaged node)
+     (when-let [^Tooltip tooltip (.getTooltip node)]
+       (let [node (or relative-node node)
+             point (.localToScene node (double 0) (double 0))
+             scene (.getScene stage)
+             _ (.show tooltip stage (double 0) (double 0))
+             half-width (- (/ (.getWidth node) 2)
+                           (/ (.getWidth tooltip) 4))
+             half-height (- (/ (.getHeight node) 2)
+                            (/ (.getHeight tooltip) 4))]
+         (doto tooltip
+           (.setOpacity 1)
+           (.show stage
+             (double (+ (.getX point) (.getX scene) (-> scene .getWindow .getX) half-width))
+             (double (+ (.getY point) (.getY scene) (-> scene .getWindow .getY) half-height)))))))))

 (defn show-tooltips! [^Stage stage]
   (let [scene (.getScene stage)]


Remove unused param from create-user-txn args

--- src/braid/core/server/db/user.clj
+++ src/braid/core/server/db/user.clj
@@ -155,7 +155,7 @@
   "given an id and email, creates and returns a user;
   the nickname and avatar are set based on the email;
   the id, email, and resulting nickname must be unique"
-  [{:keys [id email password]}]
+  [{:keys [id email]}]
   {:pre [(not (user-id-exists? id))]}
   (let [new-id (d/tempid :entities)]
     (into


Update comments to describe session handling

--- src/braid/core/server/handler.clj
+++ src/braid/core/server/handler.clj
@@ -18,6 +18,9 @@
   (-> defaults
       (assoc-in [:security :anti-forgery] true)))

+;; Here we define handlers for the various servers and subsets of the routes.  To allow late-binding/run-time configuration, we
+;; intentionally excise some middleware (e.g. session handling) from the ring default middleware configurations, sometimes even excising
+;; such middleware where it might not be included by default.
 (def static-site-defaults
   {:session false
    :params {:urlencoded true


pascal-triangle-triangle simple implementation

--- src/hackerrank/fp/pascal_triangle.clj
+++ src/hackerrank/fp/pascal_triangle.clj
@@ -20,7 +20,7 @@
       (factorial (- n r)))))

 (defn pascal-triangle-triangle [n]
-  [[1]])
+  [(range 1 (inc n))])

 (defn pascal-triangle


Move query into new function.

Move query into new function.

--- src/clj/forma/hadoop/jobs/cdm.clj
+++ src/clj/forma/hadoop/jobs/cdm.clj
@@ -63,10 +63,13 @@
         (identity z :> ?z))))

-(let [source-tap (hfs-seqfile "s3n://formaresults/finaloutput")
-      sink-tap (hfs-delimited
-                "s3n://formaresults/analysis/cdm-map-tile-coordinates.csv"
-                :delimiter ","
-                :outfields ["?x" "?y" "?z" "?p"])]
-  (?- sink-tap
-      (convert-for-vizz {:est-start "2005-12-31"} source-tap 50 "16" "32")))
+(defn forma->cdm
+  "Query that builds up the FORMA data for GFW."
+  []
+  (let [source-tap (hfs-seqfile "s3n://formaresults/finaloutput")
+        sink-tap (hfs-delimited
+                  "s3n://formaresults/analysis/cdm-map-tile-coordinates.csv"
+                  :delimiter ","
+                  :outfields ["?x" "?y" "?z" "?p"])]
+    (?- sink-tap
+        (convert-for-vizz {:est-start "2005-12-31"} source-tap 50 "16" "32"))))


implement Spark Agency

implement Spark Agency

--- src/clj/game/cards-identities.clj
+++ src/clj/game/cards-identities.clj
@@ -213,6 +213,13 @@
                                                 :effect (effect (expose target)) :msg "expose 1 card"}
                                                card nil))}}}

+   "Spark Agency: Worldswide Reach"
+   {:events
+    {:rez {:req (req (has? target :subtype "Advertisement"))
+           {:once :per-turn
+            :effect (effect (lose :runner :credit 1))
+            :msg (msg "make the Runner lose 1 [Credits] by rezzing an advertisement")}}}}
+
    "Tennin Institute: The Secrets Within"
    {:abilities [{:msg "add 1 advancement counter on a card" :choices {:req #(= (first (:zone %)) :servers)}
                  :req (req (not (:successful-run runner-reg))) :once :per-turn


Fix Patch.

Fix Patch.

--- src/clj/game/cards-operations.clj
+++ src/clj/game/cards-operations.clj
@@ -163,7 +163,7 @@

    "Patch"
    {:choices {:req #(and (= (:type %) "ICE") (:rezzed %))}
-    :effect (effect (host target (assoc card :zone [:discard] :seen true))
+    :effect (effect (host target (assoc card :zone [:discard] :seen true :installed true))
                     (update-ice-strength (get-card state target)))
     :events {:pre-ice-strength {:req (req (= (:cid target) (:cid (:host card))))
                                 :effect (effect (ice-strength-bonus 2))}}}


don't hide info

don't hide info

--- src/cljs/apollo/client/pages.cljs
+++ src/cljs/apollo/client/pages.cljs
@@ -101,7 +101,7 @@
                (and (not (nil? active-artist)) (nil? active-album))
                [:span
                 (om/build albums/album-list-partial {:artist active-artist
-                                                     :albums (sort-by (fn [a] (a "year")) (map (fn [x] (assoc x "year" (first (split (x "year") "-")))) albums))})
+                                                     :albums (sort-by (fn [a] (first (split (a "year") "-"))) albums)})
                 (om/build artists/artist-info-partial info)]
                (not (nil? active-album))
                (om/build albums/album-detail {:artist active-artist :album active-album}))]]]])))))


Fixed translation

Fixed translation

--- src/cljs/salava/user/ui/data.cljs
+++ src/cljs/salava/user/ui/data.cljs
@@ -186,7 +186,7 @@
            [:h2 {:class "uppercase-header"} (str (t :user/Socialconnections) ": ") (+ (count user_followers) (count user_following))]
            (if (not-empty user_followers)
              [:div
-              [:h3 (str (t :social/Followesrusers) ": ")]
+              [:h3 (str (t :social/Followersusers) ": ")]
               (for [follower user_followers
                     :let [id (:owner_id follower)
                           fname (:first_name follower)


move refactoring

move refactoring

--- src/cljs/triboard/logic/move.cljs
+++ src/cljs/triboard/logic/move.cljs
@@ -108,8 +108,13 @@
 ;; (def b (first (gen/sample (s/gen ::board/board) 1)))

 (defn group-by-reducer
-  [keys]
-  #(update-in %1 ((apply juxt keys) %2) conj %2))
+  [& key-fns]
+  (fn
+    ([] {})
+    ([result] result)
+    ([result val]
+      (let [keys ((apply juxt key-fns) val)]
+        (update-in result keys conj val)))))

 (defn map-values
   "Apply a function to the values of a key-value collection"
@@ -126,7 +131,7 @@

     (transduce
       (mapcat #(available-conversions-at board %))          ;; TODO - Cut that in two? (moves vs transitions)
-      (group-by-reducer [:winner :point])                   ;; TODO - it creates nil...
+      (group-by-reducer :winner :point)
       (board/empty-cells board))
     ))


shop specs product variants WIP

shop specs product variants WIP

--- src/clojure/nossal/shop/spec.cljc
+++ src/clojure/nossal/shop/spec.cljc
@@ -23,7 +23,15 @@
 (s/def ::images (s/coll-of uri? :kind vector? :distinct true :into []))
 (s/def ::characteristics (s/and
                            (s/map-of ::name ::description)
-                           #(instance? PersistentTreeMap %)))
+                           #(instance? PersistentTreeMap %)
+
+(s/def ::variant (s/keys :req [::id
+                               ::name
+                               ::price
+                               ::stock-count
+                               ::available?
+                               ::images]))
+(s/def ::variants (s/coll-of ::variant :kind vector? :distinct true :into []))

 (s/def ::product (s/keys :req-un [::id
                                   ::market-price
@@ -34,7 +42,8 @@
                                   ::images
                                   ::category
                                   ::stock-count
-                                  ::available?]))
+                                  ::available?]
+                         :opt-un [::variants]))
 (s/def ::products (s/and
                     (s/map-of ::id ::product)
                     #(instance? PersistentTreeMap %)))


Fix require-macros form

Fix require-macros form

--- src/com/wsscode/common/async.cljc
+++ src/com/wsscode/common/async.cljc
@@ -1,5 +1,5 @@
 (ns com.wsscode.common.async
-  #?(:cljs (require-macros [com.wsscode.common.async]))
+  #?(:cljs (:require-macros [com.wsscode.common.async]))
   (:require [clojure.core.async :as async]
             [clojure.core.async.impl.protocols :as async.prot]))


Fixed operator process crash

Fixed operator process crash

Signed-off-by: trauf <b8cc4d695074a5c55e7046612ecaa2660307ac88@plumgrid.com>

--- plugins/process_crash_relaunch.clj
+++ plugins/process_crash_relaunch.clj
@@ -245,7 +245,7 @@
         )
       )

-    (process-state-ek1-mk2val
+   (process-state-ek1-mk2val
       2016 [2015] e
       ; system_manager_4d1f1bb1 [5cc63441:2139:9]<013:04:48:56.859552>[143]: [process_child_exit]: pid 22877 done
       #"\[process_child_exit\]: pid (\d+) done"
@@ -256,12 +256,26 @@
         (do
           ; Process ‘bridge’ (pgname 'bridge_a615e671',ip_pid '10.22.27.26:23069' domain 'Demo' vnf_name '/0/connectivity/domain/Demo/ne/Bridge' ) exited with reason WIFSIGNALED and got relaunched successfully with ip_pid: 10.22.27.26:23807
           ; TODO: If demo & vnf_name is empty then it is operator message.
-          (def concise-msg (apply str (now) ": Process '" (:exited_service strm) "' (pgname '" (:pgname strm)
-                             "', ip_pid '" (:ip_where_proc_exit strm) ":" (:pid_of_exited_proc strm) "' domain '"
-                             (:domain_name strm) "' vnf_name '" (:vnf_name strm) "') exited with reason " (:exit_type strm)
-                             " and got relaunched successfully with ip_pid '" (:new_ip_pid strm) "'. The recovery took "
-                             (get-time-taken (:startTime strm) (:time strm)) " seconds"
-                             )
+          (let [exited-process (:exited_service strm)]
+            (if (or (= exited-process "rest_gateway") (= exited-process "cdb") (= exited-process "health_monitor")
+                    (= exited-process "tenant_manager") (= exited-process "analytics_manager")
+                    (= exited-process "CM") (= exited-process "vmw_agent") (= exited-process "metadata")
+                    (= exited-process "pem_master"))
+              (def concise-msg (apply str (now) ": Process '" (:exited_service strm) "' (pgname '" (:pgname strm)
+                                 "', ip_pid '" (:ip_where_proc_exit strm) ":" (:pid_of_exited_proc strm)
+                                 "') exited with reason " (:exit_type strm)
+                                 " and got relaunched successfully with ip_pid '" (:new_ip_pid strm) "'. The recovery took "
+                                 (get-time-taken (:startTime strm) (:time strm)) " seconds"
+                                 )
+                )
+              (def concise-msg (apply str (now) ": Process '" (:exited_service strm) "' (pgname '" (:pgname strm)
+                                 "', ip_pid '" (:ip_where_proc_exit strm) ":" (:pid_of_exited_proc strm) "' domain '"
+                                 (:domain_name strm) "' vnf_name '" (:vnf_name strm) "') exited with reason " (:exit_type strm)
+                                 " and got relaunched successfully with ip_pid '" (:new_ip_pid strm) "'. The recovery took "
+                                 (get-time-taken (:startTime strm) (:time strm)) " seconds"
+                                 )
+                )
+              )
             )
           )
         (def raw-status (:raw_status strm))


Fix bad ctia.entity.investigation merge

Fix bad ctia.entity.investigation merge

--- src/ctia/entity/investigation.clj
+++ src/ctia/entity/investigation.clj
@@ -1,24 +1,60 @@
 (ns ctia.entity.investigation
-  (:require
-   [ctia.http.routes
-    [common :refer [BaseEntityFilterParams
-                    PagingParams
-                    SourcableEntityFilterParams]]
-    [crud :refer [entity-crud-routes]]]
-   [ctia.stores.es
-    [mapping :as em]
-    [store :refer [def-es-store]]]
-   [ctia.entity.investigation.schemas
-    :refer [Investigation
-            PartialInvestigation
-            PartialStoredInvestigation
-            NewInvestigation
-            StoredInvestigation
-            PartialInvestigationList
-            realize-investigation]]
-   [schema-tools.core :as st]
-   [schema.core :as s]
-   [ctia.schemas.sorting :as sorting]))
+  (:require [ctia.domain.entities :refer [default-realize-fn]]
+            [ctia.store :refer :all]
+            [ctia.http.routes
+             [common :refer [BaseEntityFilterParams PagingParams SourcableEntityFilterParams]]
+             [crud :refer [entity-crud-routes]]]
+            [ctia.schemas
+             [utils :as csu]
+             [core :refer [def-stored-schema
+                           CTIAEntity]]
+             [sorting :as sorting]]
+            [ctia.schemas.graphql
+             [sorting :as graphql-sorting]
+             [flanders :as flanders]
+             [helpers :as g]
+             [pagination :as pagination]]
+            [ctia.stores.es
+             [mapping :as em]
+             [store :refer [def-es-store]]]
+            [ctim.schemas.investigation :as inv]
+            [flanders
+             [schema :as f-schema]
+             [spec :as f-spec]
+             [utils :as fu]]
+            [schema-tools.core :as st]
+            [schema.core :as s]
+            [ctia.schemas.graphql.ownership :as go]))
+
+(s/defschema Investigation
+  (st/merge (f-schema/->schema inv/Investigation)
+            CTIAEntity
+            {s/Keyword s/Any}))
+
+(f-spec/->spec inv/Investigation "investigation")
+
+(s/defschema PartialInvestigation
+  (st/merge (f-schema/->schema (fu/optionalize-all inv/Investigation))
+            CTIAEntity
+            {s/Keyword s/Any}))
+
+(s/defschema PartialInvestigationList
+  [PartialInvestigation])
+
+(s/defschema NewInvestigation
+  (st/merge (f-schema/->schema inv/NewInvestigation)
+            CTIAEntity
+            {s/Keyword s/Any}))
+
+(f-spec/->spec inv/NewInvestigation "new-investigation")
+
+(def-stored-schema StoredInvestigation Investigation)
+
+(s/defschema PartialStoredInvestigation
+  (csu/optional-keys-schema StoredInvestigation))
+
+(def realize-investigation
+  (default-realize-fn "investigation" NewInvestigation StoredInvestigation))

 (def snapshot-action-fields-mapping
   {:object_ids em/token


Update template dependencies

Update template dependencies

Fixes #84.

--- src/leiningen/new/re_frame/project.clj
+++ src/leiningen/new/re_frame/project.clj
@@ -1,8 +1,8 @@
 (defproject {{ns-name}} "0.1.0-SNAPSHOT"
-  :dependencies [[org.clojure/clojure "1.8.0"]
-                 [org.clojure/clojurescript "1.10.238"]
-                 [reagent "0.7.0"]
-                 [re-frame "0.10.5"]{{#re-com?}}
+  :dependencies [[org.clojure/clojure "1.10.0"]
+                 [org.clojure/clojurescript "1.10.520"]
+                 [reagent "0.8.1"]
+                 [re-frame "0.10.6"]{{#re-com?}}
                  [com.andrewmcveigh/cljs-time "0.5.2"]
                  [org.clojure/core.async "0.2.391"]
                  [re-com "2.1.0"]{{/re-com?}}{{#routes?}}
@@ -46,13 +46,13 @@
   :profiles
   {:dev
    {:dependencies [[binaryage/devtools "0.9.10"]{{#10x?}}
-                   [day8.re-frame/re-frame-10x "0.3.3"]
+                   [day8.re-frame/re-frame-10x "0.3.7-react16"]
                    [day8.re-frame/tracing "0.5.1"]{{/10x?}}{{#cider?}}
                    [figwheel-sidecar "0.5.16"]
                    [cider/piggieback "0.3.5"]{{/cider?}}{{#re-frisk?}}
-                   [re-frisk "0.5.3"]{{/re-frisk?}}]
+                   [re-frisk "0.5.4"]{{/re-frisk?}}]

-    :plugins      [[lein-figwheel "0.5.16"]{{#test?}}
+    :plugins      [[lein-figwheel "0.5.18"]{{#test?}}
                    [lein-doo "0.1.8"]{{/test?}}]}
    :prod { {{#10x?}}:dependencies [[day8.re-frame/tracing-stubs "0.5.1"]]{{/10x?}}}{{#handler?}}
    :uberjar {:source-paths ["env/prod/clj"]{{#10x?}}


It's comp, not conj dammit.

It's comp, not conj dammit.

--- src/hphelper/server/live/control.clj
+++ src/hphelper/server/live/control.clj
@@ -295,7 +295,7 @@
                       )]
     (log/trace "send-access-inner. newAccess:" newAccess)
     (-> g
-        (update-in [:access] (conj (partial take 20) (partial cons newAccess)))
+        (update-in [:access] (comp (partial take 20) (partial cons newAccess)))
         (assoc-in [:updated :access] (current-time))
         )
     )


Localize the action bar tabs

Localize the action bar tabs

--- desktop/src/nightweb_desktop/views.clj
+++ desktop/src/nightweb_desktop/views.clj
@@ -9,9 +9,9 @@

 (defn get-tab-view
   [params show-me-tab?]
-  (for [button [{:type nil :title "Me"}
-                {:type :user :title "Users"}
-                {:type :post :title "Posts"}]]
+  (for [button [{:type nil :title (utils/get-string :me)}
+                {:type :user :title (utils/get-string :users)}
+                {:type :post :title (utils/get-string :posts)}]]
     (when (or show-me-tab? (not= nil (:type button)))
       (let [active-tab (or (:subtype params) (:type params))]
         [:li {:class (when (= active-tab (:type button)) "active")}


open and close door repeatedly

open and close door repeatedly

--- examples/tilemap/src/tilemap/core.cljs
+++ examples/tilemap/src/tilemap/core.cljs
@@ -113,9 +113,29 @@
     ;; load resource url with tile sheet
     (<! (r/load-resources canvas :ui ["img/tiles.png"]))

-    (let [tile-set (tm/make-tile-set :tiles tile-set-mapping [16 16])]
+    (let [tile-set (tm/make-tile-set :tiles tile-set-mapping [16 16])
+          tile-sprites (->> tile-map-chars
+                            (tm/make-tile-map key-for)
+                            (tm/make-tile-sprites tile-set)
+                            )]
       (log "tile-set:" tile-set)
+      (log "tile-sprites:" tile-sprites)
       (m/with-sprite :tilemap
-        [tile-map (tm/make-tilemap tile-set key-for tile-map-chars
-                                   :scale 4)]
-        (<! (e/wait-frames 10000))))))
+        [tile-map (tm/make-tilemap tile-sprites
+                                   :scale 4
+                                   :particle-opts #{:uvs})]
+
+        (while true
+          ;; closed
+          (<! (e/wait-frames 120))
+          (tm/alter-tile! tile-sprites [0 2] tile-set :door-left-shut-1)
+          (tm/alter-tile! tile-sprites [1 2] tile-set :door-left-shut-2)
+          (tm/alter-tile! tile-sprites [0 3] tile-set :door-left-shut-3)
+          (tm/alter-tile! tile-sprites [1 3] tile-set :door-left-shut-4)
+
+          ;; open
+          (<! (e/wait-frames 120))
+          (tm/alter-tile! tile-sprites [0 2] tile-set :door-left-1)
+          (tm/alter-tile! tile-sprites [1 2] tile-set :door-left-2)
+          (tm/alter-tile! tile-sprites [0 3] tile-set :door-left-3)
+          (tm/alter-tile! tile-sprites [1 3] tile-set :door-left-4))))))


SearchResource: support ATOM

SearchResource: support ATOM

--- src/org/altlaw/www/SearchResource.clj
+++ src/org/altlaw/www/SearchResource.clj
@@ -1,5 +1,7 @@
 (ns org.altlaw.www.SearchResource
   (:require [org.altlaw.www.render :as tmpl]
+            [org.altlaw.www.references :as r]
+            [org.altlaw.www.pagination :as p]
             [org.altlaw.util.date :as date]
             [org.altlaw.util.courts :as courts]
             [org.altlaw.util.context :as context]
@@ -22,9 +24,6 @@

 (defn log [this & args]
   (.. this getContext getLogger (info (apply str args))))
-
-
-;;; PAGE NUMBERING

 ;;; RENDERING RESULTS
@@ -59,13 +58,11 @@
      :hits (map (partial prepare-hit (.getHighlighting solr-response))
                 docs)}))

-(defn html-results [ref data]
-  (let [params (.. ref getQueryAsForm getValuesMap)
-        current-page (Integer/parseInt (or (get params "page") "1"))
-        pagination (when (> (:total_hits data) *page-size*)
-                     (pagination-html ref current-page (:total_hits data)))]
-    (tmpl/render "search/html_results"
-                 (assoc data :pagination pagination))))
+(defn get-current-page [ref]
+  (let [params (.. ref getQueryAsForm getValuesMap)]
+    (if-let [p (get params "page")]
+      (Integer/parseInt p)
+      1)))

 (defn order-for-display [sort]
   (cond
@@ -75,22 +72,66 @@

 (defn make-sortlinks [ref sort]
   (cond
-   (= sort "score desc") [{:url (sort-ref ref "date") :name "Sort by date"}]
-   (= sort "date desc") [{:url (sort-ref ref "relevance") :name "Sort by relevance"}]))
+   (= sort "score desc") [{:url (r/sort-ref ref "date") :name "Sort by date"}]
+   (= sort "date desc") [{:url (r/sort-ref ref "relevance") :name "Sort by relevance"}]))
+
+(defn prepare-atom-result-url [ref data]
+  (assoc data :atom_results_url
+         (tmpl/h (-> ref
+                     (r/page-ref 1)
+                     (r/format-ref "atom")
+                     (r/sort-ref "date")))))
+
+(defn prepare-html-template [ref data]
+  (let [data (prepare-atom-result-url ref data)]
+    ;; Do not display "relevance" sort link when using 'all' query
+    (if (= (:query data) "docid:[* TO *]")
+      data
+      (assoc data
+        :order (order-for-display (:sort data))
+        :sortlinks (make-sortlinks ref (:sort data))))))
+
+(defn html-results [ref data]
+  (let [data (prepare-html-template ref data)
+        current-page (get-current-page ref)
+        pagination (when (> (:total_hits data) p/*page-size*)
+                     (p/pagination-html ref current-page (:total_hits data)))]
+    (tmpl/render "search/html_results"
+                 (assoc data :pagination pagination
+                        :current_page current-page))))

 (defmulti render-results (fn [this variant data] (.getMediaType variant)))

 (defmethod render-results MediaType/TEXT_HTML [this variant data]
-  (let [ref (.. this getRequest getOriginalRef)
-        ;; Do not display "relevance" sort link when using 'all' query
-        data (if (= (:query data) "docid:[* TO *]")
-               data
-               (assoc data
-                 :order (order-for-display (:sort data))
-                 :sortlinks (make-sortlinks ref (:sort data))))]
+  (let [ref (.. this getRequest getOriginalRef)]
     (StringRepresentation.
      (html-results ref data)
      MediaType/TEXT_HTML
+     Language/ENGLISH_US
+     CharacterSet/UTF_8)))
+
+(defmethod render-results MediaType/APPLICATION_ATOM_XML [this variant data]
+  (let [ref (.. this getRequest getOriginalRef)
+        atom-ref (r/format-ref ref "atom")
+        current-page (get-current-page ref)
+        last-page (p/calc-last-page (:total_hits data) p/*page-size*)
+        next-page (when (< current-page last-page) (inc current-page))
+        prev-page (when (> current-page 1) (dec current-page))
+        data (assoc data
+               :order (order-for-display (:sort data))
+               :timestamp (DateUtils/timestamp)
+               :current_page current-page
+               :page_size p/*page-size*
+               :html_results_url (tmpl/h ref)
+               :atom_results_url (tmpl/h atom-ref)
+               :atom_first_page_url (tmpl/h (r/page-ref atom-ref 1))
+               :atom_last_page_url (tmpl/h (r/page-ref atom-ref last-page))
+               :atom_prev_page_url (when prev-page (tmpl/h (r/page-ref atom-ref prev-page)))
+               :atom_next_page_url (when next-page (tmpl/h (r/page-ref atom-ref next-page)))
+               :atom_id (str "urn:uuid:" (java.util.UUID/randomUUID)))]
+    (StringRepresentation.
+     (tmpl/render "search/atom_results" data)
+     MediaType/APPLICATION_ATOM_XML
      Language/ENGLISH_US
      CharacterSet/UTF_8)))

@@ -130,7 +171,7 @@
                    (print "</pre>"))
                  (.getMessage (stacktrace/root-cause (:exception data))))))

-(defn render-exception MediaType/TEXT_HTML [this variant data]
+(defn render-exception [this variant data]
   (StringRepresentation.
    (html-exception data)
    MediaType/TEXT_HTML
@@ -144,13 +185,11 @@
      (into-array ["doctype" "docid" "name" "citations"
                   "date" "court" "size"]))

-
-
 (defn apply-page-options [this solr-query]
   (let [params (get-query-params this)
         page (if-let [p (.get params "page")]
                (Integer/parseInt p) 1)]
-    (.setStart solr-query (* *page-size* (dec page)))))
+    (.setStart solr-query (* p/*page-size* (dec page)))))

 (defn execute-search [this solr-query]
   (let [solr (.. this getContext getAttributes (get "org.altlaw.solr.server"))]


Increase mixpanel timeout for external links from 1 second to 5

--- src-cljs/frontend/controllers/controls.cljs
+++ src-cljs/frontend/controllers/controls.cljs
@@ -997,10 +997,9 @@
   [target message {:keys [path event properties]} previous-state current-state]
   (let [redirect #(js/window.location.replace path)]
     (go (alt!
-         (analytics/managed-track event properties)
-         ([v] (do (utils/mlog "tracked" v "... redirecting")
-                (redirect)))
-         (async/timeout 1000) (redirect)))))
+          (analytics/managed-track event properties) ([v] (do (utils/mlog "tracked" v "... redirecting")
+                                                              (redirect)))
+          (async/timeout 5000) (redirect)))))

 (defmethod control-event :language-testimonial-tab-selected
   [target message {:keys [index]} state]


As we only rely on the new approach for the DSL there is no need for resolving keywords.

--- src/dsbdp/data_processing_dsl.clj
+++ src/dsbdp/data_processing_dsl.clj
@@ -20,17 +20,15 @@
       (reduce
         (fn [v data-proc-def-element]
           (cond
-            (or
-              (keyword? data-proc-def-element)
-              (symbol? data-proc-def-element)) (let [s (symbol (name data-proc-def-element))]
-                                                 (condp not= nil
-                                                   (ns-resolve 'clojure.core s)
-                                                     (conj v (ns-resolve 'clojure.core s))
-                                                   (ns-resolve 'dsbdp.byte-array-conversion s)
-                                                     (conj v (ns-resolve 'dsbdp.byte-array-conversion s) 'input)
-                                                   (do
-                                                     (println "Could not resolve keyword/symbol:" s)
-                                                      v)))
+            (symbol? data-proc-def-element) (let [s data-proc-def-element]
+                                               (condp not= nil
+                                                 (ns-resolve 'clojure.core s)
+                                                   (conj v (ns-resolve 'clojure.core s))
+                                                 (ns-resolve 'dsbdp.byte-array-conversion s)
+                                                   (conj v (ns-resolve 'dsbdp.byte-array-conversion s) 'input)
+                                                 (do
+                                                   (println "Could not resolve keyword/symbol:" s)
+                                                    v)))
             (list? data-proc-def-element) (conj v (into '() (reverse (create-data-processing-sub-fn data-proc-def-element input offset))))
             :default (conj v data-proc-def-element)))
         [] data-processing-definition))))


add statement tracing to session config

add statement tracing to session config

--- src/er_cassandra/session/alia.clj
+++ src/er_cassandra/session/alia.clj
@@ -1,7 +1,7 @@
 (ns er-cassandra.session.alia
   (:require
    [plumbing.core :refer :all]
-   [taoensso.timbre :refer [trace debug info warn error]]
+   [taoensso.timbre :refer [log trace debug info warn error]]
    [environ.core :refer [env]]
    [clojure.string :as str]
    [qbits.alia :as alia]
@@ -18,28 +18,29 @@
     SpySession
     KeyspaceProvider]))

-(def ^:dynamic *trace* nil)
-
-(defmacro with-debug
-  [& forms]
-  `(binding [*trace* true]
-     ~@forms))
-
 (defn- execute*
-  [alia-session statement opts]
+  [alia-session
+   statement
+   {trace? :trace?
+    :as  opts}]
   (aliam/execute
    alia-session
    (let [str-statement (if (string? statement)
                          statement
                          (h/->raw statement))]
-     (when *trace*
-       (debug str-statement))
+     (when trace?
+       (if (true? trace?)
+         (debug str-statement)
+         (log trace? str-statement)))
      str-statement)
-   opts))
+   (dissoc opts :trace?)))

 (defn- execute-buffered*
   "execute a statement returning a Deferred<Stream<record>>"
-  [alia-session statement opts]
+  [alia-session
+   statement
+   {trace? :trace?
+    :as  opts}]
   (return
    deferred-context
    (aliam/execute-buffered
@@ -47,10 +48,12 @@
     (let [str-statement (if (string? statement)
                           statement
                           (h/->raw statement))]
-      (when *trace*
-        (debug str-statement))
+      (when trace?
+        (if (true? trace?)
+          (debug str-statement)
+          (log trace? str-statement)))
       str-statement)
-    opts)))
+    (dissoc opts :trace?))))

 (defn shutdown-session-and-cluster
   [session]
@@ -91,26 +94,29 @@
              _ (alia/execute alia-session (str "USE " keyspace ";"))]
         (return alia-session)))))

-(defrecord AliaSession [keyspace alia-session]
+(defrecord AliaSession [keyspace alia-session trace?]
   Session
   (execute [_ statement]
     (execute* alia-session statement {}))
   (execute [_ statement opts]
-    (execute* alia-session statement opts))
+    (execute* alia-session statement (assoc opts :trace? trace?)))
   (execute-buffered [_ statement]
     (execute-buffered* alia-session statement {}))
   (execute-buffered [_ statement opts]
-    (execute-buffered* alia-session statement opts))
+    (execute-buffered* alia-session statement (opts :trace? trace?)))
   (close [_]
     (shutdown-session-and-cluster alia-session)))

 (defnk create-session
-  [contact-points datacenter keyspace :as args]
+  [contact-points datacenter keyspace {trace? false}:as args]
   (with-context deferred-context
-    (mlet [datastax-session (create-alia-session* args)
-           :let [alia-session (->AliaSession
-                               keyspace
-                               datastax-session)]]
+    (mlet
+      [datastax-session (create-alia-session*
+                         (dissoc args :trace?))
+       :let [alia-session (map->AliaSession
+                           {:keyspace keyspace
+                            :alia-session datastax-session
+                            :trace? trace?})]]
       (return
        [alia-session
         (fn [] (s/close alia-session))]))))
@@ -158,18 +164,22 @@
         (s/reset-spy-log spy-session)
         (return true)))))

-(defrecord AliaSpySession [keyspace alia-session spy-log-atom truncate-on-close]
+(defrecord AliaSpySession [keyspace
+                           alia-session
+                           spy-log-atom
+                           truncate-on-close
+                           trace?]
   Session
   (execute [this statement]
     (s/execute this statement {}))
   (execute [_ statement opts]
     (swap! spy-log-atom conj statement)
-    (execute* alia-session statement opts))
+    (execute* alia-session statement (assoc opts :trace? trace?)))
   (execute-buffered [this statement]
     (s/execute-buffered this statement {}))
   (execute-buffered [_ statement opts]
     (swap! spy-log-atom conj statement)
-    (execute-buffered* alia-session statement opts))
+    (execute-buffered* alia-session statement (assoc opts :trace? trace?)))
   (close [self]
     (with-context deferred-context
       (mlet [_ (if truncate-on-close
@@ -185,14 +195,23 @@
   (reset-spy-log [_] (reset! spy-log-atom [])))

 (defnk create-spy-session
-  [contact-points datacenter keyspace {truncate-on-close nil} :as args]
+  [contact-points
+   datacenter
+   keyspace
+   {truncate-on-close nil}
+   {trace? nil}
+   :as args]
   (with-context deferred-context
-    (mlet [datastax-session (create-alia-session* (dissoc args :truncate-on-close))
-           :let [spy-session (->AliaSpySession
-                              keyspace
-                              datastax-session
-                              (atom [])
-                              truncate-on-close)]]
+    (mlet [datastax-session (create-alia-session*
+                             (dissoc args
+                                     :truncate-on-close
+                                     :trace?))
+           :let [spy-session (map->AliaSpySession
+                              {:keyspace keyspace
+                               :alia-session datastax-session
+                               :spy-log-atom (atom [])
+                               :truncate-on-close truncate-on-close
+                               :trace? trace?})]]
       (return
        [spy-session
         (fn [] (s/close spy-session))]))))
@@ -200,7 +219,13 @@
 ;; a test-session is just a spy-session which will initialise it's keyspace
 ;; if necesary and will truncate any used tables when closed
 (defnk create-test-session
-  [{contact-points nil} {port nil} {datacenter nil} {truncate-on-close nil} keyspace :as args]
+  [{contact-points nil}
+   {port nil}
+   {datacenter nil}
+   {truncate-on-close nil}
+   keyspace
+   {trace? nil}
+   :as args]
   (create-spy-session
    (merge
     args
@@ -225,4 +250,5 @@

      :truncate-on-close (if (nil? truncate-on-close)
                           true
-                          truncate-on-close)})))
+                          truncate-on-close)
+     :trace? trace?})))


terminal-reader now sends interpreter input to the human player i.e. input-receiver

Signed-off-by: Stefan Marr <46f1a0bd5592a2f9244ca321b129902a06b53e03@stefan-marr.de>

--- Clojure/src/snake/terminal_reader.clj
+++ Clojure/src/snake/terminal_reader.clj
@@ -1,4 +1,5 @@
-(ns snake.terminal-reader)
+(ns snake.terminal-reader
+  (:use snake.input-receiver))

 (defn get-input
   "Reads a string from the given input-reader if there is anything to be read"
@@ -20,19 +21,15 @@
   [input-receiver input-reader]
   (loop [data (get-input input-reader)]
     (case data
-      "\u001B[A" ;(send input-receiver move 'up)
-              (do
-                (print "UP")
-                (flush))
-              ; (recur [data (read)])
-
-      "\u001B[B" (print "DOWN")
-      "\u001B[D" (print "LEFT")
-      "\u001B[C" (print "RIGHT")
+      "\u001B[A" (send input-receiver input-direction :up   )
+      "\u001B[B" (send input-receiver input-direction :down )
+      "\u001B[D" (send input-receiver input-direction :left )
+      "\u001B[C" (send input-receiver input-direction :right)
       :nothing)
+    (. Thread sleep 80)  ;; necessary since get-input is non-blocking
     (recur (get-input input-reader))))

-(defn start
+(defn start-terminal-reader
   "Starts a new thread that is reading from standard in and will
    notify an agent about all read input."
   [input-receiver]


support of bitcoin core 0.16.0, not tested!!

--- src/bitcoinrpc/core.clj
+++ src/bitcoinrpc/core.clj
@@ -172,6 +172,24 @@
    'txid_txid-vout_n-map-list :list
    'n :long
    'true-false :boolean
+   'iswitness :boolean
+   'exclude :boolean
+   'include_removed :boolean
+   'replaceable :boolean
+   'oldpassphrase :string
+   'newpassphrase :string
+   'verbosity :long
+   'conf_target :long
+   'timeout :long
+   'start_height :long
+   'stop_height :long
+   'estimate_mode :string
+   'include :list
+   'hexstring-list :list ;what is this?
+   'address_type :string
+   'mode :string
+   'dummy :object
+   'dummy-value :object
    })

@@ -377,7 +395,7 @@

 ;;the parser can't handle these RPC function yet.
-(def not-working #{"createrawtransaction" "listunspent" "sendmany"})
+(def not-working #{"createrawtransaction" "listunspent" "sendmany" "disconnectnode"})
 ;define them hardcoded
 (def-rpc-opt createrawtransaction 2 txids addresses locktime)
 (def-rpc-opt listunspent 0 minconf maxconf  addresses include_unsafe)


Old Page Warning

Old Page Warning

Added old page warning to screencasts and articles
Revised text to not wrap on large screens

--- src/briefcase/views.clj
+++ src/briefcase/views.clj
@@ -59,8 +59,7 @@
   (when (before? (from-date (:date data)) six-months-ago)
     (hiccup.core/html
       [:blockquote.warning "This post is over 6 months old.
-      	Some details, especially technical, may have changed
-      	since posting."])))
+      	Some details, especially technical, may have changed."])))

 (defn index
   "Renders the landing page of the site"
@@ -68,11 +67,11 @@
   (main-layout request "yobriefca.se"
                (md/to-html (slurp "resources/content/index.md"))))

-
 (defn article
   "Renders an article"
   [request data]
   (main-layout request (:title data)
+               (old-entry-warning data)
                [:h1 (:title data)]
                [:div.post (:html data)]
                (footer data)))


Main should call run

Main should call run

--- src/puppetlabs/trapperkeeper/core.clj
+++ src/puppetlabs/trapperkeeper/core.clj
@@ -305,15 +305,6 @@
         required    [:config]]
     (first (cli! cli-args specs required))))

-(defn main
-  [& args]
-  (try+
-    (-> args
-        (parse-cli-args!)
-        (bootstrap))
-    (catch map? {:keys [error-message]}
-      (println error-message))))
-
 (defn run
   "TODO docstring"
   [^TrapperKeeperApp app]
@@ -322,3 +313,13 @@
       (shutdown!)
       (when-let [error (:error shutdown-reason)]
         (throw error)))))
+
+(defn main
+  [& args]
+  (try+
+    (-> args
+        (parse-cli-args!)
+        (bootstrap)
+        (run))
+    (catch map? {:keys [error-message]}
+      (println error-message))))


removing space

removing space

--- src/celestial/redis.clj
+++ src/celestial/redis.clj
@@ -67,4 +67,3 @@

 (defn clear-all []
   (wcar (car/flushdb)))
-


fixing admin role

fixing admin role

--- src/celestial/roles.clj
+++ src/celestial/roles.clj
@@ -11,5 +11,5 @@

 (def user #{::user})

-(def admin #{::user})
+(def admin #{::admin})


simplify: remove unneeded :fail-removal

simplify: remove unneeded :fail-removal

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -96,7 +96,8 @@
                        :paths paths
                        :trellis each-path-through-trellis})
                     (lazy-seq (apply combo/cartesian-product comps)))))
-     ;; 5. ...
+
+     ;; 5. TODO: explain what this step is doing.
      (map (fn [{bolt :bolt paths :paths trellis :trellis}]
             (cons bolt
                   ;; TODO: further flatten this into the overall ->> pipeline
@@ -104,29 +105,23 @@
                          (assoc-in {} path trellis))
                        (zipmap paths trellis)))))

-     ;; 6. Remove fails. (TODO: consider whether this can be removed)
-     (remove (fn [tree-parts]
-               (some #(= :fail %) tree-parts)))
-
-     ;; 7. Combine each set of tree parts into a tree.
+     ;; 6. Combine each set of tree parts into a tree.
      (map (fn [tree-parts]
             (reduce (fn [a b]
                       (unify-and-log a b model))
                     tree-parts)))

-     ;; 8. Remove fails again. (TODO: consider whether this can be removed)
-     (remove #(= :fail %))
-
-     ;; 9. Apply model's defaults, if any, to each tree.
+     ;; 7. Apply model's defaults, if any, to each tree.
      (map #(do-defaults % model))

-     ;; 10. If desired, truncate trees to just a root node with no children, for efficiency of future processing.
+     ;; 8. If desired, truncate trees to just a root node with no children, for efficiency of future processing.
      (map #(if (= true truncate)
              (dag_unify.core/strip-refs (dissoc-paths % [[:head][:comp]]))
              %))

-     ;; 11. Remove fails once more. (TODO: consider whether this can be removed)
-     (remove #(= :fail %)))))
+     ;; 11. Remove fails.
+     (remove #(= :fail %))
+     )))

 (def expensive-logging false)


transitivize-verb-rule should not transform lexeme if :transitivize=false

--- src/babel/lexiconfn.clj
+++ src/babel/lexiconfn.clj
@@ -580,6 +580,7 @@

 (defn transitive-verb-rule [lexical-entry]
   (cond (and (= (get-in lexical-entry [:synsem :cat]) :verb)
+             (not (= false (get-in lexical-entry [:transitivize])))
              (not (nil? (get-in lexical-entry [:synsem :sem :obj])))
              (not (= (get-in lexical-entry [:synsem :sem :obj]) :unspec))


[scamp] use 'networked-node->node-contact-address instead of 'get-in

--- modules/scamp/src/scamp/core.clj
+++ modules/scamp/src/scamp/core.clj
@@ -167,7 +167,8 @@

 (s/defn node->removed :- NetworkedNodeSchema
   [node :- NetworkedNodeSchema]
-  (-> (get-in node [:self :id])
+  (-> node
+      networked-node->node-contact-address
       node-contact-address->node
       (assoc :removed? true)))

@@ -237,7 +238,7 @@
                :subscription subscription
                :connection-redundancy connection-redundancy)

-  (let [self-id (get-in node [:self :id])]
+  (let [self-id (networked-node->node-contact-address node)]
     (when (= self-id subscription)
       (throw (ex-info (str "Got own new subscription: " subscription) {:node node})))

@@ -299,7 +300,10 @@
                :receive-msg-new-upstream-node
                :node node
                :upstream-node-contact-address upstream-node-contact-address)
-  [(update node :upstream maybe-conj (get-in node [:self :id]) upstream-node-contact-address)
+  [(update node :upstream
+           maybe-conj
+           (networked-node->node-contact-address node)
+           upstream-node-contact-address)
    []])

 (s/defn send-msg-new-upstream-node :- MessageEnvelopeSchema
@@ -311,7 +315,7 @@
   [:message-envelope
    upstream-node-contact-address
    :new-upstream-node
-   (get-in node [:self :id])
+   (networked-node->node-contact-address node)
    (*get-envelope-id*)])

 (s/defmethod receive-msg :forwarded-subscription :- CommUpdateSchema
@@ -331,7 +335,7 @@
                :receive-msg-forwarded-subscription
                :node node
                :subscriber-contact-address subscriber-contact-address)
-  (let [self-id (get-in node [:self :id])]
+  (let [self-id (networked-node->node-contact-address node)]
     (if (and (not= self-id subscriber-contact-address)
              (not (downstream subscriber-contact-address))
              ;; The subscription id is not for this node itself, and
@@ -374,7 +378,7 @@
   [world :- WorldSchema
    self :- NetworkedNodeSchema
    f & args]
-  (let [self-id (get-in self [:self :id])]
+  (let [self-id (networked-node->node-contact-address self)]
     (update-in world
                [:network self-id]
                #(apply f % args))))
@@ -483,8 +487,7 @@
                :unsubscribing-node-id unsubscribing-node-id
                :connection-redundancy connection-redundancy)

-  (let [get-node-id #(get-in % [:self :id])
-        node-id (get-node-id node)]
+  (let [node-id (networked-node->node-contact-address node)]

     (when (not= node-id unsubscribing-node-id)
       ;; TODO: Be more resiliant.


Work on implementing iterable interface for metrics

--- src/beehive/metrics.clj
+++ src/beehive/metrics.clj
@@ -15,8 +15,8 @@
 (ns beehive.metrics
   (:require [beehive.utils :as utils]
             [beehive.enums :as enums])
-  (:import (beehive.java EmptyEnum)
-           (net.uncontended.precipice.metrics Metrics Rolling)
+  (:import (beehive.java EmptyEnum ToCLJ)
+           (net.uncontended.precipice.metrics Metrics Rolling IntervalIterator)
            (net.uncontended.precipice.metrics.counts PartitionedCount
                                                      NoOpCounter
                                                      TotalCounts
@@ -26,24 +26,62 @@
                                                       ConcurrentHistogram
                                                       PartitionedLatency)
            (java.util.concurrent TimeUnit)
-           (java.util Iterator)))
+           (java.util Iterator NoSuchElementException)
+           (net.uncontended.precipice.metrics.tools Capturer)))

 (set! *warn-on-reflection* true)

-(deftype MetricIterator []
+(defn- counter-to-map [^PartitionedCount counts]
+  (persistent!
+    (reduce (fn [acc ^ToCLJ e]
+              (assoc! acc (.keyword e) (.getCount counts e)))
+            (transient {})
+            (.getEnumConstants (.getMetricClazz counts)))))
+
+(defn- switcher [^Metrics m]
+  ;; TODO: Clarify Precipice Interface
+  (if (instance? Capturer m)
+    nil
+    (counter-to-map m)))
+
+(deftype SingleIterator
+  [start-millis iterator-start-millis func ^:unsynchronized-mutable is-realized?]
   Iterator
   (next [this]
-    )
+    (if is-realized?
+      (throw (NoSuchElementException.))
+      (do (set! is-realized? true)
+          {:start-millis start-millis
+           :end-millis iterator-start-millis
+           :counts (func)})))
   (hasNext [this]
-    )
+    (not is-realized?))
+  (remove [_]
+    (throw (UnsupportedOperationException. "remove"))))
+
+(deftype MetricIterator [iterator-start-millis func ^IntervalIterator iterator]
+  Iterator
+  (next [this]
+    {:start-millis (+ iterator-start-millis
+                      (.toMillis TimeUnit/NANOSECONDS (.intervalStart iterator)))
+     :end-millis (+ iterator-start-millis
+                    (.toMillis TimeUnit/NANOSECONDS (.intervalEnd iterator)))
+     :counts (func this)})
+  (hasNext [this]
+    (.hasNext iterator))
   (remove [_]
     (throw (UnsupportedOperationException. "remove"))))

 (defn decorate1 [^Metrics precipice-metrics]
-  (if (instance? Rolling precipice-metrics)
-    nil
-    nil))
+  (let [current-millis (System/currentTimeMillis)]
+    (if (instance? Rolling precipice-metrics)
+      (->MetricIterator
+        current-millis
+        counter-to-map
+        (.intervals ^Rolling precipice-metrics))
+      ;; TODO: Figure out start millis
+      (->SingleIterator 0 current-millis switcher false))))

 (defprotocol CountsView


Adapt red for use with p5js

Adapt red for use with p5js

--- src/cljc/quil/core.cljc
+++ src/cljc/quil/core.cljc
@@ -3178,7 +3178,7 @@
   red
   "Extracts the red value from a color, scaled to match current color-mode."
   [c]
-  (.red (current-graphics) (unchecked-int c)))
+  (.red (current-graphics) c))

 (defn
   ^{:requires-bindings true


Use Clojure's implementation of frequencies w/ transients

Taken directly from core.clj from Clojure's current master.

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -5005,11 +5005,10 @@
   "Returns a map from distinct items in coll to the number of times
   they appear."
   [coll]
-  (reduce
-   (fn [counts x]
-     (assoc counts x (inc (get counts x 0))))
-   {}
-   coll))
+  (persistent!
+   (reduce (fn [counts x]
+             (assoc! counts x (inc (get counts x 0))))
+           (transient {}) coll)))

 (defn reductions
   "Returns a lazy seq of the intermediate values of the reduction (as


CLJS-805: add-watch returns map of watch fns instead of watched
reference

Change Atom -add-watch implementation to return `this`.

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -7146,7 +7146,8 @@
     (doseq [[key f] watches]
       (f key this oldval newval)))
   (-add-watch [this key f]
-    (set! (.-watches this) (assoc watches key f)))
+    (set! (.-watches this) (assoc watches key f))
+    this)
   (-remove-watch [this key]
     (set! (.-watches this) (dissoc watches key)))


Adding docstrings, another arity for conj

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -75,40 +75,55 @@
   (iseq [o]))

 (defn first
+  "Returns the first item in the collection. Calls seq on its
+  argument. If coll is nil, returns nil."
   [coll]
   (when coll
     (ifirst coll)))

 (defn rest
+  "Returns a possibly empty seq of the items after the first. Calls seq on its
+  argument."
   [coll]
   (when coll
     (irest coll)))

 (defn seq
+  "Returns a seq on the collection. If the collection is
+  empty, returns nil.  (seq nil) returns nil. seq also works on
+  Strings, native Java arrays (of reference types) and any objects
+  that implement Iterable."
   [coll]
   (when coll (iseq coll)))

 (defn next
+  "Returns a seq of the items after the first. Calls seq on its
+  argument.  If there are no more items, returns nil"
   [coll]
   (seq (rest coll)))

 (defn second
+  "Same as (first (next x))"
   [coll]
   (first (rest coll)))

 (defn ffirst
+  "Same as (first (first x))"
   [coll]
   (first (first coll)))

 (defn nfirst
+  "Same as (next (first x))"
   [coll]
   (next (first coll)))

 (defn fnext
+  "Same as (first (next x))"
   [coll]
   (first (next coll)))

 (defn nnext
+  "Same as (next (next x))"
   [coll]
   (next (next coll)))

@@ -156,8 +171,15 @@
   (new Cons nil first rest))

 (defn conj
+  "conj[oin]. Returns a new collection with the xs
+  'added'. (conj nil item) returns (item).  The 'addition' may
+  happen at different 'places' depending on the concrete type."
   ([coll x]
-     (if coll (iconj coll x) (cons x nil))))
+     (if coll (iconj coll x) (cons x nil)))
+  ([coll x & xs]
+     (if xs
+       (recur (iconj coll x) (first xs) (next xs))
+       (iconj coll x))))

 ;;; Math - variadic forms will not work until the following implemented:
 ;;; first, next, reduce


conclusive remarks

conclusive remarks

--- src/cljs/quiz/core.cljs
+++ src/cljs/quiz/core.cljs
@@ -36,11 +36,12 @@

 (defn end-message [score]
   (cond
-   (= score 0) "0/18: Wow, go signup for a job at amazon.com"
-   (<= 1 score 5) "1"
-   (<= 6 score 10) "2"
-   (<= 11 score 18) "3"
-   :else "you da man!"))
+   (= score 0) "Either you know all the right answers, and avoided them on purpose, or you've managed to miss them all - which is an astronomically low probability. You should put that to use playing lottery!"
+   (<= 1 score 5) "Hm... looks like you've picked up some quotes from people who read the book... why not join their ranks? It's really worth reading!"
+   (<= 6 score 10) "Hm... looks like you've read the first book... may I suggest you keep on reading? You won't be disappointed, I swear!"
+   (<= 11 score 17) "Hey, looks like we've got us a real hitchhiker! Pleasure to meet you. I bet you even know what a Hooloovoo is!"
+   (= 18 score) "I knew it! Douglas Adams isn't dead - he's alive, and is attending the Strange Loop! We salute you, sir! It's an honor to welcome you in our booth."
+   :else "Wait a minute... how did you get here? You're not supposed to be here! Who do you think you are, Ford Prefect or something?"))

 (defn tally-score []
   (let [checked-buttons (->> ["input:checked"] sel)


xyz introduced - buggy...

xyz introduced - buggy...

--- src/clojure2d/color.clj
+++ src/clojure2d/color.clj
@@ -341,14 +341,14 @@
           g (bit-and 0xff (bit-shift-right cc 8))
           b (bit-and 0xff cc)
           ^Vec4 res (f (Vec4. r g b 255))
-          nmnr (int (if (< (.x res) mnr) (.x res) mnr))
-          nmxr (int (if (> (.x res) mxr) (.x res) mxr))
-          nmng (int (if (< (.y res) mng) (.y res) mng))
-          nmxg (int (if (> (.y res) mxg) (.y res) mxg))
-          nmnb (int (if (< (.z res) mnb) (.z res) mnb))
-          nmxb (int (if (> (.z res) mxb) (.z res) mxb))]
+          nmnr (if (< (.x res) mnr) (.x res) mnr)
+          nmxr (if (> (.x res) mxr) (.x res) mxr)
+          nmng (if (< (.y res) mng) (.y res) mng)
+          nmxg (if (> (.y res) mxg) (.y res) mxg)
+          nmnb (if (< (.z res) mnb) (.z res) mnb)
+          nmxb (if (> (.z res) mxb) (.z res) mxb)]
       (if (< cc 0x1000000)
-        (recur (inc cc) nmnr nmxr nmng nmxg nmnb nmxb)
+        (recur (inc cc) (int nmnr) (int nmxr) (int nmng) (int nmxg) (int nmnb) (int nmxb))
         [nmnr nmxr nmng nmxg nmnb nmxb]))))

@@ -380,7 +380,7 @@
   "OHTA -> RGB"
   [^Vec4 c]
   (let [i1 (.x c) ; divided by 3
-        i2  (- (.y c) 127.5) ; divided by 2
+        i2 (- (.y c) 127.5) ; divided by 2
         i3 (- (* c46 (.z c)) 85.0) ; divided by 6
         r (clamp255 (+ i1 i2 i3))
         g (clamp255 (- i1 i3 i3))
@@ -407,6 +407,82 @@
         g (/ (- (.x c) (* 0.2126 r) (* 0.0722 b)) 0.7152)]
     (Vec4. (clamp255 r) (clamp255 g) (clamp255 b) (.w c))))

-;;(test-colors (comp from-YPbPr to-YPbPr))
-
-
+;; XYZ
+
+(defn- xyz-correct
+  ""
+  [v]
+  (* 100.0 (if (> v 0.04045)
+             (m/pow (/ (+ 0.055 v) 1.055) 2.4)
+             (/ v 12.92))))
+
+(defn to-XYZ-
+  ""
+  [^Vec4 c]
+  (let [r (xyz-correct (/ (.x c) 255.0))
+        g (xyz-correct (/ (.y c) 255.0))
+        b (xyz-correct (/ (.z c) 255.0))
+        x (+ (* r 0.4124) (* g 0.3576) (* b 0.1805))
+        y (+ (* r 0.2126) (* g 0.7152) (* b 0.0722))
+        z (+ (* r 0.0193) (* g 0.1192) (* b 0.9505))]
+    (Vec4. x y z (.w c))))
+
+(defn to-XYZ
+  ""
+  [c]
+  (let [^Vec4 cc (to-XYZ- c)]
+    (Vec4. (clamp255 (m/norm (.x cc) 0.0 95.05 0 255))
+           (clamp255 (* 2.55 (.y cc)))
+           (clamp255 (m/norm (.z cc) 0.0 108.899999999999 0 255))
+           (.w cc))))
+
+(def ^:const xyz-f (/ 1.0 2.4))
+
+(defn- xyz-decorrect
+  ""
+  [v]
+  (if (> v 0.0031308)
+    (- (* 1.055 (m/pow v xyz-f)) 0.055)
+    (* v 12.92)))
+
+(defn from-XYZ-
+  ""
+  [^Vec4 c]
+  (let [x (/ (.x c) 100.0)
+        y (/ (.y c) 100.0)
+        z (/ (.z c) 100.0)
+        r (xyz-decorrect (+ (* x  3.2406) (* y -1.5372) (* z -0.4986)))
+        g (xyz-decorrect (+ (* x -0.9689) (* y  1.8758) (* z  0.0415)))
+        b (xyz-decorrect (+ (* x  0.0557) (* y -0.2040) (* z  1.0570)))]
+    (Vec4. (* 255.0 r)
+           (* 255.0 g)
+           (* 255.0 b)
+           (.w c))))
+
+(defn from-XYZ
+  ""
+  [^Vec4 c]
+  (let [x (m/norm (.x c) 0 255 0.0 95.05)
+        y (/ (.y c) 2.55)
+        z (m/norm (.z c) 0 255 0.0 108.899999999999)
+        ^Vec4 rgb (from-XYZ- (Vec4. x y z (.w c)))]
+    (comment Vec4. (clamp255 (.x rgb))
+           (clamp255 (.y rgb))
+           (clamp255 (.z rgb))
+           (.w rgb))
+    rgb))
+
+;(to-XYZ (Vec4. 25 253 1 255))
+;; => #object[clojure2d.math.vector.Vec4 0x2552bd63 "[95.0, 180.0, 28.0, 255.0]"]
+;; => #object[clojure2d.math.vector.Vec4 0x6a9fb697 "[95.32428871945548, 179.67153095742873, 27.527914426466822, 255.0]"]
+
+;(from-XYZ (Vec4. 96 180 28 255))
+
+;((comp from-XYZ to-XYZ) (Vec4. 25 253 1 255))
+
+
+;(test-colors (comp from-XYZ to-XYZ))
+
+;; => [0.0 95.05 0.0 100.0 0.0 108.89999999999999]
+
+


Rejigger summaries

Rejigger summaries

--- src/angelic/search/summary_graphs_newer.clj
+++ src/angelic/search/summary_graphs_newer.clj
@@ -179,71 +179,129 @@

-;; Run KLD and return any nodes whose summaries have changed.
-(defn knuth-lightest-derivation! [active-nodes]
+ (defn summaries-decreased! [nodes]
+   (when-let [cycle-nodes (update-and-find-cycles! nodes)]
+     (knuth-lightest-derivation! cycle-nodes)))
+
+
+(defn update-and-find-cycles! [active-nodes]
+  (assert (= (count active-nodes) 1))
   (let [open  (IdentityHashMap.)
         all   (IdentityHashMap.)
         q     (queues/make-fancy-tree-search-pq)
         cost  (fn [n] (let [s (summary n)] [(- (summary/max-reward s))
-                                            (- (summary/status-val (summary/status s)))]))]
-;   (println active-nodes)
-    (doseq [n active-nodes]
-      (.put all n (summary n))
-      #_ (reset! (:summary-atom n) summary/+worst-simple-summary+)
-      (util/print-debug 2 "NILLING" n (summary n))
-      (set-summary! n summary/+worst-simple-summary+))
-    (doseq [n (keys all)]
-      (when (update-summary-inc?! n)
-        (.put open n true)
-        (queues/pq-add! q n (cost n))))
-    (while (not (queues/pq-empty? q)) ;; Can short circuit on dead too.
-      (let [n (queues/pq-remove-min! q)]
-        (.remove all n)
-        (reset! (:bound-atom n) (summary/max-reward (summary n)))
-        (util/print-debug 2 "SET" n (summary n))
-        (doseq [p (parent-nodes n)]
-          (when (.containsKey all p)
-            (when (update-summary-inc?! p)
-              (if (.containsKey open p)
-                (queues/pq-remove! q p)
-                (.put open p true))
-              (queues/pq-add! q p (cost p)))))))
-    (doseq [n (keys all)]
-      (util/print-debug 2 "KILLING" n)
-      (reset! (:bound-atom n) Double/NEGATIVE_INFINITY))))
-
-;; Also allow status increases.  maybe better to use i-c.
-(defn- update-summary-dec?! [n]
-  (when-let [old   (summary n)]
-    (let [new (update-summary! n)]
-;     (util/assert-is (summary/>= old new 0) (do (def *b* [n old new]) (pr-str n old new)))
-      #_      (not (summary/>= new old 0))
-      (or (< (summary/max-reward new) (summary/max-reward old))
-          (and (summary/live? old) (not (summary/live? new)))))))
-
-;; Find and locally update all nodes that need updating
-;; Return a conservative estimate of nodes that may be in cycles
-;; TODO: add cycle checking.
-;; Note we always include a node if its child in active set.
-;; Note: used to try to see if parent could decrease.
-;; This is wrong with bounding, and must be careful since it can change child order.
-;; Version for bounding
-(defn update-and-find-cycles! [active-nodes]
-  (let [active-set (IdentityHashMap.)]
-    (letfn [(add! [n]
-              (.put active-set n true)
-              (doseq [p (parent-nodes n)]
-                (chase! p n)))
-            (chase! [p c]
-              (when @(:summary-atom p)
-                (when-not (.containsKey active-set p)
-                  (when (some #(identical? (summary/source %) c)
-                              (summary/children (summary p)))
-                    (add! p)))))]
-      (doseq [n active-nodes]
-        (when (update-summary-dec?! n)
-          (add! n)))
-      (keys active-set))))
+                                             (- (summary/status-val (summary/status s)))]))]
+    ((fn add! [c]
+       (when-not (.containsKey all c)
+         (when-let [old @(:summary-atom c)]
+           (let [new (update-summary! c)]
+             (when (or (< (summary/max-reward new) (summary/max-reward old))
+                       (not (summary/live? new)))
+               (set-summary! c summary/+worst-simple-summary+)
+               (.put all c true)
+               (doseq [p (parent-nodes c)]
+                 (add! p)))))))
+     (first active-nodes))
+
+     (doseq [n (keys all)]
+       (when (update-summary-inc?! n)
+         (.put open n true)
+         (queues/pq-add! q n (cost n))))
+
+     (while (not (queues/pq-empty? q)) ;; Can short circuit on dead too.
+       (let [n (queues/pq-remove-min! q)]
+         (.remove all n)
+         (reset! (:bound-atom n) (summary/max-reward (summary n)))
+         (util/print-debug 2 "SET" n (summary n))
+         (doseq [p (parent-nodes n)]
+           (when (.containsKey all p)
+             (when (update-summary-inc?! p)
+               (if (.containsKey open p)
+                 (queues/pq-remove! q p)
+                 (.put open p true))
+               (queues/pq-add! q p (cost p)))))))
+
+     (doseq [n (keys all)]
+       (util/print-debug 2 "KILLING" n)
+       (reset! (:bound-atom n) Double/NEGATIVE_INFINITY))))
+
+
+(comment ;; Separte versions, strict trees.
+ ;; Run KLD and return any nodes whose summaries have changed.
+ (defn knuth-lightest-derivation! [active-nodes]
+   (let [open  (IdentityHashMap.)
+         all   (IdentityHashMap.)
+         q     (queues/make-fancy-tree-search-pq)
+         cost  (fn [n] (let [s (summary n)] [(- (summary/max-reward s))
+                                             (- (summary/status-val (summary/status s)))]))]
+                                        ;   (println active-nodes)
+     (doseq [n active-nodes]
+       (.put all n (summary n))
+       #_ (reset! (:summary-atom n) summary/+worst-simple-summary+)
+       (util/print-debug 2 "NILLING" n (summary n))
+       (set-summary! n summary/+worst-simple-summary+))
+     (doseq [n (keys all)]
+       (when (update-summary-inc?! n)
+         (.put open n true)
+         (queues/pq-add! q n (cost n))))
+     (while (not (queues/pq-empty? q)) ;; Can short circuit on dead too.
+       (let [n (queues/pq-remove-min! q)]
+         (.remove all n)
+         (reset! (:bound-atom n) (summary/max-reward (summary n)))
+         (util/print-debug 2 "SET" n (summary n))
+         (doseq [p (parent-nodes n)]
+           (when (.containsKey all p)
+             (when (update-summary-inc?! p)
+               (if (.containsKey open p)
+                 (queues/pq-remove! q p)
+                 (.put open p true))
+               (queues/pq-add! q p (cost p)))))))
+     (doseq [n (keys all)]
+       (util/print-debug 2 "KILLING" n)
+       (reset! (:bound-atom n) Double/NEGATIVE_INFINITY))))
+
+ ;; Also allow status increases.  maybe better to use i-c.
+ (defn- update-summary-dec?! [n]
+   (when-let [old   (summary n)]
+     (let [new (update-summary! n)]
+                                        ;     (util/assert-is (summary/>= old new 0) (do (def *b* [n old new]) (pr-str n old new)))
+       #_      (not (summary/>= new old 0))
+       (or (< (summary/max-reward new) (summary/max-reward old))
+           (and (summary/live? old) (not (summary/live? new)))))))
+
+ ;; Find and locally update all nodes that need updating
+ ;; Return a conservative estimate of nodes that may be in cycles
+ ;; TODO: add cycle checking.
+ ;; Note we always include a node if its child in active set.
+ ;; Note: used to try to see if parent could decrease.
+ ;; This is wrong with bounding, and must be careful since it can change child order.
+ ;; Version for bounding
+ (defn update-and-find-cycles! [active-nodes]
+   (let [active-set (IdentityHashMap.)]
+     (letfn [(add! [n]
+               (.put active-set n true)
+               (doseq [p (parent-nodes n)]
+                 (chase! p n)))
+             (chase! [p c]
+               (when @(:summary-atom p)
+                 (when-not (.containsKey active-set p)
+                   (when (some #(identical? (summary/source %) c)
+                               (summary/children (summary p)))
+                     (add! p)))))]
+       (doseq [n active-nodes]
+         (when (update-summary-dec?! n)
+           (add! n)))
+       (keys active-set))))
+
+ ;; Summaries of nodes may have decreased.  Propagate these changes upwards
+ ;; using a version of KLD, which can properly handle cycles without infinite
+ ;; loops, or the inefficiencies of an algorithm like LDFS.
+ ;; Algorithm: repeatedly find costs of active set using KLD, assuming
+ ;; all nodes out of active set are fixed, then expand active set to
+ ;; incorporate any new nodes that may change given the new updates.
+ (defn summaries-decreased! [nodes]
+   (when-let [cycle-nodes (update-and-find-cycles! nodes)]
+     (knuth-lightest-derivation! cycle-nodes))))

 (comment  ;; version for non-bounding
  (defn update-and-find-cycles! [active-nodes]
@@ -264,19 +322,6 @@

-;; Summaries of nodes may have decreased.  Propagate these changes upwards
-;; using a version of KLD, which can properly handle cycles without infinite
-;; loops, or the inefficiencies of an algorithm like LDFS.
-;; Algorithm: repeatedly find costs of active set using KLD, assuming
-;; all nodes out of active set are fixed, then expand active set to
-;; incorporate any new nodes that may change given the new updates.
-(defn summaries-decreased! [nodes]
-  (when-let [cycle-nodes (update-and-find-cycles! nodes)]
-    (knuth-lightest-derivation! cycle-nodes)))
-
-
-
-
 (defn make-simple-cached-node []
   (merge (make-node) (make-summary-cache)))


Message queue: allow `message-status` to be pipelined

--- src/taoensso/carmine/message_queue.clj
+++ src/taoensso/carmine/message_queue.clj
@@ -33,7 +33,7 @@

 (comment (map #(exp-backoff % {}) (range 10)))

-;;;; Implementation
+;;;; Admin

 (def qkey "Prefixed queue key" (memoize (partial car/key :carmine :mq)))

@@ -57,6 +57,8 @@
        (->> (car/get      (qk :eoq-backoff?))  (car/parse-bool))
        (->> (car/get      (qk :ndry-runs))     (car/parse-long))))))

+;;;; Implementation
+
 (defn message-status
   "Returns current message status, e/o:
     :queued            - Awaiting (re)handling.
@@ -65,34 +67,33 @@
     :done-with-backoff - Finished handling, awaiting dedupe timeout.
     :recently-done     - Finished handling, no dedupe timeout, awaiting GC.
     nil                - Already GC'd or invalid message id."
-  [conn qname mid]
-  (wcar conn
-    (car/parse-keyword
-     (car/lua ; Careful, logic here is necessarily quite subtle!
-      "--
-      local now         = tonumber(_:now)
-      local lock_exp    = tonumber(redis.call('hget', _:qk-locks,    _:mid) or 0)
-      local backoff_exp = tonumber(redis.call('hget', _:qk-backoffs, _:mid) or 0)
-
-      if redis.call('hexists', _:qk-messages, _:mid) ~= 1 then
+  [qname mid]
+  (car/parse-keyword
+   (car/lua ; Careful, logic here is necessarily quite subtle!
+    "--
+    local now         = tonumber(_:now)
+    local lock_exp    = tonumber(redis.call('hget', _:qk-locks,    _:mid) or 0)
+    local backoff_exp = tonumber(redis.call('hget', _:qk-backoffs, _:mid) or 0)
+
+    if redis.call('hexists', _:qk-messages, _:mid) ~= 1 then
+      if (now < backoff_exp) then return 'done-with-backoff' end
+      return nil
+    else
+      if redis.call('sismember', _:qk-recently-done, _:mid) == 1 then
         if (now < backoff_exp) then return 'done-with-backoff' end
-        return nil
-      else
-        if redis.call('sismember', _:qk-recently-done, _:mid) == 1 then
-          if (now < backoff_exp) then return 'done-with-backoff' end
-          return 'recently-done'
-        else
-          if     (now < lock_exp)    then return 'locked'
-          elseif (now < backoff_exp) then return 'retry-backoff' end
-          return 'queued'
-        end
-      end"
-      {:qk-messages      (qkey qname :messages)
-       :qk-locks         (qkey qname :locks)
-       :qk-backoffs      (qkey qname :backoffs)
-       :qk-recently-done (qkey qname :recently-done)}
-      {:now (System/currentTimeMillis)
-       :mid mid}))))
+        return 'recently-done'
+      else
+        if     (now < lock_exp)    then return 'locked'
+        elseif (now < backoff_exp) then return 'retry-backoff' end
+        return 'queued'
+      end
+    end"
+    {:qk-messages      (qkey qname :messages)
+     :qk-locks         (qkey qname :locks)
+     :qk-backoffs      (qkey qname :backoffs)
+     :qk-recently-done (qkey qname :recently-done)}
+    {:now (System/currentTimeMillis)
+     :mid mid})))

 (defn enqueue
   "Pushes given message (any Clojure datatype) to named queue and returns unique
@@ -221,7 +222,7 @@
   (clear-queues {} "myq")
   (queue-status {} "myq")
   (let [mid (wcar {} (enqueue "myq" "msg"))]
-    (message-status {} "myq" mid))
+    (wcar {} (message-status "myq" mid)))

   (wcar {} (dequeue "myq")))


Add missing license prelude to test_storages.clj file.

--- test/datoteka/tests/test_storages.clj
+++ test/datoteka/tests/test_storages.clj
@@ -1,3 +1,27 @@
+;; Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz>
+;; All rights reserved.
+;;
+;; Redistribution and use in source and binary forms, with or without
+;; modification, are permitted provided that the following conditions are met:
+;;
+;; * Redistributions of source code must retain the above copyright notice, this
+;;   list of conditions and the following disclaimer.
+;;
+;; * Redistributions in binary form must reproduce the above copyright notice,
+;;   this list of conditions and the following disclaimer in the documentation
+;;   and/or other materials provided with the distribution.
+;;
+;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+;; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+;; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+;; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+;; CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+;; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
 (ns datoteka.tests.test_storages
   (:require [clojure.test :as t]
             [datoteka.storages :as st]