Fix spelling and grammar of some combat messages

--- src/cljc/robinson/combat.cljc
+++ src/cljc/robinson/combat.cljc
@@ -84,7 +84,7 @@
               [:human :*       :punch         :tail     :dead] (format "You %s the %s in the tail causing massive injuries and it dies." (rand-punch-verb) defender-name)
               [:human :*       :punch         :wing     :dead] (format "You %s the %s in the wing ripping it clean off and it dies." (rand-punch-verb) defender-name)
               [:human :*       :punch         :eye      :dead] (format "You %s the %s in the eye exploding it upon impact and it dies." (rand-punch-verb) defender-name)
-              [:human :*       :punch         :snout    :dead] (format "You %s the %s in the snount crushing it and it dies." (rand-punch-verb) defender-name)
+              [:human :*       :punch         :snout    :dead] (format "You %s the %s in the snout crushing it and it dies." (rand-punch-verb) defender-name)
               [:human :*       :punch         :arm      :dead] (format "You %s the %s in the arm crushing bones and it dies." (rand-punch-verb) defender-name)
               [:human :*       :punch         :beak     :dead] (format "You %s the %s in the beak ripping it from its face and it dies." (rand-punch-verb) defender-name)
               [:human :*       :punch         :shell    :dead] (format "You %s the %s in the shell ripping to peices and it dies." (rand-punch-verb) defender-name)
@@ -116,7 +116,7 @@
               [:human :*       sharp-weapon?  :tail     :dead] (format "You %s the %s in the tail causing massive injuries and it dies." (rand-axe-verb) defender-name)
               [:human :*       sharp-weapon?  :wing     :dead] (format "You %s the %s in the wing ripping it clean off and it dies." (rand-axe-verb) defender-name)
               [:human :*       sharp-weapon?  :eye      :dead] (format "You %s the %s in the eye exploding it upon impact and it dies." (rand-axe-verb) defender-name)
-              [:human :*       sharp-weapon?  :snout    :dead] (format "You %s the %s in the snount crushing it and it dies." (rand-axe-verb) defender-name)
+              [:human :*       sharp-weapon?  :snout    :dead] (format "You %s the %s in the snout crushing it and it dies." (rand-axe-verb) defender-name)
               [:human :*       sharp-weapon?  :arm      :dead] (format "You %s the %s in the arm crushing bones it and it dies." (rand-axe-verb) defender-name)
               [:human :*       sharp-weapon?  :beak     :dead] (format "You %s the %s in the beak ripping it from its face and it dies." (rand-axe-verb) defender-name)
               [:human :*       sharp-weapon?  :shell    :dead] (format "You %s the %s in the shell ripping to peices and it dies." (rand-axe-verb) defender-name)
@@ -148,22 +148,24 @@
               [:human :*       ranged-weapon? :tail     :dead] (format "You %s the %s in the tail causing massive injuries and it dies." (rand-ranged-hit-verb) defender-name)
               [:human :*       ranged-weapon? :wing     :dead] (format "You %s the %s in the wing ripping it clean off and it dies." (rand-ranged-hit-verb) defender-name)
               [:human :*       ranged-weapon? :eye      :dead] (format "You %s the %s in the eye exploding it upon impact and it dies." (rand-ranged-hit-verb) defender-name)
-              [:human :*       ranged-weapon? :snout    :dead] (format "You %s the %s in the snount crushing it and it dies." (rand-ranged-hit-verb) defender-name)
+              [:human :*       ranged-weapon? :snout    :dead] (format "You %s the %s in the snout crushing it and it dies." (rand-ranged-hit-verb) defender-name)
               [:human :*       ranged-weapon? :arm      :dead] (format "You %s the %s in the arm crushing bones it and it dies." (rand-ranged-hit-verb) defender-name)
               [:human :*       ranged-weapon? :beak     :dead] (format "You %s the %s in the beak ripping it from its face and it dies." (rand-ranged-hit-verb) defender-name)
               [:human :*       ranged-weapon? :shell    :dead] (format "You %s the %s in the shell ripping to peices and it dies." (rand-ranged-hit-verb) defender-name)
               [:human :*       ranged-weapon? :tentacle :dead] (format "You %s the %s in the tentacle shredding it and it dies." (rand-ranged-hit-verb) defender-name)
               [:human :*       ranged-weapon? :*        :dead] (format "You %s the %s causing massive injuries and it dies." (rand-ranged-hit-verb) defender-name)
-              [:*     :human   :bite          :*        :miss] (format "The %s lunges at you its mouth but misses." attacker-name)
+              [:*     :human   :bite          :*        :miss] (format "The %s lunges at you with its mouth but misses." attacker-name)
               [:*     :human   :bite-venom    :*        :miss] (format "The %s snaps at you its mouth but misses." attacker-name)
               [:*     :human   :claw          :*        :miss] (format "The %s claws at you and narrowly misses." attacker-name)
               [:*     :human   :punch         :*        :miss] (format "The %s punches you but misses." attacker-name)
-              [:*     :human   :gore          :*        :miss] (format "The %s lunges at you with it's tusks." attacker-name)
+              [:*     :human   :gore          :*        :miss] (format "The %s lunges at you with its tusks." attacker-name)
               [:*     :human   :sting         :*        :miss] (format "The %s tries to sting you but misses." attacker-name)
               [:*     :human   :sting-venom   :*        :miss] (format "The %s tries to sting you but misses." attacker-name)
               [:*     :human   :squeeze       :*        :miss] (format "The %s starts to constrict around you but fumbles." attacker-name)
               [:*     :human   :clamp         :*        :miss] (format "The %s tries to clamp onto you but isn't fast enough." attacker-name)
               [:*     :human   :spike         :*        :miss] (format "You almost get poked by the %s's spikes." attacker-name)
+              [:mosquito
+                      :human   :bite          :*        :hit]  (format "The %s sinks its probiscus into your flesh." attacker-name)
               [:*     :human   :bite          :*        :hit]  (format "The %s sinks its teeth into your flesh." attacker-name)
               [:*     :human   :bite-venom    :*        :hit]  (format "The %s buries its teeth into your body and starts pumping poison into you." attacker-name)
               [:*     :human   :claw          :*        :hit]  (format "The %s claws into your flesh." attacker-name)


Make will to live drop more when outside at night without a fire

--- src/cljc/robinson/update.cljc
+++ src/cljc/robinson/update.cljc
@@ -1939,7 +1939,7 @@
                   dwtl       (if (and (rw/is-night? state)
                                       (not-any? #(= (get % :type) :fire)
                                                 (rw/cells-in-range-of-player state 3)))
-                               (+ dwtl 0.002)
+                               (+ dwtl 0.5)
                                dwtl)
                   ;; in water, cold and wet - less will to live.
                   dwtl       (+ dwtl


Saved state into local storage

Saved state into local storage

--- src/cljs/app/ghoul/state.cljs
+++ src/cljs/app/ghoul/state.cljs
@@ -3,7 +3,8 @@
   (:require [cljs.core.async :as async :refer [<!]]
             [cljs-uuid-utils :as uuid]
             [ghoul.http :as http]
-            [ghoul.feeds-storage :as storage]))
+            [ghoul.feeds-storage :as storage]
+            [hodgepodge.core :as hp]))

 ;(defn ^:export hello-world[] (js/alert "HOLA")) ; invoke through ghoul.state.hello_world() in JS
 (declare feed-store-temp)
@@ -105,6 +106,7 @@
                           (assoc :expanded true)
                           (assoc :uid (uuid/uuid-string (uuid/make-random-uuid)))
                           (assoc :subscriptions []))]
