dox for /api/query

dox for /api/query

--- src/metabase/api/query.clj
+++ src/metabase/api/query.clj
@@ -22,10 +22,13 @@
    :databases   (databases-for-org org)})

-(defendpoint GET "/" [org f]
+(defendpoint GET "/"
+  "Fetch all `Querys` for an `Org`. With filter option F (default `all`), return all queries;
+   with `mine`, only return queries created by the current user."
+  [org f]
   {org Required, f FilterOptionAllOrMine}
   (read-check Org org)
-  (-> (case (or f :all) ; default value for `f` is `:all`
+  (-> (case (or f :all)
         :all (sel :many Query
                   (where (or (= :creator_id *current-user-id*) (> :public_perms common/perms-none)))
                (where {:database_id [in (subselect Database (fields :id) (where {:organization_id org}))]})
@@ -68,20 +71,26 @@
     :database_id database))

-(defendpoint POST "/" [:as {{:keys [clone] :as body} :body}]
+(defendpoint POST "/"
+  "Clone or create a `Query` (`clone`, if passed, should be the ID of the `Query` to clone)."
+  [:as {{:keys [clone] :as body} :body}]
   {clone Integer}
   (if clone
     (query-clone clone)
     (query-create body)))

-(defendpoint GET "/:id" [id]
+(defendpoint GET "/:id"
+  "Fetch a `Query`."
+  [id]
   (->404 (sel :one Query :id id)
          read-check
          (hydrate :creator :database :can_read :can_write)))

-(defendpoint PUT "/:id" [id :as {{:keys [name public_perms details timezone database] :as body} :body}]
+(defendpoint PUT "/:id"
+  "Update a `Query`."
+  [id :as {{:keys [name public_perms details timezone database] :as body} :body}]
   {database     [Required Dict]
    name         NonEmptyString
    public_perms PublicPerms}
@@ -96,12 +105,16 @@
         (hydrate :creator :database))))

-(defendpoint DELETE "/:id" [id]
+(defendpoint DELETE "/:id"
+  "Delete a `Query`."
+  [id]
   (write-check Query id)
   (del Query :id id))

-(defendpoint POST "/:id" [id]
+(defendpoint POST "/:id"
+  "Execute a `Query` asynchronously."
+  [id]
   (let-404 [{database-id :database_id
              {:keys [sql timezone]} :details :as query} (sel :one Query :id id)]
     (read-check query)
@@ -116,11 +129,15 @@
       (driver/dataset-query dataset-query options))))

-(defendpoint GET "/:id/results" [id]
+(defendpoint GET "/:id/results"
+  "Fetch the most recent results of a `Query`."
+  [id]
   (read-check Query id)
   (sel :many QueryExecution :query_id id (order :finished_at :DESC) (limit 10)))

-(defendpoint GET "/:id/csv" [id]
+(defendpoint GET "/:id/csv"
+  "Fetch the most recent results of a `Query` as CSV."
+  [id]
   (let-404 [{{:keys [columns rows]} :result_data :as query-execution} (sel :one all-fields, :query_id id, (order :started_at :DESC))]
     (let-404 [{{:keys [can_read name]} :query} (hydrate query-execution :query)]
       (check-403 @can_read)


fix horribly broken tiles api

fix horribly broken tiles api

--- src/metabase/api/tiles.clj
+++ src/metabase/api/tiles.clj
@@ -46,22 +46,13 @@
 (defn- extract-points
   "Takes in a dataset query result object and pulls out the Latitude/Longitude pairs into nested `java.util.ArrayLists`.
    This is specific to the way we plan to feed data into `com.metabase.corvus.api.tiles.GoogleMapPinsOverlay`."
-  [{{:keys [rows cols]} :data}]
-  (try
-    (if-not (> (count rows) 0)
-      ;; if we have no rows then return an empty list of points
-      (java.util.ArrayList. [])
-      ;; otherwise we go over the data, pull out the lat/lon columns, and convert them to ArrayLists
-      (let [find-col-idx (fn [special-type]
-                           (->> (map-indexed (fn [idx itm] (when (= special-type (:special_type itm)) idx)) cols)
-                                (filter identity)
-                                first))
-            lat-col-idx (find-col-idx "latitude")
-            lon-col-idx (find-col-idx "longitude")]
-        (->> (map (fn [row] (java.util.ArrayList. [(nth row lat-col-idx) (nth row lon-col-idx)])) rows)
-             (java.util.ArrayList.))))
-    (catch Throwable e
-      (log/debug "CAUGHT EXCEPTION IN EXTRACT-POINTS (WHY?): " e))))
+  [lat-col-idx lon-col-idx {{:keys [rows cols]} :data}]
+  (if-not (> (count rows) 0)
+    ;; if we have no rows then return an empty list of points
+    (java.util.ArrayList. [])
+    ;; otherwise we go over the data, pull out the lat/lon columns, and convert them to ArrayLists
+    (->> (map (fn [row] (java.util.ArrayList. [(nth row lat-col-idx) (nth row lon-col-idx)])) rows)
+         (java.util.ArrayList.))))

 (defendpoint GET "/:zoom/:x/:y/:lat-field/:lon-field/:lat-col-idx/:lon-col-idx/"
@@ -80,7 +71,7 @@
   (let [updated-query (assoc query :query (query-with-inside-filter (:query query) lat-field lon-field x y zoom))
         result (driver/dataset-query updated-query {:executed_by *current-user-id*
                                                     :synchronously true})
-        lat-lon-points (extract-points result)]
+        lat-lon-points (extract-points lat-col-idx lon-col-idx result)]
     ;; manual ring response here.  we simply create an inputstream from the byte[] of our image
     {:status  200
      :headers {"Content-Type" "image/png"}


remove unused binding 'f-name' from let statement in #'buffer-alloc-read.

--- src/overtone/sc/buffer.clj
+++ src/overtone/sc/buffer.clj
@@ -55,8 +55,7 @@
            f    (file path)]
        (when-not (.exists f)
          (throw (Exception. (str "Unable to read file - file does not exist: " path))))
-       (let [f-name (.getName f)
-             id     (alloc-id :audio-buffer)]
+       (let [id (alloc-id :audio-buffer)]
          (with-server-sync  #(snd "/b_allocRead" id path start n-frames))
          (let [{:keys [id size rate n-channels]} (buffer-info id)]
            (when (every? zero? [size rate n-channels])


Default scsynth port is 57110 not 57710...

--- src/overtone/sc/server.clj
+++ src/overtone/sc/server.clj
@@ -81,8 +81,8 @@

 (defn connect-external-server
   "Connect to an externally running SC audio server listening to port
-  on host.  Host defaults to localhost and port defaults to 57710."
-  ([] (connect-external-server 57710))
+  on host.  Host defaults to localhost and port defaults to 57110."
+  ([] (connect-external-server 57110))
   ([port] (connect-external-server "127.0.0.1" port))
   ([host port]
      (connect host port)


deconflict clj-http.client/update with clojure.core/update

--- src/ring_curl/clj_http.clj
+++ src/ring_curl/clj_http.clj
@@ -1,6 +1,6 @@
 (ns ring-curl.clj-http
   (:require [clj-http.client :refer :all])
-  (:refer-clojure :exclude [get]))
+  (:refer-clojure :exclude [get update]))

 (def middleware
   [wrap-query-params


Added missing import.

Added missing import.

--- core/src/main/clojure/stone/core.clj
+++ core/src/main/clojure/stone/core.clj
@@ -3,7 +3,8 @@
            (com.github.jeluard.stone.api ConsolidationListener Listener Reader TimeSeries Window WindowedTimeSeries)
            (com.github.jeluard.stone.spi Storage)
            (com.github.jeluard.stone.helper Loggers Storages)
-           (com.google.common.base Optional)))
+           (com.google.common.base Optional)
+           (java.util Iterator)))

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


change the order of methods

change the order of methods

--- src/tamaki/template/page.clj
+++ src/tamaki/template/page.clj
@@ -7,7 +7,7 @@
             [net.cgrand.enlive-html :as ehtml]
             [kalar-core.config :as config]
             [clojure-csv.core :as csv]
-            [kalar-core.file :as kfile])
+            [tamaki-core.file :as tfile])
   (:import (java.io StringWriter StringReader)
            (java.text SimpleDateFormat)))

@@ -23,6 +23,23 @@
       (merge {:body body :src md} {:metadata (merge metadata {:title (-> metadata :title first)
                                                       :link (-> metadata :link first)
                                                       :template (-> metadata :template first)})}))))
+
+(defn- write-page [page]
+  (let [output (io/file (:dest (config/read-config)) (string/replace (:link page) #"^/" ""))
+        template  (:template page)]
+    (tfile/create-empty-file output)
+    (require (symbol (str/replace  template #"/.*"  "")))
+    (spit output ((var-get (resolve (symbol template))) page))))
+
+(defn- compile-pages
+  ([files i18n]
+   (let [pages-per-lang (internationalize (map #(.getAbsolutePath %) files) (map #(keyword %) i18n))
+         read-pages (reduce (fn [acc lang] (into acc (map (fn [page] (read-page page lang)) (get pages-per-lang lang))))
+                            (map #(read-page %) (:default pages-per-lang))
+                            (keys (dissoc pages-per-lang :default)))]
+     (doseq [page read-pages] (write-page page))))
+  ([]
+   (compile-pages (.listFiles (io/file (:page-dir (config/read-config)))) (:i18n (config/read-config)))))

 (defn load-markdown
   ([^String file]
@@ -56,12 +73,7 @@
       (assoc loaded-md :link (str "/" (name lang-cd) (first (:link loaded-md)))
                        :template (first (:template loaded-md))))))

-(defn- write-page [compiled-page]
-  (let [output (io/file (:dest (config/read-config)) (string/replace (:link compiled-page) #"^/" ""))
-        template  (:template compiled-page)]
-    (kfile/touch output)
-    (require (symbol (str/replace  template #"/.*"  "")))
-    (spit output ((var-get (resolve (symbol template))) compiled-page))))
+

 (defn- internationalize
   [filenames langs]
@@ -86,15 +98,7 @@
                  (vals i18-files))))
     ))

-(defn- compile-pages
-  ([files i18n]
-   (let [pages-per-lang (internationalize (map #(.getAbsolutePath %) files) (map #(keyword %) i18n))
-         read-pages (reduce (fn [acc lang] (into acc (map (fn [page] (read-page page lang)) (get pages-per-lang lang))))
-                            (map #(read-page %) (:default pages-per-lang))
-                            (keys (dissoc pages-per-lang :default)))]
-     (doseq [page read-pages] (write-page page))))
-  ([]
-   (compile-pages (.listFiles (io/file (:page-dir (config/read-config)))) (:i18n (config/read-config)))))
+

 (defn load-md-excerpt [^String md]
   (let [compiled (load-markdown md)


Fix broken search uberjar

Fix broken search uberjar

--- search-app/project.clj
+++ search-app/project.clj
@@ -34,10 +34,8 @@
          :injections [(require 'pjstadig.humane-test-output)
                       (pjstadig.humane-test-output/activate!)]}
    :docs {:dependencies [[markdown-clj "0.9.63"]]}
-   :uberjar {:aot :all
-             :dependencies [[markdown-clj "0.9.63"]]
-             :prep-tasks ["generate-docs"]
-             :main cmr.search.runner}}
+   :uberjar {:main cmr.search.runner
+             :aot :all}}

   :aliases {"generate-docs" ["exec" "-p" "./support/generate_docs.clj"]
             ;; Prints out documentation on configuration environment variables.


change bigint to long in schema

change bigint to long in schema

--- src/oarlock/schema.clj
+++ src/oarlock/schema.clj
@@ -9,10 +9,10 @@
             [:name :string]
             [:version :string] ; not null
             [:type :string] ; not null
-            [:duration-rating-days :bigint]
+            [:duration-rating-days :long]
             [:comps :ref :many]
-            [:credit-value-numerator :bigint]
-            [:credit-value-denominator :bigint]]
+            [:credit-value-numerator :long]
+            [:credit-value-denominator :long]]
     :dbfns [(constraints/unique :perf-asmt :name :version :type)
             (constraints/unique :perf-asmt :id-sk :id-sk-origin)]}
    {:namespace :task


simple documentation

simple documentation

--- src/vignette/media_types.clj
+++ src/vignette/media_types.clj
@@ -14,10 +14,15 @@
   (:image-type object-map))

 (defmethod image-type->path-prefix "images" [object-map]
+  "
+  path-prefix comes before the image-type, and can be a language code (ex: 'es') or a path (ex: /some/dir)
+  zone is further distinction of what type of image. For instance, 'temp' indicates the image is a temporary image.
+    this is needed because mediawiki supports these in filerepo->getZoneUrl
+  "
   (let [path-prefix (query-opt object-map :path-prefix)
-        zone (query-opt object-map :zone)
-        prefix (:image-type object-map)]
-    (clojure.string/join "/" (filter not-empty [path-prefix prefix zone]))))
+        image-type (:image-type object-map)
+        zone (query-opt object-map :zone)]
+    (clojure.string/join "/" (filter not-empty [path-prefix image-type zone]))))

 (defmethod image-type->path-prefix :default [object-map]
   (throw+ {:type :convert-error


Fix bad nesting

Fix bad nesting

--- src-cljs/frontend/components/build_head.cljs
+++ src-cljs/frontend/components/build_head.cljs
@@ -1174,13 +1174,12 @@
                                                                   :build-num build-num}])}
                    "with ssh"]))])
            [:div.actions
-            (when (and (build-model/can-cancel? build) has-write-settings?))
+            (when (and (build-model/can-cancel? build) has-write-settings?)
               (forms/managed-button
-                [:button.cancel_build
-                 {:data-loading-text "Canceling",
-                  :title "Cancel this build",
-                  :on-click #(raise! owner [:cancel-build-clicked {:build-id build-id
-                                                                   :vcs-url vcs-url
-                                                                   :build-num build-num}])}
-                 "Cancel"])]])))))
-
+               [:button.cancel_build
+                {:data-loading-text "Canceling",
+                 :title "Cancel this build",
+                 :on-click #(raise! owner [:cancel-build-clicked {:build-id build-id
+                                                                  :vcs-url vcs-url
+                                                                  :build-num build-num}])}
+                "Cancel"]))]])))))


