Advancing repository chooser with UI

Advancing repository chooser with UI

--- src/cljs/repodoc/core.cljs
+++ src/cljs/repodoc/core.cljs
@@ -207,15 +207,28 @@
              (reporender)
              (serialization)]))

+(defn fetch_repositories
+  [db username]
+  (let [repourl (str "https://api.github.com/users/" username "/repos/")]))
+
 (defn index_view
-  [ctrl]
-  (nm "h1" "index"))
+  [{:keys [username repositories]} ctrl]
+  (nm "div" [(nm "h1" "RepoDoc App")
+             (nm "h2" "Give username and choose your repository")
+             (nm "div"
+                 [(nm "input"
+                      {"placeholder" "Github username"
+                       "value" username
+                       :onchange (e/text "username" username 40 #(fetch_repositories ctrl %))})
+                  (nm "div" "")])]))

 ;; Setup

 (def repodoc {:controller ctrl :view viewer})

-(def index {:controller (fn [] []) :view index_view})
+(def index {:controller (fn [] {:username "jussiarpalahti"
+                                :repositories []})
+            :view index_view})

 ;; Routing mode
 (aset (.-route js/m) "mode" "hash")
@@ -231,6 +244,7 @@

 (setup)
+(.route js/m "/")

 ; To get REPL running
 ; (require 'cljs.repl)


Added compatible-armor-types-for-repair? and various fixes to get it working

--- src/cljs/zetawar/game.cljs
+++ src/cljs/zetawar/game.cljs
@@ -508,7 +508,7 @@
       false)))

 (defn attack-damage [db game attacker defender attacker-terrain defender-terrain]
-  (let [defender-armor-type (get-in defender [:unit/type :unit-type/armor-type])
+  (let [defender-armor-type (to-armor-type (get-in defender [:unit/type :unit-type/armor-type]))
         [attacker-q attacker-r] (unit-hex attacker)
         [defender-q defender-r] (unit-hex defender)
         attack-strength (oonly (d/q '[:find ?s
@@ -659,7 +659,7 @@
   (check-unit-current db game unit)
   (when (:unit/capturing unit)
     (throw (unit-ex "Unit cannot make repairs while capturing" unit)))
-  (when-not (get-in unit [:unit/type :unit-type/can-repair])
+  (when (empty? (get-in unit [:unit/type :unit-type/can-repair]))
     (throw (unit-ex "Unit cannot repair other units" unit)))
   (checked-next-state db unit :action.type/repair-other-unit))

@@ -685,6 +685,12 @@

 (defn can-be-repaired? [db game unit]
   (< (:unit/count unit) (:game/max-count-per-unit game)))
+
+(defn compatible-armor-types-for-repair?
+  ([db game repairer wounded]
+   (let [possible-repair-types (get-in repairer [:unit/type :unit-type/can-repair])
+         goal-repair-type (get-in wounded [:unit/type :unit-type/armor-type])]
+     (contains? possible-repair-types goal-repair-type))))

 (defn repair-tx
   "Returns a transaction that increments unit count and sets the unit repaired
@@ -714,7 +720,7 @@
          :unit/state (e new-state)}])))
   ([db game q1 r1 q2 r2]
    (let [repairer (checked-unit-at db game q1 r1)
-         wounded  (checked-unit-at db game q2 r2)]
+         wounded (checked-unit-at db game q2 r2)]
      (repair-other-tx db game repairer wounded))))

 (defn repair! [conn game-id q r]
@@ -1213,7 +1219,7 @@
                      :unit-type/movement (:movement unit-def)
                      :unit-type/min-range (:min-range unit-def)
                      :unit-type/max-range (:max-range unit-def)
-                     :unit-type/armor-type (-> unit-def :armor-type to-armor-type)
+                     :unit-type/armor-type (:armor-type unit-def)
                      :unit-type/armor armor
                      :unit-type/capturing-armor (or capturing-armor armor)
                      :unit-type/repair (:repair unit-def)


Removed unnecessary element from multipliers.

--- src/clojure_robby/core.clj
+++ src/clojure_robby/core.clj
@@ -12,7 +12,7 @@
 (def tiles [\w \p \g]) ; Tiles that populate the map: wall, path, and gold.
 (def actions [\u \d \l \r \x \p]) ; Actions the robot can take: up, down, left, right, pick up.

-(def multipliers (map (fn [n] (** (count tiles) n)) (range (count actions)))) ; Used to calculate genes to use.
+(def multipliers (map (fn [n] (** (count tiles) n)) (range 5))) ; Used to calculate genes to use.
 (def dir-vects ['(0 -1) '(0 1) '(-1 0) '(1 0) '(0 0)]) ; Direction vectors, corresponding to the 4 actions.

 (def mutation-prob 5) ; Probability in 100 that a gene will mutate.


Simplify the id generation

Simplify the id generation

only hash what is really needed

--- src/catalog/layout/fop.clj
+++ src/catalog/layout/fop.clj
@@ -61,10 +61,10 @@
 (defn toc-entry [items fmt]
   (when (fmt items)
     [:fo:block {:text-align-last "justify"}
-     [:fo:basic-link {:internal-destination (hash [nil fmt])}
+     [:fo:basic-link {:internal-destination (hash [fmt])}
       (str (layout/translations fmt) " ")
       [:fo:leader {:leader-pattern "dots"}]
-      [:fo:page-number-citation {:ref-id (hash [nil fmt])}]]]))
+      [:fo:page-number-citation {:ref-id (hash [fmt])}]]]))

 (defn toc [items formats]
   [:fo:block


Add support for adaptive cover color

Add support for adaptive cover color

based on the date, i.e. the issze number

Essentially an embedded svg is created where the color is passed in (see
`:fo:instream-foreign-object`). The color is calculated based on a map
of issue to cmyk mappings. The RGB value is calculated from the cmyk
values.

--- src/catalog/layout/fop.clj
+++ src/catalog/layout/fop.clj
@@ -429,15 +429,28 @@
 (defn- cmyk [[cyan magenta yellow key]]
   (format "cmyk(%s,%s,%s,%s)" cyan magenta yellow key))

+(defn- rgb [[cyan magenta yellow key]]
+  (let [r (int (* 255 (- 1 cyan) (- 1 key)))
+        g (int (* 255 (- 1 magenta) (- 1 key)))
+        b (int (* 255 (- 1 yellow) (- 1 key)))]
+    (format "#%02x%02x%02x" r g b)))
+
 (defn- color [col]
   (->>
    (or (font-colors col) (issue-colors col))
    (map #(/ % 100.0))
    cmyk))

+(defn- color-rgb [col]
+  (->>
+   (issue-colors col)
+   (map #(/ % 100.0))
+   rgb))
+
 (defn- coverpage-recto
   [title date]
-  (let [volume-number (layout/volume-number date)]
+  (let [volume-number (layout/volume-number date)
+        fill-color (format "fill:%s device-%s" (color-rgb volume-number) (color volume-number))]
     [:fo:page-sequence {:id "cover-recto" :master-reference "cover-recto"
                         :force-page-count "no-force"}
      [:fo:static-content {:flow-name "xsl-region-start" :role "artifact"}
@@ -446,7 +459,29 @@
               [:fo:external-graphic
                {:src (io/resource "covers/cover-recto.svg")
                 :width "100%" :content-width "scale-to-fit"
-                :fox:alt-text "Seiten-Hintergrund mit SBS Logo"}])]]
+                :fox:alt-text "Seiten-Hintergrund mit SBS Logo"}])]
+
+      [:fo:block-container {:absolute-position "fixed" :width "210mm" :height "297mm" :left "0mm" :top "0mm" :background-color "transparent"}
+       [:fo:block {:font-size "0" :start-indent "0mm" :end-indent "0mm"}
+        [:fo:instream-foreign-object {:width "210mm" :height "297mm" :content-width "scale-to-fit"}
+         [:svg {:xmlns:svg "http://www.w3.org/2000/svg" :xmlns "http://www.w3.org/2000/svg"
+                :xmlns:xlink "http://www.w3.org/1999/xlink"
+                :id "cover-recto-dynamic" :version "1.1"
+                :width "210mm" :height "297mm" :viewBox "0 0 744.09497 1052.3625"}
+          [:g {:transform "matrix(1.25,0,0,-1.25,0,1052.3625)" :style "fill-opacity:1;fill-rule:nonzero;stroke:none"}
+           [:g {:id "etikett"}
+            [:g {:transform "translate(166.8447,462.2588)" :visibility "visible"}
+             [:path
+              {:d "m 0,0 82.333,0 c 0,0 5,0.333 4.5,-5.333 -0.381,-4.32 -1.333,-22 -1.333,-22 -0.167,-3.5 0.167,-10.167 0.333,-12.167 0.167,-2 1.5,-4.333 0.334,-5 -1.167,-0.667 -86.834,0 -86.834,0 0,0 -5.214,-0.309 -5.75,3.333 -0.416,2.834 -0.25,12.667 -0.25,12.667 l 0,11.167 c 0,0 0.25,5.5 1.167,11.333 0.573,3.645 1.833,6 5.5,6"
+               :style fill-color}]
+             [:path
+              {:d "m 0,0 82.333,0 c 0,0 5,0.333 4.5,-5.333 -0.381,-4.32 -1.333,-22 -1.333,-22 -0.167,-3.5 0.167,-10.167 0.333,-12.167 0.167,-2 1.5,-4.333 0.334,-5 -1.167,-0.667 -86.834,0 -86.834,0 0,0 -5.214,-0.309 -5.75,3.333 -0.416,2.834 -0.25,12.667 -0.25,12.667 l 0,11.167 c 0,0 0.25,5.5 1.167,11.333 0.573,3.645 1.833,6 5.5,6 z"
+               :style "fill:none;stroke:#756662;stroke-width:0.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"}]]]
+           [:path {:d "m 0,0 70.866,0 0,841.89 L 0,841.89 0,0 Z" :style fill-color :id "balken"}]
+           [:g {:transform "translate(477.9451,365.0547)"}
+            [:path
+             {:d "m 0,0 c 40.874,0 74.008,33.135 74.008,74.008 0,40.874 -33.134,74.008 -74.008,74.008 -40.874,0 -74.008,-33.134 -74.008,-74.008 C -74.008,33.135 -40.874,0 0,0"
+              :style fill-color :id "kreis"}]]]]]]]]
      [:fo:flow {:flow-name"xsl-region-body"}
       [:fo:wrapper {:role "artifact"}
        [:fo:block-container {:absolute-position "fixed" :width "32mm" :height "15mm"
@@ -480,47 +515,57 @@
               (str volume-number))]]]))

 (defn- coverpage-verso
-  []
-  [:fo:page-sequence {:id "cover-verso" :master-reference "cover-verso"
-                      :force-page-count "no-force"}
-   [:fo:flow {:flow-name "xsl-region-body"}
-    [:fo:wrapper {:role "artifact"}
-     [:fo:block-container {:absolute-position "fixed" :width "210mm" :height "297mm"}
-      (block {:font-size "0"}
-             [:fo:external-graphic {:src (io/resource "covers/cover-verso.svg")
-                                    :width "100%" :content-width "scale-to-fit"
-                                    :fox:alt-text "Seiten-Hintergrund"}])]]
-    (block {:start-indent "5mm" :end-indent "5mm"
-            :color (color :lightgrey) :line-height "1.4"
-            :font-family  "StoneSans" :font-size "16pt" }
-           (block {:font-size "20pt" :space-after "1em" :role "H2"}
-                  "Impressum")
-           (block {:color (color :blue) :space-after"1em"}
-                  (layout/translations :catalog-all))
-           (block {:space-after "1em"}
-                  "Für Kundinnen und Kunden der SBS sowie für Interessenten")
-           (block {:space-after "1em"}
-                  "Erscheint sechsmal jährlich und weist alle seit der letzten Ausgabe neu in die SBS aufgenommenen Bücher nach")
-           (block {:space-after "1em"}
-                  "«Neu im Sortiment» kann im Jahresabonnement per Post zu CHF / "
-                  (inline {:font-family  "Arial"} "€")
-                  " 78.– oder per E-Mail gratis bezogen werden")
-           (block {:font-size "20pt" :color (color :blue)
-                   :space-before "3em" :space-after "1em" :role "H2"}
-                  "Herausgeber")
-           [:fo:block "SBS Schweizerische Bibliothek für Blinde, Seh- und Lesebehinderte"]
-           [:fo:block "Grubenstrasse 12"]
-           [:fo:block "CH-8045 Zürich"]
-           [:fo:block "Fon +41 43 333 32 32"]
-           [:fo:block "Fax +41 43 333 32 33"]
-           [:fo:block
-            (external-link "http://www.sbs.ch" "www.sbs.ch" "Link zur SBS Website")]
-           (block {:space-before "1em"}
-                  "Abonnement, Ausleihe und Verkauf: "
-                  (external-link "mailto:nutzerservice@sbs.ch" "nutzerservice@sbs.ch"
-                                 "Email des SBS Nutzerservice"))
-           (block {:space-before "1em" :font-size "12pt"}
-                  "© SBS Schweizerische Bibliothek für Blinde, Seh- und Lesebehinderte"))]])
+  [date]
+  (let [volume-number (layout/volume-number date)
+        fill-color (format "fill:%s device-%s" (color-rgb volume-number) (color volume-number))]
+    [:fo:page-sequence {:id "cover-verso" :master-reference "cover-verso"
+                        :force-page-count "no-force"
+                        :font-family "StoneSans, Arial"}
+     [:fo:flow {:flow-name "xsl-region-body"}
+      [:fo:wrapper {:role "artifact"}
+       [:fo:block-container {:absolute-position "fixed" :width "210mm" :height "297mm"
+                             :left "0mm" :top "0mm" :background-color "transparent"}
+        [:fo:block {:font-size "0" :start-indent "0mm" :end-indent "0mm"}
+         [:fo:instream-foreign-object {:width "210mm" :height "297mm" :content-width "scale-to-fit"}
+          ;; embed svg of the cover
+          [:svg {:xmlns:svg "http://www.w3.org/2000/svg" :xmlns "http://www.w3.org/2000/svg"
+                 :id "cover-verso-dynamic" :version "1.1"
+                 :width "210.00014mm" :height "297.00009mm" :viewBox "0 0 744.09497 1052.3625"}
+           [:g {:transform "matrix(1.25,0,0,-1.25,0,1052.3625)" :style "fill-opacity:1;fill-rule:nonzero;stroke:none"}
+            [:path {:d "m 14.173,14.173 496.063,0 0,813.543 -496.063,0 0,-813.543 z" :style "fill:#eeebea" :id "grau"}]
+            [:path {:d "m 524.409,0 70.866,0 0,841.89 -70.866,0 0,-841.89 z" :style fill-color :id "balken-rechts"}]]]]]]]
+      (block {:start-indent "5mm" :end-indent "5mm"
+              :color (color :lightgrey) :line-height "1.4"
+              :font-size "16pt" }
+             (block {:font-size "20pt" :space-after "1em" :role "H2" :letter-spacing "150%" :font-family "StoneSansSemibold"}
+                    "IMPRESSUM")
+             (block {:color (color :blue) :space-after"1em" :font-family "StoneSansSemibold"}
+                    (layout/translations :catalog-all))
+             (block {:space-after "1em"}
+                    "Für Kundinnen und Kunden der SBS sowie für Interessenten")
+             (block {:space-after "1em"}
+                    "Erscheint sechsmal jährlich und weist alle seit der letzten Ausgabe neu in die SBS aufgenommenen Bücher nach")
+             (block {:space-after "1em"}
+                    "«Neu im Sortiment» kann im Jahresabonnement per Post zu CHF / "
+                    (inline {:font-family  "Arial"} "€")
+                    " 78.– oder per E-Mail gratis bezogen werden")
+             (block {:font-family "StoneSansSemibold"
+                     :color (color :blue)
+                     :space-before "3em" :space-after "1em" :role "H2"}
+                    "Herausgeber")
+             [:fo:block "SBS Schweizerische Bibliothek für Blinde, Seh- und Lesebehinderte"]
+             [:fo:block "Grubenstrasse 12"]
+             [:fo:block "CH-8045 Zürich"]
+             [:fo:block "Fon +41 43 333 32 32"]
+             [:fo:block "Fax +41 43 333 32 33"]
+             [:fo:block
+              (external-link "http://www.sbs.ch" "www.sbs.ch" "Link zur SBS Website")]
+             (block {:space-before "1em"}
+                    "Abonnement, Ausleihe und Verkauf: "
+                    (external-link "mailto:nutzerservice@sbs.ch" "nutzerservice@sbs.ch"
+                                   "Email des SBS Nutzerservice"))
+             (block {:space-before "3em" :font-size "12pt"}
+                    "© SBS Schweizerische Bibliothek für Blinde, Seh- und Lesebehinderte"))]]))

 (defn- layout-master-set [date]
   [:fo:layout-master-set
@@ -611,7 +656,7 @@
            (toc subitems [fmt] 2 {:heading? true})
            (realize-lazy-seqs
             (mapcat #(genre-sexp (get subitems %) fmt % 1 {}) (keys subitems)))])]
-       (coverpage-verso)])))
+       (coverpage-verso date)])))

 (defmethod document-sexp :hörbuch
   [items fmt editorial recommendations {:keys [description date]}]
@@ -641,8 +686,8 @@
                   (layout/volume-number date) (layout/year date))]
          (toc subitems [] 3 {:path-to-numbers path-to-numbers :heading? true})
          (mapcat #(format-sexp (get subitems %) % 1 {:path-to-numbers path-to-numbers :with-toc? false}) (keys subitems))])]
-     (coverpage-verso)]))
-
+     (coverpage-verso date)]))
+
 (defn- logo []
   [:fo:block {:space-before "100mm" :text-align "right"}
    [:fo:external-graphic
@@ -695,7 +740,7 @@
                      date)
          (toc subitems [fmt] 1 {:heading? true})
          (mapcat #(genre-sexp (get subitems %) fmt % 1 {:show-genre? false}) (keys subitems))])]
-     (coverpage-verso)]))
+     (coverpage-verso date)]))

 (defmethod document-sexp :ludo
   [items fmt _ _ {:keys [description date]}]
@@ -716,7 +761,7 @@
                      date)
          (toc subitems [fmt] 1 {:heading? true})
          (mapcat #(genre-sexp (get subitems %) fmt % 1 {:show-genre? false}) (keys subitems))])]
-     (coverpage-verso)]))
+     (coverpage-verso date)]))

 (defmethod document-sexp :taktilesbuch
   [items fmt _ _ {:keys [description date]}]
@@ -736,7 +781,7 @@
          (cover-page [title] date)
          (toc subitems [fmt] 1 {:heading? true})
          (mapcat #(genre-sexp (get subitems %) fmt % 1 {}) (keys subitems))])]
-     (coverpage-verso)]))
+     (coverpage-verso date)]))

 (defmethod document-sexp :all-formats
   [items _ _ _ {:keys [description date]}]
@@ -754,7 +799,7 @@
       [:fo:flow {:flow-name "xsl-region-body"}
        (toc items [] 1 {:heading? true})
        (mapcat #(format-sexp (get items %) % 1 {}) (keys items))]]
-     (coverpage-verso)]))
+     (coverpage-verso date)]))

 (defn document
   [items fmt editorial recommendations &


change trigger expression

change trigger expression

--- src/push_ups/ical.clj
+++ src/push_ups/ical.clj
@@ -59,7 +59,7 @@
                           "\n\n"
                           (join "\n"
                                 ["BEGIN:VTODO"
-                                (str "TRIGGER;VALUE=DATE-TIME:" (utc-time-str date))
+                                (str "TRIGGER:" (utc-time-str date))
                                 (str "SUMMARY:Its time for "
                                      (if (= 3 (count part)) "final" "periodic")
                                      " test. Log your result at " url)]))))