+    (swap! global assoc :general-group-uid (:uid general-group))
     (swap! global update-in [:groups] #(conj % general-group))))

 (defn add-rss-subscription [feed-url]
@@ -129,3 +131,20 @@
             ;<!)
         (swap! global update-in [:feeds] #(conj % feed)))
       (swap! global update-in [:groups group-idx :subscriptions] #(conj % subscription)))))
+
+(defn ^:export store-state [state]
+  (assoc! hp/local-storage :state (dissoc state :feeds)))
+
+(defn ^:export restore-state [state-atom]
+  (->> (:state hp/local-storage) (reset! state-atom)))
+
+(defn start-watch []
+  (let [old-state (:state hp/local-storage)]
+    (if (not (nil? old-state))
+      (restore-state global))
+    (add-watch global
+               nil
+               (fn [context key ref old-value new-value]
+                 (store-state @global)))))
+
+(start-watch)


default window at smaller size

default window at smaller size

--- src/clojure/defgraph/core.clj
+++ src/clojure/defgraph/core.clj
@@ -79,7 +79,7 @@
           g (graph (re-pattern (str prefix ".*")))
           panel (JPanel. (BorderLayout.))
           width 1200
-          height 1000
+          height 700
           frame (JFrame. (str "defgraph" (if prefix (str " (" prefix ")") "")))]
       (.add button-panel button)
       (mx-update panel g height width button-panel)


Fix CLI args

Fix CLI args

--- src/clojure/nightmod/core.clj
+++ src/clojure/nightmod/core.clj
@@ -1,5 +1,6 @@
 (ns nightmod.core
   (:require [clojure.java.io :as io]
+            [nightcode.cli-args :as cli-args]
             [nightcode.editors :as editors]
             [nightcode.sandbox :as nc-sandbox]
             [nightcode.shortcuts :as shortcuts]
@@ -58,7 +59,7 @@
   "Launches the main window."
   [& args]
   (window/set-icon! "logo_launcher.png")
-  (window/set-theme! args)
+  (window/set-theme! (cli-args/parse-args args))
   (nc-sandbox/set-home!)
   (sandbox/set-policy!)
   (add-watch u/project-dir :load-game (fn [_ _ _ path]


JSON-LD convenience loaders

JSON-LD convenience loaders

--- src/rdf_path_examples/json_ld.clj
+++ src/rdf_path_examples/json_ld.clj
@@ -1,7 +1,9 @@
 (ns rdf-path-examples.json-ld
+  (:require [clojure.java.io :as io])
   (:import [java.io InputStream]
            [java.util LinkedHashMap]
            [com.github.jsonldjava.core JsonLdOptions JsonLdProcessor]
+           [com.github.jsonldjava.utils JsonUtils]
            [org.apache.jena.rdf.model Model ModelFactory]))

 (defonce ^:private
@@ -13,10 +15,18 @@
   [^InputStream json-ld]
   (.read (ModelFactory/createDefaultModel) json-ld nil "JSON-LD"))

-(defn compact-json-ld
+(defn compact
   "Compact `json-ld` using `context` with optional `options`"
   [^LinkedHashMap json-ld
    ^LinkedHashMap context
    & {:keys [options]
       :or {options json-ld-options}}]
   (JsonLdProcessor/compact json-ld context options))
+
+(def load-resource
+  "Load JSON resource from `resource-path`."
+  (comp #(JsonUtils/fromInputStream %) io/input-stream io/resource))
+
+(def load-context
+  "Load JSON-LD context with `file-name`."
+  (comp load-resource (partial str "contexts/")))


(PDB-5128) jdbc/do-prepared: allow string fragment vectors

--- src/puppetlabs/puppetdb/jdbc.clj
+++ src/puppetlabs/puppetdb/jdbc.clj
@@ -56,21 +56,23 @@

 (defn do-commands
   "Runs the given commands in a transaction on the database given
-  by (jdbc/db).  If a command is a seq, converts it to a string
+  by (jdbc/db).  If a command is a collection, converts it to a string
   via (clojure.string/join command)."
   [& commands]
   (sql/db-do-commands *db* true
-                      (mapv #(cond
-                               (string? %) %
-                               (seq %) (string/join %)
-                               :else %)
+                      (mapv #(if (coll? %) (string/join %) %)
                             commands)))

 (defn do-prepared
-  "Executes an optionally parametrized sql expression in a transaction on the
-  database given by (jdbc/db)."
+  "Executes an optionally parametrized sql expression in a transaction
+  on the database given by (jdbc/db).  If a command is a collection,
+  converts it to a string via (clojure.string/join command)."
   [sql & params]
-  (sql/db-do-prepared *db* true (into [sql] params) {:multi? true}))
+  (sql/db-do-prepared *db* true
+                      (apply vector
+                             (if (coll? sql) (string/join sql) sql)
+                             params)
+                      {:multi? true}))

 (defn do-commands-outside-txn [& commands]
   (let [^Connection conn (:connection *db*)


Add docstring to user-join-group-txn

Add docstring to user-join-group-txn

--- src/braid/server/db/group.clj
+++ src/braid/server/db/group.clj
@@ -174,6 +174,8 @@
     (map (fn [[tag]] [:db/add [:user/id user-id] :user/subscribed-tag tag]))))

 (defn user-join-group-txn
+  "Add a user to the given group, subscribe them to the group tags,
+  and subscribe them to the five most recent threads in the group."
   [user-id group-id]
   (concat
     (user-add-to-group-txn user-id group-id)


also limit list of events

also limit list of events

--- src/rpi_wall/calendar/server.clj
+++ src/rpi_wall/calendar/server.clj
@@ -1,9 +1,11 @@
 (ns rpi-wall.calendar.server
   (:require [rpi-wall.calendar.busy-days  :refer [get-busy-days]]
             [rpi-wall.calendar.todo-today :refer [get-day-events]]
-            [rpi-wall.helpers             :refer [fetch-insist config counter]]))
+            [rpi-wall.helpers             :refer [fetch-insist config counter limiter]]))

 ;(google-apps-clj.credentials/get-auth-map creds ["https://www.googleapis.com/auth/calendar"])
+
+(def max-lines (:max-lines config))

 (def calendar-creds
   (:google-calendar config))
@@ -22,9 +24,18 @@
         callback #(f calendar-creds shift)]
     (fetch-insist callback ms)))

+(defn limit
+  [x n]
+  (if (> (count x) n)
+    (concat (take (dec n) x) [{:start nil :end nil :name "..."}])
+    x))
+
 (defn set-cal-info!
   []
   (reset! busy-days-state  (fetcher get-busy-days))
-  (reset! todo-today-state (counter (fetcher get-day-events))))
+  (reset! todo-today-state (->> get-day-events
+                                fetcher
+                                counter
+                                (limiter limit max-lines))))

 (set-cal-info!)


:sparkles: Open URL in new tab for viewer interaction

--- frontend/src/uxbox/view/ui/viewer/interactions.cljs
+++ frontend/src/uxbox/view/ui/viewer/interactions.cljs
@@ -167,7 +167,7 @@

 (defn- run-gotourl-interaction
   [{:keys [url]}]
-  (set! (.-href js/location) url))
+  (js/window.open url "_blank"))

 (defn- run-gotopage-interaction
   [{:keys [page]}]


Add a smidgen of i18n for dtbook generation

should probably use a "real" lib for that, such as tower

--- src/mdr2/dtbook.clj
+++ src/mdr2/dtbook.clj
@@ -1,6 +1,42 @@
 (ns mdr2.dtbook
   "Functionality around [DTBook XML](http://www.daisy.org/z3986/2005/Z3986-2005.html)"
-  (:require [clojure.data.xml :as xml]))
+  (:require [clojure.data.xml :as xml]
+            [clojure.string :as s]))
+
+;; FIXME: we should probably use some ready made library for i18n.
+;; There is https://github.com/ptaoussanis/tower,
+;; https://github.com/asmala/clj18n or
+;; https://github.com/feldi/clojure-i18n. The first one seems like the
+;; most mature but has a number of weird quirks and dependencies
+(def ^:private translations
+  {:de
+   {:about "Zu diesem DAISY-Buch"
+    :bib "Bibliographische Angaben"
+    :description "Produktbeschreibung des Hörbuchverlages"
+    :blurb "Klappentexte"
+    :contributors "Mitwirkende"
+    :enclosures "Hörbuchbeilagen"
+    :end "Ende des Buches"}
+   :en
+   {:about "About this DAISY book"
+    :bib "Bibliographic information"
+    :description "Product description by talking book publisher"
+    :blurb "Blurbs"
+    :contributors "Contributors"
+    :enclosures "Talking book enclosures"
+    :end "End of book"}})
+
+(defn- fallback
+  "Return the `language` or the fallback language if `language` is blank"
+  [language]
+  (if (s/blank? language)
+    "de"
+    language))
+
+(defn- translate
+  "Return a string for the given `key` and `locale`"
+  [locale key]
+  (get-in translations [locale key] key))

 (defn default-book
   "Return an default book sexp"
@@ -15,32 +51,37 @@

 (defn commercial-audiobook
   "Return an sexp for the body of a commercial audiobook"
-  [title creator]
-  [:book
-   [:frontmatter
-    [:doctitle title]
-    [:docauthor creator]
-    [:level1
-     [:h1 "Zu diesem DAISY-Buch"]
-     [:p]]
-    [:level1
-     [:h1 "Bibliographische Angaben"]
-     [:p]]
-    [:level1
-     [:h1 "Klappentexte"]
-     [:p]]]
-   [:bodymatter
-    [:level1 [:h1 "[Audioimport]"] [:p]]]
-   [:rearmatter
-    [:level1
-     [:h1 "Mitwirkende"]
-     [:p]]
-    [:level1
-     [:h1 "Hörbuchbeilagen"]
-     [:p]]
-    [:level1
-     [:h1 "Ende des Buches"]
-     [:p]]]])
+  [title creator language]
+  (let [locale (keyword (fallback language))
+        t (partial translate locale)]
+    [:book
+     [:frontmatter
+      [:doctitle title]
+      [:docauthor creator]
+      [:level1
+       [:h1 (t :about)]
+       [:p]]
+      [:level1
+       [:h1 (t :bib)]
+       [:p]]
+      [:level1
+       [:h1 (t :description)]
+       [:p]]
+      [:level1
+       [:h1 (t :blurb)]
+       [:p]]]
+     [:bodymatter
+      [:level1 [:h1 "[Audioimport]"] [:p]]]
+     [:rearmatter
+      [:level1
+       [:h1 (t :contributors)]
+       [:p]]
+      [:level1
+       [:h1 (t :enclosures)]
+       [:p]]
+      [:level1
+       [:h1 (t :end)]
+       [:p]]]]))

 (defn- dtbook-sexp
   [{:keys [title creator subject description publisher date identifier source language rights
@@ -81,7 +122,7 @@
     [:meta {:name "dtb:totalTime" :content totaltime}]
     [:meta {:name "dtb:audioFormat" :content audioformat}]]
    (if librarynumber
-     (commercial-audiobook title creator)
+     (commercial-audiobook title creator language)
      (default-book title creator))])

 (defn dtbook


added an example to `tabular` doc-string

--- src/midje/sweet.clj
+++ src/midje/sweet.clj
@@ -95,6 +95,14 @@
 (generate-future-fact-variants)

 (defmacro tabular
-  "Generate a table of related facts."
+  "Generate a table of related facts.
+
+   Ex. (tabular \"table of simple math\"
+         (fact (+ a b) => c)
+
+           a b      c
+           1 2      3
+           3 4      7
+           9 10     19 )"
   [& _]
   (tabular* (keys &env) &form))


Move last categories button down a bit to make it look separate

--- src-cljs/acfe/core.cljs
+++ src-cljs/acfe/core.cljs
@@ -116,8 +116,17 @@
   (update-and-render))

+(defn disadvantaged-suburbs-hack
+  "Move last categories button down a bit so it looks separate from the others."
+  []
+  (-> (d/create-element :li)
+	  (d/set-style! :height "20px")
+	  (d/insert-before! (last (sel [:#categories :li])))))
+
+
 (defn init
   []
+  (disadvantaged-suburbs-hack)
   (GET "/data/places.clj" {:handler on-places-load})
   (GET "/data/areas.clj" {:handler on-areas-load}))


Removed some clutter

Removed some clutter

--- src-cljs/qcon/main.cljs
+++ src-cljs/qcon/main.cljs
@@ -9,7 +9,6 @@
 (ns qcon.main
   (:require-macros [cljs.core.async.macros :refer [go go-loop]])
   (:require
-;;   qcon.snippets
    [om.core :as om :include-macros true]
    [goog.events.KeyCodes :as kc]
    [om.dom :as dom :include-macros true]
@@ -82,36 +81,6 @@
           (.appendChild (om/get-node owner) pre)
           )))))

-#_(defn clj-source-snippet [data owner fname]
-  (reify
-    om/IWillMount
-    (will-mount [_]
-      (GET "/source"
-          (-> {:handler (fn [e]
-                          (om/set-state! owner :text e))
-               :headers {"Accept" "text/plain"}
-               :response-format :raw})))
-    om/IRender
-    (render [_]
-      #_(println "rendering source: " (om/get-state owner :text))
-      (html
-       [:div]))
-    om/IDidUpdate
-    (did-update [this prev-props prev-state]
-      ;; Attempt at syntax highlighting
-      (println "did-update" (om/get-state owner :text))
-      (println (.-value (hljs.highlightAuto "(foo)")))
-
-      #_(println (SyntaxHighlighter.getHtml (om/get-state owner :text)))
-      (when (om/get-state owner :text)
-        (let [n (om/get-node owner)]
-          (while (.hasChildNodes n)
-            (.removeChild n (.-lastChild n))))
-        (let [pre (.createElement js/document "pre")]
-          (set! (.-innerHTML pre) (.-value (hljs.highlightAuto (om/get-state owner :text))))
-          (.appendChild (om/get-node owner) pre)
-          )))))
-
 (defn new-random-pick [owner]
   (go-loop [c 4]
     (om/set-state! owner :pending-put nil)
@@ -207,8 +176,6 @@
             radius (om/get-state owner :radius)]
         (html
          [:div
-          ;;(om/build source-snippet data {})
-
           [:svg svg-attrs
            (border)

@@ -222,9 +189,6 @@
              (when-let [n (om/get-state owner :pending-put)]
                [:text {:x 20 :y 150 :style {:font-size "64pt"
                                             :color "white"} :fill "white"} (str n)])]
-
-            ;;
-

             ;; Put
             [:g {:transform "translate(160,65)"


Sped up generating patches by a factor of 100.

--- src/clj/think/image/patch.clj
+++ src/clj/think/image/patch.clj
@@ -55,11 +55,19 @@

 (defn is-rect-completely-within-mask?
   "Is this rect contained by the mask"
-  ([mask-img ^Rectangle rect byte-data]
+  ([mask-img ^Rectangle rect ^bytes byte-data]
    (image/->array mask-img rect byte-data)
-   (>= (double (/ (mat/esum (map pixel-byte->double byte-data))
-                  (* (.width rect) (.height rect))))
-       *content-threshold-cutoff*))
+   (let [num-bytes (alength byte-data)
+         byte-sum (loop [idx 0
+                         sum 0]
+                    (if (< idx num-bytes)
+                      (recur (inc idx)
+                             (+ sum (bit-and 0xFF (unchecked-int
+                                                   (aget byte-data idx)))))
+                      sum))]
+    (>= (double (/ byte-sum
+                   (* (.width rect) (.height rect) 255.0)))
+        *content-threshold-cutoff*)))
   ([mask-img ^Rectangle rect]
    (is-rect-completely-within-mask? mask-img rect (byte-array (* (.width rect) (.height rect))))))


add balance sheet report to web

add balance sheet report to web

--- src/clj_money/web/reports.clj
+++ src/clj_money/web/reports.clj
@@ -51,8 +51,11 @@
                                                end-date))])

 (defmethod render-report :balance-sheet
-  [params]
-  [:h1 "Balance Sheet"])
+  [{:keys [entity-id as-of]}]
+  [:table.table.table-striped
+   (map report-row (reports/balance-sheet (env :db)
+                                          entity-id
+                                          as-of))])

 (defmulti render-filter
   (fn [params]
@@ -75,7 +78,13 @@

 (defmethod render-filter :balance-sheet
   [params]
-  )
+  [:form {:action "#" :method :get}
+   [:div.form-group
+    [:label.control-label {:for :start-date} "As of"]
+    [:input.form-control.date-field {:type :text
+                                     :name :as-of
+                                     :value (format-date (:as-of params))}]]
+   [:input.btn.btn-primary {:type :submit :value "Show"}]])

 (defn render
   [params]
@@ -85,7 +94,9 @@
                    (assoc :start-date (or (parse-date (:start-date params))
                                           (default-start-date))
                           :end-date (or (parse-date (:end-date params))
-                                        (default-end-date))))]
+                                        (default-end-date))
+                          :as-of (or (parse-date (:as-of params))
+                                     (default-end-date))))]
     (layout
       "Reports" {}
       [:div.row


And again

And again

--- src/cljs/babelfeesh/core.cljs
+++ src/cljs/babelfeesh/core.cljs
@@ -4,7 +4,7 @@

 (enable-console-print!)

-(defonce app-state (atom {:text "Hello Babelfeesh!! Woooo!"}))
+(defonce app-state (atom {:text "Hello Babelfeesh!! Woooo! Again!"}))

 (defn main []
   (om/root


Check screen type as well

Check screen type as well

--- src/clojure/nightmod/game.clj
+++ src/clojure/nightmod/game.clj
@@ -25,7 +25,8 @@
            ; make sure the game screens are valid
            (doseq [screen game-screens
                    required-key [:show :render :hide :pause :resize :resume]]
-             (when-not (contains? screen required-key)
+             (when (or (not (map? screen))
+                       (not (contains? screen required-key)))
                (throw (Exception. "Invalid screen given to set-game-screen!"))))
            ; set the supplied screen(s) with the overlay screen added at the end
            (apply set-screen!


figwheel.main: better handling of exception reporting

--- figwheel-main/src/figwheel/main.cljc
+++ figwheel-main/src/figwheel/main.cljc
@@ -127,12 +127,16 @@
                                            (.endsWith % ".cljc"))
                                       files))]
                            (log/debug "Reloading clj files: " (pr-str (map str clj-files)))
-                           (figwheel.core/reload-clj-files clj-files))
+                           (try
+                             (figwheel.core/reload-clj-files clj-files)
+                             (catch Throwable t
+                               (log/syntax-exception t)
+                               (figwheel.core/notify-on-exception cenv t {})
+                               (throw t))))
                          (log/debug "Detected changed cljs files: " (pr-str (map str files)))
                          (fig-core-build id inputs opts cenv files)
-                         (catch Throwable t
-                           (figwheel.core/notify-on-exception cenv t {})
-                           false))))))}))))
+                         ;; exceptions are reported by the time they get to here
+                         (catch Throwable t false))))))}))))

 (def validate-config!*
   (when (try


offset from direction

offset from direction

--- clojure/src/dnd/character.cljs
+++ clojure/src/dnd/character.cljs
@@ -18,6 +18,18 @@
   (if (= dx 0)
     (if (= dy 1) "s" "n")
     (if (= dx 1) "e" "w")))
+
+(defn direction->offset [direction]
+  (case direction
+    "n" [0 -1]
+    "s" [0  1]
+    "w" [-1 0]
+    "e" [1  0]))
+
+(defn character->offset [character]
+  (-> character
+      :direction
+      direction->offset))

 (defn rand-rgb-vec [] (vec (repeatedly 3 #(rand-int 256))))


Handle errors even better in front-end

Handle errors even better in front-end

--- front-end/src/front_end/data.clj
+++ front-end/src/front_end/data.clj
@@ -15,12 +15,13 @@
               :user-agent "front-end"})

 (defn- handle-response
-  [resp]
-  (let [status (:status @resp)]
-    (if (and (>= 200 status)
-             (< status 300))
-      @resp
-      (throw (Exception. (str "Error getting response: status " status " returned"))))))
+  [response]
+  (let [error (:error @response)
+        status (:status @response)]
+    (cond (not (nil? error))                   (throw (Exception. "Feed returned error" error))
+          (nil? status)                        (throw (Exception. (str "Could not get status of response" response)))
+          (or (< status 200) (>= status 300))  (throw (Exception. (str "Error getting response: status " status " returned")))
+          :else                                @response)))

 (defn get-quote []
   (http/get (str quote-service-url "/api/quote") options))


Trying to figure out assemble and match-tiles ...

--- src/mosaic/tile.clj
+++ src/mosaic/tile.clj
@@ -68,3 +68,12 @@
 	    (first samples)
 	    (rest samples))))