fix ex-info vs ex-data usage

fix ex-info vs ex-data usage

Signed-off-by: Chris Granger <5654cde260ae99bc4d30054171b8bcd902efd19a@gmail.com>

--- lein-light-nrepl/src/lighttable/nrepl/eval.clj
+++ lein-light-nrepl/src/lighttable/nrepl/eval.clj
@@ -90,12 +90,12 @@
            :stack trace
            :ex true})
         (catch Throwable e2
-          (let [msg (str (.getName (class e)) ": " (.getMessage e) (ex-info e))])
-          {:meta (meta f)
-           :form f
-           :result msg
-           :stack msg
-           :ex true}
+          (let [msg (str (.getName (class e)) ": " (.getMessage e) (ex-data e))]
+            {:meta (meta f)
+             :form f
+             :result msg
+             :stack msg
+             :ex true})
           )))))

 (defn require|create-ns [ns]


add test for create fnc

add test for create fnc

--- datomic-dsl/test/datomic_dsl/create_nested_test.clj
+++ datomic-dsl/test/datomic_dsl/create_nested_test.clj
@@ -5,3 +5,30 @@
             [datomic-dsl.common-test :refer :all]
             [clojure.pprint :refer :all]
             [datomic.api :as d]))
+
+(def borrowevent-schema-dsl
+  "Define our data structure."
+  {"book" {"title" "string"
+           "author" "string"}
+   "borrower" {"name" "string"}
+   "date" "string"})
+
+(def nested-book-schema
+  "Use the created API to create some Datomic schema syntax.
+  Add a pprint to see what this looks like."
+  (create-schema-nested "borrowevent" borrowevent-schema-dsl))
+
+(def trans-result
+  "Add the schema to the database. Save the result in a symbol if need to look at it."
+  (d/transact conn nested-book-schema))
+
+;;(pprint nested-book-schema)
+
+(def book-schema-query-print
+  "Query the schema to see if it exists -  schemas are entities too!"
+  (d/touch (d/entity (d/db conn) :borrower/name)))
+
+(deftest schema-created-test
+  (testing "Is the schema created with a borrower name?"
+    (is book-schema-query-result)))
+


convert over remaining endpoints

convert over remaining endpoints

--- src/semtag_web/service.clj
+++ src/semtag_web/service.clj
@@ -10,6 +10,12 @@
 (defn home-page [request] (ring-resp/response (views/home)))
 (defn add-page [request] (ring-resp/response (views/home "entity_add")))
 (defn all-page [request] (ring-resp/response (views/all)))
+(defn type-stats-page [request] (ring-resp/response (views/type-stats)))
+(defn tag-stats-page [request] (ring-resp/response (views/tag-stats)))
+(defn type-page [request]
+  (ring-resp/response (views/type-show (-> request :params :type))))
+(defn thing-page [request]
+  (ring-resp/response (views/thing-show (-> request :params :tag))))

 (interceptor/defon-response html-content-type
   [response]
@@ -20,6 +26,13 @@
      ^:interceptors [html-content-type]
      ["/add" {:get add-page}]
      ["/all" {:get all-page}]
+     ["/type-stats" {:get type-stats-page}]
+     ["/tag-stats" {:get tag-stats-page}]
+     ["/:type" {:get type-page}]
+     ["/thing/:tag" {:get thing-page}]
+
+     ;; TODO: Add api routes for testing and examples
+     ;;["/api/*"]
      ]]])

 ;; You can use this fn or a per-request fn via io.pedestal.service.http.route/url-for


Include TODOS on more aggressive reduction.