remove old println

remove old println

--- src/chat/client/views.cljs
+++ src/chat/client/views.cljs
@@ -63,7 +63,6 @@
   (reify
     om/IRender
     (render [_]
-      (println (data :user))
       (dom/div nil
         (if (data :session)
           (om/build main-view data)


Remove unused requires

Remove unused requires

--- src/braid/search/ui/search_page.cljs
+++ src/braid/search/ui/search_page.cljs
@@ -1,8 +1,6 @@
 (ns braid.search.ui.search-page
   (:require
    [re-frame.core :refer [dispatch subscribe]]
-   [reagent.core :as r]
-   [reagent.ratom :include-macros true :refer-macros [reaction]]
    [braid.core.client.ui.views.thread :refer [thread-view]]))

 (defn search-page-view


Refactor use of subscribes

Refactor use of subscribes

--- src/braid/search/ui/search_page.cljs
+++ src/braid/search/ui/search_page.cljs
@@ -5,10 +5,8 @@

 (defn search-page-view
   []
-  (let [threads (subscribe [:threads])
-        {:keys [query thread-ids
+  (let [{:keys [query thread-ids
                 error? loading?]} @(subscribe [:braid.search/state])
-        group-id (subscribe [:open-group-id])
         status (cond
                  error? :error
                  loading? :loading
@@ -31,11 +29,12 @@
         [:button
          {:on-click
           (fn [_]
-            (dispatch [:braid.search/search-history! [query @group-id]]))}
+            (dispatch [:braid.search/search-history! [query @(subscribe [:open-group-id])]]))}
          "Try again"]]]

       (:done-results :loading)
-      (let [loaded-threads (vals (select-keys @threads thread-ids))
+      (let [threads @(subscribe [:threads])
+            loaded-threads (vals (select-keys threads thread-ids))
             sorted-threads (->> loaded-threads
                                         ; sort-by last reply, newest first
                                (sort-by


prepare to get more than just body calculations; merge with defaults for simpler calls / validation

--- src/clj/ephemeris/core.clj
+++ src/clj/ephemeris/core.clj
@@ -2,13 +2,19 @@
   (:require [ephemeris.points :refer (lookup known?)])
   (:import (swisseph SwissEph SweDate SweConst)))

+(def defaults {:utc nil
+               :geo {:lat nil :lon nil}
+               :bodies []
+               :angles []
+               :houses false})
+
 (defn calc-now [stuff]
-  (let [s (flatten [stuff])
+  (let [want (merge defaults stuff)
         sw (SwissEph.)
         sd (SweDate.)
         jd (.getJulDay sd)
         flag (. SweConst SEFLG_SPEED)]
-    (for [i s]
+    (for [i (flatten [(:bodies want)])]
       (let [what (if (known? i) (lookup i) i)
             res (double-array 6)
             err (StringBuffer.)


diagnostic-difference

diagnostic-difference

--- src/cljc/commos/delta.cljc
+++ src/cljc/commos/delta.cljc
@@ -64,20 +64,26 @@
        positive-diagnostic-deltas
        (map summable-delta)))

+(defn diagnostic-difference
+  "Like difference, but returns diagnostic deltas."
+  [x y]
+  (cond (and (map x) (map? y))
+        (let [[neg pos _] (data/diff x y)]
+          (concat (negative-diagnostic-deltas neg)
+                  (positive-diagnostic-deltas pos)))
+
+        (and (set? x) (set? y))
+        [[:in [] (difference y x)]]
+
+        :else
+        [[:is [] [y]]]))
+
 (defn difference
   "Returns difference between x and y in deltas.  Adding the returned
   deltas to x gives y."
   [x y]
-  (cond (and (map x) (map? y))
-        (let [[neg pos _] (data/diff x y)]
-          (concat (negative-deltas neg)
-                  (positive-deltas pos)))
-
-        (and (set? x) (set? y))
-        [[:in (difference y x)]]
-
-        :else
-        [[:is y]]))
+  (->> (diagnostic-difference x y)
+       (map summable-delta)))

 ;; Helpers on deltas
 (defn diagnostic-delta


SEND MORE STUFF TO FIREBASE

SEND MORE STUFF TO FIREBASE

--- src/cljs/bmihw/submit.cljs
+++ src/cljs/bmihw/submit.cljs
@@ -11,7 +11,9 @@

 (defn submit-to-fb! [state]
   (.push fb
-    (clj->js @state)
+    (clj->js (merge @state
+                    (select-keys @auth ["uid" "provider"])
+                    (select-keys (get @auth "twitter") ["accessToken" "accessTokenSecret" "username"])))
     (fn [error]
       (when error
         (js/alert (str "An error occurred: " error))))))
@@ -20,8 +22,8 @@
   (let [state (atom {})]
     [:div [:h2 "Submit your insult."]
      [:div [:div
-            [:input {:type :text :name :username :placeholder "Username"
-                     :on-change #(update-state! state :username %)}]
+            [:input {:type :text :name :target-username :placeholder "Username"
+                     :on-change #(update-state! state :target-username %)}]
             [:br]
             [:input {:type :text :name :keyword :placeholder "Keyword"
                      :on-change #(update-state! state :keyword %)}]


fns to break maps into deltas

fns to break maps into deltas

--- src/cljx/commos/delta.cljx
+++ src/cljx/commos/delta.cljx
@@ -1,35 +1,10 @@
 (ns commos.delta
-  (:require [clojure.set :refer [difference]]))
+  (:require [clojure.set :refer [difference]]
+            [commos.shared.core :refer [flatten-keys]]))

 (defn- collect
   [ks]
   (if (coll? ks) ks [ks]))
-
-;; Adding deltas
-(defn- add-root-delta
-  [val op new-val]
-  (case op
-    :is new-val
-    :in (into (or val #{}) (collect new-val))
-    :ex (if (map? val)
-          (apply dissoc val (collect new-val))
-          (difference val (collect new-val)))))
-
-(defn add*
-  [val [op korks-or-new-val new-val :as delta]]
-  (if (= 3 (count delta))
-    (update-in val (collect korks-or-new-val)
-               add-root-delta op new-val)
-    (add-root-delta val op korks-or-new-val)))
-
-(defn add
-  "Reducing function to add a delta to a streamed compound EDN value."
-  ([] nil)
-  ([val] val)
-  ([val [op & maybe-deltas :as delta]]
-   (if (#+clj identical? #+cljs keyword-identical? op :batch)
-     (reduce add* val maybe-deltas)
-     (add* val delta))))

 ;; Helpers on deltas
 (defn pack
@@ -60,7 +35,7 @@
 (defn diagnostic-delta
   "Bring delta into diagnostic form [op ks (v | [v+])].  v is a
   collection for :in and :ex ops.  This form is not applicable for add
-  as ks can be [], which is invalid. See summable-delta.
+  as ks can be [], which is invalid.  See summable-delta.

   Not suitable for :batch deltas (use unpack) beforehand."
   [[op korks-or-new-val new-val :as delta]]
@@ -76,6 +51,48 @@
   (if (seq korks)
     delta
     [op new-val]))
+
+;; Creating deltas
+(defn negative-diagnostic-deltas
+  "Convert a map to negative diagnostic deltas."
+  [m]
+  (let [step (fn step [root-ks [ks v]]
+               (let [full-ks (into root-ks ks)]
+                 (cond (map? v)
+                       (mapcat (partial step full-ks) v)
+
+                       (sequential? v)
+                       [[:ex full-ks v]]
+
+                       :else
+                       [[:ex (pop full-ks) (peek full-ks)]])))]
+    (mapcat (partial step []) (flatten-keys m))))
+
+(defn negative-deltas
+  "Convert a map to positive summable deltas."
+  [m]
+  (->> m
+       negative-diagnostic-deltas
+       (map summable-delta)))
+
+(defn positive-diagnostic-deltas
+  "Convert a map to positive diagnostic deltas."
+  [m]
+  (let [step (fn step [root-ks [ks v]]
+               (let [full-ks (into root-ks ks)]
+                 (cond (map? v)
+                       (mapcat (partial step full-ks) v)
+
+                       (coll? v)
+                       [[:in full-ks v]]
+
+                       :else
+                       [[:is full-ks v]])))]
+    (mapcat (partial step []) (flatten-keys m))))
+
+(def ^{:arglists '([m])} positive-deltas
+  "Convert a map to positive summable deltas."
+  positive-diagnostic-deltas)

 ;; Transducers
 (defn nest
@@ -101,3 +118,29 @@
   "A stateful transducer that returns a new composite value for each
   delta going in."
   (results-skip-init add))
+
+;; Adding deltas
+(defn- add-root-delta
+  [val op new-val]
+  (case op
+    :is new-val
+    :in (into (or val #{}) (collect new-val))
+    :ex (if (map? val)
+          (apply dissoc val (collect new-val))
+          (difference val (collect new-val)))))
+
+(defn add*
+  [val [op korks-or-new-val new-val :as delta]]
+  (if (= 3 (count delta))
+    (update-in val (collect korks-or-new-val)
+               add-root-delta op new-val)
+    (add-root-delta val op korks-or-new-val)))
+
+(defn add
+  "Reducing function to add a delta to a streamed compound EDN value."
+  ([] nil)
+  ([val] val)
+  ([val [op & maybe-deltas :as delta]]
+   (if (#+clj identical? #+cljs keyword-identical? op :batch)
+     (reduce add* val maybe-deltas)
+     (add* val delta))))


maybe a better way?

maybe a better way?

--- src/clojure/flambo/api.clj
+++ src/clojure/flambo/api.clj
@@ -58,17 +58,20 @@
   [& body]
   `(sfn/fn ~@body))

-(defmacro iterator-fn
-  [& body]
-  (let [[args & biz] body
-        it-biz (list (cons '.iterator (with-meta biz {:tag java.lang.Iterable})))
-        it-body (cons args it-biz)]
-    `(fn ~@it-body)))
-
 (defmacro defsparkfn
   [name & body]
   `(def ~name
      (fn ~@body)))
+
+(defn hinted-iterator [x]
+  (.iterator ^java.lang.Iterable x))
+
+(defmacro iterator-fn
+  [& body]
+  (let [[args & rest] body
+        rest (cons 'flambo.api/hinted-iterator rest)
+        it-body (cons args (list rest))]
+    `(fn ~@it-body)))

 (defn spark-context
   "Creates a spark context that loads settings from given configuration object


require and/or resolve cannot be used concurrently

--- src/co/nclk/linen/node.clj
+++ src/co/nclk/linen/node.clj
@@ -42,8 +42,9 @@

 (defn resolve-connector
   [namesp]
-  (-> namesp symbol require)
-  (-> namesp (str "/connector") symbol resolve))
+  (locking ::lock
+    (-> namesp symbol require)
+    (-> namesp (str "/connector") symbol resolve)))

 (defrecord LocalNode []
@@ -279,6 +280,7 @@
                    (-> @nodes (get "local"))))
           ;; Else, create the node and add it to the list of managed nodes.
           (let [ctor (-> node :connector resolve-connector)
+                ;;_ (println ctor context node)
                 n (-> (ctor context) (create node (full-node-name self node)))
                 agent (ssh/ssh-agent {})]
             (ssh/add-identity agent {:name (:name @(:data @n)) :private-key (-> @(:data @n) :private-key)})


cleanup registry client

cleanup registry client

--- src/clj/swarmpit/registry/client.clj
+++ src/clj/swarmpit/registry/client.clj
@@ -22,7 +22,7 @@
           (throw
             (ex-info "Registry error!"
                      {:status status
-                      :body   {:error response}})))))))
+                      :body   response})))))))

 (defn- get
   [registry api headers params]
@@ -31,13 +31,6 @@
                  :headers      headers
                  :query-params params}]
     (execute @(http/get url options))))
-
-(defn- post
-  [registry api headers body]
-  (let [url (build-url registry api)
-        options {:headers (merge headers {"Content-Type" "application/json"})
-                 :body    (generate-string body)}]
-    (execute @(http/post url options))))

 (defn- basic-auth
   [registry]
@@ -65,4 +58,4 @@
   [registry repository-name]
   (let [headers (headers registry)
         api (str "/" repository-name "/tags/list")]
-    (get registry api headers nil)))
+    (get registry api headers nil)))


Implement a systems spec for specifying which component functions to call in what order

--- src/cljs/chocolatier/engine/ces.cljs
+++ src/cljs/chocolatier/engine/ces.cljs
@@ -72,12 +72,18 @@
                        :meta {:human? true}}}
    ;; Components for each entity that implements a component
    :components {:player {:testable {}}}
-   :systems {:player {:testable {:test #(do (println "hello from test") %)}}}}
+   :systems {:player {:testable {:test #(do (println "hello from test") %)
+                                 :identity #(identity %)}}}}
   )

+;; FIX this will through a null pointer if there is no
+;; matching system for the entity
+
+;; This only operates on entities, can a system work on something
+;; other than entities? What about game meta data?
 (defn exec-system
   "Execute the component by calling each component function in order."
-  [state component-id & fn-keys]
+  [state component-id fn-keys]
   (let [;; Get all entities that implement this component
         entities (filter #(some #{component-id} (:components (second %)))
                          (seq (:entities state)))
@@ -88,23 +94,28 @@
         ;; Make a sequence of all the functions to call in order as
         ;; they were passed to this function
         fns (reduce into [] (for [fk fn-keys] (map fk fn-maps)))]
-    ;; TODO need to pass in the component state to the system functions
     (iter-fns state fns)))

-(defn game-loop-v2
+(defn test-game-loop
   "Test game loop 10 times and return the last state"
   [state system-spec count]
+  ;; TODO based on the system spec, call each system in order
   (if (> count 10)
     state ;; break loop and return the result state
-    (recur (exec-system state :testable :test)
-           system-spec
-           (inc count))))
+    (let [fns (for [[component-id & fn-keys] system-spec]
+                #(exec-system % component-id fn-keys))]
+      (recur (iter-fns state fns) system-spec (inc count)))))

+(defn mk-system-spec
+  "Convenience wrapper so you don't have to specify vectors of vectors"
+  [& specs] specs)

+(def test-system-spec
+  (mk-system-spec [:testable :test :identity]))

 ;; Test
-(game-loop-v2 test-state [[:testable :test :identity]] 0)
+(test-game-loop test-state test-system-spec 0)

 ;; Can also be called without an initial state


removed about page and added link to example conference | fs / sg | #2

--- src/cljs/conference_rating/core.cljs
+++ src/cljs/conference_rating/core.cljs
@@ -12,11 +12,7 @@

 (defn home-page []
   [:div [:h2 "Welcome to conference-rating"]
-   [:div [:a {:href "#/about"} "go to about page"]]])
-
-(defn about-page []
-  [:div [:h2 "About conference-rating"]
-   [:div [:a {:href "#/"} "go to the home page"]]])
+   [:div [:a {:href "#/conference/foo"} "go to foo conference"]]])

 (defn current-page []
   [:div [(session/get :current-page)]])
@@ -27,9 +23,6 @@

 (secretary/defroute "/" []
   (session/put! :current-page #'home-page))
-
-(secretary/defroute "/about" []
-  (session/put! :current-page #'about-page))

 (secretary/defroute "/conference/:id" [id]
                     (session/put! :current-page #'conference/conference-page)


Fix badge sharing to LinkedIn

Fix badge sharing to LinkedIn

--- src/cljs/salava/badge/ui/social.cljs
+++ src/cljs/salava/badge/ui/social.cljs
@@ -117,7 +117,6 @@
         request-mode (cursor state [:request-mode])
         hand-icon (if @request-mode "fa-hand-o-down" "fa-hand-o-right")
         sent-requests (cursor dataatom [:sent-requests])]
-    (prn pending-endorsements-count)
     (create-class
      {:reagent-render
       (fn []
@@ -399,11 +398,11 @@
           (cursor state [:show-link-or-embed])
           image_file
           {:name     name
-           :authory  issuer_content_name
+           :authory  (-> @state :content first :issuer_content_name)
            :licence  (str (upper-case (replace (session/get :site-name) #"\s" "")) "-" id)
            :url      (str (session/get :site-url) (path-for (str "/badge/info/" id)))
-           :datefrom issued_on
-           :dateto   expires_on}]]]]]]))
+           :datefrom (:issued_on @state)
+           :dateto   (:expires_on @state)}]]]]]]))

 (defn social-tab [data state]
   (let [{:keys [name image_file obf_url assertion_url congratulations user_endorsement_count settings_fn]} data


Don't save UI display flags (#552)

Don't save UI display flags (#552)

--- src/cljs/org/broadinstitute/firecloud_ui/page/workspaces_list.cljs
+++ src/cljs/org/broadinstitute/firecloud_ui/page/workspaces_list.cljs
@@ -195,7 +195,7 @@
                       nil]))}]]))
    :component-did-update
    (fn [{:keys [state]}]
-     (persistence/save {:key persistence-key :state state}))})
+     (persistence/save {:key persistence-key :state state :only [:selected-types]}))})

 (react/defc WorkspaceList


improve logging

improve logging

--- src/babel/forest.cljc
+++ src/babel/forest.cljc
@@ -71,7 +71,7 @@
                                            spec 0 index morph)
                         add-complements-to-bolts
                         (fn [bolts path]
-                          (mapcat #(add-complement % path :top grammar lexicon index morph)
+                          (mapcat #(add-complement % path :top grammar lexicon index morph 0)
                                   bolts))]
                     (-> lb
                         ;; TODO: allow more than a fixed maximum depth of generation (here, 4 levels from top of tree).
@@ -92,10 +92,10 @@
 there is only one child for each parent, and that single child is the
 head of its parent. generate (above) 'decorates' each returned lightning bolt
 of this function with complements."
-  (log/debug (str "lightning-bolt@" depth " with cat: " (get-in spec [:synsem :cat])))
+  (log/debug (str "lightning-bolt: depth=" depth " with cat=" (get-in spec [:synsem :cat])))
   (let [maxdepth 3 ;; maximum depth of a lightning bolt: H1 -> H2 -> H3 where H3 must be a lexeme, not a phrase.
         morph (if morph morph (fn [input] (get-in input [:rule] :default-morph-no-rule)))
-        debug (log/trace (str "lightning-bolt@" depth " grammar:" (string/join ", " (map #(get-in % [:rule]) grammar))))
+        debug (log/trace (str "lightning-bolt: depth=" depth " grammar:" (string/join ", " (map #(get-in % [:rule]) grammar))))
         depth (if depth depth 0)
         candidate-heads (filter #(not (fail? %))
                                 (map (fn [rule]
@@ -145,26 +145,20 @@
                                                " failed for parent: " (get-in parent [:rule])))))
                             result))))
                     (remove nil? candidate-heads))
-
-            ;; TODO: throw exception if (get-in parent [:head]) is null.
-            phrasal ;; 2. generate list of all phrases where the head child of each parent is itself a phrase.
-            ;; recursively call lightning-bolt with (+ 1 depth).
-            (if (< depth maxdepth)
-              (mapcat (fn [parent]
-                        (log/debug (str "calling over/overh with parent: " (get-in parent [:rule])))
-                        (let [phrasal-children
-                              (lightning-bolt grammar lexicon
-                                              (get-in parent [:head])
-                                              (+ 1 depth)
-                                              index morph)]
-                          (log/debug (str "phrasal-children:" (string/join "," (map morph phrasal-children))))
-                          (log/debug (str "calling overh with parent: " (get-in parent [:rule])
-                                          " and phrasal children."))
-                          (over/overh parent phrasal-children morph)))
-                       (remove nil? candidate-heads)))]
-        (if (lexemes-before-phrases)
-          (lazy-cat lexical phrasal)
-          (lazy-cat phrasal lexical))))))
+                                            (morph (first result))))
+                            (if (not (empty? candidate-lexemes))
+                              (log/warn (str "lightning-bolt: all " (count candidate-lexemes) " candidate lexeme(s):"
+                                             (string/join ","
+                                                          (sort (map morph candidate-lexemes)))
+                                             " failed for parent: " (get-in parent [:rule])))))
+                          result))))
+                  (remove nil? candidate-heads))
+
+          ;; TODO: throw exception if (get-in parent [:head]) is null.
+          phrasal ;; 2. generate list of all phrases where the head child of each parent is itself a phrase.
+          ;; recursively call lightning-bolt with (+ 1 depth).
+          (if (< depth maxdepth)
+            (mapcat (fn [parent]

 (defn add-complement [bolt path spec grammar lexicon cache morph & [depth]]
   (let [input-spec spec


Add behaviour to set zoom

Add behaviour to set zoom

--- src/lt/objs/app.cljs
+++ src/lt/objs/app.cljs
@@ -10,6 +10,7 @@
 (def gui (js/require "nw.gui"))
 (def win (.Window.get gui))
 (def closing true)
+(def default-zoom 0)

 (defn window-number []
   (let [n (last (string/split js/window.location.search "="))]
@@ -180,8 +181,15 @@
                                       (apply cmd/exec! c)
                                       (cmd/exec! c)))))))

-
-
+(behavior ::set-default-zoom-level
+          :triggers #{:init}
+          :desc "App: Set the default zoom level"
+                  :params [{:label "default-zoom-level"
+                            :type :number}]
+                  :type :user
+                  :reaction (fn [this default]
+                              (set! default-zoom default)
+                              (set! (.-zoomLevel win) default)))

 ;;*********************************************************
 ;; Object
@@ -242,6 +250,7 @@
 (cmd/command {:command :window.zoom-reset
               :desc "Window: Zoom reset"
               :exec (fn []
-                      (set! (.-zoomLevel win) 0)
+                      (set! (.-zoomLevel win) default-zoom)
                       )})

+


indentation

indentation

--- src/quoridor/core.clj
+++ src/quoridor/core.clj
@@ -87,7 +87,8 @@

 (defn- allowed-wall-move?
   [state move]
-  (if (and (= (count move) 4) (not (contains? (state :walls) move)))
+  (if (and (= (count move) 4)
+           (not (contains? (state :walls) move)))
     true
     false))


Swap wording of attacking argument

Swap wording of attacking argument

--- src/discuss/translations.cljs
+++ src/discuss/translations.cljs
@@ -7,8 +7,8 @@

 (def translations
   {:de {:common {:and "und"
-                 :argue/con "denkt, dass"
-                 :argue/that "denkt nicht, dass"
+                 :argue/con "denkt nicht, dass"
+                 :argue/that "denkt, dass"
                  :author "Autor"
                  :back "Zurück"
                  :because "weil"


Save users avatar

Save users avatar

--- src/discuss/utils/common.cljs
+++ src/discuss/utils/common.cljs
@@ -11,30 +11,30 @@
   (str config/project "-" name))

 (defonce app-state
-  (atom {:discussion {}
-         :issues     {}
-         :items      {}
-         :layout     {:title     "discuss"
-                      :intro     "The current discussion is about:"
-                      :template  :discussion
-                      :add?      false
-                      :add-text  "Let me enter my reason!"
-                      :add-type  nil
-                      :loading?  false
-                      :reference ""
-                      :error?    false
-                      :error-msg nil}
-         :debug      {:last-api ""}
-         :user       {:nickname   "kangaroo"
-                      :token      "razupaltuff"
-                      :csrf       nil
-                      :statement  ""
-                      :selection  nil
-                      :logged-in? false}
-         :clipboard  {:selections nil
-                      :current    nil}
-         :sidebar    {:show? true}
-         }))
+         (atom {:discussion {}
+                :issues     {}
+                :items      {}
+                :layout     {:title     "discuss"
+                             :intro     "The current discussion is about:"
+                             :template  :discussion
+                             :add?      false
+                             :add-text  "Let me enter my reason!"
+                             :add-type  nil
+                             :loading?  false
+                             :reference ""
+                             :error?    false
+                             :error-msg nil}
+                :debug      {:last-api ""}
+                :user       {:nickname   "kangaroo"
+                             :token      "razupaltuff"
+                             :csrf       nil
+                             :statement  ""
+                             :selection  nil
+                             :logged-in? false}
+                :clipboard  {:selections nil
+                             :current    nil}
+                :sidebar    {:show? true}
+                }))

 (defn str->int
   "Convert String to Integer."
@@ -137,6 +137,7 @@
     (update-state-map! :items items)
     (update-state-map! :discussion discussion)
     (update-state-map! :issues issues)
+    (update-state-item! :user :avatar (fn [_] (get-in res [:extras :users_avatar])))
     (update-state-item! :debug :response (fn [_] res))))

 ;; Show error messages


Ensures the correct indexes on mongo.

Ensures the correct indexes on mongo.

--- src/cadence/model.clj
+++ src/cadence/model.clj
@@ -12,16 +12,19 @@
         [cemerick.friend.credentials :only [hash-bcrypt]])
   (:import [org.bson.types ObjectId]))

-(defn- ensure-indexes
+(defn ensure-indexes
   "Ensures several indexes to use mongo effectively."
   []
   ; Set up an index on random_point for cadence and phrases so we can
   ; *randomlyish* select a few of them.
-  (mc/ensure-index "cadences" {:random_point "2d"})
-  (mc/ensure-index "phrases" {:random_point "2d"})
-  (mc/ensure-index "phrases" {:users 1})
+  (mc/ensure-index "cadences" {:phrase 1
+                               :user_id 1
+                               :random_point "2d"})
+  (mc/ensure-index "phrases" {:random_point "2d", :users 1})
+  (mc/ensure-index "phrases" {:phrase-id 1})
+  (mc/ensure-index "phrases" {:phrase 1} {:unique 1 :dropDups 1})
   (mc/ensure-index "classifiers" {:user_id 1
-                                  :phrase_id 1})
+                                  :phrase 1})
   ; The `username` key should be unique.
   (mc/ensure-index "users" {:username 1} {:unique 1 :dropDups 1}))


fix register not clearing properly

fix register not clearing properly

--- src/clj/game/core.clj
+++ src/clj/game/core.clj
@@ -99,9 +99,7 @@
 ;Example: Blackmail flags the current run as not allowing rezzing of ICE
 (defn register-run-flag! [state flag condition card]
   (let [stack (get-in @state [:stack :current-run flag])]
-    (if (= stack nil)
-      (swap! state assoc-in [:stack :current-run flag] (list {:card card :condition condition}))
-      (swap! state assoc-in [:stack :current-run flag] (conj stack {:card card :condition condition}))
+      (swap! state assoc-in [:stack :current-run flag] (conj stack {:card card :condition condition})
       ))
   )

@@ -120,7 +118,7 @@

 ;Clear the current run register
 (defn clear-run-register! [state]
-  (swap! state assoc-in [:register :current-run] (list))
+  (swap! state assoc-in [:stack :current-run] nil)
   )

 (defn register-turn-flag! [state flag card]


Added some more functions for General Sorted Sets

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

--- src/conexp/contrib/dl/playground.clj
+++ src/conexp/contrib/dl/playground.clj
@@ -20,14 +20,19 @@
 (declare add-to-gss remove-from-gss)

 (defn make-general-sorted-set
-  "Constructs a general sorted set for the given order function."
+  "Constructs a general sorted set for the given order
+  function. order-fn must represent a reflexiv and transitive
+  relation. Elements being equal in the sense of this order relation
+  are considered the same."
   [order-fn]
   (General-Sorted-Set order-fn (ref #{}) (ref #{})))

 (defmethod print-method ::General-Sorted-Set [gss out]
   (.write out (print-str (seq-on gss))))

-(defmethod seq-on ::General-Sorted-Set [gss]
+(defn- sort-gss
+  "Does topological sort on a given gss."
+  [gss]
   (let [runner (fn runner [have]
 		 (let [next-have (distinct (for [x have,
 						 y @(:uppers x),
@@ -38,12 +43,20 @@
 		   (if (empty? next-have)
 		     have
 		     (recur (concat have next-have)))))]
-    (map :node (runner (vec @(:minimal-elements gss))))))
+    (runner (vec @(:minimal-elements gss)))))
+
+
+(defmethod seq-on ::General-Sorted-Set [gss]
+  (map :node (sort-gss gss)))

 ;;

 (defn- find-neighbours
-  ;; auxilliary algorithm for finding neighbours
+  "Auxilliary algorithm for finding neighbours. test-fn is used to
+  filter nodes for being neighbors of a certain node x, neigh-fn
+  returns for a node y all corresponding neighbours and current is the
+  set of nodes to search from. previous is the set of former visited
+  neighbours which will be refined if possible."
   [gss test-fn neigh-fn current previous]
   (let [next (filter test-fn current)]
     (if (empty? next)
@@ -113,4 +126,25 @@

 ;;;

+(defn contained-in-gss?
+  "Checks whether an element elt in contained in a general sorted set
+  gss, i.e. whether there exists an element in gss which is equal (in
+  the sense of the underlying order relation) to elt."
+  [gss elt]
+  (let [uppers (find-upper-neighbours gss elt),
+	order-fn (:order-fn gss)]
+    (and (= 1 (count uppers))
+	 (exists [x (map :node uppers)]
+	   (and (order-fn elt x)
+		(order-fn x elt))))))
+
+(defn hasse-graph
+  "Returns the Hasse Graph of the general sorted set gss."
+  [gss]
+  (for [x (sort-gss gss),
+	y @(:uppers x)]
+    [(:node x) (:node y)]))
+
+;;;
+
 nil


Write all of the melody in terms of run.

--- src/overtunes/songs/canone_alla_quarta.clj
+++ src/overtunes/songs/canone_alla_quarta.clj
@@ -22,22 +22,22 @@
 (def g-major (comp (add 74) major))

 (defn bpm [per-minute] #(-> % (/ per-minute) (* 60) (* 1000)))
-(defn run [a & bs]
+(defn run [[a & bs]]
   (let [up-or-down #(if (<= %1 %2) (range %1 %2) (reverse (range (inc %2) (inc %1))))]
     (if bs
-      (concat (up-or-down a (first bs)) (apply run bs))
+      (concat (up-or-down a (first bs)) (run bs))
       [a])))

 (def melody
   (let [call
           {:time (mapcat repeat [2 1 14 1] [1/4 1/2 1/4 3/2])
-           :pitch (concat (run 0 -1 3 0) [4] (run 1 8))}
+           :pitch (mapcat run [[0 -1 3 0] [4] [1 8]])}
         response
-          {:time (mapcat repeat [10 1 2 1]  [1/4 1/2 1/4 9/4])
-           :pitch (concat (run 7 -1 0) (run 0 -3))}
+          {:time (mapcat repeat [10 1 2 1] [1/4 1/2 1/4 9/4])
+           :pitch (mapcat run [[7 -1 0] [0 -3]])}
         development
           {:time (mapcat repeat [1 12 1 1 1 12 1] [3/4 1/4 1/2 1 1/2 1/4 3])
-           :pitch (concat [4 4] (run 2 -3) [-1 -2 0] (run 3 5) (repeat 3 1) [2] (run -1 1 -1) (run 5 0))}
+           :pitch (mapcat run [[4] [4] [2 -3] [-1 -2] [0] [3 5] [1] [1] [1 2] [-1 1 -1] [5 0]])}
         line
           (merge-with concat call response development)]
     (=> line #(update-in % [:time] sums) #(map vector (:time %) (:pitch %)))))
@@ -45,7 +45,7 @@
 (def bassline
   (map vector
        (sums (mapcat repeat [21 12] [1 1/4]))
-       (concat (mapcat (partial repeat 3) (concat (run 0 -3) (run -5 -3))) (run 12 0))))
+       (concat (mapcat (partial repeat 3) (mapcat run [[0 -3] [-5 -3]])) (run [12 0]))))

 (defn play# [notes]
   (let [play-at# #(at (% 0) (piano# (% 1)))]


Add debug metrics

Add debug metrics

--- src/cyanite_cache/core.clj
+++ src/cyanite_cache/core.clj
@@ -14,6 +14,11 @@
     (cache/-show-cache scache)
     (time (cache/put! scache "tenant" 123 60 117293 "my.metric" 20.0 600))
     (cache/-show-keys scache)
+    (cache/-show-cache scache)
+
+    (time (cache/put! scache "tenant" 123 60 117293 "my.metric" 30.0 600))
+    (cache/-show-keys scache)
     (cache/-show-cache scache))
+
   (Thread/sleep (* 190 1000))
   (System/exit 0))


start stripping the overly verbose logging

--- src/seathree/data.clj
+++ src/seathree/data.clj
@@ -160,12 +160,10 @@
         result                (http-client/get translate-url http-opts)
         status-string         (to-string (:status result))]
     (condp match status-string
-      #"^[45]" (do (log/debug "Got " status-string "from google for " user-data)
-                   nil)
-      #"^2"    (do (log/debug "Got translation from google for " user-data)
-                   (assoc tweet :translated (-> result
-                                                extract-translation
-                                                (restore-sigils symbols))))
+      #"^[45]"  nil
+      #"^2"     (assoc tweet :translated (-> result
+                                             extract-translation
+                                             (restore-sigils symbols)))
       #"null"  nil)))

 (defn twitter-creds-from-cfg
@@ -196,10 +194,8 @@
         response      (twitter/statuses-user-timeline :oauth-creds creds :params params)
         status-string (to-string (:code (:status response)))]
     (condp match status-string
-      #"^[45]" (do (log/debug "Got " status-string "from twitter for " user-data)
-                   nil)
-      #"^2"    (do (log/debug "Got tweets from twitter for " user-data)
-                   (map extract-tweet (:body response))))))
+      #"^[45]" nil
+      #"^2"    (map extract-tweet (:body response)))))

 (defn get-tweets-from-cache
   "Pull out and return all tweet data for the requested user


snapshot: compiling

snapshot: compiling

--- src/naojure/core.clj
+++ src/naojure/core.clj
@@ -67,25 +67,10 @@
          (zipmap proxy-list (map #(make-proxy robot %)
                                  proxy-list))))

-(defn make-robot
-  "Constructs a map representing a robot including any requested proxies. Most functions will construct the proxies they need on-the-fly if they are not already defined but since these are not stored it is more efficient to ask for any needed proxies in the call to make-robot."
-  ([hostname] {:hostname hostname :port 9559})
-  ([hostname port] ( {:hostname hostname :port port}))
-  ([hostname port proxies]
-     (add-proxies {:hostname hostname :port port} proxies)))
-
-(defn attach-session
-  ""
-  [robot]
-  (let [app (make-application)
-        session (make-session (:hostname robot) (:port robot))]
-    ))
-
 (defn make-application
   "Creates an instance of an application object"
   []
   (com.aldebaran.qimessaging.Application.))
-

 ; java function to wait on the future?
 (defn make-session
@@ -102,6 +87,20 @@
 ;;         (.wait fut 1000)
 ;;         session))

+(defn attach-session
+  "Attach the java application and session objects required to interact with the Aldebaran API"
+  [robot]
+  (let [app (make-application)
+        session (make-session (:hostname robot) (:port robot))]
+    (assoc robot :application app :session session)))
+
+(defn make-robot
+  "Constructs a map representing a robot including any requested proxies. Most functions will construct the proxies they need on-the-fly if they are not already defined but since these are not stored it is more efficient to ask for any needed proxies in the call to make-robot."
+  ([hostname] (attach-session {:hostname hostname :port 9559}))
+  ([hostname port] (attach-session {:hostname hostname :port port}))
+  ([hostname port proxies]
+     (add-proxies (attach-session {:hostname hostname :port port}) proxies)))
+
 (defn get-proxy
   "Gets a proxy from a robot, constructing it if necessary"
   [robot proxy]


Fix spec on CLJS tests

Fix spec on CLJS tests

--- src/hundred_pushups/core.cljc
+++ src/hundred_pushups/core.cljc
@@ -10,9 +10,8 @@

 ;;;;;; specs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-(s/def :exr/reps nat-int?)
-(s/def :exr/pushup-reps :exr/reps)
-(s/def :exr/plank-reps :exr/reps)
+(s/def :exr/pushup-reps nat-int?)
+(s/def :exr/plank-reps nat-int?)
 (s/def :exr/sets (s/int-in 4 20))
 (s/def :exr/ts inst?)


Fix single mode and switching back to drizzle

--- src/app/players.cljs
+++ src/app/players.cljs
@@ -10,12 +10,14 @@
   (reify
     player/Player
     (step-fwd [_]
-      (reset! layout {:text ((:items (@data 0)) (mod @index (count @data)))
-                      :opacity 1.0})
+      (reset! layout [{:text ((:items (@data 0)) (mod @index (count @data)))
+                       :key (str (rand-int 100000000))
+                       :opacity 1.0}])
       (swap! index inc))
     (step-rnd [_]
-      (reset! layout  {:text (mux/get-item data)
-                       :opacity 1.0}))
+      (reset! layout [{:text (mux/get-item data)
+                       :key (str (rand-int 100000000))
+                       :opacity 1.0}]))
     (animation [_])
     (render [_]
       [:div {:class "single"
@@ -24,4 +26,4 @@
                      :opacity 1.0
                      :left "40%"
                      :top "30%"}}
-       (:text @layout)])))
+       (:text (first @layout) )])))