+(defn assemble [tx ty n ^BufferedImage b]
+  (let [x (* tx n)
+	y (* ty n)
+	s (rescale x y b)
+	o (BufferedImage. x y BufferedImage.TYPE_INT_BGR)]
+    ))
+
+(defn match-tiles [coll tx ty n ^BufferedImage b]
+  )


Start implementing manga-reader site

Start implementing manga-reader site

--- resources/sites/manga-reader.clj
+++ resources/sites/manga-reader.clj
@@ -1 +1,17 @@
-{}
+{
+ :image-selector [:div#imgholder :a :img#img]
+ :page-normalize-pattern #"(?<=/\d{1,5})/\d+$"
+ :page-normalize-format "%s%s"
+
+ :chapter-number-pattern #"(?<=/\d{1,5})/\d+$"
+
+ :page-list-selector [:div#selectpage :select#pageMenu :option]
+
+ ;; :root-url "http://www.mangareader.net"
+ ;; :manga-url-format "%s/"
+ ;; :manga-url-suffix-pattern #"/(.*?)$"
+
+ ;; :chapter-number-match-pattern #"/(\d+)$"
+
+
+ }


rename :channel -> :user in tests as well

--- test/open_company/integration/company/company_create.clj
+++ test/open_company/integration/company/company_create.clj
@@ -105,7 +105,7 @@
                 (:bot @sqs-msg) =>    {:id "abc" :token "xyz"}
                 (:script @sqs-msg) => {:id :onboard :params {:user/name "Albert" :company/name "Hello World"
                                                              :company/description "x" :company/slug "hello-world" :company/currency "USD"}}
-                (:receiver @sqs-msg) => {:type :channel :id "1960-01-04"}
+                (:receiver @sqs-msg) => {:type :user :id "1960-01-04"}
                 (str "Bearer " (:api-token @sqs-msg)) => mock/jwtoken-camus)))
         (fact "trigger is sent if user is owner of Slack Team"
           (let [sqs-msg (atom nil)]


Increase default core.async thread pool size

--- src/onyx/system.clj
+++ src/onyx/system.clj
@@ -56,6 +56,10 @@
             [onyx.extensions :as extensions]
             [onyx.interop]))

+;; Temporary workaround
+;; Increase default core.async thread poll size to avoid blocking issues due to alts!!
+(System/setProperty "clojure.core.async.pool-size" (or (System/getProperty "clojure.core.async.pool-size") "32"))
+
 (def development-components [:monitoring :logging-config :log :bookkeeper])

 (def peer-group-components [:logging-config :monitoring :query-server :messaging-group :peer-group-manager])


pep-032 wip

pep-032 wip