--- src/smallex/reductions.clj
+++ src/smallex/reductions.clj
@@ -185,7 +185,7 @@
                           (get-in not-op [:args 0 :value]))})

 (defn- flatten-cat
-  "Flattens a `cat`, whenever possible."
+  "Flattens a `cat` inside a `cat`, whenever possible."
   [cat-op]
   (assoc cat-op
     :args (->> (:args cat-op)
@@ -198,6 +198,8 @@
   "Reduces a `cat`, whenever possible."
   [cat-op]
   (cond (every? #(= :string (:type %)) (:args cat-op))
+        ;; This is not general enough. (cat "f" "g" expr [x] "y") could be
+        ;; reduced to (cat "fg" expr "xy")
         {:type :string, :value (apply str (map :value (:args cat-op)))}
         (= 1 (count (:args cat-op)))
         (first (:args cat-op))
@@ -205,7 +207,7 @@
         cat-op))

 (defn- flatten-or
-  "Flattens an `or`, whenever possible."
+  "Flattens an `or` inside an `or`, whenever possible."
   [or-op]
   (assoc or-op
     :args (->> (:args or-op)
@@ -218,6 +220,8 @@
   "Reduces an `or` whenever possible."
   [or-op]
   (cond (every? #(= :char-set (:type %)) (:args or-op))
+        ;; Not general enough. (or [ax] expr [by] "c") could be reduced to
+        ;; (or [abcxy] expr).
         {:type :char-set,
          :value (apply set/union (map :value (:args or-op)))}
         (= 1 (count (:args or-op)))


Animate boolean gauge transition.

Animate boolean gauge transition.

This makes it easier to see what is happening when you turn an encoder
to adjust a boolean cue variable, and to relate the motion to the
result.

--- src/afterglow/controllers/ableton_push_2.clj
+++ src/afterglow/controllers/ableton_push_2.clj
@@ -2406,7 +2406,8 @@
   while the encoder is being held."
   [controller note cue v effect info]
   (let [x (quot note 2)
-        var-index (rem note 2)]
+        var-index (rem note 2)
+        fraction (atom nil)]
     (if (> (count (:variables cue)) 1)
       ;; More than one variable, adjust whichever's encoder was touched
       (reify controllers/IOverlay
@@ -2415,13 +2416,17 @@
         (adjust-interface [this _]
           (when (same-effect-active controller cue (:id info))
             (let [cur-val (or (cues/get-cue-variable cue v :show (:show controller) :when-id (:id info)) false)]
-              (draw-boolean-gauge controller note 1 cur-val :active? true)
+              (draw-boolean-gauge controller note 1 cur-val :active? true :fraction (or @fraction 1.0))
               (set-touch-strip-from-value controller (if cur-val 1 0) 0 1 touch-strip-mode-pan))
+            (swap! fraction (fn [v] (when v (let [result (+ v 0.25)] (when (< result 1.0) result)))))
             (swap! (:next-top-pads controller) assoc (inc (* 2 x)) off-color)
             true))
         (handle-control-change [this message]
           (when (= (:note message) (control-for-top-encoder-note note))
-            (adjust-boolean-value controller message cue v (:id info)))
+            (let [cur-val (or (cues/get-cue-variable cue v :show (:show controller) :when-id (:id info)) false)]
+              (adjust-boolean-value controller message cue v (:id info))
+              (when (not= cur-val (cues/get-cue-variable cue v :show (:show controller) :when-id (:id info)))
+                (swap! fraction (fn [v] (if (nil? v) 0.25 (- 1.0 v)))))))
           true)
         (handle-note-on [this message])
         (handle-note-off [this message]
@@ -2429,7 +2434,8 @@
         (handle-aftertouch [this message])
         (handle-pitch-bend [this message]
           (cues/set-cue-variable! cue v (true? (>= (value-from-touch-strip message 0 100) 50))
-                                  :show (:show controller) :when-id (:id info))))
+                                  :show (:show controller) :when-id (:id info))
+          (reset! fraction nil)))

       ;; Just one variable, take full cell, using either encoder,
       ;; suppress the other one.


cleanup

cleanup

--- src/clj/com/matthiasnehlsen/inspect/main.clj
+++ src/clj/com/matthiasnehlsen/inspect/main.clj
@@ -13,10 +13,10 @@
   [interval msg-type msg]
   (go-loop [] (<! (timeout interval)) (inspect msg-type msg) (recur)))

-(interval-put-loop  1000 :interval-put {:origin :every-second :payload {:msg "every second"}})
-(interval-put-loop  5000 :interval-put {:origin :every-five-seconds :payload {:msg "every five seconds"}})
-(interval-put-loop 10000 :interval-put {:origin :every-ten-seconds :payload {:msg "every ten seconds"}})
-(interval-put-loop 60000 :interval-put {:origin :every-minute :payload {:msg "every minute"}})
+(interval-put-loop  1000 :interval-put/every-second {:msg "every second"})
+(interval-put-loop  5000 :interval-put/every-five-seconds {:msg "every five seconds"})
+(interval-put-loop 10000 :interval-put/every-ten-seconds {:msg "every ten seconds"})
+(interval-put-loop 60000 :interval-put/every-minute {:msg "every minute"})

 (defn reload [] (inspect/stop) (refresh) (inspect/start))


Have rpi impl compiling (w/o edge)

Have rpi impl compiling (w/o edge)

--- src/clj_bots/pin_ctrl_rpi/implementation.clj
+++ src/clj_bots/pin_ctrl_rpi/implementation.clj
@@ -4,7 +4,7 @@
              [protocols :as pcp]
              [implementation :as impl]]
             [clj-bots.pin-ctrl :as pc]
-            [clj-gpio :as gpio]
+            [gpio.core :as gpio]
             [clojure.core.async :as async :refer [chan >!! <!! go <! >! go-loop]]))

@@ -15,7 +15,7 @@

 (defmulti read-pin*
   "Inner method for reading from a pin; dispatches on pin mode"
-  pc/pin-mode)
+  (fn [board pin-n mode] mode))

 (defmulti unset-mode*
   "Inner method for unsetting a pin mode, in particular for being run before moving to another mode or turned off"
@@ -27,49 +27,46 @@

 (defmulti write-value*
   "Inner method for writing a value to a pin"
-  (fn [board pin-n val]
-    (pc/pin-mode board pin-n)))
+  (fn [board pin-n mode val] mode))

 (defrecord RPiBoard
-  [pin-modes edge-channels config]
+  [edge-channels config]
   pcp/PBoard
   (available-pin-modes [_] (:pin-modes config))
-  (pin-modes [_] @pin-modes)
-  (get-config [_] config)
-  (update-config [this f] (update-in this [:config] f))

   pcp/PPinConfigure
   (set-mode! [board pin-n mode]
     (unset-mode* board pin-n)
-    (set-mode* board pin-n mode)
-    (swap! pin-modes assoc pin-n mode))
+    (set-mode* board pin-n mode))

   pcp/PReadablePin
-  (read-value [board pin-n]
-    (read-pin* board pin-n))
+  (read-value [board pin-n mode]
+    (read-pin* board pin-n mode))

   pcp/PWriteablePin
-  (write-value! [board pin-n val]
+  (write-value! [board pin-n mode val]
     (write-value* board pin-n val))

-  pcp/PEdgeDetectablePin
-  (set-edge! [board pin-n edge buffer]
-    (gpio/set-edge! pin-n edge)
-    (let [[c m] (or (get @edge-channels pin-n)
-                    )]
-      (if (= :none edge)
-        (do (async/close! c)
-            (swap! edge-channels dissoc pin-n))
-        (let [p (open-channel-port
-                  c (create-edge-channel pin-n)
+  ;pcp/PEdgeDetectablePin
+  ;(set-edge! [board pin-n edge buffer]
+    ;(gpio/set-edge! pin-n edge)
+    ;(let [[c m] (or (get @edge-channels pin-n)
+                    ;)]
+      ;(if (= :none edge)
+        ;(do (async/close! c)
+            ;(swap! edge-channels dissoc pin-n))
+        ;(let [p (open-channel-port
+                  ;c (create-edge-channel pin-n)

-      (do (async/close! (@edge-channels pin-n))
-          (swap! edge-channels dissoc pin-n))
-                      (let [c (chan buffer)]
-                        [c (async/mult c)]))
-            (
+      ;(do (async/close! (@edge-channels pin-n))
+          ;(swap! edge-channels dissoc pin-n))
+                      ;(let [c (chan buffer)]
+                        ;[c (async/mult c)]))
+            ;(
+
+  )


use custom type transaction in SqlStorage

--- src/clj_money/models/storage/sql_storage.clj
+++ src/clj_money/models/storage/sql_storage.clj
@@ -7,7 +7,8 @@
             #_[clj-time.jdbc]
             [clj-time.core :as t]
             [clj-time.coerce :refer [to-sql-date
-                                     to-sql-time]]
+                                     to-sql-time
+                                     to-local-date]]
             [honeysql.core :as sql]
             [honeysql.helpers :as h]
             [clj-postgresql.types]
@@ -19,21 +20,20 @@
                      Date]
            org.joda.time.LocalDate))

+(extend-protocol jdbc/IResultSetReadColumn
+  Date
+  (result-set-read-column [v _ _]
+    (to-local-date v)))
+
 (extend-protocol jdbc/ISQLValue
   LocalDate
   (sql-value [v]
-    (let [result (to-sql-date v)]
-      (pprint {:sql-value v
-               :result result})
-      result)))
+    (to-sql-date v)))

 (extend-protocol jdbc/ISQLValue
   org.joda.time.DateTime
   (sql-value [v]
-    (let [result (to-sql-time v)]
-      (pprint {:sql-value v
-               :result result})
-      result)))
+    (to-sql-time v)))

 (defn- id-criteria?
   [value]


Fix removal of queries

Fix removal of queries

--- src/cljs/cglossa/search_inputs/cwb/core.cljs
+++ src/cljs/cglossa/search_inputs/cwb/core.cljs
@@ -66,13 +66,16 @@
 (defn- focus-text-input [c]
   (.focus (dom/findNode (reagent/dom-node c) #(= "text" (.-type %)))))

-(defn- wrapped-query-changed [queries index query]
+(defn- wrapped-query-changed [queries index query-ids query]
   "Takes a changed query, performs some cleanup on it, and swaps it into
   the appropriate position in the vector of queries that constitutes the
   current search. If the query is nil, removes it from the vector instead."
   (if (nil? query)
-    (swap! queries #(into (subvec % 0 index)
-                          (subvec % (inc index))))
+    (do
+      (swap! query-ids #(into (subvec % 0 index)
+                              (subvec % (inc index))))
+      (swap! queries #(into (subvec % 0 index)
+                            (subvec % (inc index)))))
     (let [query* (as-> (:query query) $
                        (if (:headword-search query)
                          (->headword-query $)
@@ -183,77 +186,86 @@
   "Component that lets the user select a search view (simple, extended
   or CQP query view) and displays it."
   [{:keys [search-view search-queries]} {:keys [corpus]}]
-  (reagent/create-class
-    {:display-name
-     "search-inputs"
-
-     :component-did-mount
-     focus-text-input
-
-     :reagent-render
-     (fn [{:keys [search-view search-queries]} {:keys [corpus]}]
-       (let [view          (case @search-view
-                             :extended extended
-                             :cqp cqp
-                             simple)
-             languages     (:langs @corpus)
-             multilingual? (> (count languages) 1)
-             set-view      (fn [view e] (reset! search-view view) (.preventDefault e))]
-         [:span
-          [:div.row.search-input-links>div.col-md-12
-           (if (= view simple)
-             [:b "Simple"]
-             [:a {:href     ""
-                  :title    "Simple search box"
-                  :on-click #(set-view :simple %)}
-              "Simple"])
-           " | "
-           (if (= view extended)
-             [:b "Extended"]
-             [:a {:href     ""
-                  :title    "Search for grammatical categories etc."
-                  :on-click #(set-view :extended %)}
-              "Extended"])
-           " | "
-           (if (= view cqp)
-             [:b "CQP query"]
-             [:a {:href     ""
-                  :title    "CQP expressions"
-                  :on-click #(set-view :cqp %)}
-              "CQP query"])
-           [search-button (if (= @search-view :extended) 75 233)]
-           (when multilingual? [add-language-button])]
-
-          ; Now create a cursor into the search-queries ratom for each search expression
-          ; and display a row of search inputs for each of them. The doall call is needed
-          ; because ratoms cannot be derefed inside lazy seqs.
-          (let [nqueries             (count @search-queries)
-                show-remove-row-btn? (> nqueries 1)]
-            (doall (for [index (range nqueries)]
-                     ;; Use wrap rather than cursor to send individual queries down to
-                     ;; child components (and in the extended view, we do the same for
-                     ;; individual terms). When a query (or query term) changes, the wrap
-                     ;; callbacks are called all the way up to the one setting the top-level
-                     ;; search-queries ratom, and all query views (potentially) re-render.
-                     ;;
-                     ;; By using cursors we could have restricted re-rendering to smaller
-                     ;; sub-views, but we need to do some processing of the query (such as
-                     ;; changing " .* " to []) before updating it in the search-queries ratom.
-                     ;; We could do this with a getter/setter-style cursor, but then we would
-                     ;; have to update the search-queries ratom anyway, causing the same potential
-                     ;; re-rendering of all query views.
-                     ;;
-                     ;; Probably the most efficient approach would be to use a standard cursor
-                     ;; (which only re-renders the view that derefs it) and explicitly call the
-                     ;; query processing function before updating the cursor, but then we would
-                     ;; have to make sure to do that every time we change a query...
-                     (let [wrapped-query     (reagent/wrap
-                                               (nth @search-queries index)
-                                               wrapped-query-changed search-queries index)
-                           selected-language (-> @wrapped-query :query :lang)]
-                       ^{:key index}
-                       [:div.row>div.col-md-12
-                        (when multilingual?
-                          [language-select languages selected-language])
-                        [view @corpus wrapped-query show-remove-row-btn?]]))))
-          (when-not multilingual? [add-phrase-button view])]))}))
+  (let [query-ids (atom nil)]
+    (reagent/create-class
+      {:display-name
+       "search-inputs"
+
+       :component-did-mount
+       focus-text-input
+
+       :reagent-render
+       (fn [{:keys [search-view search-queries]} {:keys [corpus]}]
+         (let [view          (case @search-view
+                               :extended extended
+                               :cqp cqp
+                               simple)
+               languages     (:langs @corpus)
+               multilingual? (> (count languages) 1)
+               set-view      (fn [view e] (reset! search-view view) (.preventDefault e))]
+           [:span
+            [:div.row.search-input-links>div.col-md-12
+             (if (= view simple)
+               [:b "Simple"]
+               [:a {:href     ""
+                    :title    "Simple search box"
+                    :on-click #(set-view :simple %)}
+                "Simple"])
+             " | "
+             (if (= view extended)
+               [:b "Extended"]
+               [:a {:href     ""
+                    :title    "Search for grammatical categories etc."
+                    :on-click #(set-view :extended %)}
+                "Extended"])
+             " | "
+             (if (= view cqp)
+               [:b "CQP query"]
+               [:a {:href     ""
+                    :title    "CQP expressions"
+                    :on-click #(set-view :cqp %)}
+                "CQP query"])
+             [search-button (if (= @search-view :extended) 75 233)]
+             (when multilingual? [add-language-button])]
+
+            ; Now create a cursor into the search-queries ratom for each search expression
+            ; and display a row of search inputs for each of them. The doall call is needed
+            ; because ratoms cannot be derefed inside lazy seqs.
+            (let [nqueries             (count @search-queries)
+                  query-range          (range nqueries)
+                  show-remove-row-btn? (> nqueries 1)]
+              ;; See explanation of query-term-ids in the extended view - query-ids is used
+              ;; in the same way, but for queries instead of query terms
+              (when (nil? @query-ids)
+                (reset! query-ids (vec query-range)))
+              (doall (for [index query-range
+                           :let [query-id (nth @query-ids index)]]
+                       ;; Use wrap rather than cursor to send individual queries down to
+                       ;; child components (and in the extended view, we do the same for
+                       ;; individual terms). When a query (or query term) changes, the wrap
+                       ;; callbacks are called all the way up to the one setting the top-level
+                       ;; search-queries ratom, and all query views (potentially) re-render.
+                       ;;
+                       ;; By using cursors we could have restricted re-rendering to smaller
+                       ;; sub-views, but we need to do some processing of the query (such as
+                       ;; changing " .* " to []) before updating it in the search-queries ratom.
+                       ;; We could do this with a getter/setter-style cursor, but then we would
+                       ;; have to update the search-queries ratom anyway, causing the same
+                       ;; potential re-rendering of all query views.
+                       ;;
+                       ;; Probably the most efficient approach would be to use a standard cursor
+                       ;; (which only re-renders the view that derefs it) and explicitly call the
+                       ;; query processing function before updating the cursor, but then we would
+                       ;; have to make sure to do that every time we change a query...
+                       (let [wrapped-query     (reagent/wrap
+                                                 (nth @search-queries index)
+                                                 wrapped-query-changed search-queries
+                                                 index query-ids)
+                             selected-language (-> @wrapped-query :query :lang)]
+                         ^{:key query-id}
+                         [:div.row
+                          [:div.col-md-12
+                           (when multilingual?
+                             [language-select languages selected-language])
+                           [view @corpus wrapped-query show-remove-row-btn?]]]))))
+            (when-not multilingual? [add-phrase-button view])]))})))


Make full house pugly

Make full house pugly

--- yatzy-clj/src/yatzy_clj/yatzy.clj
+++ yatzy-clj/src/yatzy_clj/yatzy.clj
@@ -50,10 +50,10 @@
 (defn fours [d1 d2 d3 d4 _5]
   (let [dice [d1 d2 d3 d4 _5]
         sum (apply +
-           (for [at (range 0 5)]
-             (if (= 4 (nth dice at)) 4 0)
-             )
-           )]
+                   (for [at (range 0 5)]
+                     (if (= 4 (nth dice at)) 4 0)
+                     )
+                   )]
     sum
     )
   )
@@ -62,10 +62,10 @@
 (defn fives_ [d1 d2 d3 d4 _5]
   (let [dice [d1 d2 d3 d4 _5]
         s (apply +
-           (for [i (range 0 (count dice))]
-             (if (= 5 (nth dice i)) 5 0)
-             )
-           )]
+                 (for [i (range 0 (count dice))]
+                   (if (= 5 (nth dice i)) 5 0)
+                   )
+                 )]
     s
     )
   )
@@ -73,26 +73,26 @@
 (defn sixes [d1 d2 d3 d4 _5]
   (let [dice [d1 d2 d3 d4 _5]
         sum (apply +
-           (for [at (range 0 (count dice))]
-             (if (= 6 (nth dice at)) 6 0)
-             )
-           )]
+                   (for [at (range 0 (count dice))]
+                     (if (= 6 (nth dice at)) 6 0)
+                     )
+                   )]
     sum
     )
   )

 (defn score_pair [dice]
   (let [counts (tally-die dice)
-      result (first
-               (remove nil?
-                       (for [at (range 0 6)]
-                         (if (>= (nth counts (- 6 at 1)) 2)
-                           (* (- 6 at) 2)
-                           nil
+        result (first
+                 (remove nil?
+                         (for [at (range 0 6)]
+                           (if (>= (nth counts (- 6 at 1)) 2)
+                             (* (- 6 at) 2)
+                             nil
+                             )
                            )
                          )
-                       )
-               )]
+                 )]
     (if (= nil result) 0 result)))

 (defn two-pair [dice]
@@ -103,24 +103,6 @@
                     (reduce +)
                     (* 2))]
     (if (= nil result) 0 result)))
-
-;public static int yatzy(int... dice)
-;{
-; int[] counts = new int[6];
-;    for (int die : dice)
-;    counts[die-1]++;
-; for (int i = 0; i != 6; i++)
-;    if (counts[i] == 5)
-;        return 50;
-; return 0;
-; }
-
-
-
-(defn get-first-tally [tallies value]
-  (->> (range 0 6)
-       (filter #(= value (nth tallies %)))
-       (first)))

 (defn four-of-a-kind [dice]
   (let [tallies (tally-die dice)
@@ -186,4 +168,33 @@
       0)))

 (defn full-house [dice]
-  (+ (score_pair dice) (three-of-a-kind dice)))+  (+
+    (let [counts (tally-die dice)
+          result (first
+                   (remove nil?
+                           (for [at (range 0 6)]
+                             (if (>= (nth counts (- 6 at 1)) 2)
+                               (* (- 6 at) 2)
+                               nil
+                               )
+                             )
+                           )
+                   )]
+      (if (= nil result) 0 result))
+    (let [t (tally-die dice)
+          result (first
+                   (remove nil?
+                           (for [i (range 0 6)]
+                             (if (>= (nth t i) 3)
+                               (* (+ i 1) 3)
+                               nil
+                               )
+                             )
+                           ))]
+      (if (= nil result)
+        0 result
+        )
+      )
+    )
+  )
+


csv-ize code-age data

csv-ize code-age data


Implemented concatenation of finger trees.

--- PersistentDataStructures/finger_trees.clj
+++ PersistentDataStructures/finger_trees.clj
@@ -6,7 +6,9 @@
 (defrecord finger-tree-single [v])
 (defrecord finger-tree-deep [l m r])

+(defn make-node-2 [a b] (node-2. a b))
 (defn make-node-3 [a b c] (node-3. a b c))
+(derive Object ::any)

 ; Reverse cons
 (defn snoc [a lst] (concat lst [a]))
@@ -14,7 +16,7 @@
 (defn tser [lst] (take (dec (count lst)) lst))

 ; Adds a new element to the front of the finger tree
-(defmulti push-front (fn [a _] (class a)))
+(defmulti push-front (fn [tree value] (class tree)))
 (defmethod push-front finger-tree-empty [_ a]
     (finger-tree-single. a))
 (defmethod push-front finger-tree-single [{r :v} a]
@@ -29,7 +31,7 @@
             r)))

 ; Adds a new element to the back of the finger tree
-(defmulti push-back (fn [a _] (class a)))
+(defmulti push-back (fn [tree value] (class tree)))
 (defmethod push-back finger-tree-empty [_ a]
     (finger-tree-single. a))
 (defmethod push-back finger-tree-single [{r :v} a]
@@ -43,6 +45,57 @@
                 (delay (push-back m-forced (apply make-node-3 (tser r)))))
             [(last r) a])))

+(defn nodes [a b & r]
+    (case (count r)
+        0 [(node-2. a b)]
+        1 [(node-3. a b (first r))]
+        2 [(node-2. a b) (apply make-node-2 r)]
+        (cons (node-3. a b (first r)) (apply nodes (rest r)))))
+
+(defmulti app3 (fn [l m r] [(class l) (class r)]))
+(defmethod app3 [finger-tree-empty ::any] [l m r]
+    (if (empty? m)
+        r
+        (app3
+            l
+            (tser m)
+            (push-front r (last m)))))
+(defmethod app3 [::any finger-tree-empty] [l m r]
+    (if (empty? m)
+        l
+        (app3
+            (push-back l (first m))
+            (rest m)
+            r)))
+(defmethod app3 [finger-tree-single ::any] [l m r]
+    (push-front (app3 (finger-tree-empty.) m r) (:v l)))
+(defmethod app3 [::any finger-tree-single] [l m r]
+    (push-back (app3 l m (finger-tree-empty.)) (:v r)))
+(defmethod app3 [finger-tree-deep finger-tree-deep] [l m r]
+    (finger-tree-deep.
+        (:l l)
+        (app3
+            (force (:m l))
+            (apply nodes (concat (:r l) m (:l r)))
+            (force (:m r)))
+        (:r r)))
+
+(prefer-method app3 [finger-tree-empty ::any] [::any finger-tree-empty])
+(prefer-method app3 [finger-tree-single ::any] [::any finger-tree-single])
+(prefer-method app3 [finger-tree-empty ::any] [::any finger-tree-single])
+
+(defmulti concatenate (fn [a b] [(class a) (class b)]))
+(defmethod concatenate [::any finger-tree-empty] [a _] a)
+(defmethod concatenate [finger-tree-empty ::any] [_ b] b)
+(defmethod concatenate [::any finger-tree-single] [a b]
+    (push-back a (:v b)))
+(defmethod concatenate [finger-tree-single ::any] [a b]
+    (push-front (:v a) b))
+(defmethod concatenate [finger-tree-deep finger-tree-deep] [a b]
+    (finger-tree-deep.
+        (:l a)
+        (app3 (force (:m a)) (apply nodes (concat (:r a) (:l b))) (force (:m b)))
+        (:r b)))

 ; Functions to print finger-trees to graphviz
 (defn object-id [x] (System/identityHashCode x))
@@ -51,37 +104,38 @@
 (defmethod print-entry node-2 [node parent-id]
     (do
         (println (object-id node) " [label=\"Node2\"]")
-        (println parent-id " -> " (object-id node))
+        (println parent-id " -> " (object-id node) " [weight=2]")
         (print-entry (:a node) (object-id node))
         (print-entry (:b node) (object-id node))))
 (defmethod print-entry node-3 [node parent-id]
     (do
         (println (object-id node) " [label=\"Node3\"]")
-        (println parent-id " -> " (object-id node))
+        (println parent-id " -> " (object-id node) " [weight=2]")
         (print-entry (:a node) (object-id node))
         (print-entry (:b node) (object-id node))
         (print-entry (:c node) (object-id node))))
 (defmethod print-entry :default [entry parent-id]
     (do
         (println (object-id entry) " [label=\"" entry "\"]")
-        (when parent-id (println parent-id " -> " (object-id entry)))))
+        (when parent-id (println parent-id " -> " (object-id entry) " [weight=1]"))))

 (defn print-digits [node parent-id]
     (do
         (println (object-id node) " [label=\"Digits\"]")
-        (when parent-id (println parent-id " -> " (object-id node)))
+        (when parent-id (println parent-id " -> " (object-id node) " [weight=3]"))
         (dorun (map (fn [x] (print-entry x (object-id node))) node))))

 (defmulti print-finger-tree (fn [node parent-id] (class node)))
 (defmethod print-finger-tree finger-tree-empty [_ _] nil)
 (defmethod print-finger-tree finger-tree-single [node parent-id]
     (do
-        (println (object-id node) " [label=\"Single\n" (:v node) "\"]")
-        (when parent-id (println parent-id " -> " (object-id node)))))
+        (println (object-id node) " [label=\"Single\"]")
+        (when parent-id (println parent-id " -> " (object-id node) " [weight=4]"))
+        (print-entry (:v node) (object-id node))))
 (defmethod print-finger-tree finger-tree-deep [node parent-id]
     (do
         (println (object-id node) " [label=\"Deep\"]")
-        (when parent-id (println parent-id " -> " (object-id node)))
+        (when parent-id (println parent-id " -> " (object-id node) " [weight=4]"))
         (print-digits (:l node) (object-id node))
         (print-finger-tree (force (:m node)) (object-id node))
         (print-digits (:r node) (object-id node))))