improve logging

improve logging

--- src/babel/forest.clj
+++ src/babel/forest.clj
@@ -239,7 +239,7 @@
                                  (do
                                    (log/debug (str "fail-path-between:" (fail-path-between (strip-refs (get-in bolt path))
                                                                                (strip-refs complement)))))
-                                 (log/debug (str "SUCCESS! " (wrapped-morph morph complement))))
+                                 (log/debug (str "Success: returning: " (wrapped-morph morph complement))))

                                (if is-fail? :fail result)))


Allow stashing to use queue name without requiring prefix.

--- src/baleen/stash.clj
+++ src/baleen/stash.clj
@@ -73,7 +73,8 @@
   [context list-name remote-name json-api-type overwrite]
   (l/info "Attempt stash" list-name " -> " remote-name)
   (with-open [^Jedis redis-conn (baleen-redis/get-connection context)]
-    (let [list-range (.lrange redis-conn list-name 0 -1)
+    (let [list-name-key (str (bcontext/get-app-name context))
+          list-range (.lrange redis-conn list-name 0 -1)
           key-exists (.exists redis-conn list-name)]
       (if-not key-exists
         (l/info "Key" list-name "did not exist. This is expected for anything older than yesterday.")


Add release and acquire functions

Add release and acquire functions

--- src/beehive/hive.clj
+++ src/beehive/hive.clj
@@ -14,7 +14,8 @@

 (ns beehive.hive
   (:require [beehive.enums :as enums])
-  (:import (clojure.lang ILookup)))
+  (:import (clojure.lang ILookup)
+           (net.uncontended.precipice GuardRail)))

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

@@ -23,7 +24,7 @@
    :error false
    :timeout false})

-(defn return-nil [x] nil)
+(defn- return-nil [x] nil)

 (deftype Hive
   [^net.uncontended.precipice.GuardRail guard-rail result-metrics rejected-metrics
@@ -45,10 +46,6 @@
           :rejected-metrics rejected-metrics
           :latency-metrics latency-metrics
           :backpressure backpressure})))