--- src/pep_032/wip.clj
+++ src/pep_032/wip.clj
@@ -126,10 +126,47 @@
   (for
     [a (range 1 100)
      b (range 100 10000)
-     :let [c (* a b)]
+     :let [c (* a b)
+           abc (str a b c)]
      :when (and
+             (= (count abc) 9)
              (not-any? #(= \0 %) (str a b c))
-             (= (count (str c)) 4)
-             (= (count (reduce conj #{} (str a b))) 5)
+             ;(= (count (str c)) 4)
+             ;(= (count (reduce conj #{} (str a b))) 5)
              (= (count (reduce conj #{} (str a b c))) 9))]
     c)) ; 56370 <-- wrong
+
+(reduce +
+  (for
+    [a (range 1 1000)
+     b (range 1 10000)
+     :let [c (* a b)
+           abc (str a b c)]
+     :when (and
+             (not-any? #(= \0 %) abc)
+             (= (count abc) 9)
+             (= (count (reduce conj #{} abc)) 9))]
+    c)) ; 97936
+
+(reduce +
+  (reduce conj #{}
+    (for
+      [a (range 1 1000)
+       b (range 1 10000)
+       :let [c (* a b)
+             abc (str a b c)]
+       :when (and
+               (not-any? #(= \0 %) abc)
+               (= (count abc) 9)
+               (= (count (reduce conj #{} abc)) 9))]
+      c))) ; 45228 <-- try!
+
+(count
+  (for
+    [a (range 1 1000)
+     b (range 1 10000)
+     :let [ab (str a b)]
+     :when (and
+             (not-any? #(= \0 %) ab)
+             (= (count (reduce conj #{} ab)) (count ab)))]
+    [a b]))


increase keen top count time

increase keen top count time

--- src/ontrail/keen.clj
+++ src/ontrail/keen.clj
@@ -20,7 +20,7 @@
 (def connection
   (merge {:accept :json
           :throw-exceptions false
-          :socket-timeout 5000  ;; in milliseconds
+          :socket-timeout 20000  ;; in milliseconds
           :conn-timeout 120000}
          {:connection-manager conman}))


Add wrapper around .setResizable call.

Add wrapper around .setResizable call.

--- src/quil/applet.clj
+++ src/quil/applet.clj
@@ -57,7 +57,8 @@
       (.setDefaultCloseOperation JFrame/DO_NOTHING_ON_CLOSE))
     (javax.swing.SwingUtilities/invokeLater
      (fn []
-       (.setResizable frame resizable?)
+       (when resizable?
+         (.setResizable frame resizable?))
        (.setAlwaysOnTop frame keep-on-top?)))
     applet))


Generalized guards to positive boolean combinations of difference formulae.

--- src/player/core.cljs
+++ src/player/core.cljs
@@ -69,25 +69,29 @@
         intervals))

 (defn flatten-intervals [intervals]
-  (reduce (fn [sofar interval]
-            (if (simple? interval)
-              (conj sofar interval)
-              (into sofar (flatten-intervals interval))))
-          []
-          intervals))
+  (if (simple? intervals)
+    intervals
+    (reduce (fn [sofar interval]
+              (if (simple? interval)
+                (conj sofar interval)
+                (into sofar (flatten-intervals interval))))
+            []
+            intervals)))

 (defn merge-overlapping [intervals]
-  (let [intervals (flatten-intervals intervals)
-        intervals (sort-intervals intervals)
-        [last-i merged] (reduce (fn [[[amin amax :as a] merged] [bmin bmax :as b]]
-                                  (if (intersection a b)
-                                    [[amin (.max js/Math amax bmax)] merged]
-                                    [[bmin bmax] (conj merged a)]))
-                                [(first intervals) []]
-                                (rest intervals))]
-    (if (empty? intervals)
-      []
-      (conj merged last-i))))
+  (if (simple? intervals)
+    intervals
+    (let [intervals (flatten-intervals intervals)
+          intervals (sort-intervals intervals)
+          [last-i merged] (reduce (fn [[[amin amax :as a] merged] [bmin bmax :as b]]
+                                    (if (intersection a b)
+                                      [[amin (.max js/Math amax bmax)] merged]
+                                      [[bmin bmax] (conj merged a)]))
+                                  [(first intervals) []]
+                                  (rest intervals))]
+      (if (empty? intervals)
+        []
+        (conj merged last-i)))))

 (defn constrain-times [interval]
   (if (simple? interval)
@@ -95,13 +99,15 @@
     (mapv constrain-times interval)))

 (defn intersect-all [intervals]
-  (constrain-times
-    (reduce (fn [a b]
-              (if-let [intr (intersection a b)]
-                intr
-                [Infinity Infinity]))
-            [time-unit Infinity]
-            intervals)))
+  (if (simple? intervals)
+    intervals
+    (constrain-times
+      (reduce (fn [a b]
+                (if-let [intr (intersection a b)]
+                  intr
+                  [Infinity Infinity]))
+              [time-unit Infinity]
+              intervals))))

 (defn union-all [intervals]
   (merge-overlapping intervals))
@@ -148,7 +154,7 @@
     (seqable? c) (apply ({'+ + '- - '* * '/ /} (first c))
                         (map #(constant-from-expr has ha %) (rest c)))))

-(defn guard-satisfied? [rel v10 v20 c]
+(defn simple-guard-satisfied? [rel v10 v20 c]
   (let [diff (- v10 v20)]
     (case rel
       :gt (> diff c)
@@ -165,7 +171,7 @@
         v2k (if (= (count simple-guard) 4) (third simple-guard) nil)
         [v10 v1f] (get-var-and-flow has ha v1k)
         [v20 v2f] (get-var-and-flow has ha v2k)
-        sat (guard-satisfied? rel v10 v20 c)
+        sat (simple-guard-satisfied? rel v10 v20 c)
         #_(println (str "(" v10 " + " v1f "t) - (" v20 " + " v2f "t) "
                         (case rel :gt ">" :geq ">=" :leq "<=" :lt "<") " " c))
         ; by algebra: A0+fA*dt-B0-fB*dt-C~0 --> (fA-fB)*dt ~ (-A0 + B0 + C) --> dt ~ (-A0 + B0 + C)/(fA-fB)
@@ -212,10 +218,15 @@
               ;  > : t  > rhs --> guard becomes true once t exceeds rhs
               :gt [(.max js/Math (+ rhs (/ time-unit 16)) min-t) Infinity]))))

+(defn guard-interval [has ha g]
+  (case (first g)
+    :and (intersect-all (map #(guard-interval has ha %) (rest g)))
+    :or (union-all (map #(guard-interval has ha %) (rest g)))
+    (simple-interval has ha g)))
+
 (defn transition-interval [has ha transition]
   #_(println "Transition" (:id ha) "et" (:entry-time ha) (:target transition) (:guard transition))
-  (let [intervals (map #(simple-interval has ha %) (:guard transition))
-        interval (intersect-all intervals)]
+  (let [interval (merge-overlapping (guard-interval has ha (:guard transition)))]
     #_(println "interval:" intervals "->" interval)
     ; TODO: handle cases where transition is also guarded on states
     {:interval   interval
@@ -250,6 +261,10 @@
                                          ha
                                          Infinity
                                          (required-transitions ha)))
+        ; If req has a non-simple interval, replace that with the first interval in the set
+        req (if (simple? (:interval req))
+              req
+              (update req :interval first))
         _ (println "New required transitions" (transition-intervals has
                                                                     ha
                                                                     Infinity
@@ -269,29 +284,27 @@
          init
          (zipmap (map :id states) states)))

+(defn guard? [g]
+  (and (vector? g)
+       (case (first g)
+         (:gt :geq :leq :lt) (or (= (count g) 3) (= (count g) 4))
+         (:and :or) (every? guard? (rest g)))))
+
 ; edge label is a set containing :required | button masks
 (defn make-edge [target guard label]
-  (assert (every? #(#{:gt :geq :leq :lt} (first %)) guard)
-          "Guard must be a list of difference formulae.")
+  (assert (guard? guard) "Guard must be a boolean combination of difference formulae.")
   (println "guard:" guard)
   {:target target :guard guard :label label :update identity})
-
-(defn invert-guard [g]
-  (case (first g)
-    :gt (assoc g 0 :leq)
-    :geq (assoc g 0 :lt)
-    :leq (assoc g 0 :gt)
-    :lt (assoc g 0 :geq)))

 (defn make-state [id flows & edges]
   (let [edges (flatten [edges])
         edge-guards (map :guard (filter #(:required (:label %)) edges))]
     ; invariant is a disjunction of negated guards
     (println "es" edges "eguards" edge-guards)
-    {:id id :flows flows :edges edges :invariant (map #(map invert-guard %) edge-guards)}))
-
-(defn valid-for-inputs [_transition _inputs]
-  ;todo
+    {:id id :flows flows :edges edges}))
+
+(defn valid-for-inputs [transition inputs]
+  ;todo: some :inputs label in transition's label must be a subset of inputs
   false)

 (defn next-transition [has ha then inputs]
@@ -331,18 +344,25 @@

 (defn term-dependencies [guard-term]
   (cond
+    ; catch guards
+    (and (vector? guard-term)
+         (#{:gt :geq :leq :lt :and :or} (first guard-term))) (mapcat term-dependencies (rest guard-term))
     ; catch [:d ID v]
-    (and (vector? guard-term) (= (first guard-term) :d) (= 3 (count guard-term))) [(second guard-term)]
+    (and (vector? guard-term)
+         (= (first guard-term) :d)
+         (= 3 (count guard-term))) [(second guard-term)]
     ; catch [ID v]
-    (and (vector? guard-term) (not= (first guard-term) :d) (= 2 (count guard-term))) [(first guard-term)]
+    (and (vector? guard-term)
+         (not= (first guard-term) :d)
+         (= 2 (count guard-term))) [(first guard-term)]
     ; must be (+-*/ ...)
-    (and (not (vector? guard-term)) (seqable? guard-term)) (mapcat term-dependencies (rest guard-term))
+    (and (not (vector? guard-term))
+         (seqable? guard-term)) (mapcat term-dependencies (rest guard-term))
     :else []))

 (defn ha-dependencies [ha]
-  (let [all-guards (mapcat :guard (:edges (current-state ha)))
-        all-ha-refs (mapcat (fn [g] (mapcat term-dependencies (rest g)))
-                            all-guards)
+  (let [all-guards (map :guard (:edges (current-state ha)))
+        all-ha-refs (mapcat term-dependencies all-guards)
         ;_ (println all-ha-refs)
         ]
     (into #{} all-ha-refs)))
@@ -365,6 +385,7 @@
         ; mentioned above, they might have calculated their new intervals based on stale information.
         ; calculating intervals is idempotent and has no second-order effects so it is fine to do it repeatedly
         ; and it also suffices to do it a single time once all the HAs are updated with new times, values and flows.
+        ; todo: cache these?
         deps (into #{} (filter (fn [k]
                                  (some transitioned-ids (ha-dependencies (get has k))))
                                (keys has)))
@@ -407,23 +428,28 @@
 (defonce last-time nil)

 (defn moving-inc-c [vbl width limit]
-  [[:lt vbl (- limit width)]
+  [:and
+   [:lt vbl (- limit width)]
    [:geq vbl (list '- limit width [:d vbl])]])

 (defn moving-dec-c [vbl limit]
-  [[:gt vbl limit]
+  [:and
+   [:gt vbl limit]
    [:leq vbl (list '- limit [:d vbl])]])

 (defn moving-inc [vbl width other-ha]
-  [[:lt vbl [other-ha vbl] (- width)]
+  [:and
+   [:lt vbl [other-ha vbl] (- width)]
    [:geq vbl [other-ha vbl] (list '- [:d other-ha vbl] [:d vbl] width)]])

 (defn moving-dec [vbl width other-ha]
-  [[:gt vbl [other-ha vbl] width]
+  [:and
+   [:gt vbl [other-ha vbl] width]
    [:leq vbl [other-ha vbl] (list '+ [:d other-ha vbl] width (list '- [:d vbl]))]])

 (defn between-c [vbl min max]
-  [[:geq vbl min]
+  [:and
+   [:geq vbl min]
    [:lt vbl max]])

 (defn goomba [id x y speed state others walls]
@@ -440,8 +466,9 @@
                (mapcat (fn [[x y w h]]
                          ; left-transition means bumping into left side of wall
                          [(make-edge :left
-                                     (concat (moving-inc-c :x 16 x)
-                                             (between-c :y 0 100 #_(- y 16) #_(+ y h)))
+                                     [:and
+                                      (moving-inc-c :x 16 x)
+                                      (between-c :y 0 100 #_(- y 16) #_(+ y h))]
                                      #{:required [:this id] [:other [:wall x y w h]]})])
                        walls)
                ; x + 16 < x2 && x + dx*frame + 16 >= x2 + dx2*frame
@@ -455,8 +482,9 @@
                (mapcat (fn [[x y w h]]
                          ; right-transition means bumping into right side of wall
                          [(make-edge :right
-                                     (concat (moving-dec-c :x (+ x w))
-                                             (between-c :y (- y 16) (+ y h)))
+                                     [:and
+                                      (moving-dec-c :x (+ x w))
+                                      (between-c :y (- y 16) (+ y h))]
                                      #{:required [:this id] [:other [:wall x y w h]]})])
                        walls)
                ; x > x2 + 16 && x + dx*frame <= x2 + dx2*frame + 16 -->


Add a support to pause and resume a session

--- src/tomato/core.clj
+++ src/tomato/core.clj
@@ -28,9 +28,9 @@
   (future (while true (do (Thread/sleep ms) (callback)))))

 (defn set-timeout [callback ms]
-  (swap! state assoc :timer (future (do (Thread/sleep ms)
-                                        (swap! state assoc :timer nil)
-                                        (callback)))))
+  (future (do (Thread/sleep ms)
+              (swap! state assoc :timer nil)
+              (callback))))

 (defn send-m
@@ -55,39 +55,44 @@
 (defn remaining-time []
   (ms->sec (- (base-time) (elapsed-time))))

-(defn edit-message [id message]
-  (edit-m message id))
-
 (defn session-alive? [state]
   (not (nil? (:timer state))))
+
+(defn session-paused? [state]
+  (and (nil? (:timer state)) (not (nil? (:elapsed state)))))

 (defn send-remaining [message-id byline]
   (if (nil? message-id)
-    (->> (send-m (str "남은 시간은 " (remaining-time) "초"))
+    (->> (send-m (str "남은 시간은 " (remaining-time) "초") {:disable_notification true})
          :result
          :message_id
          (swap! state assoc :message-id))
     (edit-m (str "남은 시간은 " (remaining-time) "/" (ms->sec (base-time)) "초 by " byline) message-id)))

+(defn remaining-each-10s [get-messageid]
+  (set-interval #(send-remaining (get-messageid) "interval") (secs 10)))
+

 (defn goto-x [key]
   (let [mode (key modes)]
-    (send-m ((:text mode)))
-    (swap! state assoc :mode key)
-    (swap! state assoc :started (System/currentTimeMillis))
-    (swap! state assoc :message-id nil)
     (when-not (nil? (:interval @state)) (future-cancel (:interval @state)))
-    (swap! state assoc :interval (set-interval #(send-remaining (:message-id @state) "interval") (secs 10)))
+    (swap! state assoc
+           :mode key
+           :started (System/currentTimeMillis)
+           :message-id nil
+           :interval (remaining-each-10s #(:message-id @state))
+           :timer (set-timeout #(goto-x (:next mode)) (:during mode)))
+
     (when (= key :relax)
       (swap! counted inc))
-    (set-timeout #(goto-x (:next mode)) (:during mode))))
+    (send-m ((:text mode)))))

 ;;;; Handlers
-(defn timer-start []
+(defn start-session []
   (if (session-alive? @state)
     (send-m "이미 세션이 진행중입니다")
     (goto-x :pomodoro)))
@@ -95,25 +100,51 @@
 (defn check-remaining []
   (if (session-alive? @state)
     (send-remaining (:message-id @state) "manual")
-    (send-m "타이머가 돌고 있지 않음")))
+    (send-m "세션이 진행중이 아닙니다")))

-(defn cancel-timer []
+(defn cancel-session []
   (if (session-alive? @state)
     (do
       (future-cancel (:timer @state))
       (future-cancel (:interval @state))
       (swap! state assoc :timer nil)
       (send-m (str (:mode @state) " 취소되었습니다")))
-    (send-m "진행중인 태스크가 없습니다")))
+    (send-m "취소할 세션이 없습니다")))

 (defn send-counted [counted]
   (send-m (str counted)))

+(defn pause-session []
+  (if (session-alive? @state)
+    (do
+      (future-cancel (:timer @state))
+      (future-cancel (:interval @state))
+      (swap! state assoc
+             :elapsed (elapsed-time)
+             :timer nil)
+      (send-m (str (:mode @state) " 잠시 중단 되었습니다")))
+    (send-m "중단할 세션이 없습니다")))
+
+(defn resume-session []
+  (if (session-paused? @state)
+    (let [elapsed (:elapsed @state)
+          mode ((:mode @state) modes)
+          during (- (:during mode) elapsed)]
+
+      (swap! state assoc
+             :started (- (System/currentTimeMillis) elapsed)
+             :timer (set-timeout #(goto-x (:next mode)) during)
+             :interval (remaining-each-10s #(:message-id @state)))
+      (send-m "세션을 다시 시작합니다"))
+    (send-m "다시 시작할 세션이 없습니다")))
+
 (defhandler bot-api
-            (command "go" [] (timer-start))
+            (command "go" [] (start-session))
             (command "check" [] (check-remaining))
             (command "count" [] (send-counted @counted))
-            (command "cancel" [] (cancel-timer)))
+            (command "cancel" [] (cancel-session))
+            (command "pause" [] (pause-session))
+            (command "resume" [] (resume-session)))

 (def channel (atom nil))

@@ -123,6 +154,10 @@
 (defn stop []
   (p/stop @channel))

+(defn restart []
+  (do (stop)
+      (start)))
+
 (defn -main
   "I don't do a whole lot ... yet."
   []


Fixed #187 - an input-text bug where what's displayed in the component can get out of sync with what the caller sends to it

--- src/re_com/misc.cljs
+++ src/re_com/misc.cljs
@@ -124,18 +124,22 @@
                                                   (if validation-regex (re-find validation-regex new-val) true))
                                             (reset! internal-model new-val)
                                             (when-not change-on-blur?
+                                              (reset! external-model @internal-model)
                                               (on-change @internal-model)))))
                          :on-blur     (handler-fn
                                         (when (and
                                                 on-change
                                                 change-on-blur?
                                                 (not= @internal-model @external-model))
+                                          (reset! external-model @internal-model)
                                           (on-change @internal-model)))
                          :on-key-up   (handler-fn
                                         (if disabled?
                                           (.preventDefault event)
                                           (case (.-which event)
-                                            13 (when on-change (on-change @internal-model))
+                                            13 (when on-change
+                                                 (reset! external-model @internal-model)
+                                                 (on-change @internal-model))
                                             27 (reset! internal-model @external-model)
                                             true)))}
                         attr)]]


Calculate text justification on word lengths only. MAJOR speedup <3

--- src/text_justification/model.cljs
+++ src/text_justification/model.cljs
@@ -1,11 +1,12 @@
 (ns ^:figwheel-always text-justification.model
     (:require [reagent.core :as reagent :refer [atom]]
-              [goog.string :as gstring]
-              [text-justification.utils :as utils]))
+              [goog.string :as gstring]))

 (enable-console-print!)

 ;;;; TODO filter out empty words
+;;;; TODO precalc badness to hash ?
+;;;; TODO remove has-memo?

 ;;;;
 ;;;; consts
@@ -16,6 +17,7 @@
 ;;;;
 ;;;; state
 ;;;;
+
 (defonce state (atom []))

 (defn- set-state [new-state]
@@ -29,6 +31,59 @@
 ;;;;
 ;;;; implementation
 ;;;;
+
+(defn- badness
+  "given line and page width returns measurement how `pretty` the line is"
+  [line-lens page-width]
+  (let [total-length (+ (reduce + line-lens) (count line-lens) -1)] ;; remember to count whitespaces
+    (if (> total-length page-width)
+      js/Infinity
+      (let [a (- page-width total-length)] (* a a a)) )))
+
+
+;; cache results (memo)
+;; f.e. result for 'justify text after X word is: [lines]'
+(def tj-memo (atom {}))
+(defn- clear-memo [] (reset! tj-memo {}))
+(defn- add-memo   [arg-val return-val] (swap! tj-memo #(assoc % arg-val return-val)))
+(defn- has-memo?  [arg-val] (contains? @tj-memo arg-val))
+(defn- get-memo   [arg-val] (get @tj-memo arg-val))
+
+(defn- tj-inner ;;; text-justification-inner
+  "fits words into lines so that whole text looks pretty
+  @return [`pretty` metric value, [justified lines]]"
+  ([word-lens page-width] ;; lens as in lengths, not actual lens
+    (clear-memo)
+    (second (tj-inner word-lens page-width 0)))
+  ([word-lens page-width word-idx]
+    (cond
+      (empty? word-lens) [0.0 []]
+      (has-memo? word-idx) (get-memo word-idx)
+      :else
+        (reduce
+          (fn [acc word-id]
+             (let [line-lens (subvec word-lens 0 word-id) rest-words-lengths (subvec word-lens word-id)
+                   next-word-idx (+ word-idx word-id)
+                   [sub-prob-badness sub-prob-lines] (tj-inner rest-words-lengths page-width next-word-idx)
+                   ugliness (+ (badness line-lens page-width) sub-prob-badness)
+                   ;; solution-proposal (cons line sub-prob-lines)]
+                   solution-proposal (cons word-id sub-prob-lines)]
+              ; (print "sub" line "|words in line" (count words))
+              (add-memo next-word-idx [sub-prob-badness sub-prob-lines]) ;; write to memo
+              (if (< ugliness (first acc)) [ugliness solution-proposal] acc)))
+          [js/Infinity []]
+          (map inc (range (count word-lens))) )))) ;; TODO (dec (count words)) ?
+
+
+(defn- prepare-text
+  "split by paragraphs or treat text as single text flow"
+  [text separate-paragraphs]
+  (if separate-paragraphs
+    (seq (.split text "\n"))
+    [(clojure.string/replace text #"\n" " ")]
+    ))
+
+
 (defn- prepare-word
   "remove whitespaces, split word if it is too long"
   [max-len word-raw]
@@ -47,60 +102,11 @@
 ; (prepare-word-test "aaabbbccc111aaabbbccc111")
 ; (prepare-word-test "aaabbbccc111aaabbbccc111aaabbbccc111")

-(defn- badness
-  "given line and page width returns measurement how `pretty` the line is"
-  [line page-width]
-  (let [total-length (utils/line-length line)]
-    (if (> total-length page-width)
-      js/Infinity
-      (let [a (- page-width total-length)] (* a a a)) )))
-
-
-;; cache results (memo)
-;; f.e. result for 'justify text after X word is: [lines]'
-(def tj-memo (atom {}))
-(defn- clear-memo [] (reset! tj-memo {}))
-(defn- add-memo   [arg-val return-val] (swap! tj-memo #(assoc % arg-val return-val)))
-(defn- has-memo?  [arg-val] (contains? @tj-memo arg-val))
-(defn- get-memo   [arg-val] (get @tj-memo arg-val))
-
-(defn- text-justification-inner
-  "fits words into lines so that whole text looks pretty
-  @return [`pretty` metric value, [justified lines]]"
-  ([words page-width]
-    (clear-memo)
-    (second (text-justification-inner words page-width 0)))
-  ([words page-width word-idx]
-    (cond
-      (empty? words) [0.0 []]
-      (has-memo? word-idx) (get-memo word-idx)
-      :else
-        (reduce
-          (fn [acc word-id]
-             (let [line (subvec words 0 word-id) rest-words (subvec words word-id)
-                   next-word-idx (+ word-idx word-id)
-                   [sub-prob-badness sub-prob-lines] (text-justification-inner rest-words page-width next-word-idx)
-                   ugliness (+ (badness line page-width) sub-prob-badness)
-                   solution-proposal (cons line sub-prob-lines)]
-              ; (print "sub" line "|words in line" (count words))
-              (add-memo next-word-idx [sub-prob-badness sub-prob-lines]) ;; write to memo
-              (if (< ugliness (first acc)) [ugliness solution-proposal] acc)))
-          [js/Infinity []]
-          (map inc (range (count words))) )))) ;; TODO (dec (count words)) ?
-
-
-(defn- prepare-text
-  "split by paragraphs or treat text as single text flow"
-  [text separate-paragraphs]
-  (if separate-paragraphs
-    (seq (.split text "\n"))
-    [(clojure.string/replace text #"\n" " ")]
-    ))
-
-
+(defn- word-lens-to-text [])
 ;;;;
 ;;;; public interface
 ;;;;
+
 (defn text-justification
   "justify text provided as a collection of words to given page width"
   [text separate-paragraphs page-width]
@@ -108,13 +114,24 @@
   (clear-state)
   (doseq [paragraph (prepare-text text separate-paragraphs)]
     ; (println "PARAGRAPH:" paragraph)
-    ; (.profile js.console "text-justification")
-    (let [words-raw (.split paragraph #" ")
+    (.profile js.console "text-justification")
+    (let [words-raw (.split paragraph #" +")
+          ;;words (vec (filter .blank? (flatten (map #(prepare-word page-width %) words-raw))))
           words (vec (flatten (map #(prepare-word page-width %) words-raw)))
-          justified-text (text-justification-inner words page-width)]
+          word-lens (vec (map count words))
+          justified-text (tj-inner word-lens page-width)]
         ; (.log js/console "words" (count words) ":" words)
         ; (.log js/console "state" (count justified-text) ":" justified-text)
-        (update-state justified-text)
+        (update-state
+        (second (reduce
+          (fn [[start-word-idx lines-atm] words-in-line]
+            (let [next-word-start-idx (+ start-word-idx words-in-line)
+                  words-in-this-line (subvec words start-word-idx next-word-start-idx)]
+              ; (println words-in-this-line)
+              [next-word-start-idx (conj lines-atm words-in-this-line)]
+              ))
+          [0 []]
+          justified-text)))
       )
-    ; (.profileEnd js.console)
+    (.profileEnd js.console)
   ))


Make model functions private (it is not enforced, so it is just a hint)

--- src/text_justification/model.cljs
+++ src/text_justification/model.cljs
@@ -8,7 +8,7 @@
 (defonce invisible-char (gstring/unescapeEntities " ")) ;; \u00A0 ?

-(defn prepare-word
+(defn- prepare-word
   "remove whitespaces, split word if it is too long"
   [max-len word-raw]
   (let [word (gstring/trim word-raw) len (count word)]
@@ -23,9 +23,7 @@
 ; (println "long:" (prepare-word 2 "abc"))
 ; (println "test:" (prepare-word 11 "aaabbbccc111"))

-;; TODO make functions private
-
-(defn badness
+(defn- badness
   "given line and page width and returns measurement how `pretty` the line is"
   [line page_width]
   (let [total_length (utils/line-length line)]
@@ -33,7 +31,7 @@
       js/Infinity
       (utils/exp (- page_width total_length) 3))))

-(defn text_justification
+(defn- text_justification
   "given words to fit and page width returns vector of `pretty` measurement and vector of justified lines"
   [words page_width]
   (if (empty? words)


Support vars as response and other functions

--- src/yada/schema.clj
+++ src/yada/schema.clj
@@ -155,6 +155,8 @@
   (as-fn [_] "Coerce to function"))

 (extend-protocol FunctionCoercion
+  clojure.lang.Var
+  (as-fn [f] f)
   clojure.lang.Fn
   (as-fn [f] f)
   Object


[default] cljc stuff.

[default] cljc stuff.

--- src/cortex/impl/default_.cljc
+++ src/cortex/impl/default_.cljc
@@ -32,7 +32,7 @@
 ;; - no ability to back-propagate gradients
 ;; - zero length input gradient
 (extend-protocol cp/PNeuralTraining
-  Object
+  #?(:clj Object :cljs object)
     (forward [this input]
       (cp/calc this input))


Tidy up

Tidy up

--- src/discuss/utils/common.cljs
+++ src/discuss/utils/common.cljs
@@ -23,12 +23,11 @@
                              :template      :discussion
                              :next-template :discussion
                              :add?          false
-                             :add-text      "Ein neues Argument hinzufügen"
                              :add-type      nil
                              :loading?      false
                              :error?        false
                              :error-msg     nil
-                             :language      :en}
+                             :language      :de}
                 :user       {:nickname   "kangaroo"
                              :token      "razupaltuff"
                              :avatar     ""


improved owrd ID generation by using a regular expression

--- src/distillery/processing.clj
+++ src/distillery/processing.clj
@@ -165,12 +165,12 @@
   [{:keys [^String lexical-form] :as word}]
   (comment "TODO Needs to be improved for arbitrary characters!")
   (-> lexical-form
-      (.replace " " "_")
       (.toLowerCase)
       (.replace "ß" "ss")
       (.replace "ä" "ae")
       (.replace "ö" "oe")
-      (.replace "ü" "ue")))
+      (.replace "ü" "ue")
+      (string/replace #"\W" "_")))

 (defn- compute-index-entry-stats
   [{:keys [occurrences] :as entry}]


whitespace

whitespace

--- support/src/figwheel/client.cljs
+++ support/src/figwheel/client.cljs
@@ -54,8 +54,7 @@
 (defn css-loaded-state? [msg-names]
   (= :css-files-changed (first msg-names)))

-;; plugins
-
+;;
 (defn file-reloader-plugin [opts]
   (let [ch (chan)]
     (go-loop []


reverting part of previous change

reverting part of previous change

--- src/shuppet/core.clj
+++ src/shuppet/core.clj
@@ -80,8 +80,7 @@
     (if (env-config? config)
       (shuppet/try-env-config config)
       (when-let [config (shuppet/try-app-config (or env "poke") (or app-name "app-name") config)]
-        (when app-name
-          (validate config))
+        (validate config)
         config))))

 (defn create-config


Add env updating and layers dependent on env values, like time

Layer fns now take the environment map as a parameter along with the leds so far. Implemented a basic sine-wave brightness map. It seems like this is working, but it's hard to tell without connecting some real LEDs

--- src/sparkle/core.clj
+++ src/sparkle/core.clj
@@ -12,17 +12,17 @@
 (def leds (take 5 (repeat black)))

 (defn static-color [color]
-  (fn [leds]
+  (fn [env leds]
     (map (constantly color) leds)))

 (defn scale-brightness [factor]
-  (fn [leds]
+  (fn [env leds]
     (map (fn [led]
            (fmap #(* factor %) led))
          leds)))

 (defn brightness-gradient [start-factor end-factor]
-  (fn [leds]
+  (fn [env leds]
     (let [step (/ (- end-factor start-factor)
                   (- (count leds) 1))
           factors (iterate #(+ % step) start-factor)]
@@ -30,8 +30,19 @@
              (fmap #(* factor %) led))
            leds factors))))

-(defn apply-layers [layers leds]
-  ((apply comp layers) leds))
+(defn pulse-brightness [{:keys [time] :as env} leds]
+  (let [scaled-time (/ time 10000)
+        brightness-factor (Math/sin scaled-time)]
+    (map (fn [led]
+           (fmap #(* % brightness-factor) led))
+         leds)))
+
+(defn apply-layers [layers env leds]
+  (let [env-applied-layers (for [layer layers] (partial layer env))]
+    ((apply comp env-applied-layers) leds)))
+
+
+(defrecord RenderState [env model])

 (defn display [{:keys [frame-chan] :as displayer} frame]
@@ -60,39 +71,49 @@
     (close! frame-chan)
     displayer))

-(defn render [layers displayer]
-  (display displayer (apply-layers layers leds)))
+
+(defn get-env-updates [env]
+  (-> env
+      (assoc :time (System/currentTimeMillis))))
+
+
+(defn render-step [{:keys [env model] :as state}]
+  (let [{:keys [layers]} model
+        updated-env (get-env-updates env)]
+    (->> leds
+         (apply-layers layers updated-env))))
+

 (defn send-command [{:keys [command-chan] :as renderer} command]
   (>!! command-chan command))

 (defmulti execute (fn [command layers status] (:type command)))

-(defmethod execute :start [_ layers status]
-  [layers :running])
+(defmethod execute :start [_ state status]
+  [state :running])

-(defmethod execute :pause [_ layers status]
-  [layers :paused])
+(defmethod execute :pause [_ state status]
+  [state :paused])

-(defmethod execute :update [{:keys [new-layers]} layers status]
-  [new-layers status])
+(defmethod execute :update [{:keys [new-state]} state status]
+  [new-state status])

 (defmethod execute :stop [_ _ _]
   nil)

 (defn start-rendering [{:keys [command-chan displayer] :as renderer}]
   (thread
-    (loop [layers []
+    (loop [state (-> RenderState {} {})
            status :running]
-      (let [[layers status :as loop-result]
+      (let [[state status :as loop-result]
             (if (= status :running)
-              (alt!! command-chan ([command] (execute command layers status))
-                    :default (do
-                               (render layers displayer)
-                               [layers :running]))
-              (execute (<!! command-chan) layers status))]
+              (alt!! command-chan ([command] (execute command state status))
+                     :default (let [next-frame (render-step state)]
+                                (display displayer next-frame)
+                                [state :running]))
+              (execute (<!! command-chan) state status))]
         (if loop-result
-          (recur layers status)
+          (recur state status)
           (println "Shutting down render loop"))))))

 (defrecord Renderer [command-chan displayer]


Add friendly msg when starting server

Add friendly msg when starting server

--- src/t2000/server.clj
+++ src/t2000/server.clj
@@ -31,10 +31,13 @@
 (defonce server (atom nil))

 (defn start-server []
-  (reset! server (run-server #'app {:port 3000 :join? false})))
+  (let [port 3000]
+    (reset! server (run-server #'app {:port port :join? false}))
+    (println (str "Http server started on http://127.0.0.1:" port))))

 (defn stop-server []
   (if-let [stop-fn @server]
     (stop-fn))
-  (reset! server nil))
+  (reset! server nil)
+  (println "Http server stopped."))


PLD: change summary charts to charts

PLD: change summary charts to charts

--- src/hatti/views/dataview.cljs
+++ src/hatti/views/dataview.cljs
@@ -34,7 +34,7 @@
            :label "Table"
            :component table-page}
    :chart {:view :chart
-           :label "Summary Charts"
+           :label "Charts"
            :component chart-page}
    :saved-charts {:view :saved-charts
                   :label "Dashboard"


Solved problem 85 (power set) finally

Solved problem 85 (power set) finally

--- src/fourclojure/4_clojure.clj
+++ src/fourclojure/4_clojure.clj
@@ -65,6 +65,6 @@

 (defn powerset [s]
   (if (seq s)
-    (for [e s :let [t (powerset (disj s e))]]
-      (clojure.set/union t (op-f e t)))
+    (let [e (first s) t (powerset (disj s e))]
+      (clojure.set/union t (map #(conj % e) t)))
     #{#{}}))


truncate=true by default

truncate=true by default

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -29,7 +29,7 @@

 ;; whether to remove [:head] and [:comp] paths from generated trees after generation:
 ;; for performance.
-(def ^:const truncate false)
+(def ^:const truncate true)

 (declare candidate-parents)
 (declare comp-path-to-complements)


renaming and comments

renaming and comments

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -11,21 +11,21 @@

 ;; during generation, will not decend deeper than this when creating a tree:
 ;; TODO: should also be possible to override per-language.
-(def ^:const max-total-depth 2)
+(def ^:const max-total-depth 8)

 ;; use map or pmap.
 (def ^:const mapfn map)

 ;; deterministic generation:
-;;(def ^:const shufflefn (fn [x] x))
+(def ^:const shufflefn (fn [x] x))

 ;; nondeterministic generation
-(def ^:const shufflefn shuffle)
-
+;;(def ^:const shufflefn shuffle)
+
+(def ^:const randomize-lexemes-before-phrases
+  false)
 ;;(def ^:const randomize-lexemes-before-phrases
-;;  false)
-(def ^:const randomize-lexemes-before-phrases
-  true)
+;;  true)

 (def ^:const truncate true)

@@ -47,11 +47,12 @@
     (->>
      (lightning-bolts model spec depth max-depth)
      (filter not-fail?)
-     (map (fn [bolt] ;; create a map of paths within the bolt to possible complements in the bolt.
+     (map (fn [bolt] ;; for each bolt, create a map of complement positions within the bolt to possible complements for that position
             (assoc
              (comp-paths-to-complements bolt (find-comp-paths bolt) model depth max-depth)
              [] [bolt])))
-     (mapcat (fn [each-bolt-and-comps]
+     (mapcat (fn [each-bolt-and-comps] ;; for each such map in each bolt, find all possible combinations of complements, taking one complement per path.
+               ;; the result is a trellis for each bolt, and a path through this trellis is one complement for each complement position.
                (map (fn [each-path-through-trellis]
                       (zipmap (keys each-bolt-and-comps)
                               each-path-through-trellis))
@@ -59,14 +60,15 @@
      (map (fn [bolt-and-comps]
             (apply unify
                    (let [bolt (get bolt-and-comps [])
-                         bolt-and-comps (dissoc bolt-and-comps [])]
+                         paths-and-comps (dissoc bolt-and-comps [])
+                         paths (keys paths-and-comps)]
                      (cons bolt
-                           (->> (keys bolt-and-comps)
-                                (map (fn [path]
-                                       (let [result (assoc-in bolt path (get bolt-and-comps path))]
-                                         (if (= true truncate)
-                                           (dissoc-paths result [path])
-                                           result))))))))))
+                           (map (fn [path]
+                                  (let [result (assoc-in bolt path (get paths-and-comps path))]
+                                    (if (= true truncate)
+                                      (dissoc-paths result [path])
+                                      result)))
+                                paths))))))
      (map (fn [expression]
             (do-defaults expression model)))
      (filter not-fail?)
@@ -169,7 +171,7 @@
 (defn comp-path-to-complements
   "return a lazy sequence of bolts for all possible complements that can be added to the end of the _path_ within _bolt_."
   [bolt path model depth max-depth]
-  (log/trace (str "comp-path-to-complements:" depth "/" max-depth ":" ((:morph-ps model) bolt) "@" path))
+  (log/info (str "comp-path-to-complements:" depth "/" max-depth ":" ((:morph-ps model) bolt) "@" path))
   (let [spec (get-in bolt path)
         lexemes (shufflefn (get-lexemes model spec))
         bolts-at (if (< depth max-depth)


randomize

randomize

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -19,17 +19,14 @@
 ;; use map or pmap.
 (def ^:const mapfn map)

-;; should generation be deterministic or random?
-(def ^:const deterministic false)
-
 ;; deterministic generation:
-(def ^:const shufflefn (fn [x] x))
+;;(def ^:const shufflefn (fn [x] x))

 ;; nondeterministic generation
-;;(def ^:const shufflefn shuffle)
+(def ^:const shufflefn shuffle)

 (def ^:const randomize-lexemes-before-phrases
-  false)
+  true)

 (def ^:const error-if-no-complements false)


+(defn do-defaults)

+(defn do-defaults)

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -216,6 +216,10 @@
       bolts)
      language-model total-depth (rest comp-paths)
      truncate-children max-total-depth top-level-spec)))
+
+(defn do-defaults [expr]
+  (log/info (str "do-defaults.."))
+  expr)

 (defn add-complement-to-bolt [bolt path language-model total-depth top-level-spec
                               & {:keys [max-total-depth truncate-children]


fix depth comparison

fix depth comparison

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -229,7 +229,7 @@
           (when (= false (get-in spec [:head :phrasal] false))
             (lazy-mapcat
              (fn [parent]
-               (log/debug (str "parent: " (:rule parent) " over lexical heads."))
+               (log/debug (str "lightning-bolts: parent: " (:rule parent) " over lexical heads."))
                (let [lexicon (or (:lexicon (:generate language-model)) (:lexicon language-model))
                      subset (if-let [index-fn (:index-fn language-model)]
                               (do
@@ -260,7 +260,7 @@
                          (get-in % [:head :phrasal] false))
                      parents)))
           phrasal ;; 2. generate list of all phrases where the head child of each parent is itself a phrase.
-          (if (and (< total-depth max-total-depth)
+          (if (and (< depth max-total-depth)
                    (= true (get-in spec [:head :phrasal] true)))
             (lazy-mapcat (fn [parent]
                            (log/debug (str "parent: " (:rule parent) " over phrasal heads."))
@@ -488,7 +488,7 @@
                     " for spec: " (strip-refs spec)))
     (if (empty? result)
       (log/debug (str "candidate-parents: "
-                      "no parents found for spec: " spec))
+                      "no parents found for spec: " (spec-info spec)))
       (log/debug (str "candidate-parents: "
                     (string/join "," (map :rule result))
                     " for: " (spec-info spec))))


Update the date's of task

Update the date's of task

--- src/balance/events.cljs
+++ src/balance/events.cljs
@@ -17,7 +17,7 @@
   [_ _]
   (save-store-debounced!))

-(def default-interceptors [(after save-database)])
+(def save-database-interceptor (after save-database))

 ;; -- Effects ---------------------------------------------------------------

@@ -26,11 +26,29 @@
   (fn [[path-key & params]]
     (rr/navigate-to path-key (or (first params) {}))))

+;; -- Co-effects -----------------------------------------------------------
+
+(reg-cofx
+ :now
+ (fn [coeffects _]
+   (assoc coeffects :now (js.Date.))))
+
 ;; -- Helpers --------------------------------------------------------------

 (defn filter-nil [m]
   "Remove from map all key-value pairs where value is nil"
   (into {} (filter (comp some? val) m)))
+
+(defn insert-creation-date [task now]
+  (if (neg? (:db/id task))
+    (assoc task :task/creation-date now)
+    task))
+
+(defn extend-task [task now]
+  (-> task
+       filter-nil
+       (assoc :task/last-update-date now)
+       (insert-creation-date now)))

 ;; -- Handlers --------------------------------------------------------------

@@ -41,10 +59,11 @@

 (reg-event-fx
   :commit-task
-  default-interceptors
-  (fn [_ [_ task]]
-    (let [task (filter-nil task)]
-      (if (contains? task :task/title)
+  [save-database-interceptor
+   (inject-cofx :now)]
+  (fn [{:keys [now]} [_ task]]
+    (let [extended-task (extend-task task now)]
+      (if (contains? exteded-task :task/title)
         { :navigate [:back] }
-        { :transact [task]
+        { :transact [extended-task]
           :navigate [:back] }))))


Add es6 allocator implementation.

Add es6 allocator implementation.

--- src/bytebuf/buffer.cljx
+++ src/bytebuf/buffer.cljx
@@ -207,3 +207,16 @@
 (defmethod allocate [:direct :netty]
   [size & _]
   (.directBuffer allocator size))
+
+#+cljs
+(defmethod allocate [:heap :es6]
+  [size & _]
+  (let [bf (js/ArrayBuffer. size)]
+    (js/DataView. bf)))
+
+;; #+cljs
+;; (defmethod allocate [:heap :node]
+;;   [size & _]
+;;   (let [bf (js/require "buffer")
+;;         bf (.-Buffer bf)]
+;;     (bf. size)))


Avoid printing entire resource on error

Avoid printing entire resource on error

To avoid potential StackOverflowError

--- src/yada/methods.clj
+++ src/yada/methods.clj
@@ -174,10 +174,11 @@

      (d/catch
          (fn [e]
-           ;;(infof e "Error on GET")
            (if (:status (ex-data e))
              (throw e)
-             (throw (ex-info "Error on GET" (select-keys ctx [:response :resource]) e))))))))
+             (throw (ex-info "Error on GET" {:response (:response ctx)
+                                             :resource (type (:resource ctx))
+                                             :error e}))))))))

 ;; --------------------------------------------------------------------------------


Just use identity func for echo cmd prep func.

--- src/cbfg/world-net.cljs
+++ src/cbfg/world-net.cljs
@@ -7,8 +7,7 @@
             [cbfg.world-base :refer [replay-cmd-ch world-replay
                                      render-client-hist start-test]]))

-(def cmd-handlers
-  {"echo" (fn [c] c)})
+(def cmd-handlers {"echo" identity})

 (defn server-conn-loop [actx server-send-ch server-recv-ch close-server-recv-ch]
   (ago-loop server-conn-loop actx [num-requests 0]


Use pipes instead of escalation marks.

Use pipes instead of escalation marks.

--- src/cli4clj/example.clj
+++ src/cli4clj/example.clj
@@ -23,11 +23,11 @@
 ;;; In the simplest scenario only the commands have to be defined.
 ;;; In the following, an example using a simple scenario along with some explanations is provided:
 ;;;     cli4clj is configured via an "options" map.
-;;;     !         Commands are stored in a nested map using the key :cmds in the options map.
-;;;     !         !      As first simple example command, we define a command called "test".
-;;;     !         !      !      The function to be called for the command is defined via :fn.
-;;;     !         !      !      !  In this example we use an anonymous function.
-;;;     !         !      !      !  However, arbitrary functions can be used.
+;;;     |         Commands are stored in a nested map using the key :cmds in the options map.
+;;;     |         |      As first simple example command, we define a command called "test".
+;;;     |         |      |      The function to be called for the command is defined via :fn.
+;;;     |         |      |      |  In this example we use an anonymous function.
+;;;     |         |      |      |  However, arbitrary functions can be used.
   (let [cli-opts {:cmds {:test {:fn #(println "This is a test.")
 ;;;                             Optionally a short information text can be given.
                                 :short-info "Test Command"


typos

typos

--- src/cljc/quil/core.cljc
+++ src/cljc/quil/core.cljc
@@ -870,7 +870,7 @@
   upY:      1
   upZ:      0

-  Similar imilar to gluLookAt() in OpenGL, but it first clears the
+  Similar to gluLookAt() in OpenGL, but it first clears the
   current camera settings."
   ([] (.camera (current-graphics)))
   ([eyeX eyeY eyeZ centerX centerY centerZ upX upY upZ]
@@ -919,7 +919,7 @@
      clip
      "Limits the rendering to the boundaries of a rectangle defined by
   the parameters. The boundaries are drawn based on the state of
-  the (image-mode) fuction, either :corner, :corners, or :center.
+  the (image-mode) function, either :corner, :corners, or :center.
   To disable use (no-clip)."
      [x y w h]
      (.clip (current-graphics) (float x) (float y) (float w) (float h))))
@@ -1249,7 +1249,7 @@
     :subcategory "Curves"
     :added "1.0"}
   curve-point
-  "Evalutes the curve at point t for points a, b, c, d. The parameter
+  "Evaluates the curve at point t for points a, b, c, d. The parameter
   t varies between 0 and 1, a and d are points on the curve, and b c
   and are the control points. This can be done once with the x
   coordinates and a second time with the y coordinates to get the
@@ -1432,7 +1432,7 @@
     :subcategory "Attributes"
     :added "1.0"}
   ellipse-mode
-  "Modifies the origin of the ellispse according to the specified mode:
+  "Modifies the origin of the ellipse according to the specified mode:

   :center  - specifies the location of the ellipse as
              the center of the shape. (Default).
@@ -2184,7 +2184,7 @@
   the fill method will not affect the color of a line. 2D lines are
   drawn with a width of one pixel by default, but this can be changed
   with the stroke-weight function. The version with six parameters
-  allows the line to be placed anywhere within XYZ space. "
+  allows the line to be placed anywhere within XYZ space."
   ([p1 p2] (apply line (concat p1 p2)))
   ([x1 y1 x2 y2] (.line (current-graphics) (float x1) (float y1) (float x2) (float y2)))
   ([x1 y1 z1 x2 y2 z2]
@@ -2575,7 +2575,7 @@
   "Adjusts the character and level of detail produced by the Perlin
   noise function. Similar to harmonics in physics, noise is computed
   over several octaves. Lower octaves contribute more to the output
-  signal and as such define the overal intensity of the noise, whereas
+  signal and as such define the overall intensity of the noise, whereas
   higher octaves create finer grained details in the noise
   sequence. By default, noise is computed over 4 octaves with each
   octave contributing exactly half than its predecessor, starting at
@@ -3327,7 +3327,7 @@
   direction. Transformations apply to everything that happens after
   and subsequent calls to the function accumulates the effect. For
   example, calling (rotate HALF-PI) and then (rotate HALF-PI) is the
-  same as (rotate PI). All tranformations are reset when draw begins
+  same as (rotate PI). All transformations are reset when draw begins
   again.

   Technically, rotate multiplies the current transformation matrix by
@@ -3793,8 +3793,8 @@
     :added "1.0"}
   specular
   "Sets the specular color of the materials used for shapes drawn to
-  the screen, which sets the color of hightlights. Specular refers to
-  light which bounces off a surface in a perferred direction (rather
+  the screen, which sets the color of highlights. Specular refers to
+  light which bounces off a surface in a preferred direction (rather
   than bouncing in all directions like a diffuse light). Used in
   combination with emissive, ambient, and shininess in setting
   the material properties of shapes."
@@ -4639,7 +4639,7 @@
                                     inside functions provided to sketch (like
                                     draw, mouse-click, key-pressed and
                                     other). By default all exceptions thrown
-                                    inside these functions are catched. This
+                                    inside these functions are caught. This
                                     prevents sketch from breaking when bad
                                     function was provided and allows you to
                                     fix it and reload it on fly. You can
@@ -4684,7 +4684,7 @@

    :host           - String id of canvas element or DOM element itself.
                      Specifies host for the sketch. Must be specified in sketch,
-                     may be omitted in defsketch. If ommitted in defsketch,
+                     may be omitted in defsketch. If omitted in defsketch,
                      :host is set to the name of the sketch. If element with
                      specified id is not found on the page and page is empty -
                      new canvas element will be created. Used in ClojureScript.


remove most protocol extensions to nil, just handle directly

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -514,8 +514,11 @@
   structures define -equiv (and thus =) as a value, not an identity,
   comparison."
   ([x] true)
-  ([x y] (or (identical? x y)
-             ^boolean (-equiv x y)))
+  ([x y]
+    (if (nil? x)
+      (nil? y)
+      (or (identical? x y)
+        ^boolean (-equiv x y))))
   ([x y & more]
      (if (= x y)
        (if (next more)
@@ -527,40 +530,8 @@
 (declare hash-map list equiv-sequential)

 (extend-type nil
-  IEquiv
-  (-equiv [_ o] (nil? o))
-
   ICounted
-  (-count [_] 0)
-
-  IEmptyableCollection
-  (-empty [_] nil)
-
-  INext
-  (-next [_] nil)
-
-  IMap
-  (-dissoc [_ k] nil)
-
-  ISet
-  (-disjoin [_ v] nil)
-
-  IStack
-  (-peek [_] nil)
-  (-pop [_] nil)
-
-  IMeta
-  (-meta [_] nil)
-
-  IWithMeta
-  (-with-meta [_ meta] nil)
-
-  IKVReduce
-  (-kv-reduce [_ f init]
-    init)
-
-  IHash
-  (-hash [o] 0))
+  (-count [_] 0))

 ;; TODO: we should remove this and handle date equality checking
 ;; by some other means, probably by adding a new primitive type
@@ -852,7 +823,8 @@
 (defn empty
   "Returns an empty collection of the same category as coll, or nil"
   [coll]
-  (-empty coll))
+  (when-not (nil? coll)
+    (-empty coll)))

 (defn- accumulating-seq-count [coll]
   (loop [s (seq coll) acc 0]
@@ -1022,10 +994,11 @@
   ([coll k]
      (-dissoc coll k))
   ([coll k & ks]
-     (let [ret (dissoc coll k)]
-       (if ks
-         (recur ret (first ks) (next ks))
-         ret))))
+    (when-not (nil? coll)
+      (let [ret (dissoc coll k)]
+        (if ks
+          (recur ret (first ks) (next ks))
+          ret)))))

 (defn ^boolean fn? [f]
   (or ^boolean (goog/isFunction f) (satisfies? Fn f)))
@@ -1042,26 +1015,30 @@
         (-invoke [_ & args]
           (apply o args)))
       meta)
-    (-with-meta o meta)))
+    (when-not (nil? o)
+      (-with-meta o meta))))

 (defn meta
   "Returns the metadata of obj, returns nil if there is no metadata."
   [o]
-  (when (satisfies? IMeta o)
+  (when (and (not (nil? o))
+             (satisfies? IMeta o))
     (-meta o)))

 (defn peek
   "For a list or queue, same as first, for a vector, same as, but much
   more efficient than, last. If the collection is empty, returns nil."
   [coll]
-  (-peek coll))
+  (when-not (nil? coll)
+    (-peek coll)))

 (defn pop
   "For a list or queue, returns a new list/queue without the first
   item, for a vector, returns a new vector without the last item.
   Note - not the same as next/butlast."
   [coll]
-  (-pop coll))
+  (when-not (nil? coll)
+    (-pop coll)))

 (defn disj
   "disj[oin]. Returns a new set of the same (hashed/sorted) type, that
@@ -1070,10 +1047,11 @@
   ([coll k]
      (-disjoin coll k))
   ([coll k & ks]
-     (let [ret (disj coll k)]
-       (if ks
-         (recur ret (first ks) (next ks))
-         ret))))
+    (when-not (nil? coll)
+      (let [ret (disj coll k)]
+        (if ks
+          (recur ret (first ks) (next ks))
+          ret)))))

 ;; Simple caching of string hashcode
 (def string-hash-cache (js-obj))
@@ -1108,6 +1086,8 @@

     (string? o)
     (check-string-hash-cache o)
+
+    (nil? o) 0

     :else
     (-hash o)))
@@ -1420,7 +1400,9 @@
   and f is not called. Note that reduce-kv is supported on vectors,
   where the keys will be the ordinals."
   ([f init coll]
-     (-kv-reduce coll f init)))
+    (if-not (nil? coll)
+      (-kv-reduce coll f init)
+      init)))

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


Use the correct title for the jar versions page

A typo in f89ec309e8d766203108973fbfa3179230dc604c caused the currently
logged in account name to be used as the title for the versions page,
and caused the current account to be displayed at the top of the page.

Thanks to @peeja for the report.

--- src/clojars/web/jar.clj
+++ src/clojars/web/jar.clj
@@ -168,7 +168,7 @@
                 ]])))

 (defn show-versions [account jar versions]
-  (html-doc account (str "all versions of "(jar-name jar)) {:account account}
+  (html-doc (str "all versions of "(jar-name jar)) {:account account}
             [:div.light-article
              [:h1 "all versions of "(jar-link jar)]
              [:div.versions


Fix lower and upper bounds for the sensor.

--- src/kixi/hecuba/data/misc.clj
+++ src/kixi/hecuba/data/misc.clj
@@ -198,11 +198,11 @@
   (db/with-session [session (:hecuba-session store)]
     (let [start      (tc/to-date min-date)
           end        (tc/to-date max-date)
-          new-bounds (update-bounds start end sensor)
           where      (where-from sensor)
           s          (first (db/execute session
                                         (hayt/select :sensor_metadata
-                                                     (hayt/where where))))]
+                                                     (hayt/where where))))
+          new-bounds (update-bounds start end s)]
       (when-let [columns (columns-to-update? s start end new-bounds)]
         (db/execute session
                     (hayt/update :sensor_metadata


Add :use-debug-keystore? flag to simplify testing release builds

--- src/leiningen/droid/build.clj
+++ src/leiningen/droid/build.clj
@@ -227,24 +227,24 @@
   Either a debug keystore key or a release key is used based on
   whether the build type is the debug one. Creates a debug keystore if
   it is missing."
-  [{{:keys [out-apk-path sigalg
+  [{{:keys [out-apk-path sigalg use-debug-keystore?
             keystore-path key-alias keypass storepass]} :android :as project}]
   (info "Signing APK with" keystore-path "...")
-  (let [dev-build (dev-build? project)
+  (let [debug (or (dev-build? project) use-debug-keystore?)
         unaligned-path (append-suffix out-apk-path "unaligned")
         sigalg (or sigalg "SHA1withRSA")]
-    (when (and dev-build (not (.exists (io/file keystore-path))))
+    (when (and debug (not (.exists (io/file keystore-path))))
       ;; Create a debug keystore if there isn't one
       (create-debug-keystore keystore-path))
     (ensure-paths unaligned-path keystore-path)
-    (let [storepass     (or (when dev-build "android")
-                            storepass
-                            (System/getenv "STOREPASS")
-                            (read-password "Enter storepass: "))
-          keypass       (or (when dev-build "android")
-                            keypass
-                            (System/getenv "KEYPASS")
-                            (read-password "Enter keypass: "))]
+    (let [storepass (or (when debug "android")
+                        storepass
+                        (System/getenv "STOREPASS")
+                        (read-password "Enter storepass: "))
+          keypass   (or (when debug "android")
+                        keypass
+                        (System/getenv "KEYPASS")
+                        (read-password "Enter keypass: "))]
       (sh "jarsigner"
           "-sigalg" sigalg
           "-digestalg" "SHA1"


Adding version parsing function and commandline flag.

--- src/leiningen/git_version.clj
+++ src/leiningen/git_version.clj
@@ -27,6 +27,16 @@
   (let [{:keys [ctime sha]} gver]
     (str "-" (formatted-timestamp fmt ctime) "-" sha)))

+(defn ver-parse
+  "Parses jar-path-like-string or versioned-artifact-string to find ctime and sha.
+   Can handle cases in the range of:
+     foo-1.2.3-20120219223112-abc123f
+     /path/to/foo-1.2.3-20120219223112-abc123f19ea8d29b13.jar"
+  [ver-str]
+  (let [[_ ctime sha] (re-matches #".*-([0-9]{14})-([a-f0-9]{5,40})(?:\.jar)?$" ver-str)]
+    (when (and ctime sha)
+      {:ctime ctime :sha sha})))
+
 (defn git-version
   [project & args]
   (let [[kstrs sargs] (split-with #(.startsWith % ":") args)
@@ -41,6 +51,7 @@
     ;; TODO throw exception if dirty
     ;; TODO throw exception if upstream doesn't contain this commit
     ;; args :insanely-allow-dirty-working-copy :no-upstream :print :long-sha
-    (if (some #{:print} kargs)
-      (println (upfn (:version project)))
-      (lmain/resolve-and-apply nnproj sargs))))
+    (cond
+     (some #{:print} kargs) (println (upfn (:version project)))
+     (some #{:parse} kargs) (prn (ver-parse (first sargs)))
+     :else (lmain/resolve-and-apply nnproj sargs))))


Fix handlers tests.

Fix handlers tests.

--- test/catacumba/handlers_tests.clj
+++ test/catacumba/handlers_tests.clj
@@ -28,7 +28,7 @@
   (testing "Explicit body parsing with multipart request with multiple files."
     (let [p (promise)
           handler (fn [context]
-                    (let [form (ct/parse-formdata context)]
+                    (let [form (ct/get-formdata context)]
                       (deliver p form)
                       "hello world"))]
       (with-server {:handler handler}
@@ -53,7 +53,7 @@
     (let [p (promise)
           app (ct/routes [[:any (hs/body-params)]
                           [:any #(do
-                                   (deliver p (:body %))
+                                   (deliver p (:data %))
                                    "hello world")]])]
       (with-server {:handler app}
         (let [response (client/post base-url {:form-params {:foo "bar"}})]
@@ -63,7 +63,7 @@
     (let [p (promise)
           app (ct/routes [[:any (hs/body-params)]
                           [:any #(do
-                                   (deliver p (:body %))
+                                   (deliver p (:data %))
                                    "hello world")]])]
       (with-server {:handler app}
         (let [response (client/post base-url {:body (json/generate-string {:foo "bar"})
@@ -165,15 +165,22 @@
   (testing "Simple cors request"
     (let [p (promise)
           handler (fn [ctx] (deliver p ctx) "hello world")
-          handler (ct/routes [[:any hs/basic-request]
-                              [:any handler]])]
+          handler (ct/routes [[:any handler]])]
       (with-server {:handler handler}
         (let [response (client/get (str base-url "/foo"))
               ctx (deref p 1000 {})]
+          (is (contains? ctx :body))
+          (is (contains? ctx :query))
+          (is (contains? ctx :query-params))
+          (is (contains? ctx :route-params))
+          (is (contains? ctx :headers))
+          (is (contains? ctx :cookies))
+          (is (contains? ctx :path))
+          (is (contains? ctx :catacumba/request))
+          (is (contains? ctx :catacumba/context))
+          (is (contains? ctx :catacumba/response))
           (is (= (:body response) "hello world"))
-          (is (= (:status response) 200))
-          (is (= (:method ctx) :get))
-          (is (= (:path ctx) "/foo")))))))
+          (is (= (:status response) 200)))))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Session tests
@@ -233,32 +240,25 @@

 (deftest interceptors-tests
   (let [counter (atom 0)
-        p1 (promise)
-        p2 (promise)
-        p3 (promise)
-        p4 (promise)]
+        p1 (promise)]
     (letfn [(interceptor [_ type continuation]
-              (deliver p1 (swap! counter inc))
+              ;; (println "interceptor:init", type)
+              (swap! counter inc)
               (continuation)
-              (deliver p2 (swap! counter inc)))
-
+              (swap! counter inc))
             (handler2 [context]
-              (deliver p3 (swap! counter inc))
               (ct/delegate context))
-
             (handler3 [context]
-              (deliver p4 (swap! counter inc))
+              (deliver p1 nil)
               "hello world")]
       (with-server {:handler (ct/routes [[:interceptor interceptor]
                                          [:any handler2]
                                          [:any handler3]])}
         (let [response (client/get base-url)]
+          (is (nil? (deref p1 1000 nil)))
           (is (= (:body response) "hello world"))
           (is (= (:status response) 200))
-          (is (= (deref p1 1000 nil) 1))
-          (is (= (deref p2 1000 nil) 4))
-          (is (= (deref p3 1000 nil) 2))
-          (is (= (deref p4 1000 nil) 3)))))))
+          (is (= @counter 6)))))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


don't write swank logs on a bogus "nul" file, but rather /dev/null

--- src/main/clojure/alfresco.clj
+++ src/main/clojure/alfresco.clj
@@ -2,4 +2,4 @@

 (defn start-swank []
   (clojure.main/with-bindings
-    (swank.swank/start-server "nul" :encoding "utf-8" :port 4005)))
+    (swank.swank/start-server "/dev/null" :encoding "utf-8" :port 4005)))


Use env.

Use env.

--- test/onyx/peer/min_peers_test.clj
+++ test/onyx/peer/min_peers_test.clj
@@ -12,8 +12,7 @@

 (def env-config (assoc (:env-config config) :onyx/id id))

-(def peer-config (assoc (:peer-config config) :onyx/id id
-                        :onyx.messaging/impl :core.async))
+(def peer-config (assoc (:peer-config config) :onyx/id id))

 (def env (onyx.api/start-env env-config))


Fix atom log initialisation

Fix atom log initialisation

--- test/onyx/task_lifecycle_test.clj
+++ test/onyx/task_lifecycle_test.clj
@@ -8,7 +8,7 @@
                :onyx.core/id :peer-id-1
                :onyx.core/task-id :task-id-1
                :onyx.core/replica (atom {:task-slot-ids {:job-1 {:task-id-1 {:peer-id-1 :slot-0}}}})
-               :onyx.core/test-entries-log {:slot-0 (atom [])}}
+               :onyx.core/test-entries-log (atom {:slot-0 (atom [])})}
         log (state-extensions/initialise-log :atom event)]
     (is (= @log []))))


Tidy up compojure.route ns declaration

Tidy up compojure.route ns declaration

--- src/compojure/route.clj
+++ src/compojure/route.clj
@@ -1,11 +1,10 @@
 (ns compojure.route
   "Route functions that define common behavior."
   (:require [compojure.response :as response])
-  (:use compojure.core
-        [ring.util.response :only (file-response resource-response status)]
-        [ring.util.codec :only (url-decode)]
-        ring.middleware.content-type
-        ring.middleware.head))
+  (:use [compojure.core :only [GET]]
+        [ring.util.response :only [file-response resource-response status]]
+        [ring.middleware.content-type :only [wrap-content-type]]
+        [ring.middleware.head :only [wrap-head]]))

 (defn- add-wildcard
   "Add a wildcard to the end of a route path."


removed redundancy codes.

removed redundancy codes.

--- clojure/abcdefghppp.clj
+++ clojure/abcdefghppp.clj
@@ -1,28 +1,23 @@
 ; http://m2.hkgolden.com/view.aspx?message=6307521&type=SW&page=1
 ; binc

-(require 'clojure.set)
-
 (defn make-seq []
-  (map read-string
-       (for [x (range 10)
-             y (range 10)
-             :when (and (not= x y) (not= x 0))]
-         (apply str [x y]))))
+  (for [x (range 10)
+        y (range 10)
+        :when (and (not= x y) (not= x 0))]
+    (+ (* 10 x) y)))

 (defn test-form []
-  (let [mq (make-seq)
-        v2s (fn [v] (reduce #(clojure.set/union %1 (set (str %2))) #{} v))]
-    (->>
-     (for [ab mq
-           cd mq
-           gh mq
-           :let [ef (- ab cd)
-                 ppp (+ ef gh)]
-           :when (and (= 1 (count (set (str ppp))))
-                      (> ppp 99))]
-       [ab cd ef gh ppp])
-     (filter #(= 9 (count (v2s %)))))))
+  (let [mq (make-seq)]
+    (for [ab mq
+          cd mq
+          gh mq
+          :let [ef (- ab cd)
+                ppp (+ ef gh)
+                form [ab cd ef gh ppp]]
+          :when (and (= ppp 111)
+                     (= 9 (->> form (apply str) set count)))]
+      form)))

 (prn (test-form))