@@ -92,16 +146,25 @@
         (print-finger-tree tree nil)
         (println "}")))))

-(defn go [t n func filename]
+(defn go [t vec func filename]
     (do
         (println t "\n")
-        (if (<= n 0)
-            (print-finger-tree-to-file t filename)
-            (go (func t n) (dec n) func filename))))
+        (if (empty? vec)
+            (do
+                (print-finger-tree-to-file t filename)
+                t)
+            (go (func t (first vec)) (rest vec) func filename))))

 (println "Forwards..")
-(go (finger-tree-empty.) 20 push-front "/tmp/forwards.dot")
+(def t1 (go (finger-tree-empty.) (range 1 20) push-front "/tmp/forwards.dot"))

 (println "Backwards..")
-(go (finger-tree-empty.) 20 push-back "/tmp/backwards.dot")
+(def t2 (go (finger-tree-empty.) (range 20 40) push-back "/tmp/backwards.dot"))

+(print-finger-tree-to-file
+    (concatenate t1 t2)
+    "/tmp/concat1.dot")
+(print-finger-tree-to-file
+    (concatenate t2 t1)
+    "/tmp/concat2.dot")
+


Don't allow delays to nest.  I think this is the correct thing to do, but I'm not totally sure.

--- PersistentDataStructures/finger_trees.clj
+++ PersistentDataStructures/finger_trees.clj
@@ -23,9 +23,9 @@
         (finger-tree-deep. (cons a l) m r)
         (finger-tree-deep.
             [a (first l)]
-            (delay (push-front (force m) (apply make-node-3 (rest l))))
+            (let [m-forced (force m)]
+                (delay (push-front m-forced (apply make-node-3 (rest l)))))
             r)))
-

 ; Adds a new element to the back of the finger tree
 (defmulti push-back (fn [a _] (class a)))