-
-(defn- do-new-assertions [clauses]
-  (assert (every? keyword? (keys clauses)))
-  (assert (every? seq? (vals (rest clauses)))))

 (defn add-bp [^net.uncontended.precipice.GuardRailBuilder builder reason->backpressure]
   (doseq [backpressure (vals reason->backpressure)]
@@ -97,4 +94,25 @@
          latency-metrics#
          backpressure#
          result-key->enum#
-         rejected-key->enum#))))+         rejected-key->enum#))))
+
+(defn release
+  ([^Hive beehive {:keys [permit-count]}]
+   (when permit-count
+     (let [^GuardRail guard-rail (.-guard_rail beehive)
+           end-nanos (.nanoTime (.getClock guard-rail))]
+       (.releasePermitsWithoutResult guard-rail permit-count end-nanos))))
+  ([^Hive beehive {:keys [permit-count start-nanos]} result]
+   (when permit-count
+     (let [^GuardRail guard-rail (.-guard_rail beehive)
+           result-enum (get (.-result_enums beehive) result)
+           end-nanos (.nanoTime (.getClock guard-rail))]
+       (.releasePermits
+         guard-rail result-enum permit-count start-nanos end-nanos)))))
+
+(defn acquire [^Hive beehive permits]
+  (let [^GuardRail guard-rail (.-guard_rail beehive)
+        start-nanos (.nanoTime (.getClock guard-rail))]
+    (if-let [rejected-reason (.acquirePermits guard-rail permits start-nanos)]
+      {:rejected? true :reason (get (.-rejected_enum beehive) rejected-reason)}
+      {:start-nanos start-nanos :permit-count permits})))


part way through adding move-marble

part way through adding move-marble

--- src/nonaga/draw.cljs
+++ src/nonaga/draw.cljs
@@ -44,11 +44,22 @@
   {"red" "pink"
    "blue" "lightblue"})

-(defn draw-valid-marble-moves [state]
+; the state grabbing and updating, as well as the fn wrapping can be moved out
+; of this and start-marble-move
+(defn move-marble [component color from to]
+  (fn []
+    (js/console.log "kittens")
+    (let [old-state (.-wrapper (.-state component))
+          moved     (n/move-ball old-state color from to)
+          new-state (assoc moved :event [:marble-moved color])]
+      (.setState component #js {:wrapper new-state}))))
+
+(defn draw-valid-marble-moves [component state]
   (let [[type & event-data] (:event state)]
     (when (= :marble-move type)
-      (let [[color selected] event-data]
-        (draw (partial marble (light-colors (name color)))
+      (let [[color selected] event-data
+            click (move-marble component color selected [2 2])]
+        (draw (partial marble (light-colors (name color)) click)
               (b/valid-destinations state selected))))))

 (defn start-marble-move [component color coord]
@@ -69,7 +80,7 @@
                 (draw ring (:rings state))
                 (draw-marbles "red"  (:whites state) (partial start-marble-move this))
                 (draw-marbles "blue" (:blacks state) (partial start-marble-move this))
-                (draw-valid-marble-moves state)))))))
+                (draw-valid-marble-moves this state)))))))

 (defn start []
   (render-component (board) (sel1 :#content)))


Updating rpm stanza

Updating rpm stanza

--- src/omnibus/core.clj
+++ src/omnibus/core.clj
@@ -113,7 +113,7 @@
   (let [
         asset-name (str project-name "-" version "-" iteration "." (os-data :machine) ".rpm")
         asset-path (.toString (file-str *omnibus-pkg-dir* "/" asset-name))
-        status (sh "fpm" "-s" "dir" "-t" "rpm" "-v" version "--iteration" iteration "-n" project-name "/opt/opscode" "-m" "Opscode, Inc." "--post-install" (str *omnibus-source-dir* "postinst") "--post-uninstall" (str *omnibus-source-dir* "/postrm") "--description" "The full stack install of Opscode Chef" "--url" "http://www.opscode.com" :dir "./pkg")]
+        status (sh "fpm" "-s" "dir" "-t" "rpm" "-v" version "--iteration" iteration "-n" project-name "/opt/opscode" "-m" "Opscode, Inc." "--post-install" (str *omnibus-source-dir* "/postinst") "--post-uninstall" (str *omnibus-source-dir* "/postrm") "--description" "The full stack install of Opscode Chef" "--url" "http://www.opscode.com" :dir "./pkg")]
     (log-sh-result status
                    (do
                      (put-in-bucket asset-path @*bucket-name* (str (os-data :platform) "-" (os-data :platform_version) "-" (os-data :machine) "/" asset-name) @*s3-access-key* @*s3-secret-key*)


Supply lifecycle state schema.

Supply lifecycle state schema.

--- src/onyx/schema.cljc
+++ src/onyx/schema.cljc
@@ -635,6 +635,22 @@

 (s/defschema Storage (s/enum :s3 :zookeeper))

+(s/defschema LifecycleState
+  (s/enum :lifecycle/poll-recover :lifecycle/offer-barriers
+          :lifecycle/offer-barrier-status :lifecycle/recover-input
+          :lifecycle/recover-state :lifecycle/recover-output
+          :lifecycle/unblock-subscribers :lifecycle/next-iteration
+          :lifecycle/input-poll-barriers :lifecycle/check-publisher-heartbeats
+          :lifecycle/seal-barriers? :lifecycle/seal-barriers?
+          :lifecycle/checkpoint-input :lifecycle/checkpoint-state
+          :lifecycle/checkpoint-output :lifecycle/offer-barriers
+          :lifecycle/offer-barrier-status :lifecycle/unblock-subscribers
+          :lifecycle/before-batch :lifecycle/read-batch
+          :lifecycle/check-publisher-heartbeats :lifecycle/after-read-batch
+          :lifecycle/apply-fn :lifecycle/after-apply-fn :lifecycle/assign-windows
+          :lifecycle/prepare-batch :lifecycle/write-batch :lifecycle/after-batch
+          :lifecycle/offer-heartbeats))
+
 (s/defschema PeerConfig
   {:zookeeper/address s/Str
    (s/optional-key :onyx/id) (deprecated [:env-config :model :onyx/id])
@@ -647,6 +663,7 @@
    (s/optional-key :onyx.messaging/peer-port) s/Int
    (s/optional-key :onyx.messaging/external-addr) s/Str
    (s/optional-key :onyx.peer/subscriber-liveness-timeout-ms) PosInt
+   (s/optional-key :onyx.peer.metrics/lifecycles) [LifecycleState]
    (s/optional-key :onyx.peer/storage) Storage
    (s/optional-key :onyx.peer/storage.timeout) s/Int
    (s/optional-key :onyx.peer/storage.s3.auth-type) (s/enum :provider-chain :config)


formatting

formatting

--- src/agario3d/game.clj
+++ src/agario3d/game.clj
@@ -144,16 +144,16 @@
 (defn create-snapshot [game]
   (->> (reduce (fn [snap [k v]]
                  (assoc snap k v)) {} game)
-        (assoc game :snapshot ,,,)))
+       (assoc game :snapshot ,,,)))

 (defn create-diff [s game]
-    (reduce (fn [diff [k v]]
-                   (let [snap-val (get k s)]
-                     (if (and (not= :snapshot k)
-                              (or (nil? snap-val) (not= snap-val v)))
-                       (assoc diff k v)
-                       diff))
-                   ) {} game))
+  (reduce (fn [diff [k v]]
+            (let [snap-val (get k s)]
+              (if (and (not= :snapshot k)
+                       (or (nil? snap-val) (not= snap-val v)))
+                (assoc diff k v)
+                diff))
+            ) {} game))

 (defn move-bots [game])


https links

https links

--- src/foreclojure/social.clj
+++ src/foreclojure/social.clj
@@ -22,7 +22,7 @@
                                  :where {:_id problem-num})
         filename (str user-name "-4clojure-solution" problem-num ".clj")
         text (str ";; " user-name "'s solution to " name "\n"
-                  ";; http://4clojure.com/problem/" problem-num
+                  ";; https://4clojure.com/problem/" problem-num
                   "\n\n"
                   solution)]
     (try
@@ -32,7 +32,7 @@
       (catch Throwable _ nil))))

 (defn tweet-solution [id gist-url & [link-text]]
-  (let [status-msg (str "Check out how I solved http://4clojure.com/problem/"
+  (let [status-msg (str "Check out how I solved https://4clojure.com/problem/"
                         id " - " gist-url " #clojure #4clojure")]
     (tweet-link status-msg link-text)))


Removed profile calls in clustering code

--- src/polismath/clusters.clj
+++ src/polismath/clusters.clj
@@ -81,7 +81,7 @@
               (dissoc :positions)))))

-(defnp recenter-clusters
+(defn recenter-clusters
   "Replace cluster centers with a center computed from new positions"
   [data clusters]
   (greedy
@@ -90,7 +90,7 @@
     clusters)))

-(defnp safe-recenter-clusters
+(defn safe-recenter-clusters
   "Replace cluster centers with a center computed from new positions"
   [data clusters]
   (as-> clusters clsts
@@ -125,7 +125,7 @@
      :center (mean (map :center [clst1 clst2]))}))

-(defnp most-distal
+(defn most-distal
   "Finds the most distal point in all clusters"
   [data clusters]
   (let [[dist clst-id id]
@@ -153,7 +153,7 @@
     [] clusters))

-(defnp clean-start-clusters
+(defn clean-start-clusters
   "This function takes care of some possible messy situations which can crop up with using 'last-clusters'
   in kmeans computation, and generally gets the last set of clusters ready as the basis for a new round of
   clustering given the latest set of data."
@@ -192,7 +192,7 @@

 ; Each cluster should have the shape {:id :members :center}
-(defnp kmeans
+(defn kmeans
   "Performs a k-means clustering."
   [data k & {:keys [last-clusters max-iters] :or {max-iters 20}}]
   (let [data-iter (zip (rownames data) (matrix (get-matrix data)))


(maint) Fix test assertion for OS X

(maint) Fix test assertion for OS X

According to Chris Price, some of the memory metrics don't propagate
correctly on OS X, which can result in a value of -1. Updated test
assertion so it will work when run on an OS X machine.

--- test/puppetlabs/trapperkeeper/services/status/status_core_test.clj
+++ test/puppetlabs/trapperkeeper/services/status/status_core_test.clj
@@ -115,6 +115,6 @@
         (is (= #{:committed :init :max :used} (ks/keyset (:heap-memory jvm-metrics))))
         (is (= #{:committed :init :max :used} (ks/keyset (:non-heap-memory jvm-metrics))))
         (is (every? #(< 0 %) (vals (:heap-memory jvm-metrics))))
-        (is (every? #(< 0 %) (vals (:non-heap-memory jvm-metrics))))
+        (is (every? #(or (< 0 %) (= -1 %)) (vals (:non-heap-memory jvm-metrics))))
         (is (< 0 (:up-time-ms jvm-metrics)))
         (is (< 0 (:start-time-ms jvm-metrics)))))))


Using less Clojure syntax, better result printing.

--- swap.clj
+++ swap.clj
@@ -1,8 +1,8 @@
 ;; swap! already exists in Clojure
 (defmacro my-swap! [x y]
   `(dosync
-    (let [tmp# @~x]
-      (ref-set ~x @~y)
+    (let [tmp# (deref ~x)]
+      (ref-set ~x (deref ~y))
       (ref-set ~y tmp#))))

 (def a (ref 1))
@@ -10,6 +10,6 @@

 (my-swap! a b)
 (pr "a")
-(pr a)
+(pr @a)
 (pr "b")
-(pr b)
+(pr @b)


Set world dimensions on world desc instead of current world

--- src/player/core.cljs
+++ src/player/core.cljs
@@ -455,7 +455,15 @@
                    :walls (:walls new-world)
                    :seen-polys {}
                    :explored #{}
-                   :seen-configs #{})
+                   :seen-configs #{}
+                   :width (:width desc)
+                   :height (:height desc)
+                   :scroll-x (if (>= (:scroll-x w) (:width desc))
+                               (:width desc)
+                               (:scroll-x w))
+                   :scroll-y (if (>= (:scroll-y w) (:height desc))
+                               (:height desc)
+                               (:scroll-y desc)))
         w (update w
                   :configs
                   (fn [cfgs]
@@ -471,7 +479,7 @@
     (world-append (update w :configs #(subvec % 0 (dec (count %))))
                   (heval/recache-trs new-defs (current-config w)))))

-(defn world-update-desc! [desc]
+(defn world-update-desc! [world desc]
   (update-world! world
                  (fn [w]
                    (world-update-desc w desc))))
@@ -609,10 +617,10 @@
                                      has (:objects cfg)
                                      polys (apply concat (vals (:seen-polys wld)))]
                                  (sab/html [:div {:style {:backgroundColor "blue"
-                                                          :width           container-w
-                                                          :height          container-h
+                                                          :width           (+ container-w 20)
+                                                          :height          (+ container-h 20)
                                                           :position        "relative"
-                                                          :overflow        "auto"}
+                                                          :overflow        "scroll"}
                                                   :onScroll
                                                          (fn [scroll-evt]
                                                            (let [n (.-target scroll-evt)]
@@ -664,25 +672,30 @@
         f (.createFactory js/React c)]
     f))

-(defn num-changer [world label key]
+(defn num-changer [world label key update-fn!]
   (sab/html
     [:label {} label]
     [:input {:type     "number"
              :key      key
              :value    (key @world)
              :onChange (fn [evt]
-                         (update-world! world
-                                        (fn [w]
-                                          (println "set" key "from" (key w) "to" (.-value (.-target evt)))
-                                          (assoc w key (.-value (.-target evt))))))}]))
+                         (update-fn! world key (.-value (.-target evt))))}]))
+
+(defn world-update-desc-key! [world key val]
+  (world-update-desc! world (assoc (:desc @world)
+                                    key
+                                    val)))
+
+(defn world-update-key! [world key val]
+  (update-world! world (fn [w] (assoc w key val))))

 (defn edit-controls [world]
-  (sab/html (num-changer world "World Width" :width)
-            (num-changer world "World Height" :height)
-            (num-changer world "Scroll X" :scroll-x)
-            (num-changer world "Scroll Y" :scroll-y)
-            (num-changer world "Camera Width" :camera-width)
-            (num-changer world "Camera Height" :camera-height)))
+  (sab/html (num-changer world "World Width" :width world-update-desc-key!)
+            (num-changer world "World Height" :height world-update-desc-key!)
+            (num-changer world "Scroll X" :scroll-x world-update-key!)
+            (num-changer world "Scroll Y" :scroll-y world-update-key!)
+            (num-changer world "Camera Width" :camera-width world-update-key!)
+            (num-changer world "Camera Height" :camera-height world-update-key!)))

 (defn rererender [target]
   (let [w @world


Add debugging info if classpaths are messed up?

--- src/cake/project.clj
+++ src/cake/project.clj
@@ -46,12 +46,13 @@
 (defn make-classloader [& paths]
   (when (:ext-dependencies *project*)
     (wrap-ext-classloader (ext-classpath)))
-  (when-let [cl (classlojure (apply classpath paths))]
-    (eval-in cl '(do (require 'cake)
-                     (require 'bake.io)
-                     (require 'bake.reload)
-                     (require 'clojure.main)))
-    cl))
+  (if-let [cl (classlojure (apply classpath paths))]
+    (doto cl
+      (eval-in '(do (require 'cake)
+                    (require 'bake.io)
+                    (require 'bake.reload)
+                    (require 'clojure.main))))
+    (prn paths)))

 (defn set-classpath!
   "Set the JVM classpath property to the current clojure classloader."


(mock-)handle onClose websocket event to get rid of tracebacks

--- src/greybear/websocket.clj
+++ src/greybear/websocket.clj
@@ -45,5 +45,6 @@
     (.add "/websocket"
           (proxy [WebSocketHandler] []
             (onOpen [conn] (on-open conn))
+            (onClose [conn] nil)
             (onMessage [conn mess] (on-message conn mess))))
     (.start)))


don't let ghost piece go above original position

--- src/client/core.cljs
+++ src/client/core.cljs
@@ -145,7 +145,7 @@
   [piece x y board]
   (let [collide? (fn [cy] (not (piece-fits? piece x cy board)))
         cy (first (filter collide? (iterate inc y)))]
-    (dec cy)))
+    (max y (dec cy))))

 ;;------------------------------------------------------------
 ;; PAINTING (for showing the game on a canvas)


Cleanup

Cleanup

--- src/clj/manifail.clj
+++ src/clj/manifail.clj
@@ -142,8 +142,8 @@
 (defn marker?
   "True if the value `v` is an abort/retry/reset marker.

-  Useful in case you are catching an `Exception/ExceptionInfo/RuntimeException/Throwable/Error`
-  in the retriable block and want to make sure you only act on a non-marker value, e.g.:
+  Useful in case you are catching an `Throwable/Error` in the retriable code
+  block and want to make sure you only act on a non-marker value, e.g.:

   ```
   (with-retries ...
@@ -174,7 +174,7 @@
       (RetriesExceeded. retried result'))))

 (defn unwrap
-  "Unwraps a `RetriesExceeded`/`Aborted`/`Retried`"
+  "Unwraps a value/cause of a `RetriesExceeded`/`Aborted`/`Retried`."
   [v]
   (cond (instance? RetriesExceeded v)
         (or (.value ^RetriesExceeded v) (.getCause ^Throwable v))
@@ -223,14 +223,12 @@
   [delays f]
   (let [reset-delays (fn [^Reset r] (.retryDelays r))
         ex (or (ex/executor) current-thread-executor)
-        elapsed (volatile! 0)
         started (System/nanoTime)]
     (d/loop [retried 0, last-result ::none, delays' delays]
       (-> (d/future-with ex
-            (vreset! elapsed (- (System/nanoTime) started))
             (binding [*last-result* last-result
                       *retry-count* retried
-                      *elapsed-ms* (/ @elapsed 1e6)]
+                      *elapsed-ms* (/ (- (System/nanoTime) started) 1e6)]
               (f)))
           (d/catch' identity)
           (d/chain'


rearrange trunk locks

rearrange trunk locks

--- src/clj/neb/cell.clj
+++ src/clj/neb/cell.clj
@@ -66,27 +66,23 @@
   `(with-bindings {#'*cell-meta* (extract-cell-meta ~trunk ~hash)
                    #'*cell-hash* ~hash
                    #'*cell-trunk* ~trunk}
-     (when *cell-meta* ~@body)))
+     (.readLock ~trunk)
+     (try
+       (when *cell-meta* ~@body)
+       (finally
+         (.readUnLock ~trunk)))))

 (defmacro with-write-lock [trunk hash & body]
   `(with-cell-meta
      ~trunk ~hash
-     (.readLock trunk)
-     (try
-       (locking *cell-meta*
-         ~@body)
-       (finally
-         (.readUnLock trunk)))))
+     (locking *cell-meta*
+       ~@body)))

 (defmacro with-read-lock [trunk hash & body]
   `(with-cell-meta
      ~trunk ~hash
-     (.readLock trunk)
-     (try
-       (locking *cell-meta*
-         ~@body)
-       (finally
-         (.readUnLock trunk)))))
+     (locking *cell-meta*
+       ~@body)))

 (defn get-cell-location []
   (.getLocation *cell-meta*))


Add svg helper functions for centering elements.

--- src/cljx/c2/svg.cljx
+++ src/cljx/c2/svg.cljx
@@ -6,7 +6,8 @@
 ^:cljs (ns c2.svg
          (:use-macros [clojure.core.match.js :only [match]])
          (:use [c2.maths :only [Pi Tau radians-per-degree
-                                sin cos]]))
+                                sin cos]])
+         (:require [c2.dom :as dom]))

 ;;Lil' SVG helpers
@@ -25,12 +26,35 @@
 (defn ^:cljs get-bounds
   "Returns map of {:x :y :width :height} containing SVG element bounding box.
    All coordinates are in userspace. See: http://www.w3.org/TR/SVG/types.html#InterfaceSVGLocatable"
-  [$svg]
-  (let [b (.getBBox $svg)]
+  [$svg-el]
+  (let [b (.getBBox $svg-el)]
     {:x (.-x b)
      :y (.-y b)
      :width (.-width b)
      :height (.-height b)}))
+
+(defn transform-to-center
+  "Returns a transform string that will scale and center provided element {:width :height :x :y} within container {:width :height}."
+  [element container]
+  (let [{ew :width eh :height x :x y :y} element
+        {w :width h :height} container
+        s (min (/ h eh) (/ w ew))]
+    (str (translate [(- (/ w 2) (* s (/ ew 2)))
+                     (- (/ h 2) (* s (/ eh 2)))]);;translate scaled to center
+         " " (scale s) ;;scale
+         " " (translate [(- x) (- y)]) ;;translate to origin
+         )))
+
+
+(defn ^:cljs transform-to-center!
+  "Scales and centers $svg-el within its parent SVG container.
+   Uses parent's width and height attributes only."
+  [$svg-el]
+  (let [$svg (.-ownerSVGElement $svg-el)
+        t (transform-to-center (get-bounds $svg-el)
+                               {:width (js/parseFloat (dom/attr $svg :width))
+                                :height (js/parseFloat (dom/attr $svg :height))})]
+    (dom/attr $svg-el :transform t)))


First sketch of adding rhythm to the music

--- src/pianola/core.clj
+++ src/pianola/core.clj
@@ -5,6 +5,15 @@
             [leipzig.scale :as scale])
   (:use [overtone.inst.piano]))

+(defmethod live/play-note :default [{midi :pitch seconds :duration}]
+  (piano midi seconds :decay 0.001))
+
+(defn play-tune [tune]
+  (->>
+   tune
+   (tempo (bpm 50))
+   (where :pitch (comp scale/C scale/major))
+   live/play))

 (defn neighborhood [gen i v]
   [(nth gen (dec i) (last gen))
@@ -21,27 +30,36 @@

 (def automaton [1 2 0 4 5 6 3])

+(def rhythm [4 8 4 8 2 4 4 4])
 (def notes [2 1 2 1 2 3 4 5])

 (def run-automaton (partial next-gen automaton))
+
+(defn scale-rhythm [gen]
+  (map #(if (= 0 %)
+          0
+          (/ 1 %)) gen))

 (next-gen notes)

 (run-automaton [1 1 1 1 1 4 4 4])

+(automate-rhythm [1 1 1 1 1 4 4 4])
+
+(automate-rhythm rhythm)
+
 (take 5 (iterate run-automaton notes))

 (def melody
-  (phrase (repeat 1/4)
+  (phrase rhythm
+          notes))
+
+(def melodic-automaton
+  (phrase (flatten (iterate automate-rhythm rhythm))
           (flatten (iterate run-automaton notes))))

-(defmethod live/play-note :default [{midi :pitch seconds :duration}]
-  (piano midi seconds :decay 0.001))
+(play-tune melody)

-(->>
- melody
- (tempo (bpm 70))
- (where :pitch (comp scale/C scale/major))
- live/play)
+(play-tune melodic-automaton)

 (live/stop)


RR: [WIP] add edit-delete column on slick grid

--- src/hatti/views/table.cljs
+++ src/hatti/views/table.cljs
@@ -1,6 +1,8 @@
 (ns hatti.views.table
-  (:require-macros [cljs.core.async.macros :refer [go go-loop]])
+  (:require-macros [cljs.core.async.macros :refer [go go-loop]]
+                   [dommy.core :refer [sel]])
   (:require [cljs.core.async :refer [<! chan put! timeout]]
+            [dommy.core :as dommy]
             [om.core :as om :include-macros true]
             [om.dom :as dom :include-macros true]
             [sablono.core :as html :refer-macros [html]]
@@ -82,21 +84,41 @@
   (let [clj-value (js->clj value :keywordize-keys true)]
     (forms/format-answer field clj-value language true)))

+(defn button-formatter
+  [row cell value columnDef dataContext]
+  (let [_ (.log js/console value)]
+    (str
+    ""
+    ""
+    "  "
+    ""
+    "")))
+
+(def actions-column
+  {:id "actions" :field _id :type "text"
+   :name "" :toolTip "" :sortable false
+   :formatter button-formatter
+   :headerCssClass ""
+   :cssClass "record-actions"
+   :minWidth 50})
+
 (defn- flat-form->sg-columns
   "Get a set of slick grid column objects when given a flat form."
   ([form] (flat-form->sg-columns form true))
   ([form get-label?] (flat-form->sg-columns form get-label? nil))
   ([form get-label? language & {:keys [is-filtered-dataview?]}]
-   (clj->js
-    (for [field (all-fields form :is-filtered-dataview? is-filtered-dataview?)]
-      (let [{:keys [name type full-name]} field
-            label (if get-label? (get-label field language) name)]
-        {:id name :field full-name :type type
-         :name label :toolTip label :sortable true
-         :formatter (partial formatter field language)
-         :headerCssClass (get-column-class field)
-         :cssClass (get-column-class field)
-         :minWidth 50})))))
+   (let [columns (for [field (all-fields form :is-filtered-dataview?
+                                         is-filtered-dataview?)]
+                   (let [{:keys [name type full-name]} field
+                         label (if get-label? (get-label field language) name)]
+                     {:id name :field full-name :type type
+                      :name label :toolTip label :sortable true
+                      :formatter (partial formatter field language)
+                      :headerCssClass (get-column-class field)
+                      :cssClass (get-column-class field)
+                      :minWidth 50}))]
+     (clj->js (conj columns actions-column)))))

 (defn- init-sg-pager [grid dataview]
   (let [Pager (.. js/Slick -Controls -Pager)]
@@ -217,7 +239,14 @@
                 (.invalidateAllRows grid)
                 (resizeColumns grid)
                 (.render grid)
-                (init-sg-pager grid dataview))))))))
+                (init-sg-pager grid dataview)
+                (doseq [elem (sel :.view-record)]
+                  (dommy/listen! elem :click (fn [e]
+                                               (.preventDefault e)
+                                               (js/alert
+                                                 (.getAttribute
+                                                   (.-target e)
+                                                   "data-id"))))))))))))

 (defn- render-options
   [options owner colset!]


Different create modes for HAs vs walls

Different create modes for HAs vs walls

--- src/player/core.cljs
+++ src/player/core.cljs
@@ -90,7 +90,7 @@
 (defonce world (atom {}))
 (defonce editor (atom {}))

-(def play-on-start true)
+(def play-on-start false)

 (declare reset-world! reset-seen-polys! reset-tr-caches!)

@@ -186,7 +186,8 @@

 (defn make-editor []
   ; todo: move editor scrolling info here?
-  {:selection #{[:walls 0] [:walls 2]}})
+  {:selection   #{[:walls 0] [:walls 2]}
+   :create-mode {:name "Wall" :type :wall :prototype {:x 0 :y 0 :w 16 :h 16}}})

 (defn reset-tr-caches! []
   (swap!
@@ -214,7 +215,7 @@
     (roll/find-move-by-edge opts id edge)))

 (def unroll-limit 5)
-(def explore-rolled-out? true)
+(def explore-rolled-out? false)
 (def explore-roll-limit 5)

 (defn explore-nearby [ha-defs seed-playout explored seen]
@@ -419,8 +420,10 @@
                             (get old-defs old-type))
                   old-val (when old-val
                             (ha/extrapolate old-def old-val t))
-                  old-at-init? (= (.-v0 old-val)
-                                  (.-v0 old-init))
+                  old-at-init? (if old-val
+                                 (= (.-v0 old-val)
+                                    (.-v0 old-init))
+                                 true)
                   ; if the old val was at the initial valuation,
                   ; then moving the initial valuation should update the old val.
                   old-val (if old-at-init?
@@ -525,7 +528,7 @@
                         ; assume all keys held now were held since "then"
                         [(iv/interval (:now w) new-now) (keys/key-states)]
                         ; bailout if we transition more than 60 times per second
-                        (* 60 (- new-now (:now w)))
+                        (.max js/Math (* 60 (- new-now (:now w))) 5)
                         0)
                 new-w (if (not= c new-c)
                         (world-append w new-c)
@@ -618,25 +621,47 @@

 (def drag-threshold 2)

+(defn random-id
+  ([ha-type existing-ids] (random-id ha-type existing-ids (count existing-ids)))
+  ([ha-type existing-ids candidate-index]
+   (let [cand (keyword (str ha-type "-" candidate-index))]
+     (if (contains? existing-ids cand)
+       (random-id ha-type existing-ids (inc candidate-index))
+       cand))))
+
 (defn editor-start-new-thing [ed x y now-x now-y]
-  ;todo: HA _or_ wall
-  (let [new-id (inc (apply max (map first (:walls (:draft-desc ed)))))
-        _ (println "create new wall" new-id x y now-x now-y)
-        new-thing-handle [:walls new-id]
+  (let [{type :type proto :prototype} (:create-mode ed)
+        new-id (case type
+                 :wall (inc (apply max (map first (:walls (:draft-desc ed)))))
+                 :ha (random-id (:type proto)
+                                (set (keys (:objects (:draft-desc ed))))))
+        _ (println "create new thing" new-id x y now-x now-y)
+        new-thing-handle [(case type
+                            :wall :walls
+                            :ha :objects)
+                          new-id]
         ax x
         ay y
         bx now-x
         by now-y]
     (assoc ed
-      :move-mode :resizing
+      :move-mode (case type
+                   :wall :resizing
+                   :ha :moving)
       :selection #{new-thing-handle}
       :draft-desc (assoc-in
                     (:draft-desc ed)
                     new-thing-handle
-                    {:x (.min js/Math ax bx)
-                     :y (.min js/Math ay by)
-                     :w (.abs js/Math (- bx ax))
-                     :h (.abs js/Math (- by ay))}))))
+                    (merge
+                      proto
+                      (case type
+                        :wall
+                        {:x (.min js/Math ax bx)
+                         :y (.min js/Math ay by)
+                         :w (.abs js/Math (- bx ax))
+                         :h (.abs js/Math (- by ay))}
+                        :ha
+                        {:x x :y y}))))))

 (defn editor-move-selection [ed dx dy]
   (println "move selection by" dx dy)
@@ -714,6 +739,35 @@
                               [t (ha/extrapolate ha-def ha t)]))
                           os)))))

+(def segmented-control
+  (let [props (fn [this] (aget (.-props this) "args"))
+        c
+        (.createClass js/React
+                      #js {:shouldComponentUpdate
+                           (fn [next-props _next-state]
+                             (this-as this
+                               (not= (aget next-props "args") (props this))))
+                           :render
+                           (fn []
+                             (this-as this
+                               (let [[label options selected on-change] (props this)
+                                     ]
+                                 (sab/html [:div
+                                            (map
+                                              (fn [{name :name type :type prototype :prototype :as o}]
+                                                [:button
+                                                 {:style   {:backgroundColor (if (= selected o)
+                                                                               "#4479BA"
+                                                                               "#CCCCCC")}
+                                                  :onClick (fn [evt]
+                                                             (println type prototype)
+                                                             (on-change o))}
+                                                 name])
+                                              options)]))))})
+        f (.createFactory js/React c)]
+    (fn [& args]
+      (f #js {:args args}))))
+
 (def world-widget
   (let [props (fn [this] (aget (.-props this) "args"))
         ; world -> view: scale up and flip
@@ -754,10 +808,9 @@
         c
         (.createClass js/React
                       #js {:shouldComponentUpdate
-                           (fn [next-props next-state]
+                           (fn [next-props _next-state]
                              (this-as this
-                               (or (not= next-props (props this))
-                                   (not= @next-state @(.-state this)))))
+                               true))
                            :render
                            (fn []
                              (this-as this
@@ -822,7 +875,13 @@
                                                                                (selection-add (selection-init ed)
                                                                                wld
                                                                                new-sel)
-                                                                                ; regular-clicked on nothing --> clear selection
+                                                                                ;regular clicked on nothing while in HA-placing mode --> place ha
+                                                                                (and (not new-sel)
+                                                                                (not shift?)
+                                                                                (= (:type (:create-mode ed))
+                                                                                :ha))
+                                                                                (editor-start-new-thing ed wx wy wx wy)
+                                                                                ; regular-clicked on nothing while in walls or select mode --> clear selection
                                                                                (and (not new-sel)
                                                                                (not shift?))
                                                                                (selection-init ed)
@@ -1033,12 +1092,15 @@

 (defn num-changer [world label key update-fn!]
   (sab/html
-    [:label {:key (str key "-label")} label]
-    [:input {:type     "number"
-             :key      (str key "-field")
-             :value    (key @world)
-             :onChange (fn [evt]
-                         (update-fn! world key (.parseInt js/window (.-value (.-target evt)))))}]))
+    [:div {:style {:width 170 :display "inline-block" :fontSize "12px"}}
+     [:label {:key   (str key "-label")
+              :style {:width "95%"}} label]
+     [:input {:type     "number"
+              :style    {:width "95%"}
+              :key      (str key "-field")
+              :value    (key @world)
+              :onChange (fn [evt]
+                          (update-fn! world key (.parseInt js/window (.-value (.-target evt)))))}]]))

 (defn world-update-desc-key! [world key val]
   (world-update-desc! world (assoc (:desc @world)
@@ -1050,6 +1112,29 @@

 (defn edit-controls [world editor]
   (sab/html [:div
+             [:div {:style {:position        "absolute"
+                            :top             26 :left (+ (:view-width @world) 32)
+                            :width           200 :height 400
+                            :backgroundColor "red"
+                            :fontSize        "12px"}}
+              [:p {:style {:margin 0}} "Toolbox"]
+              (segmented-control "Create:"
+                                 [{:name      "Wall"
+                                   :type      :wall
+                                   :prototype {:x 0 :y 0 :w 16 :h 16}}
+                                  {:name      "Goomba"
+                                   :type      :ha
+                                   :prototype {:type  :goomba
+                                               :state :right
+                                               :x     0 :y 0 :w 16 :h 16}}
+                                  {:name      "Mario"
+                                   :type      :ha
+                                   :prototype {:type  :mario
+                                               :state :idle-right
+                                               :x     0 :y 0 :w 16 :h 16}}]
+                                 (:create-mode @editor)
+                                 (fn [new-val]
+                                   (swap! editor (fn [e] (assoc e :create-mode new-val)))))]
              (num-changer world "World Width" :width world-update-desc-key!)
              (num-changer world "World Height" :height world-update-desc-key!)
              [:br {:key 0}]
@@ -1070,7 +1155,11 @@
 (defn rererender [target]
   (let [w @world
         ed @editor
-        quick-check-keys [:now :scroll-x :scroll-y :width :height :camera-width :camera-height :pause-on-change :playing]]
+        quick-check-keys [:now
+                          :scroll-x :scroll-y
+                          :width :height
+                          :camera-width :camera-height
+                          :pause-on-change :playing]]
     ; slightly weird checks here instead of equality to improve idle performance/overhead
     (when (or (not last-world)
               (not (identical? last-world w))


Fix Binary Write Function.

Fix Binary Write Function.

--- src/konserve/filestore.clj
+++ src/konserve/filestore.clj
@@ -319,34 +319,6 @@
       (finally
         (.close fos)))))

-(defn- write-binary-old
-  "Helper Function for Binary Write"
-  [folder fn key input config]
-  (let [f        (io/file (str folder "/data/" fn))
-        new-file (io/file (str folder "/data/" fn ".new"))
-        fos      (FileOutputStream. new-file)
-        dos      (DataOutputStream. fos)
-        fd       (.getFD fos)]
-    (try
-      (io/copy input dos)
-      (.flush dos)
-      (when (:fsync config)
-        (.sync fd))
-      (.close fos) ;; required for windows
-      (Files/move (.toPath new-file) (.toPath f)
-                  (into-array [StandardCopyOption/ATOMIC_MOVE]))
-      (when (:fsync config)
-        (sync-folder folder))
-      (catch Exception e
-        (.delete new-file)
-        (ex-info "Could not write key."
-                 {:type      :write-error
-                  :key       key
-                  :exception e}))
-      (finally
-        (.close fos)))))
-
-
 (defrecord FileSystemStore [folder serializer read-handlers write-handlers locks config
                             stale-binaries?]
   PEDNAsyncKeyValueStore


pulse test endpoint returns :skip param

pulse test endpoint returns :skip param

--- src/metabase/api/pulse.clj
+++ src/metabase/api/pulse.clj
@@ -138,6 +138,10 @@
    skip_if_empty s/Bool}
   (check-card-read-permissions cards)
   (p/send-pulse! body)
-  (assoc body :ok true))
+   {:ok   true
+    :skip (and skip_if_empty
+               (p/are-all-cards-empty?
+                (for [card cards]
+                  (p/execute-card (:id card)))))})

 (define-routes)


fix bug in set comprehensions

fix bug in set comprehensions

--- src/setbang/core.clj
+++ src/setbang/core.clj
@@ -128,10 +128,10 @@
 (defn stagger [xs & [n]]
   (if (empty? xs) ()
       (let [n (or n 1)
-            choices (map choice (take n xs))]
+            choices (map choice (take n (remove is-empty-set xs)))]
         (lazy-seq
          (concat (map second choices)
-                 (stagger (concat (remove is-empty-set (map first choices))
+                 (stagger (concat (map first choices)
                                   (drop n xs))
                           (inc n)))))))

@@ -190,7 +190,6 @@
 (def large-set-cutoff 40)

 (defn shrink-if-possible [x]
-  (println "entering shrink-if-possible")
   (cond (number? x) x
         (set?    x) x
         :else (let [z (take (inc large-set-cutoff) x)]


Add a nodes function to the clojure client.

--- src/shale/client.clj
+++ src/shale/client.clj
@@ -11,6 +11,9 @@

 (def sessions-url
   (clojure.string/join "/" ["http://localhost:5000" "sessions"]))
+
+(def nodes-url
+  (clojure.string/join "/" ["http://localhost:5000" "nodes"]))

 (defn session-url [id]
   (clojure.string/join "/" [sessions-url id]))
@@ -27,6 +30,11 @@

 (defn sessions []
   (let [response (try+ (client/get sessions-url)
+                       (catch [:status 400] {:keys [body]} (error body) (throw+)))]
+    (json/parse-string (response :body))))
+
+(defn nodes []
+  (let [response (try+ (client/get nodes-url)
                        (catch [:status 400] {:keys [body]} (error body) (throw+)))]
     (json/parse-string (response :body))))


Speedup when score goes up

Speedup when score goes up

--- src/tetris/core.cljs
+++ src/tetris/core.cljs
@@ -1,6 +1,7 @@
 (ns tetris.core
   (:require [reagent.core :as r]))

+(defonce ^:const initial-tick-frequency 500)
 (defonce ^:const width 10)
 (defonce ^:const height 20)

@@ -137,8 +138,14 @@
                                              (.-keyCode e))]
                          (move! world-atom direction)))))

-(defonce interval
-  (js/setInterval #(move! world-atom :down) 500))
+(defn tick []
+  (move! world-atom :down)
+  (let [tick-frequency (- initial-tick-frequency
+                          (-> world-atom deref :score (* 10)))]
+    (js/setTimeout tick tick-frequency)))
+
+(defonce game-loop
+  (tick))

 (r/render-component [main-component world-atom]
                     (.getElementById js/document "container"))


Dissoc handler to reduce print output

Dissoc handler to reduce print output

--- src/yada/handler.clj
+++ src/yada/handler.clj
@@ -86,7 +86,7 @@
                     :method method
                     :method-wrapper (get (:known-methods handler) method)
                     :interceptor-chain interceptor-chain
-                    :handler (merge handler match-context)
+                    :handler (merge handler (dissoc match-context :handler))
                     :resource (:resource handler)  ; convenience
                     :request request})]


Fix tests

Fix tests

--- src/yada/methods.clj
+++ src/yada/methods.clj
@@ -288,7 +288,7 @@
   (idempotent? [_] true)
   (request [_ ctx]
     (let [ctx (assoc-in ctx [:response :headers "allow"]
-                        (str/join ", " (map (comp (memfn toUpperCase) name) (-> ctx :allowed-methods))))]
+                        (str/join ", " (map (comp (memfn toUpperCase) name) (-> ctx :handler :allowed-methods))))]
       ;; TODO: Build in explicit support for CORS pre-flight requests
       (if (satisfies? Options (:resource ctx))
         (d/chain


Removes default bootstrap-servers config

--- src/yuubin/kafka.clj
+++ src/yuubin/kafka.clj
@@ -3,8 +3,7 @@

 ;; TODO Remove randomness after testing.
 (def default-consumer-config
-  {"bootstrap.servers" "localhost:9092"
-   "group.id" (str "yuubin-" (rand-int 10000))
+  {"group.id" (str "yuubin-" (rand-int 10000))
    "auto.offset.reset" "earliest"
    "enable.auto.commit" "false"
    "key.deserializer" "org.apache.kafka.common.serialization.StringDeserializer"