@@ -38,7 +38,8 @@
         (finger-tree-deep. l m (snoc a r))
         (finger-tree-deep.
             l
-            (delay (push-back (force m) (apply make-node-3 (tser r))))
+            (let [m-forced (force m)]
+                (delay (push-back m-forced (apply make-node-3 (tser r)))))
             [(last r) a])))

 (defn go [t n func]


Move cljs tag outside state-proxy function

--- src/om_tools/core.cljx
+++ src/om_tools/core.cljx
@@ -57,10 +57,10 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Public

+#+cljs
 (defn state-proxy
   "Returns an atom-like object for reading and writing Om component state"
   [owner]
-  #+cljs
   (when owner
     (let [get-state #(om.core/get-state owner)]
       (reify


High level automation helper API

High level automation helper API


fix #1157

fix #1157

--- src/status_im/components/contact/styles.cljs
+++ src/status_im/components/contact/styles.cljs
@@ -55,6 +55,7 @@
   {:background-color (if checked common/color-light-blue common/color-gray5)
    :alignItems     :center
    :justifyContent :center
+   :margin-right   16
    :android        {:border-radius 2
                     :width         17
                     :height        17}


Deal with cljs stackoverflow.

Deal with cljs stackoverflow.


Harmonised play-melody and play-progression.

--- src/overtunes/core.clj
+++ src/overtunes/core.clj
@@ -43,19 +43,16 @@
   "Plays a chord progression on instrument according to metro's timing."
   [progression instrument metro]
   (when-not (empty? (first progression))
-    (let [weighted-chord (map first progression)
-          chord (first weighted-chord)
-          beats (second weighted-chord)]
+    (let [[[chord & chords] [timing & timings]] progression]
       (at (metro) (chord# chord))
-      (play-progression (map rest progression) instrument
-        (metronome-from metro beats)))))
+      (play-progression [chords timings] instrument (metronome-from metro timing)))))

 (defn play-melody
   "Plays a seq of weighted notes on instrument.
   Takes a relative metronome in addition to the melody.
   (play-melody [[:C3 :E3 :G3][1/1 1/2 3/2]] organ-cornet metro)"
   [melody instrument metro]
-  (let [[names timings] melody
-        notes (map note names)
-        melody-chords [(map #(hash-map :i %) notes) timings]]
-    (play-progression melody-chords instrument metro)))
+  (when-not (empty? (first melody))
+    (let [[[note & notes] [timing & timings]] melody]
+      (at (metro) (note# note))
+      (play-melody [notes timings] instrument (metronome-from metro timing)))))


Only attempt pdfs

Only attempt pdfs

--- src/tax_extractor/core.clj
+++ src/tax_extractor/core.clj
@@ -69,7 +69,6 @@
     (when-not (empty? (:name name-and-title))
       (.setTessVariable tess "tessedit_char_whitelist" number-chars)
       (assoc name-and-title
-        :hours (parse-hours (doocr (hours-rect y-off)))
         :reportable-internal-comp (parse-comp (doocr (reportable-internal-comp y-off)))
         :reportable-external-comp (parse-comp (doocr (reportable-external-comp y-off)))
         :other-comp (parse-comp (doocr (other-comp y-off)))))))
@@ -123,10 +122,13 @@
           (println "ERROR: Failed processing" (.getName pdf) "," (.getMessage e))))))
   (println " DONE"))

+(defn pdf? [file]
+  (.endsWith (.getName file) ".pdf"))
+
 (defn -main [path out-path]
   (.setTessVariable (Tesseract/getInstance) "debug_file" "/dev/null")
   (let [f (File. path)]
     (if (.isDirectory f)
-      (doseq [pdf (.listFiles f)]
+      (doseq [pdf (filter pdf? (.listFiles f))]
         (process-pdf pdf out-path))
       (process-pdf f out-path))))


Make S3 key a bit more palatable in URLs.

= is just gonna cause problems, let's not do that.

--- src/uswitch/bifrost/s3.clj
+++ src/uswitch/bifrost/s3.clj
@@ -13,7 +13,7 @@
 (def buffer-size 100)

 (defn generate-key [consumer-group-id topic partition first-offset]
-  (format "%s/%s/partition=%s/%s.baldr.gz"
+  (format "%s/%s/partition%02d/%s.baldr.gz"
           consumer-group-id
           topic
           partition


SER-1546 | add delete-thumbnails tests

SER-1546 | add delete-thumbnails tests

--- test/vignette/storage/static_assets_test.clj
+++ test/vignette/storage/static_assets_test.clj
@@ -103,3 +103,35 @@
             (provided
               (get-object #vignette.storage.core.ImageStorage{:store ..disk-store.., :cache-thumbnails true}
                           "abcd" "images/thumb/d6f0194a-ea6a-410d-9c45-81411b43abcd/nullpx-nullpx-null[format=webp]") => ..resource..)))
+
+(facts :static-assets :delete-thumbnails
+  (let [store (create-image-storage ..disk-store..)]
+
+    (delete-thumbnails (sa/create-static-image-storage store --static-asset-get--)
+      {:options {}, :image-type "images", :uuid "d6f0194a-ea6a-410d-9c45-81411b43abcd"}) => true
+    (provided
+      (object-exists? store "abcd" "images/thumb/d6f0194a-ea6a-410d-9c45-81411b43abcd/") => true
+      (list-objects store "abcd" "images/thumb/d6f0194a-ea6a-410d-9c45-81411b43abcd/") => {})
+
+    (delete-thumbnails (sa/create-static-image-storage store --static-asset-get--)
+      {:options {}, :image-type "images", :uuid "d6f0194a-ea6a-410d-9c45-81411b43abcd"}) => true
+    (provided
+      (object-exists? store "abcd" "images/thumb/d6f0194a-ea6a-410d-9c45-81411b43abcd/") => true
+      (list-objects store "abcd" "images/thumb/d6f0194a-ea6a-410d-9c45-81411b43abcd/") => {:objects [{:key "images/thumb/d6f0194a-ea6a-410d-9c45-81411b43abcd/test-thumb"}]}
+      (delete-object store "abcd" "images/thumb/d6f0194a-ea6a-410d-9c45-81411b43abcd/test-thumb") => nil)
+
+
+    (delete-thumbnails (sa/create-static-image-storage store --static-asset-get--)
+      {:options {}, :image-type "images", :uuid "d6f0194a-ea6a-410d-9c45-81411b43abcd"}) => true
+    (provided
+      (object-exists? store "abcd" "images/thumb/d6f0194a-ea6a-410d-9c45-81411b43abcd/") => false)
+
+    (delete-thumbnails (sa/create-static-image-storage store --static-asset-get--)
+      {:options {}, :image-type "images", :uuid "d6f0194a-ea6a-410d-9c45-81411b43abcd"}) => true
+    (provided
+      (object-exists? store "abcd" "images/thumb/d6f0194a-ea6a-410d-9c45-81411b43abcd/") => true
+      (list-objects store "abcd" "images/thumb/d6f0194a-ea6a-410d-9c45-81411b43abcd/") => {:objects [{:key "images/thumb/d6f0194a-ea6a-410d-9c45-81411b43abcd/test-thumb"},
+                                                                                {:key "images/thumb/d6f0194a-ea6a-410d-9c45-81411b43abcd/test-other-thumb"}]}
+      (delete-object store "abcd" "images/thumb/d6f0194a-ea6a-410d-9c45-81411b43abcd/test-thumb") => nil
+      (delete-object store "abcd" "images/thumb/d6f0194a-ea6a-410d-9c45-81411b43abcd/test-other-thumb") => nil)
+    ))


more cleanup

more cleanup


don't NPE when querying room-is-private? on non-extant rooms

--- src/subrosa/client.clj
+++ src/subrosa/client.clj
@@ -211,7 +211,7 @@
                     :mode mode))))

 (defn room-is-private? [room-name]
-  ((mode-for-room room-name) \p))
+  ((or (mode-for-room room-name) #{}) \p))

 (defn nicks-in-room [room-name]
   (map :user-nick (db/get :user-in-room :room-name room-name)))


Bump deps in example project.

Bump deps in example project.

--- example/project.clj
+++ example/project.clj
@@ -1,7 +1,7 @@
 (defproject my-lambda-project "0.1.0-SNAPSHOT"
   :description "Example lambada project."
-  :dependencies [[org.clojure/clojure "1.6.0"]
+  :dependencies [[org.clojure/clojure "1.8.0"]
                  [org.clojure/data.json "0.2.6"]
-                 [uswitch/lambada "0.1.0"]]
+                 [uswitch/lambada "0.1.2"]]
   :profiles {:uberjar {:aot :all}}
   :uberjar-name "my-lambda-project.jar")


Fact type fn works

Fact type fn works

--- src/todomvc/rules.cljs
+++ src/todomvc/rules.cljs
@@ -1,76 +1,103 @@
 (ns todomvc.rules
   (:require-macros [clara.macros :refer [defrule defquery defsession]])
-  (:require [clara.rules :refer [insert insert! insert-all! insert-all-unconditional!
+  (:require [clara.rules :refer [insert insert-all insert! insert-all! insert-all-unconditional!
                                  retract! query fire-rules]]
             [clara.rules.accumulators :as acc]))

-(defrecord Todo [id title done])
+;(defrecord Todo [id title done])
+;
+;(defrecord Showing [key])
+;
+;(defrecord VisibleTodos [todos])
+;
+;(defrecord ToggleComplete [])
+;
+;(defrule show-all
+;  [Showing (= key :all)]
+;  [?todos <- (acc/all) :from [Todo]]
+;  =>
+;  (prn "show-all rule fired" ?todos)
+;  (insert! (->VisibleTodos ?todos)))
+;
+;(defrule show-done
+;  [Showing (= key :done)]
+;  [?todos <- (acc/all) :from [Todo (= done true)]]
+;  =>
+;  (prn "show-done rule fired")
+;  (insert! (->VisibleTodos ?todos)))
+;
+;(defrule show-active
+;  [Showing (= key :active)]
+;  [?todos <- (acc/all) :from [Todo (= done false)]]
+;  =>
+;  (prn "show-active rule fired")
+;  (insert! (->VisibleTodos ?todos)))
+;
+;(defrule toggle-all-complete
+;  [?toggle <- ToggleComplete]
+;  [?todos <- (acc/all) :from [Todo]]
+;  =>
+;  (prn "toggle-all-complete rule fired")
+;  (prn "inserting" (map #(update % :done not) ?todos))
+;  (retract! ?toggle)
+;  (apply retract! ?todos)
+;  (insert-all-unconditional! (map #(update % :done not) ?todos)))
+;
+;(defquery find-showing
+;  []
+;  [?showing <- Showing])
+;
+;(defquery find-visible-todos
+;  []
+;  [?visible-todos <- VisibleTodos])
+;
+;(defquery find-todos
+;  []
+;  [?todos <- (acc/all) :from [Todo]])
+;
+;(defquery find-todo
+;  [:?id]
+;  [?todo <- Todo (= id ?id)])
+;
+;(defquery find-max-id
+;  []
+;  [?id <- (acc/max :id) :from [Todo]])
+;
+;(defquery find-all-done
+;  []
+;  [?todos <- (acc/all) :from [Todo (= done true)]])
+;
+;(defquery find-done-count
+;  []
+;  [?count <- (acc/count) :from [Todo (= done true)]])
+;
+(defquery really-find-todos
+  []
+  [?all <- (acc/all) :from [:todo/title]])

-(defrecord Showing [key])
+(defrule find-todos
+  [?x <- :todo/status [[e a v]] (= v :done)]
+  =>
+  (println)
+  (println "Found------------------------------ " ?x))

-(defrecord VisibleTodos [todos])
+(defn todo [v]
+  (let [temp-id (random-uuid)]
+    [[temp-id :todo/title v]
+     [temp-id :todo/status :done]]))

-(defrecord ToggleComplete [])
+(todo "Hi")

-(defrule show-all
-  [Showing (= key :all)]
-  [?todos <- (acc/all) :from [Todo]]
-  =>
-  (prn "show-all rule fired" ?todos)
-  (insert! (->VisibleTodos ?todos)))
+(defsession todos 'todomvc.rules :fact-type-fn (fn [[e a v]]
+                                                 (println [e a v])
+                                                 a))

-(defrule show-done
-  [Showing (= key :done)]
-  [?todos <- (acc/all) :from [Todo (= done true)]]
-  =>
-  (prn "show-done rule fired")
-  (insert! (->VisibleTodos ?todos)))
+(def facts (reduce concat (repeatedly 5 #(todo "TODO"))))

-(defrule show-active
-  [Showing (= key :active)]
-  [?todos <- (acc/all) :from [Todo (= done false)]]
-  =>
-  (prn "show-active rule fired")
-  (insert! (->VisibleTodos ?todos)))
+(println "facts" facts)

-(defrule toggle-all-complete
-  [?toggle <- ToggleComplete]
-  [?todos <- (acc/all) :from [Todo]]
-  =>
-  (prn "toggle-all-complete rule fired")
-  (prn "inserting" (map #(update % :done not) ?todos))
-  (retract! ?toggle)
-  (apply retract! ?todos)
-  (insert-all-unconditional! (map #(update % :done not) ?todos)))
+(fire-rules (insert-all todos facts))

-(defquery find-showing
-  []
-  [?showing <- Showing])
-
-(defquery find-visible-todos
-  []
-  [?visible-todos <- VisibleTodos])
-
-(defquery find-todos
-  []
-  [?todos <- (acc/all) :from [Todo]])
-
-(defquery find-todo
-  [:?id]
-  [?todo <- Todo (= id ?id)])
-
-(defquery find-max-id
-  []
-  [?id <- (acc/max :id) :from [Todo]])
-
-(defquery find-all-done
-  []
-  [?todos <- (acc/all) :from [Todo (= done true)]])
-
-(defquery find-done-count
-  []
-  [?count <- (acc/count) :from [Todo (= done true)]])
-
-(defsession todos 'todomvc.rules)
+(query session really-find-todos)


Add a sc field to the mock

Add a sc field to the mock

--- test/doctopus/test_utilities.clj
+++ test/doctopus/test_utilities.clj
@@ -46,6 +46,7 @@
   (map->Tentacle {:name (mock-data :string 10)
                   :html-commands [(mock-data :string 10)]
                   :output-root (mock-data :string 15)
+                  :source-control "git"
                   :source-location (mock-data :string 10)
                   :entry-point (mock-data :string 10)}))


Extra debugging

Extra debugging

--- src-shared/cljs/cljs_webrepl/repl_thread.cljs
+++ src-shared/cljs/cljs_webrepl/repl_thread.cljs
@@ -10,14 +10,20 @@
 (def script-name "js/repl-thread.js")

 (defn worker? []
-  (undefined? (.-document js/self)))
+  (nil? js/self.document))
+
+(defn worker-type []
+  (if (worker?)
+    :worker
+    :master))

 (defn- deserialize [reader msg]
+  (debugf "Deserialize: %s %s" (worker-type) (.-data.msg msg))
   (some->> (.-data.msg msg)
            (t/read reader)))

-(defn- serialzie [writer msg]
-  (debugf "Serialize: %s %s" (if (worker?) :worker :master) msg)
+(defn- serialize [writer msg]
+  (debugf "Serialize: %s %s"  (worker-type) msg)
   (let [msg (t/write writer msg)]
     (js-obj "msg" msg)))

@@ -30,7 +36,7 @@
         writer     (t/writer :json)

         finally-fn (fn []
-                     (debugf "Cleaning up WebWorker (worker thread? %s)" (worker?))
+                     (debugf "Cleaning up WebWorker %s" (worker-type))
                      (close! input-ch)
                      (close! output-ch)
                      (when close-fn
@@ -54,9 +60,9 @@
       (loop []
         (when-let [msg (<! input-ch)]
           (try
-            (.postMessage target (serialzie writer msg))
+            (.postMessage target (serialize writer msg))
             (catch js/Error e
-              (.postMessage target (serialzie writer [:webworker/error nil (str e)]))))
+              (.postMessage target (serialize writer [:webworker/error nil (str e)]))))
           (recur)))
       (finally-fn))
     {:input-ch  input-ch


Mihir | improving code, using composition rather than multiple methods

--- src/aggregatequeryservice/rendertemplates.clj
+++ src/aggregatequeryservice/rendertemplates.clj
@@ -4,10 +4,9 @@

 (defn get-query-result [query-results query-to-render]
   (->> query-results
-       (filter (fn [query]
-                 (= query-to-render (get query :queryName))))
-       (first)
-       (#(get %1 :result {}))
+       (filter-first (fn [query]
+                       (= query-to-render (get query :queryName))))
+       (:result)
        (first-one))
   )


adds tests for form params and basic auth

--- test/ring_curl/clj_http_test.clj
+++ test/ring_curl/clj_http_test.clj
@@ -16,8 +16,13 @@
              (subject/convert {:method :get}) => (contains {:request-method :get}))

        (fact ":url"
-             (subject/convert {:url "https://server-name:8080/some-path/here?query=param"}) => (contains {:scheme       :https
-                                                                                :server-name  "server-name"
-                                                                                :server-port  8080
-                                                                                :uri          "/some-path/here"
-                                                                                :query-string "query=param"})))+             (subject/convert {:url "https://server-name:8080/some-path/here?query=param"}) => (contains {:scheme      :https
+                                                                                :server-name "server-name"
+                                                                                :server-port 8080
+                                                                                :uri         "/some-path/here"}))
+
+       (fact ":form-params"
+             (subject/convert {:request-method :post :form-params {:foo "bar"}}) => (contains {:body "foo=bar"}))
+
+       (fact ":basic-auth"
+             (subject/convert {:basic-auth ["user" "pass"]}) => (contains {:headers {"authorization" "Basic dXNlcjpwYXNz"}})))


enable table links on thing, all and search pages

--- pedestal-app/app/src/semtag_web/rendering.cljs
+++ pedestal-app/app/src/semtag_web/rendering.cljs
@@ -72,7 +72,7 @@
 (defn set-search-title [renderer [_ path _ new-value] _]
   (dom/set-html! (dom/by-id "search_title") new-value))

-(defn render-search-results [_ [_ _ _ new-value] _]
+(defn render-search-results [_ [_ _ _ new-value] input-queue]
   (let [{:keys [things tags]} new-value]
     (dom/swap-content!
       (dom/by-id "table_stats")
@@ -84,7 +84,8 @@
       (p/generate-table "search_table" things
                         :fields [:type :name :url :desc :tags]
                         :row-partial p/tag-search-row
-                        :caption (format "Total: %s" (count (map :url things)))))))
+                        :caption (format "Total: %s" (count (map :url things)))))
+    (enable-clickable-links-on "#search_table td:not([data-field=url])" input-queue)))

 ;; we'd like to destroy/hide these but that requires changing render-search-results
 (defn clear-search [_ _ _]
@@ -153,15 +154,16 @@

   (enable-clickable-links-on "#tag_stats_table" input-queue))

-(defn render-all-results [_ [_ _ _ new-value] _]
+(defn render-all-results [_ [_ _ _ new-value] input-queue]
   (dom/set-html!
     (dom/by-id "content")
     (p/generate-table "all_table" new-value
                       :row-partial p/all-row
                       :caption (str "Total: " (count new-value))
-                      :fields [:type :name :url :tags :created-at])))
-
-(defn render-thing-results [_ [_ path _ new-value] _]
+                      :fields [:type :name :url :tags :created-at]))
+  (enable-clickable-links-on "#all_table td:not([data-field=url])" input-queue))
+
+(defn render-thing-results [_ [_ path _ new-value] input-queue]
   (let [thing-id (nth path (- (count path) 2))]
     (dom/set-html!
       (dom/by-id "content")
@@ -170,7 +172,8 @@
                         ;; TODO - fix id when it renders
                         :caption (if (re-find #"\d+$" thing-id) "" (p/link-tagged thing-id))
                         :row-partial p/thing-row
-                        :fields [:attribute :value]))))
+                        :fields [:attribute :value])))
+  (enable-clickable-links-on "#thing_show_table" input-queue))

 (defn href-sets-focus [{:keys [transform messages event]}]
   (if-let [screen (route/url->screen (->> event .-currentTarget .-href (re-find #"#.*?$")))]


Fix tests when $TERM is unset

Fix tests when $TERM is unset

This test did not reflect the behavior of config.edn

--- test/aero/core_test.cljc
+++ test/aero/core_test.cljc
@@ -111,7 +111,7 @@

 (deftest format-test
   (let [config (read-config "test/aero/config.edn")]
-    (is (= (#?(:clj format :cljs gstring/format) "My favorite flavor is %s %s" (str (env "TERM")) :chocolate)
+    (is (= (#?(:clj format :cljs gstring/format) "My favorite flavor is %s %s" (or (env "TERM") "flaa") :chocolate)
            (:flavor-string config)))))

 (deftest ref-test


when already creates an implicit do

when already creates an implicit do

--- src/overtone/sc/machinery/server/comms.clj
+++ src/overtone/sc/machinery/server/comms.clj
@@ -102,9 +102,8 @@
            key  (uuid)]
        (on-event "/synced"
                  (fn [msg] (when (= id (first (:args msg)))
-                            (do
-                              (deliver prom true)
-                              :overtone/remove-handler)))
+                            (deliver prom true)
+                            :overtone/remove-handler))
                  key)
        (let [res (action-fn)]
          (server-snd "/sync" id)


(maint) clean up imports

(maint) clean up imports

--- src/puppetlabs/trapperkeeper/bootstrap.clj
+++ src/puppetlabs/trapperkeeper/bootstrap.clj
@@ -1,15 +1,12 @@
 (ns puppetlabs.trapperkeeper.bootstrap
   (:import (java.io Reader FileNotFoundException)
            (java.net URI))
-  (:require [clojure.java.io :refer [IOFactory]]
-            [clojure.string :as string]
-            [clojure.java.io :refer [reader resource file input-stream]]
+  (:require [clojure.string :as string]
+            [clojure.java.io :as io]
             [clojure.tools.logging :as log]
             [puppetlabs.trapperkeeper.plugins :as plugins]
-            [puppetlabs.trapperkeeper.config :refer [parse-config-data
-                                                     initialize-logging!]]
-            [puppetlabs.trapperkeeper.internal :as i]
-            [puppetlabs.trapperkeeper.services :as s]))
+            [puppetlabs.trapperkeeper.internal :as internal]
+            [puppetlabs.trapperkeeper.services :as services]))

 (def bootstrap-config-file-name "bootstrap.cfg")

@@ -40,14 +37,14 @@
   [resolve-ns service-name]
   {:pre  [(string? resolve-ns)
           (string? service-name)]
-   :post [(satisfies? s/ServiceDefinition %)]}
+   :post [(satisfies? services/ServiceDefinition %)]}
   (try (require (symbol resolve-ns))
        (catch FileNotFoundException e
          (throw (IllegalArgumentException.
                   (str "Unable to load service: " resolve-ns "/" service-name)
                   e))))
   (if-let [service-def (ns-resolve (symbol resolve-ns) (symbol service-name))]
-    (i/validate-service-graph! (var-get service-def))
+    (internal/validate-service-graph! (var-get service-def))
     (throw (IllegalArgumentException.
              (str "Unable to load service: " resolve-ns "/" service-name)))))

@@ -64,14 +61,14 @@

 (defn- get-config-source
   [config-path]
-  (let [config-file (file config-path)]
+  (let [config-file (io/file config-path)]
     (if (.exists config-file)
       config-file

       ;; if that didn't work (won't for a URI of a file inside a .jar),
       ;; get a bigger hammer
       (try
-        (input-stream (URI. config-path))
+        (io/input-stream (URI. config-path))
         (catch Exception ignored
           ;; If that didn't work either, we can't read it.  Don't wrap and
           ;; re-throw here, as `ignored` may be misleading (in the case of a
@@ -90,7 +87,7 @@
   [cli-data]
   {:pre  [(map? cli-data)]
    :post [(or (nil? %)
-              (satisfies? IOFactory %))]}
+              (satisfies? io/IOFactory %))]}
   (when (contains? cli-data :bootstrap-config)
     (when-let [config-path (cli-data :bootstrap-config)]
       (let [config-file (get-config-source config-path)]
@@ -104,9 +101,9 @@
   directory;  if so, return it."
   []
   {:post [(or (nil? %)
-              (satisfies? IOFactory %))]}
+              (satisfies? io/IOFactory %))]}
   (let [config-file (-> bootstrap-config-file-name
-                        (file)
+                        (io/file)
                         (.getAbsoluteFile))]
     (when (.exists config-file)
       (log/debug (str "Loading bootstrap config from current working directory: '"
@@ -118,8 +115,8 @@
   if so, return it."
   []
   {:post [(or (nil? %)
-              (satisfies? IOFactory %))]}
-  (when-let [classpath-config (resource bootstrap-config-file-name)]
+              (satisfies? io/IOFactory %))]}
+  (when-let [classpath-config (io/resource bootstrap-config-file-name)]
     (log/debug (str "Loading bootstrap config from classpath: '" classpath-config "'"))
     classpath-config))

@@ -132,7 +129,7 @@
   [cli-data]
   {:pre  [(map? cli-data)]
    :post [(or (nil? %)
-              (satisfies? IOFactory %))]}
+              (satisfies? io/IOFactory %))]}
   (if-let [bootstrap-config (or (config-from-cli cli-data)
                                 (config-from-cwd)
                                 (config-from-classpath))]
@@ -146,10 +143,10 @@
   that is the result of merging the graphs of all of the services specified in
   the configuration."
   [config]
-  {:pre  [(satisfies? IOFactory config)]
+  {:pre  [(satisfies? io/IOFactory config)]
    :post [(sequential? %)
-          (every? #(satisfies? s/ServiceDefinition %) %)]}
-  (let [lines (line-seq (reader config))]
+          (every? #(satisfies? services/ServiceDefinition %) %)]}
+  (let [lines (line-seq (io/reader config))]
     (when (empty? lines) (throw (Exception. "Empty bootstrap config file")))
     (for [line (map remove-comments lines)
           :when (not (empty? line))]


form replicas -> single label instead of chip ..

--- src/cljs/swarmpit/component/service/list.cljs
+++ src/cljs/swarmpit/component/service/list.cljs
@@ -10,17 +10,6 @@
 (def cursor [:page :service :list :filter])

 (def headers ["Name" "Image" "Mode" "Replicas" "Status" "Updates"])
-
-(def form-replicas-style
-  {:backgroundColor "rgb(245, 245, 245)"
-   :border          "1px solid rgb(224, 228, 231)"})
-
-(def form-replicas-label-style
-  {:fontSize "13px"})
-
-(defn- form-replicas [value]
-  (comp/chip {:style      form-replicas-style
-              :labelStyle form-replicas-label-style} value))

 (defn- form-updates [value]
   (let [status (if value "loading" "ready")]
@@ -53,7 +42,7 @@
   (let [value (val item)]
     (case (key item)
       :state (form-state value)
-      :info (form-replicas value)
+      :info (comp/label-info value)
       :update (form-updates value)
       value)))


Fix bug in f> f>= f< f<= 2-arity forms

Fix bug in f> f>= f< f<= 2-arity forms

--- src/clojure/uncomplicate/neanderthal/math.clj
+++ src/clojure/uncomplicate/neanderthal/math.clj
@@ -22,25 +22,25 @@
   ([^double x ^double y ^double nepsilons]
    (< (Precision/compareTo x y (* Precision/EPSILON nepsilons)) 0))
   ([^double x ^double y]
-   (< (Precision/compareTo x y Precision/EPSILON))))
+   (< (Precision/compareTo x y Precision/EPSILON) 0)))

 (defn f<=
   ([^double x ^double y ^double nepsilons]
    (<= (Precision/compareTo x y (* Precision/EPSILON nepsilons)) 0))
   ([^double x ^double y]
-   (<= (Precision/compareTo x y Precision/EPSILON))))
+   (<= (Precision/compareTo x y Precision/EPSILON) 0)))

 (defn f>
   ([^double x ^double y ^double nepsilons]
    (> (Precision/compareTo x y (* Precision/EPSILON nepsilons)) 0))
   ([^double x ^double y]
-   (> (Precision/compareTo x y Precision/EPSILON))))
+   (> (Precision/compareTo x y Precision/EPSILON) 0)))

 (defn f>=
   ([^double x ^double y ^double nepsilons]
    (>= (Precision/compareTo x y (* Precision/EPSILON nepsilons)) 0))
   ([^double x ^double y]
-   (>= (Precision/compareTo x y Precision/EPSILON))))
+   (>= (Precision/compareTo x y Precision/EPSILON) 0)))

 (defn pow-of-2? [^long n]
   (= 0 (bit-and n (- n 1))))


Add NOTE regarding automatic tag-document-push.

--- src-cljs/pepa/api.cljs
+++ src-cljs/pepa/api.cljs
@@ -235,6 +235,9 @@
   (go
     (store-tags! state (<! (fetch-tags true)))))

+;;; TODO: We might want to store all document-ids for a tag. That
+;;; would allow us to skip querying the server when doing a tag
+;;; search. This should work as tags are always up-to-date (via push).
 (defn refresh-tag! [state tag]
   (go
     (println "refreshing tag" (pr-str tag))


Fix missing function calls

Fix missing function calls

--- src/bakyeono/litedocx.clj
+++ src/bakyeono/litedocx.clj
@@ -1,7 +1,7 @@
 (ns bakyeono.litedocx
   "litedocx is a light-weight DOCX format writer library for Clojure."
   (:use [bakyeono.litedocx.util])
-  (:use [bakyeono.litedocx.wpml]))
+  (:require [bakyeono.litedocx.wpml :as w]))

 (defrecord Resource [id type content-type part-name])

@@ -10,13 +10,13 @@
 (defn create-docx-package
   "Creates DOCX package."
   [dst]
-  (let [content-types-xml (snippet-content-types-xml [])
-        doc-props-app-xml (snippet-doc-props-app-xml)
-        doc-props-core-xml (snippet-doc-props-core-xml)
-        word-document-xml (snippet-word-document-xml)
-        word-styles-xml (snippet-word-styles-xml [])
+  (let [content-types-xml (w/content-types-xml [])
+        doc-props-app-xml (w/doc-props-app-xml)
+        doc-props-core-xml (w/doc-props-core-xml)
+        word-document-xml (w/word-document-xml)
+        word-styles-xml (w/word-styles-xml [])
         word-media-resources nil
-        word-rels-document-xml-rels (snippet-word-rels-document-xml-rels [])]
+        word-rels-document-xml-rels (w/word-rels-document-xml-rels [])]
     (write-zip dst
                "[Content_Types].xml" content-types-xml
                "docProps/app.xml" doc-props-app-xml


[#1450] Use akvo.util/conform for spec validation

--- backend/specs/akvo/lumen/specs/import.clj
+++ backend/specs/akvo/lumen/specs/import.clj
@@ -1,5 +1,6 @@
 (ns akvo.lumen.specs.import
   (:require [akvo.lumen.specs :as lumen.s]
+            [akvo.lumen.util :as u]
             [akvo.lumen.specs.import.column :as c]
             [clojure.spec.alpha :as s]
             [clojure.spec.gen.alpha :as gen]
@@ -25,7 +26,7 @@
                              (range (count headers))))
         _         (do
                     ;; "ensure columns headers are valid specs"
-                    (reduce #(assert (s/valid? ::c/header %2) %) [] columns))
+                    (reduce (fn [_ i] (u/conform ::c/header i)) [] columns))
         row-types (map (fn [t]
                          (let [t (if (sequential? t) (first t) t)]
                            (kw->body-spec t))) types-gens-tuple)
@@ -39,6 +40,6 @@
                           [] (range rows-count))
         _         (do
                    ;;  "ensure column bodies (cells) are valid specs"
-                    (reduce #(assert (s/valid? ::c/body %2) %) [] (flatten rows0)))
+                    (reduce (fn [_ i] (u/conform ::c/body i)) [] (flatten rows0)))
         rows      (mapv #(mapv (fn [c] (dissoc c :type)) %) rows0)]
     {:columns columns :rows rows}))


[#532] Implement some parial pivot queries

--- backend/src/akvo/lumen/lib/pivot_impl.clj
+++ backend/src/akvo/lumen/lib/pivot_impl.clj
@@ -47,7 +47,7 @@
                           (range categories-count)))
        ");"))

-(defn run-query [conn dataset query filter-str]
+(defn apply-pivot [conn dataset query filter-str]
   (let [categories (unique-values conn
                                   (:table-name dataset)
                                   (:category-column query)
@@ -65,9 +65,43 @@
                         {:as-arrays? true}))
      :columns columns}))

+(defn apply-empty-query [conn dataset filter-str]
+  (let [count (rest (jdbc/query conn
+                                [(format "SELECT count(rnum) FROM %s WHERE %s"
+                                         (:table-name dataset)
+                                         filter-str)]
+                                {:as-arrays? true}))]
+    {:columns [{"type" "number"
+                "title" "Total"}]
+     :rows count}))
+
+(defn apply-empty-category-query [conn dataset query filter-str]
+  {:rows []
+   :columns []})
+
+(defn apply-empty-row-query [conn dataset query filter-str]
+  {:rows []
+   :columns []})
+
+(defn apply-empty-value-query [conn dataset query filter-str]
+  {:rows []
+   :columns []})
+
+(defn apply-query [conn dataset query filter-str]
+  (cond
+    (and (nil? (:row-column query))
+         (nil? (:category-column query)))
+    (apply-empty-query conn dataset filter-str)
+    (nil? (:category-column query))
+    (apply-empty-category-query conn dataset query filter-str)
+    (nil? (:row-column query))
+    (apply-empty-row-query conn dataset query filter-str)
+    (nil? (:value-column query))
+    (apply-empty-value-query conn dataset query filter-str)
+    :else (apply-pivot conn dataset query filter-str)))
+
 (defn find-column [columns column-name]
-  (first (filter #(= column-name (get % "columnName"))
-                 columns)))
+  (first (filter #(= column-name (get % "columnName")) columns)))

 (defn build-query
   "Replace column names with proper column metadata from the dataset"
@@ -86,7 +120,11 @@
     (if-let [dataset (dataset-by-id conn {:id dataset-id})]
       (let [q (build-query (:columns dataset) query)]
         (if (valid-query? q)
-          (http/ok (run-query conn dataset q (filter/sql-str (:columns dataset) (:filters q))))
+          (try
+            (http/ok (apply-query conn dataset q (filter/sql-str (:columns dataset) (:filters q))))
+            (catch clojure.lang.ExceptionInfo e
+              (http/bad-request (merge {:message (.getMessage e)}
+                                       (ex-data e)))))
           (http/bad-request {"query" query})))
       (http/not-found {"datasetId" dataset-id}))))

@@ -100,11 +138,20 @@
   (def q {"categoryColumn" "c16"
           "rowColumn" "c4"
           "valueColumn" "c19"
-          "aggregation" "avg"})
+          "aggregation" "avg"
+          "filters" [{"column" "c2"
+                      "columnType" "text"
+                      "operation" "keep"
+                      "strategy" "is"
+                      "value" "Ethiopia"}]})

-  (run-query tenant-conn dataset {:category-column (second (:columns dataset))})
+  (def empty-q {"categoryColumn" nil
+                "rowColumn" nil
+                "valueColumn" nil
+                "aggregation" "count"
+                "filters" []})

-  (query tenant-conn dataset-id q)
+  (query tenant-conn dataset-id empty-q)

   (unique-categories tenant-conn dataset-id)


First version that passed a simple test.

--- src/blutwurst/planner.clj
+++ src/blutwurst/planner.clj
@@ -4,21 +4,23 @@
               [clojure.pprint :refer :all]))

 (defn- find-nodes-without-incoming-connections [nodes edges]
+ (if (empty? edges)
+  nodes
  (filter #(some (complement (fn [e]
                              (and (= (:to-schema e) (:schema %))
                                   (= (:to-name e) (:name %)))))
                  edges)
-         nodes))
+         nodes)))

 (defn- incoming-to-node [node edge]
  (and (= (:to-schema edge) (:schema node))
       (= (:to-name edge) (:name edge))))

 (defn- topological-schema-sort [all-nodes nonentrant-nodes edges result]
- (trace "Entering topological schema sort non-entrant: " (pr-str (seq nonentrant-nodes))
-        "Edges: " (pr-str (seq edges ))
-        "Result: " (pr-str (seq result))
-        "All nodes: " (pr-str (seq all-nodes)))
+ (trace "Entering topological schema sort non-entrant: " (pr-str (seq nonentrant-nodes)))
+        (trace "Edges: " (pr-str (seq edges )))
+        (trace "Result: " (pr-str (seq result)))
+        ;(trace "All nodes: " (pr-str (seq all-nodes)))

  (if (empty? nonentrant-nodes)
   (if (not (empty? edges))
@@ -28,13 +30,13 @@
   (let [current-node (first nonentrant-nodes)
         nonentrant-nodes (rest nonentrant-nodes)
         result (cons current-node result)
-        pruned-edges (keep (complement (partial incoming-to-node current-node)) edges)]
+        pruned-edges (filter (partial incoming-to-node current-node) edges)
+       ]
+
+    (trace "Edges after pruning: " (pr-str (seq pruned-edges)))

     (recur all-nodes
-           (concat nonentrant-nodes
-                  (find-nodes-without-incoming-connections (setops/intersection all-nodes result nonentrant-nodes)
-                                                           pruned-edges))
-           ;nonentrant-nodes
+          (find-nodes-without-incoming-connections (setops/difference (set all-nodes) (set result)) pruned-edges)
            pruned-edges
            result)
   ))


fix comment typo

fix comment typo

--- src/bract/core/config.clj
+++ src/bract/core/config.clj
@@ -111,7 +111,7 @@
       (let [pre-config (ctx-config context)]
         (as-> config-filenames <>
           (keypin/read-config <> (assoc keypin-opts
-                                   :realize? false)) ; read config, but do not relalize (i.e. evaluate variables)
+                                   :realize? false)) ; read config, but do not realize (i.e. evaluate variables)
           (kputil/clojurize-data <>)
           (merge pre-config <>)                      ; merge config onto the pre-existing config
           (keypin/realize-config <> keypin-opts)


Fix missing )

Fix missing )

--- frontend/controllers/controls.cljs
+++ frontend/controllers/controls.cljs
@@ -13,7 +13,7 @@
 ;; --- Helper Methods ---

 (defn container-id [container]
-  (int (last (re-find #"container_(\d+)" (.-id container))))
+  (int (last (re-find #"container_(\d+)" (.-id container)))))

 ;; --- Navigation Multimethod Declarations ---


add shutdown hook to execute shutdown sequence on jvm shutdown (#103)

--- src/clj/lambdacd/core.clj
+++ src/clj/lambdacd/core.clj
@@ -10,8 +10,10 @@

 (defn- add-shutdown-sequence! [ctx]
   (doto (Runtime/getRuntime)
-    (.addShutdownHook (fn []
-                        ((:shutdown-sequence (:config ctx)) ctx)))))
+    (.addShutdownHook (Thread. (fn []
+                                 (log/info "Shutting down LambdaCD...")
+                                 ((:shutdown-sequence (:config ctx)) ctx)))))
+  ctx)

 (def default-shutdown-sequence
   (fn [ctx]
@@ -35,7 +37,8 @@
                                     (event-bus/initialize-event-bus)
                                     (running-builds-tracking/initialize-running-builds-tracking)
                                     (assoc :pipeline-state-component pipeline-state-component)
-                                    (initialize-pipeline-state-updater))]
+                                    (initialize-pipeline-state-updater)
+                                    (add-shutdown-sequence!))]
      {:context                context
       :pipeline-def           pipeline-def})))


filter out empty string tokens

filter out empty string tokens

--- src/clj/om_lette/copy.clj
+++ src/clj/om_lette/copy.clj
@@ -83,7 +83,8 @@
                       0 nil
                       1 [:om-text (first x)]
                       2 [:om-text (-> x drop-delim first)]
-                      3 [:om-code (second x)])))))
+                      3 [:om-code (second x)])))
+       (filter #(-> % second not-empty))))

 (defn grab-om-attrs
   [a ks]
@@ -109,7 +110,7 @@
                                     (like-html-vec? t) (update-in t [1] grab-om-attrs [:om-if :om-repeat])
                                     :else t)))))

-#_(html->template "

")
+#_(html->template "

")

 #_(-> "

"
       hick/parse-fragment


fix 'help' command and allow multiple slack cmds

now sending a message like:

    123 this taht
    855 foo bar

will behave as you might expect!

--- src/clj/tictag/server.clj
+++ src/clj/tictag/server.clj
@@ -112,8 +112,8 @@
     (debugf "Making pings sleepy: %s" (pr-str sleepy-pings))
     (update-pings! component user (map #(assoc % :tags #{"sleep"}) sleepy-pings))
     (slack! component user ["sleepings pings: %s to %s"
-                  (f/unparse wtf (:local-time (last sleepy-pings)))
-                  (f/unparse wtf (:local-time (first sleepy-pings)))])))
+                            (f/unparse wtf (:local-time (last sleepy-pings)))
+                            (f/unparse wtf (:local-time (first sleepy-pings)))])))

 (defmethod apply-command! :tag-ping-by-id [{db :db :as component} user _ {:keys [id tags]}]
   (tag-ping component user (db/ping-from-id db user id) (set tags)))
@@ -128,12 +128,13 @@
   (let [[last-ping second-to-last-ping] (db/last-pings db user 2)]
     (tag-ping component user last-ping (:tags second-to-last-ping))))

-(defmethod apply-command! :help [_ user _ _]
-  (slack! user ["Tag the most recent ping (e.g. by saying `ttc`)
+(defmethod apply-command! :help [c user _ _]
+  (slack! c user ["Tag the most recent ping (e.g. by saying `ttc`)
 Tag a ping by its id (e.g. by saying `113 ttc`)
 Tag a ping by its long-time (e.g. by saying `1494519002000 ttc`)
 `sleep` command: tag the most recent set of contiguous pings as `sleep`
 `\"` command: tags the last ping with whatever the second-to-last ping had
+Separate commands with a newline to apply multiple commands at once
 "]))

 (defn apply-command [component user cmd]
@@ -152,7 +153,8 @@
   (taoensso.timbre/logged-future
     (when-let [user (and (valid-slack? component params)
                          (slack-user db params))]
-      (apply-command component user (slack-text params))))
+      (doseq [c (str/split (slack-text params) #"\n")]
+        (apply-command component user c))))
   {:status 200 :body ""})

 (defn timestamp [{:keys [db] :as component} {:keys [params user-id]}]


metadata reader

metadata reader

--- src/cljs/cljs/reader.cljs
+++ src/cljs/cljs/reader.cljs
@@ -46,6 +46,11 @@
   "Checks whether the character begins a comment."
   [ch]
   (= \; ch))
+
+(defn- meta-prefix?
+  "Checks whether the character begins metadata"
+  [ch]
+  (= \^ ch))

 (defn- number-literal?
   "Checks whether the reader is at the start of a number literal"
@@ -148,6 +153,24 @@
 (defn read-symbol
   [reader initch is-recursive])

+(defn desugar-meta
+  [f]
+  (cond
+   (symbol? f) {:tag f}
+   (string? f) {:tag f}
+   (keyword? f) {f true}
+   :else f))
+
+(defn read-meta
+  [rdr _]
+  (let [m (desugar-meta (read rdr true nil true))]
+    (when-not (map? m)
+      (throw "Metadata must be Symbol,Keyword,String or Map"))
+    (let [o (read rdr true nil true)]
+      (if (satisfies? IWithMeta o)
+        (with-meta o (merge (meta o) m))
+        (throw "Metadata can only be applied to IWithMetas")))))
+
 (defn read
   "Reads the first object from a PushbackReader. Returns the object read.
 Returns sentinel if the reader did not contain any forms."
@@ -162,6 +185,7 @@
      (list-prefix? ch) (read-list reader ch)
      (vector-prefix? ch) (read-vector reader ch)
      (map-prefix? ch) (read-map reader ch)
+     (meta-prefix? ch) (read-meta reader ch)
      :default (read-symbol reader ch))))


Follow advice from Joy of Clojure - use  when there's no else condition

--- src/cljs/fatlip/core.cljs
+++ src/cljs/fatlip/core.cljs
@@ -722,8 +722,8 @@
 (defn check-alignment
   "Checks whether a predecessor is a valid alignment candidate"
   [pred last-idx marked]
-  (if (and (< last-idx (:idx pred))
-           (not (contains? marked (:edge pred))))
+  (when (and (< last-idx (:idx pred))
+             (not (contains? marked (:edge pred))))
     pred))


fixed bug updating unit resource

fixed bug updating unit resource

--- src/cljs/lokate/unit.cljs
+++ src/cljs/lokate/unit.cljs
@@ -135,8 +135,9 @@
   (update-unit unit :resources
     (if active?
       #(dissoc % (:id rsc))
-      #(when (not (contains? % (:id rsc)))
-         (assoc % (:id rsc) (unit-rsc rsc))))))
+      #(if-not (contains? % (:id rsc))
+         (assoc % (:id rsc) (unit-rsc rsc))
+         %))))

 (defn rsc-block
   [[{:keys [action]} block] owner]


Add src to Edge records, refine cross counting to count based on the layer with fewer nodes

--- src/cljs/nchart/core.cljs
+++ src/cljs/nchart/core.cljs
@@ -23,7 +23,7 @@

 (defrecord Node [id layer-id characters])
-(defrecord Edge [dest characters])
+(defrecord Edge [src dest characters])
 (defrecord Layer [id duration nodes marked])
 (defrecord SegmentContainer [segments])
 (defrecord Segment [edge])
@@ -32,9 +32,20 @@

 (defn- add-edge [graph last-node node characters]
   "Creates an edge and adds it to the graph as a whole and to each participating node"
-  (-> graph
-      (update-in [:succs last-node] (fnil conj #{}) (Edge. node characters))
-      (update-in [:preds node] (fnil conj #{}) (Edge. last-node characters))))
+  (let [forward-edge (Edge. last-node node characters)
+        ;; We record the "true" forward edge here, for marking edges that
+        ;; cross segment containers. The ordering algorithm works through
+        ;; the graph backwards on every second pass, and the cross counting
+        ;; algorithm switches the order of the layers depending on which
+        ;; is smaller, but we always layout and draw the graph forward, so the
+        ;; marked edges need to be the forward ones.
+        edge-1 (-> forward-edge
+                   (assoc :forward-edge forward-edge))
+        edge-2 (-> (Edge. node last-node characters)
+                   (assoc :forward-edge forward-edge))]
+    (-> graph
+        (update-in [:succs last-node] (fnil conj #{}) edge-1)
+        (update-in [:preds node] (fnil conj #{}) edge-2))))

 (defn- make-node [graph layer-id input]
@@ -348,18 +359,19 @@

-(defn- sorted-next-edge-order
+(defn- sorted-edge-order
   "Sorts edges between two ordered layers first by their index in the source
   layer, and then by their index in the destination layer. Then, returns seq
   of [order edge] pairs of the edge targets in the destination layer, using
   this edge ordering"
-  [graph ordered next-ordered]
+  [ordered next-ordered graph-edges]
   (let [next-order-map (->> next-ordered
                             (map-indexed #(-> [%2 %1]))
                             (into {}))
         ;; Edges between segment containers need to be counted as well
         ;; but they change with each new ordering, so we just temporarily
-        ;; merge the current segment edges with the immutable node -> node edges
+        ;; merge the current segment edges with the never-changing
+        ;; node -> node edges
         edges (->> next-ordered
                    (filter #(instance? SegmentContainer %))
                    (map (juxt identity
@@ -367,9 +379,9 @@
                                 (mapcat #(-> % :edge :characters)
                                         (:segments seg-c)))))
                    (map (fn [[seg-c characters]]
-                          [seg-c (Edge. seg-c characters)]))
+                          [seg-c (Edge. seg-c seg-c characters)]))
                    (into {})
-                   (merge (:succs graph)))]
+                   graph-edges)]
     (->> ordered
          (mapcat (fn [item]
                    (sort-by #(get next-order-map (:dest %))
@@ -402,7 +414,7 @@
   adding right siblings, for a total count of edges that cross this one"
   [layer tree orig-index edge]
   (let [weight (count (:characters edge))
-        is-seg-c (instance? SegmentContainer edge)]
+        is-seg-c (instance? SegmentContainer (:dest edge))]
     (loop [layer layer
            tree tree
            index orig-index
@@ -418,7 +430,7 @@
                   marked (if is-seg-c
                            (:node-edges right-sib)
                            (if (:is-seg-c right-sib)
-                             #{edge}
+                             #{(:forward-edge edge)}
                              #{}))
                   l (update-in layer [:marked] set/union marked)]
               (recur l tree parent-index c))
@@ -426,7 +438,7 @@
                         (update-in [index :weight] + weight)
                         (cond->
                          is-seg-c (assoc-in [index :is-seg-c] true)
-                         (not is-seg-c) (update-in [index :node-edges] conj edge)))]
+                         (not is-seg-c) (update-in [index :node-edges] conj (:forward-edge edge))))]
               (recur layer t parent-index crossings))))))))

@@ -435,15 +447,18 @@
   bi-layer ordering. Implements the algorithm found in Bilayer Cross Counting,
   by Wilhelm Barth, Petra Mutzel and Michael Jünger"
   [graph layer next-layer]
-  (let [next-edge-order (sorted-next-edge-order graph
-                                                (:minus-ps layer)
-                                                (:without-qs next-layer))
-        tree-size (next-power-of-2-minus-1 (count (:without-qs next-layer)))
+  (let [minus-p (:minus-ps layer)
+        without-qs (:without-qs next-layer)
+        [layer-1 layer-2 edges] (if (< minus-p without-qs)
+                                  [without-qs minus-p (:preds graph)]
+                                  [minus-p without-qs (:succs graph)])
+        edge-order (sorted-edge-order layer-1 layer-2 edges)
+        tree-size (next-power-of-2-minus-1 (count layer-2))
         first-leaf (/ (dec tree-size) 2)]
     (loop [layer layer
            tree (vec (repeat tree-size (AccumulatorNode. 0 #{} false)))
            crossings 0
-           order next-edge-order]
+           order edge-order]
       (if (empty? order)
         [layer crossings]
         (let [[ord edge] (first order)


Added argument sorting

Added argument sorting

--- src/clojure/iroh/core.clj
+++ src/clojure/iroh/core.clj
@@ -20,7 +20,62 @@

 (defmacro .$> [obj & forms])

+(def sort-terms #{:by-name :by-params :by-flags :by-return-type})

-(.* 1)
+(def display-terms #{:name :params :flags :return-type :attributes})

-(.# Object :private)
+(defn argument-type [p]
+  (cond (sort-terms p)               :sort-terms
+        (display-terms p)            :display-terms
+        (keyword? p)                 :flags
+        (or (string? p) (regex? p))  :name
+        (or (set? p) (vector? p))    :params
+        (hash-map? p)                :attributes
+        (symbol? p)                  :return))
+
+(defn convert-param [p]
+  (condp = p
+    'bool 'Boolean/TYPE
+    'short 'Short/TYPE
+    'int 'Integer/TYPE
+    'long 'Long/TYPE
+    'float 'Float/TYPE
+    'double 'Double/TYPE
+    'void   'Void/TYPE
+    p))
+
+(defn convert-params [ps]
+  (map (fn [v]
+         (if (vector? v)
+           (mapv convert-param v)
+           (convert-param v)))
+       ps))
+
+(->> [:private :static '[int String] 'int :name :by-name]
+     (group-by param-type)
+     (#(update-in % [:params] convert-params))
+     (#(update-in % [:return] (comp convert-param last))))
+
+(comment
+  (defn group-by-search-terms [arr]
+    )
+
+  (.* 1)
+
+  (.# Object :private) ;; => lists all the private variables
+
+  (.# Object :private :static [int String]) ;; => lists all the private static members of return type int String
+
+  (.# Object :private :static :field)
+
+  (.# Object :private :static :method)
+
+  (.# Object :constructor)
+
+  (.# Object "toString")
+
+  (.# Object :private #"get")
+
+  (.# Object :static #"get")
+
+)


Actually repeat the body of the while

Actually repeat the body of the while

--- src/clojure_ruby/core.clj
+++ src/clojure_ruby/core.clj
@@ -128,9 +128,8 @@
     (create-string val)))

 (defmethod evaluate-one :while [stmt]
-  (let [[_ predicate & body] stmt
-        predicate (evaluate predicate)]
-    (if predicate
+  (let [[_ predicate & body] stmt]
+    (while (evaluate predicate)
       (mapv evaluate body))))

 (defmethod evaluate-one :case [stmt]


Random usernames,.

Random usernames,.

--- src/clojurecraft/core.clj
+++ src/clojurecraft/core.clj
@@ -27,6 +27,10 @@

 ; Connections ----------------------------------------------------------------------
+
+(defn- random-username []
+   (apply str (repeatedly 10 #(rand-nth "abcdefghijklmnopqrstuvwxyz"))))
+
 (defn login [bot username]
   ; Send handshake
   (write-packet bot :handshake {:username username})
@@ -64,7 +68,8 @@

 (defn connect [server username]
-  (let [socket (Socket. (:name server) (:port server))
+  (let [username (or username (random-username))
+        socket (Socket. (:name server) (:port server))
         in (DataInputStream. (.getInputStream socket))
         out (DataOutputStream. (.getOutputStream socket))
         conn (ref {:in in :out out})
@@ -115,7 +120,7 @@
 ; Scratch --------------------------------------------------------------------------
 (def minecraft-local {:name "localhost" :port 25565})

-;(def bot (connect minecraft-local "Honeydew"))
+(def bot (connect minecraft-local nil))
 ;(act/move bot -2 0 0)
 ;(pprint @(:packet-counts-in bot))
 ;(pprint @(:packet-counts-out bot))


[#1152] Fix typo

[#1152] Fix typo

--- backend/project.clj
+++ backend/project.clj
@@ -38,7 +38,7 @@
                  [ring/ring-defaults "0.3.1"]
                  [ring/ring-json "0.4.0"]
                  [selmer "1.11.1"]
-                 [net.postgis/postgis-jdbc "2.2.1" :exclusions [org.postgresql/postgresql]]
+                 [net.postgis/postgis-jdbc "2.2.1" :exclusions [org.postgresql/postgresql]]]
   :uberjar-name "akvo-lumen.jar"
   :repl-options {:timeout 120000}
   ;; :pedantic? :abort


Revert "Release 0.1.0"

Revert "Release 0.1.0"

This reverts commit 0ae93963df9ef6a4eb30b38d736c707c2296d3d9.

--- backend/project.clj
+++ backend/project.clj
@@ -1,4 +1,4 @@
-(defproject lambdaui "0.1.0"
+(defproject lambdaui "0.1.0-SNAPSHOT"
   :description "LambdaCD-Plugin that provides a modern UI for your pipeline."
   :url "https://github.com/sroidl/lambda-ui"
   :license {:name "Apache License 2.0"


Align message to center

Align message to center

--- src/build_mon/core.clj
+++ src/build_mon/core.clj
@@ -40,7 +40,7 @@
          "<link rel=\"shortcut icon\" href=\"/favicon_" background-colour ".ico\" />"
          ""
          ""
-         "
" text "
"
+         "
" text "
"
          "")))

 (defn handler [account project token request]