updating project.clj

updating project.clj

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/meltwater/dropwizard-logstash-encoder.git/'


Release 0.8.4.

Release 0.8.4.

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject clojars-web "0.8.4-SNAPSHOT"
+(defproject clojars-web "0.8.4"
   :dependencies [[org.clojure/clojure "1.4.0"]
                  [org.clojure/tools.cli "0.2.1"]
                  [org.apache.maven/maven-model "3.0.4"


Version 1.10.3-SNAPSHOT

Version 1.10.3-SNAPSHOT

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/starcity-properties/odin.git/'


bump version to 2.7.0

bump version to 2.7.0

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/B2W-Digital/pdg-core.git/'


Include org.immutant/core, the minimal dependency.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/ballot-notification-works.git/'


Update core.clj

Update core.clj

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/colophon/clarango.git/'


Add basic unit tests for Go.cd sync

Add basic unit tests for Go.cd sync

error: pathspec 'test/buildviz/go/sync_jobs_test.clj' did not match any file(s) known to git

--- test/buildviz/go/sync_jobs_test.clj
+++ test/buildviz/go/sync_jobs_test.clj
@@ -0,0 +1,129 @@
+(ns buildviz.go.sync-jobs-test
+  (:require [buildviz.go.sync-jobs :as sut]
+            [buildviz.util.url :as url]
+            [cheshire.core :as j]
+            [clj-http.fake :as fake]
+            [clj-time.core :as t]
+            [clojure.string :as str]
+            [clojure.test :refer :all]))
+
+(defn- successful-json-response [body]
+  (fn [_] {:status 200
+           :body (j/generate-string body)}))
+
+(defn- successful-response [body]
+  (fn [_] {:status 200
+           :body body}))
+
+(defn- a-stage [name]
+  {:name name})
+
+(defn- a-pipeline [name & stages]
+  {:name name
+   :stages stages})
+
+(defn- a-pipeline-group [name & pipelines]
+  {:name name
+   :pipelines pipelines})
+
+(defn- a-config [& pipeline-groups]
+  [["http://gocd:8513/api/config/pipeline_groups"
+    (successful-json-response pipeline-groups)]])
+
+(defn- a-job-run [name scheduled-date]
+  {:name name
+   :scheduled_date scheduled-date})
+
+(defn- a-stage-run [pipeline-run stage-run result & jobs]
+  {:pipeline_counter pipeline-run
+   :counter stage-run
+   :result result
+   :jobs jobs})
+
+(defn- a-short-history [pipeline-name stage-name & stage-runs]
+  [[(format "http://gocd:8513/api/stages/%s/%s/history/0" pipeline-name stage-name)
+    (successful-json-response {:stages stage-runs})]
+   [(format "http://gocd:8513/api/stages/%s/%s/history/%s" pipeline-name stage-name (count stage-runs))
+    (successful-json-response {:stages '()})]])
+
+(defn- a-material-revision [revision id]
+  {:modifications [{:revision revision}]
+   :material {:id id}})
+
+(defn- a-pipeline-run [pipeline-name pipeline-run & revisions]
+  [[(format "http://gocd:8513/api/pipelines/%s/instance/%s" pipeline-name pipeline-run)
+    (successful-json-response {:build_cause {:material_revisions revisions}})]])
+
+(defn- build-properties [pipeline-name pipeline-run stage-name stage-run build-name
+                         {:keys [start-time end-time actual-stage-run outcome]}]
+  (str/join "\n" (list "cruise_agent,cruise_job_duration,cruise_job_id,cruise_job_result,cruise_pipeline_counter,cruise_pipeline_label,cruise_stage_counter,cruise_timestamp_01_scheduled,cruise_timestamp_02_assigned,cruise_timestamp_03_preparing,cruise_timestamp_04_building,cruise_timestamp_05_completing,cruise_timestamp_06_completed"
+                       (format "dont_care,dont_care,dont_care,%s,dont_care,dont_care,%s,dont_care,dont_care,dont_care,%s,dont_care,%s" outcome actual-stage-run start-time end-time))))
+
+(defn- a-builds-properties [pipeline-name pipeline-run stage-name stage-run
+                            build-name content]
+  [[(format "http://gocd:8513/properties/%s/%s/%s/%s/%s"
+            pipeline-name pipeline-run stage-name stage-run build-name)
+    (successful-response (build-properties pipeline-name pipeline-run
+                                           stage-name stage-run build-name
+                                           content))]])
+
+(defn- a-file-list [pipeline-name pipeline-run stage-name stage-run build-name & files]
+  [[(format "http://gocd:8513/files/%s/%s/%s/%s/%s.json" pipeline-name pipeline-run stage-name stage-run build-name)
+    (successful-json-response [{:name "a_folder"
+                                :files files}])]])
+
+(defn- provide-buildviz-and-capture-puts [map-ref]
+  [[#"http://buildviz:8010/builds/(.+)/(.+)"
+    (fn [req]
+      (swap! map-ref #(conj % [(:uri req)
+                               (j/parse-string (slurp (:body req)) true)]))
+      {:status 200 :body ""})]])
+
+(defn- serve-up [& routes]
+  (->> routes
+       (mapcat identity)
+       (into {})))
+
+(def beginning-of-2016 (t/date-midnight 2016))
+
+
+(deftest test-sync-jobs
+  (testing "should handle no pipeline groups"
+    (fake/with-fake-routes-in-isolation (serve-up (a-config))
+      (with-out-str (sut/sync-stages (url/url "http://gocd:8513") (url/url "http://buildviz:8010") beginning-of-2016 nil nil))))
+
+  (testing "should handle empty pipeline group"
+    (fake/with-fake-routes-in-isolation (serve-up (a-config (a-pipeline-group "Development")))
+      (with-out-str (sut/sync-stages (url/url "http://gocd:8513") (url/url "http://buildviz:8010") beginning-of-2016 nil nil))))
+
+  (testing "should handle empty pipeline"
+    (fake/with-fake-routes-in-isolation (serve-up (a-config (a-pipeline-group "Development"
+                                                                              (a-pipeline "Build"))))
+      (with-out-str (sut/sync-stages (url/url "http://gocd:8513") (url/url "http://buildviz:8010") beginning-of-2016 nil nil))))
+
+  (testing "should sync a stage"
+    (let [store (atom [])]
+      (fake/with-fake-routes-in-isolation
+        (serve-up (a-config (a-pipeline-group "Development"
+                                              (a-pipeline "Build"
+                                                          (a-stage "DoStuff"))))
+                  (a-short-history "Build" "DoStuff"
+                                   (a-stage-run 42 "1" "Passed"
+                                                (a-job-run "AlphaJob" 1493201298062)))
+                  (a-pipeline-run "Build" 42
+                                  (a-material-revision "AnotherPipeline/21" 7))
+                  (a-builds-properties "Build" 42 "DoStuff" "1" "AlphaJob"
+                                       {:start-time (t/date-time 2017 1 1 10 0 0)
+                                        :end-time (t/date-time 2017 1 1 12 0)
+                                        :outcome "Passed"
+                                        :actual-stage-run "1"})
+                  (a-file-list "Build" 42 "DoStuff" "1" "AlphaJob")
+                  (provide-buildviz-and-capture-puts store))
+        (with-out-str (sut/sync-stages (url/url "http://gocd:8513")
+                                       (url/url "http://buildviz:8010")
+                                       beginning-of-2016 nil nil)))
+      (is (= [["/builds/Build%20DoStuff/42%201" {:start 1483264800000
+                                                 :end 1483272000000
+                                                 :outcome "pass"
+                                                 :inputs [{:revision "AnotherPipeline/21", :sourceId 7}]}]]
+             @store)))))


Convert partners-service-test to response-for

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/turbovote-http-api.git/'


assoc :rethunked? if not already there

assoc :rethunked? if not already there

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/michaelsbradleyjr/transwarp.git/'


Better error message when query can't be parsed.

--- src/clojars/web/search.clj
+++ src/clojars/web/search.clj
@@ -29,21 +29,24 @@
   (html-doc account (str (h query) " - search")
     [:h1 "Search for " (h query)]
     [:ul
-     (let [results (search/search query)]
-       (if (empty? results)
-         [:p "No results."]
-         (for [jar results
-               ;; bc too lazy to see why blank entries are showing up
-               :when (not (nil? (:artifact-id jar)))]
-           [:li.search-results
-            (jar-link {:jar_name (:artifact-id jar)
-                       :group_name (:group-id jar)}) " " (h (:version jar))
-            [:br]
-            (when (seq (:description jar))
-              [:span.desc (h (:description jar))
-               [:br]])
-            [:span.details (if-let [created (:created jar)]
-                             [:td (format-date created)])]])))]))
+     (try
+       (let [results (search/search query)]
+         (if (empty? results)
+           [:p "No results."]
+           (for [jar results
+                 ;; bc too lazy to see why blank entries are showing up
+                 :when (not (nil? (:artifact-id jar)))]
+             [:li.search-results
+              (jar-link {:jar_name (:artifact-id jar)
+                         :group_name (:group-id jar)}) " " (h (:version jar))
+              [:br]
+              (when (seq (:description jar))
+                [:span.desc (h (:description jar))
+                 [:br]])
+              [:span.details (if-let [created (:created jar)]
+                               [:td (format-date created)])]])))
+       (catch Exception _
+         [:p "Could not search; please check your query syntax."]))]))

 (defn search [account params]
   (let [q (params :q)]


chapter 16 examples

chapter 16 examples

error: pathspec 'pcl/chap_16/chap_16.clj' did not match any file(s) known to git

--- pcl/chap_16/chap_16.clj
+++ pcl/chap_16/chap_16.clj
@@ -0,0 +1,36 @@
+(ns pcl.chap_16
+    (refer-clojure))
+
+; multimethods
+(defmulti draw :shape)
+(defmethod draw :square [shape] "TBD: draw a sqaure")
+(defmethod draw :circle [shape] "TBD: draw a circle")
+
+; using multimethods
+(defn raw-withdraw [account amount]
+  (when (< (:balance account) amount)
+    (throw (IllegalArgumentException. "Account overdrawn")))
+  (assoc account :balance (- (:balance account) amount)))
+
+(defmulti withdraw :account-type)
+
+(defmethod withdraw :bank [account amount]
+  (raw-withdraw account amount))
+
+; note the implicit deposit: problem?
+(defmethod withdraw :checking [account amount]
+  (let [overdraft
+	(- amount (:balance account))
+	safe-account
+	(if (> overdraft 0)
+	  (merge account
+		 {:overdraft-account (withdraw (account :overdraft-account) overdraft)
+		  :balance amount})
+	  account)]
+    (raw-withdraw safe-account amount)))
+
+; dispatching on more than one argument
+(defmulti beat (fn [d s] [(:drum d)(:stick s)]))
+(defmethod beat [:snare-drum :brush] [drum stick] "snare drum and brush")
+(defmethod beat [:snare-drum :soft-mallet] [drum stick] "snare drum and soft mallet")
+(defmethod beat :default [drum stick] "default value, if you want one")


Split function.

Split function.

--- src/re_frame/handlers.cljs
+++ src/re_frame/handlers.cljs
@@ -31,23 +31,25 @@
 ;; Moves events from "dispatch" to the router loop.
 ;; Allows for the aysnc handling of events.
 ;;
-(def ^:private event-chan (chan))    ;; TODO: how big should we make the buffer?
+(def ^:private event-chan (chan))    ;; TODO: set buffer size?

 ;; -- lookup and call -----------------------------------------------------------------------------
+(defn lookup-handler
+  [event-id]
+  (get @id->fn event-id))

-(defn- handle
+(defn handle
   "Given an event vector, look up the right handler, then call it.
   By default, handlers are not assumed to be pure. They are called with
   two paramters:
   - the `app-db` atom and
   - the event vector
   The handler is assumed to side-effect on the atom, the return value is ignored.
-   To write handlers that are pure functions, use the \"pure\" middleware at handler
-   registration time."
+  To write pure handlers, use the \"pure\" middleware when registering the handler."
   [event-v]
   (let [event-id    (first-in-vector event-v)
-        handler-fn  (get @id->fn event-id)]
+        handler-fn  (lookup-handler event-id)]
     (if (nil? handler-fn)
       (warn "re-frame: no event handler registered for: \"" event-id "\". Ignoring.")   ;; TODO: make exception
       (handler-fn app-db event-v))))
@@ -80,9 +82,11 @@
 ;; -- dispatch ------------------------------------------------------------------------------------

 (defn dispatch
-  "reagent components use this function to send events.
+  "Send an event to be processed by the registered handler.
+
   Usage example:
-     (dispatch [:delete-item 42])"
+     (dispatch [:delete-item 42])
+  "
   [event-v]
   (if (nil? event-v)
     (warn "re-frame: \"dispatch\" is ignoring a nil event.")     ;; nil would close the channel


add arguments and docs to graph methods

add arguments and docs to graph methods


Fix: respond in status code >= 400

Fix: respond in status code >= 400

Signed-off-by: selmeci <bb938fc7591901d0e874df22e3ae174886bcb931@infones.com>

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/infones/http-kit.git/'


Indexa kendu.

Indexa kendu.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/lnmnd/magnet.zer.git/'


Add upload-complete link to schema

Add upload-complete link to schema

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/physion/ovation-webapi.git/'


add clojure based scraper

add clojure based scraper

error: pathspec 'src/thinking/scraper.clj' did not match any file(s) known to git

--- src/thinking/scraper.clj
+++ src/thinking/scraper.clj
@@ -0,0 +1,21 @@
+(ns scraper
+  (:require [net.cgrand.enlive-html :as html]))
+
+(def ^:dynamic *base-url* "http://www.public-domain-poetry.com/a-h-laidlaw/printpoem/weep-not-for-him-22324")
+
+(defn fetch-url [url]
+  (html/html-resource (java.net.URL. url)))
+
+(defn title []
+  (map html/text (html/select (fetch-url *base-url*) [:font.t0])))
+
+(defn author []
+  (map html/text (html/select (fetch-url *base-url*) [:font.t1 :a])))
+
+(defn poem []
+  (map html/text (html/select (fetch-url *base-url*) [:font.t3a])))
+
+
+(title)
+(author)
+(poem)


lint free

lint free

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/CraZySacX/wgetjava.git/'


tweaks to default lein profile

tweaks to default lein profile

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/sw1nn/dotfiles.git/'


remove pprint

remove pprint


Serve favicons

Serve favicons

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/zk/rx.git/'


Fixing twitter

Fixing twitter

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/just-cloud/uxtweet-client.git/'


Ensure phase param to buf-rd is audio rate

--- src/overtone/sc/machinery/ugen/metadata/buf_io.clj
+++ src/overtone/sc/machinery/ugen/metadata/buf_io.clj
@@ -53,6 +53,7 @@
                :default 2
                :doc "1 means no interpolation, 2 is linear, 4 is cubic interpolation"}]
        :summary "Read the contents of a buffer at a specified index"
+       :check (when-ar (nth-input-ar 2))
        :doc "reads the contents of a buffer at a given index."}

       {:name "BufWr",


Added empty dispatcher

Added empty dispatcher

error: pathspec 'src/cljs/funnel_front/dispatcher/app_dispatcher.cljs' did not match any file(s) known to git

--- src/cljs/funnel_front/dispatcher/app_dispatcher.cljs
+++ src/cljs/funnel_front/dispatcher/app_dispatcher.cljs
@@ -0,0 +1 @@
+(ns funnel-front.dispatcher.app-dispatcher)


Add publish logging

Add publish logging

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Yleisradio/rabid.git/'


Add election-id search test

Add election-id search test

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/electorate-works.git/'


Delay queue construction so compiler doesn't look silly.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/couragelabs/coachbot.git/'


bump to 3.1.0

bump to 3.1.0

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/B2W-BIT/restQL-server.git/'


lein 2

lein 2

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/mprencipe/tarjoushaukka.git/'


Upgrade schema to latest version

Upgrade schema to latest version

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/election-authority-works.git/'


chore(dependencies) Update Cheshire version to v5.8.1

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/B2W-Digital/pdg-core.git/'


Update dependencies

Update dependencies

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/scheduled-message-works.git/'


Update dependencies.

Update dependencies.

--- project.clj
+++ project.clj
@@ -6,16 +6,16 @@
   :lein-release {:deploy-via :clojars}
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}
-  :dependencies [[com.facebook/react "0.9.0"]
+  :dependencies [[com.facebook/react "0.9.0.1"]
                  [org.clojure/clojure "1.5.1"]
-                 [org.clojure/clojurescript "0.0-2173"]]
+                 [org.clojure/clojurescript "0.0-2197"]]
   :cljsbuild {:builds []}
   :profiles {:dev {:dependencies [[reagent "0.4.2"]
                                   [crate "0.2.5"]
                                   [prismatic/dommy "0.1.2"]]
                    :plugins [[com.keminglabs/cljx "0.3.2"] ;; Must be before Austin: https://github.com/cemerick/austin/issues/37
                              [com.cemerick/austin "0.1.4"]
-                             [com.cemerick/clojurescript.test "0.2.2"]
+                             [com.cemerick/clojurescript.test "0.3.0"]
                              [lein-cljsbuild "1.0.2"]]
                    :hooks [cljx.hooks leiningen.cljsbuild]
                    :cljx {:builds [{:source-paths ["src"]


add project.clj

add project.clj

error: pathspec 'project.clj' did not match any file(s) known to git

--- project.clj
+++ project.clj
@@ -0,0 +1,6 @@
+(defproject tabledoc "0.1.0"
+  :description "Oracle Schema documentation generator."
+  :license {:name "The MIT License (MIT)"
+            :url "http://opensource.org/licenses/MIT"}
+  :dependencies [[org.clojure/clojure "1.5.1"]
+                 ])


initially created project.clj

initially created project.clj

--- project.clj
+++ project.clj
@@ -0,0 +1,27 @@
+(defproject org.domaindrivenarchitecture/dda-managed-ide "0.1.0-SNAPSHOT"
+  :description "module to install and configure ide based on ubuntu vm."
+  :url "https://www.domaindrivenarchitecture.org"
+  :pallet {:source-paths ["src"]}
+  :license {:name "Apache License, Version 2.0"
+            :url "https://www.apache.org/licenses/LICENSE-2.0.html"}
+  :dependencies [[org.clojure/clojure "1.7.0"]
+                 [com.palletops/pallet "0.8.12"]
+                 [com.palletops/stevedore "0.8.0-beta.7"]
+                 [org.domaindrivenarchitecture/dda-pallet-commons "0.2.0"]]
+  :profiles {:dev
+             {:dependencies
+              [[com.palletops/pallet "0.8.12" :classifier "tests"]
+               [org.domaindrivenarchitecture/dda-pallet-commons "0.2.0" :classifier "tests"]]
+              :plugins
+              [[com.palletops/pallet-lein "0.8.0-alpha.1"]
+               [lein-sub "0.3.0"]]}
+              :leiningen/reply
+               {:dependencies [[org.slf4j/jcl-over-slf4j "1.7.21"]]
+                :exclusions [commons-logging]}}
+   :local-repo-classpath true
+   :repositories [["snapshots" :clojars]
+                  ["releases" :clojars]]
+   :deploy-repositories [["snapshots" :clojars]
+                         ["releases" :clojars]]
+   :classifiers {:tests {:source-paths ^:replace ["test"]
+                         :resource-paths ^:replace []}})


Codox can now create nice docs

Codox can now create nice docs

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/colophon/clarango.git/'


[WM] update upstream deps again

[WM] update upstream deps again

...since it's been awhile since this PR went up.


update dependency postal

update dependency postal

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/vincentstorme/clojureme.git/'


Version 69

Version 69

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/tobias/clojars-web.git/'


update payment format

update payment format

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/mprokopov/privat24-manager.git/'


remove not used ns

remove not used ns

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/fhirbase/fhirterm.git/'


Intern /. to λ

Intern /. to λ

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/michaelsbradleyjr/shen.clj.git/'


[WM] add update & delete tests

[WM] add update & delete tests

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/user-http-api.git/'


Draft markdown resource

Draft markdown resource

error: pathspec 'dev/src/yada/dev/markdown_resource.clj' did not match any file(s) known to git

--- dev/src/yada/dev/markdown_resource.clj
+++ dev/src/yada/dev/markdown_resource.clj
@@ -0,0 +1,18 @@
+;; Copyright © 2015, JUXT LTD.
+
+(ns yada.dev.markdown-resource
+  (:require
+   [clj-time.core :refer [now]]
+   [schema.core :as s]
+   [yada.protocols :as p]))
+
+(s/defrecord MarkdownResource [content :- String]
+  p/ResourceProperties
+  (resource-properties
+   [_]
+   {:allowed-methods #{:get}
+    :representations [{:media-type #{"text/html"}}]
+    ::create-time (.getMillis (now))})
+  (resource-properties
+   [_ ctx]
+   {:last-modified (-> ctx :resource-properties ::create-time)}))


Add dash-astar, for w/pess version of prev.

error: pathspec 'src/angelic/search/implicit/dash_astar.clj' did not match any file(s) known to git

--- src/angelic/search/implicit/dash_astar.clj
+++ src/angelic/search/implicit/dash_astar.clj
@@ -0,0 +1,543 @@
+(ns angelic.search.implicit.dash-astar
+  (:require [edu.berkeley.ai.util :as util]
+            [edu.berkeley.ai.util.traits :as traits]
+            [angelic.env.state :as state]
+            [angelic.search.summary :as summary]
+            [angelic.search.summaries :as summaries]
+            [angelic.search.function-sets :as fs])
+  (:import [java.util HashMap ArrayList]))
+
+;; A revampting of dash_astar_opt, to move subsumption relationships and caching
+;; out into a separate class.  This is necessary to keep pessimistic and optimistic
+;; things in sync, and should help simplify and generalize subsumption stuff.
+
+;; All TODOs from dash_astar_opt also apply here.
+
+;; TODO: Split out SP "name" from stub
+;; TODO: SP has hash table from (state-abstracted context) input set to stub (?).
+;; TODO: stub has link back to parent SP
+;; TODO: How are subsumption links handled?
+;;
+
+(set! *warn-on-reflection* true)
+
+(def *left-recursive*        true) ;; Use left, not right recursion for seqs (((a . b) . c) . d)
+(def *collect-equal-outputs* true) ;; Collect identical output sets
+(def *decompose-cache*       true) ;; nil for none, or bind to hashmap
+(def *state-abstraction*     :eager ) ;; Or lazy or nil.
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;       Utilities      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;      Watches      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Stubs have at most one output (SP), SPs have any number
+
+(defprotocol Watched
+  (add-watcher! [s w] "Add a watcher to be notified of all outputs to this.
+                       A watcher is just a fn of new-subproblem.")
+  (add-output!  [sw o] "O is a subproblem.  sw may have an updated summary,
+                        but will not call summary-changed! on its parents.
+                        The receiver is responsible for handling this change.
+                        This allows handling decrease+increase in lock-step. ")
+  (get-outputs  [sw]  "List current outputs"))
+
+(def *out-count* (atom 1))
+
+(traits/deftrait watched-node
+  []
+  [^ArrayList watchers (ArrayList.)
+   ^ArrayList outputs (ArrayList.)]
+  [summaries/simple-cached-node]
+  Watched
+  (add-watcher! [sw w] #_(println :AW sw w)
+    (.add watchers w)
+    (doseq [o (doall (seq outputs))] (swap! *out-count* inc) (w o)) )
+  (add-output! [sw o] ;               (println :AO sw o) (Thread/sleep 10)
+    (.add outputs o)
+    (doseq [w (doall (seq watchers))] (swap! *out-count* inc) (w o)))
+  (get-outputs [sw] (doall (seq outputs))))
+
+(defn- connect-and-watch! [p c f]
+  (summaries/connect! p c false)
+  (add-watcher! c f))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;     Stubs     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defprotocol Stub
+  (stub-name   [s])
+  (input-set   [s]))
+
+(traits/deftrait simple-stub [name inp] [] [watched-node]
+  Stub (input-set [s] inp)
+       (stub-name [s] name))
+
+(defmethod print-method angelic.search.implicit.dash_astar.Stub [s o]
+  (print-method (format "#<ST$%8h %s>" (System/identityHashCode s) (stub-name s)) o))
+
+;; Stub must implement Summarizable, optionally implements Evaluable
+
+(defprotocol Evaluable (evaluate! [s]))
+(defn- can-evaluate? [s] (instance? angelic.search.implicit.dash_astar.Evaluable s))
+
+(defn- set-stub-output! [stub sp]
+  (assert (empty? (get-outputs stub)))
+  (summaries/summary-changed-local! stub)
+  (add-output! stub sp))
+
+
+(defn- get-stub-output  [s] (first (get-outputs s)))
+(defn- get-stub-output! [s] (util/safe-singleton (get-outputs s)))
+
+;; Just give output directly if subproblem is ready
+;; Return true if waiting
+(defn- connect-and-watch-stub! [p c f]
+  (assert (instance? angelic.search.implicit.dash_astar.Stub c))
+  (if-let [sp (get-stub-output c)]
+    (do (f sp) false)
+    (do (summaries/connect! p c false)
+        (add-watcher! c f)
+        true)))
+
+;; Used when p needs update if c does not produce immediate output.
+(defn- connect-and-watch-stub-up! [p c f]
+  (when (connect-and-watch-stub! p c f) (summaries/summary-changed! p)))
+
+(defn- make-wrapping-stub [[name in-set] inner-stub sp-fn]
+  (let [ret (traits/reify-traits [summaries/or-summarizable (simple-stub name in-set)])]
+    (connect-and-watch-stub! ret inner-stub #(set-stub-output! ret (sp-fn ret %)))
+    ret))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;     Subproblems     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defprotocol Subproblem
+  (stub              [s])
+  (output-set        [s])
+  (tree-summarizer   [s] "Summarizer that includes children.")
+  (terminal?         [s] "Subproblem will not return any outputs.")
+  (refine-input      [s refined-input-set] "Return a child stub."))
+
+(defn- subproblem-name [s] (stub-name (stub s)))
+
+(defmethod print-method angelic.search.implicit.dash_astar.Subproblem [sp o]
+  (print-method (format "#<SP$%8h %s>" (System/identityHashCode (stub sp)) (subproblem-name sp)) o))
+
+
+(defn- connect-subsuming! [child subsuming-sp]
+  (when subsuming-sp (summaries/connect! child (tree-summarizer subsuming-sp) true)))
+
+(defn- add-sp-child! [sp child-sp]
+  (assert (not (terminal? sp)))
+  (summaries/summary-changed-local! sp)
+  (add-output! sp child-sp))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Tree Summarizer  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+
+;; TODO: propagate top-down-bounds downward in smarter way using existing IS?
+;; TODO: we need to make sure tree sums get called on add-output! first to ensure
+;;       consistency with top-down-bounds ?
+;; TODO: top-down bound business does not actually help at all
+;;  (except ensuring consistency if we're asserting it...)
+
+(defprotocol TreeSummarizer
+  (top-down-bound    [s])
+  (add-top-down-bound! [s b]))
+
+(defn- tree-summarizer? [s] (instance? angelic.search.implicit.dash_astar.TreeSummarizer s))
+
+(defn- make-tree-summarizer [init-bound]
+ (let [tdb-atom (atom  init-bound)]
+   (traits/reify-traits [summaries/simple-cached-node]
+     TreeSummarizer (top-down-bound [s] @tdb-atom)
+                    (add-top-down-bound! [s b]
+                      (when (< b @tdb-atom) ;; ;; Note: adding < current max-reward actually hurts...
+                        (reset! tdb-atom b)
+                        (doseq [c (summaries/node-ordinary-children s)]
+                          (when (tree-summarizer? c)
+                            (add-top-down-bound! c b)))
+                        (summaries/summary-changed! s)))
+     summaries/Summarizable (summarize [s] (summaries/or-summary s  @tdb-atom)))))
+
+(defn- init-tree-summarizer! [ts inner-sp subsuming-sp]
+  (connect-and-watch! ts inner-sp
+    (fn [child-sp]
+      (summaries/connect! ts (tree-summarizer child-sp) false)
+      (add-top-down-bound! (tree-summarizer child-sp) (top-down-bound ts))
+      (summaries/summary-changed! ts))) ;; TODO: speedup by checking child reward?
+  (connect-subsuming! ts subsuming-sp))
+
+(defn- get-inner-sp [ts]
+  (->> (summaries/node-ordinary-children ts)
+       (remove tree-summarizer?)
+       util/safe-singleton))
+
+(defn- ts-str [sp])
+(defmethod print-method angelic.search.implicit.dash_astar.TreeSummarizer [ts o]
+  (let [stub (stub (get-inner-sp ts))]
+    (print-method (format "#<TS$%8h %s>" (System/identityHashCode stub) (stub-name stub)) o)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Subproblem Impl  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(traits/deftrait simple-subproblem [stb out-set ts term? ri-fn] [] [watched-node]
+  Subproblem (stub            [s] stb)
+             (output-set      [s] out-set)
+             (tree-summarizer [s] ts)
+             (terminal?       [s] term?)
+             (refine-input    [s ni] (ri-fn s ni)))
+
+
+(defn- make-simple-subproblem [stub subsuming-sp out-set terminal? summary-fn ri-fn init-bound]
+  (let [ts  (make-tree-summarizer init-bound)
+        ret (traits/reify-traits [(simple-subproblem stub out-set ts terminal? ;; Note ni may have different context.
+                                                     (fn [s ni] (if (= ni (input-set stub)) stub (ri-fn s ni))))]
+              summaries/Summarizable (summarize [s] (summary-fn s (top-down-bound ts))))]
+    (init-tree-summarizer! ts ret subsuming-sp)
+    ret))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;     Wrappers     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;     Output Collection     ;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(declare make-output-collecting-subproblem)
+(defn- make-output-collecting-stub [inner-stub]
+  (assert (not (= (first (stub-name inner-stub)) :OS)))
+  (assert (not (= (first (stub-name inner-stub)) :SA)))
+  (make-wrapping-stub
+   [[:OS (stub-name inner-stub)] (input-set inner-stub)]
+   inner-stub make-output-collecting-subproblem))
+
+
+(defn- =-state-sets [s1 s2]
+  (util/assert-is (= (state/current-context s1) (state/current-context s2)) "%s" [s1 s2])
+  (= s1 s2))
+
+(defn- make-output-collecting-subproblem [stb inner-sp]
+  (let [;        counter (HashMap.)
+        ts  (tree-summarizer inner-sp)
+        ret (traits/reify-traits
+             [(simple-subproblem stb (output-set inner-sp) ts false
+                                 #(doto (if (= (input-set stb) %2) stb (refine-input inner-sp %2)) ;Needed when SA off
+                                    (-> stub-name first #{:SA :OS} assert)))]
+             summaries/Summarizable (summarize [s] (summaries/or-summary s (top-down-bound ts))))]
+    (connect-and-watch! ret inner-sp
+      (fn child-watch [o]
+        (if (=-state-sets (output-set inner-sp) (output-set o))
+          (do (connect-and-watch! ret o child-watch)
+              (summaries/summary-changed! ret))
+          (do #_ (let [c (.get counter (input-set (stub o)))]
+                (when c (println c (stub-name (stub o))))
+                (.put counter (input-set (stub o)) (inc (or c 0))))
+
+              (if (#{:SA :OS} (first (subproblem-name o)))
+                (add-sp-child! ret o)
+                (connect-and-watch-stub! ret (make-output-collecting-stub (stub o)) #(add-sp-child! ret %))))))) ;; No update needed
+    ret))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;     State Abstraction     ;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(declare make-state-abstracted-subproblem)
+(defn- make-eager-state-abstracted-stub [inner-stub in-set]
+  (make-wrapping-stub [[:SA (stub-name inner-stub)] in-set] inner-stub make-state-abstracted-subproblem))
+
+
+(defn- make-deliberate-state-abstracted-stub [inner-stub in-set]
+  (if-let [out (get-stub-output inner-stub)]
+    (let [done? (atom false)
+          ret
+          (traits/reify-traits
+           [(simple-stub [:SA (stub-name inner-stub) in-set] in-set)]
+           summaries/Summarizable
+           (summarize [s]
+            (if @done? summary/+worst-simple-summary+
+                (summary/make-live-simple-summary
+                 (summary/max-reward (summaries/summary (tree-summarizer out))) s)))
+           Evaluable
+           (evaluate! [s] (reset! done? true)
+            (set-stub-output! s (make-state-abstracted-subproblem s out))))]
+      (summaries/connect! ret out false)
+      ret)
+    (make-eager-state-abstracted-stub inner-stub in-set)))
+
+
+(defn- make-state-abstracted-stub [inner-stub in-set]
+  ((case *state-abstraction*
+     :eager make-eager-state-abstracted-stub
+     :deliberate make-deliberate-state-abstracted-stub)
+   inner-stub in-set))
+
+
+;; Note: subsumed subproblems can have different irrelevant vars
+(defn- make-state-abstracted-subproblem [stb inner-sp]
+  (let [ts  (tree-summarizer inner-sp)
+        in  (input-set stb)
+        out (state/transfer-effects in (output-set inner-sp))
+        ri-fn #(if (=-state-sets %2 in) stb (refine-input inner-sp %2))
+        ret (traits/reify-traits
+             [summaries/or-summarizable (simple-subproblem stb out ts (terminal? inner-sp) ri-fn)])]
+    (connect-and-watch! ret inner-sp
+      (fn [o] (connect-and-watch-stub-up! ret (make-state-abstracted-stub (stub o) in) #(add-sp-child! ret %))))
+    ret))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;     Core Subproblems     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;      Atomic       ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(declare make-fs-seq-stub get-atomic-stub)
+
+(defn- make-atomic-subproblem [stub function-set subsuming-sp out-set reward status]
+  (let [inp-set  (input-set stub)
+        ri-fn    (fn [s ri] (get-atomic-stub s ri function-set))]
+    (cond (not (= status :live))
+          (make-simple-subproblem
+           stub subsuming-sp out-set true
+           (fn [s b] (summary/make-simple-summary (min b reward) status s)) ri-fn reward)
+
+          (and subsuming-sp (not (terminal? subsuming-sp)))
+          (let [ret (make-simple-subproblem stub subsuming-sp out-set false summaries/or-summary ri-fn reward)]
+            (connect-and-watch! ret subsuming-sp
+              (fn [sub-out]
+                (connect-and-watch-stub-up! ret (refine-input sub-out inp-set) #(add-sp-child! ret %))))
+            ret)
+
+          :else
+          (let [ret (make-simple-subproblem stub subsuming-sp out-set false summaries/or-summary ri-fn reward)]
+            (doseq [child (map #(make-fs-seq-stub inp-set %) (fs/child-seqs function-set inp-set))]
+              (connect-and-watch-stub! ret child #(add-sp-child! ret %)))
+            ret))))
+
+;; Note: this is double-stage to lazily generate children.  Could be simpler single-stage.
+(defn- make-atomic-stub [name subsuming-sp inp-set function-set]
+  (let [state (atom :ready) ;; set to [out-set reward] after first eval, then :go after second.
+        ret
+        (traits/reify-traits [(simple-stub name inp-set)]
+         summaries/Summarizable
+         (summarize [s]
+           (cond (= :ready @state) (summary/make-live-simple-summary (summaries/subsuming-bound s) s)
+                 (= :go    @state) summary/+worst-simple-summary+
+                 :else             (summary/make-live-simple-summary
+                                    (min (summaries/subsuming-bound s) (second @state)) s)))
+         Evaluable
+         (evaluate! [s]
+           (assert (not (= :go @state)))
+           (let [ready? (= :ready @state)]
+             (if-let [[out-set reward :as op] (if ready? (fs/apply-opt function-set inp-set) @state)]
+               (let [status (if ready? (fs/status function-set inp-set)   :live)]
+;                 (println "eval" s ready? status reward)
+                 (if (or (not ready?) (not (= status :live)))
+                   (do (reset! state :go)
+                       (->> (make-atomic-subproblem s function-set subsuming-sp out-set reward status)
+                            (set-stub-output! s)))
+                   (do (reset! state op) (summaries/summary-changed! s))))
+               (do (reset! state :go) (summaries/summary-changed! s))))))]
+    (connect-subsuming! ret subsuming-sp)
+    ret))
+
+;; Note: we must always wrap in S-A stub to get effects out of logger.
+(defn- get-atomic-stub [subsuming-sp inp-set function-set]
+  (let [full-name [:Atomic (fs/fs-name function-set)
+                   (if *state-abstraction* (fs/extract-context function-set inp-set) inp-set)]
+        make-stub #(let [r (make-atomic-stub [:Atomic (fs/fs-name function-set)] subsuming-sp % function-set)]
+                     (if *collect-equal-outputs* (make-output-collecting-stub r) r))]
+    (if-let [^HashMap dc *decompose-cache*]
+      (if *state-abstraction*
+        (let [stub (util/cache-with dc full-name (make-stub (fs/get-logger function-set inp-set)))]
+          (make-state-abstracted-stub stub inp-set))
+        (util/cache-with dc full-name (make-stub inp-set)))
+     (make-stub inp-set))))
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;   Sequences    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(declare make-pair-stub1 make-pair-stub2)
+
+;; NOTE: subsumption doesn't seem to help
+;; TODO: fix up subsuming, parent, etc.
+;; nils at bottom should chase subsuming-sp.
+;; Note: this is the only place logic depends on summary.  Potential for problems?
+(defn- make-pair-subproblem [subsuming-sp pair-stub left-sp right-sp]
+  (let [expand-right? (and (summary/solved? (summaries/summary left-sp)) (empty? (get-outputs left-sp)))
+        kids (if expand-right? [(tree-summarizer left-sp) right-sp] [left-sp (tree-summarizer right-sp)])
+        ss   (summaries/make-sum-summarizer kids)
+        ret (make-simple-subproblem
+             pair-stub subsuming-sp (output-set right-sp) false
+             (if (or expand-right? (not *collect-equal-outputs*)) summaries/or-summary
+                 (let [left-done? (atom false)] ;; Manually take into account left-solved, when no output message.
+                   (fn [s b]
+                     (when (and (not @left-done?) (summary/solved? (summaries/summary left-sp)))
+                       (reset! left-done? true)
+                       (summaries/disconnect! s ss)
+                        ;; Make sure we don't double count, because child will use tree-summarizer of left.
+                       (add-watcher! left-sp (fn [o] (def *sum* [s left-sp o])
+                                               (throw (RuntimeException. "Solved and children."))))
+                       (connect-and-watch-stub! s (make-pair-stub2 subsuming-sp left-sp (stub right-sp))
+                                           (fn [os] (connect-and-watch! s os #(add-sp-child! s %))))) ;; no update needed
+                     (summaries/or-summary s b))))
+             (fn [s ri] (make-pair-stub1 s (refine-input left-sp ri)
+                          (subproblem-name right-sp) #(refine-input right-sp %)))
+             0)]
+
+    (summaries/connect! ret ss false)
+
+    (let [[watch stub-f] (if expand-right?
+                           [right-sp #(make-pair-stub2 nil left-sp (stub %))]
+                           [left-sp #(make-pair-stub2 nil % (refine-input right-sp (output-set %)))])]
+      (add-watcher! watch
+         (fn [o]
+           (summaries/summary-changed-local! ss)
+           (connect-and-watch-stub-up! ret (stub-f o) #(add-sp-child! ret %)))))
+
+    ret))
+
+(comment
+  ;; Old test used this -- do we need to split on right for blocked left?
+  (not (summary/live? (summaries/summary left-sp)))
+ (not (= Double/NEGATIVE_INFINITY (summary/max-reward (summaries/summary left-sp)))))
+
+(defn- make-pair-stub2 [subsuming-sp left-sp right-stub]
+  (let [nm [:Pair (subproblem-name left-sp) (stub-name right-stub)]
+        is (input-set (stub left-sp))]
+    (if (get-stub-output right-stub) ;; short-circuit the mess below
+      (doto (make-wrapping-stub [nm is] right-stub #(make-pair-subproblem subsuming-sp %1 left-sp %2))
+        (-> get-stub-output assert)) ;; summary of wrapping stub would be wrong, otherwise...
+      (let [ret (traits/reify-traits [summaries/sum-summarizable (simple-stub nm is)])]
+        (connect-subsuming! ret subsuming-sp)
+        (summaries/connect! ret (tree-summarizer left-sp) false)
+        (connect-and-watch-stub! ret right-stub
+            #(set-stub-output! ret (make-pair-subproblem subsuming-sp ret left-sp %)))
+        ret))))
+
+(defn- make-pair-stub1 [subsuming-sp left-stub right-name right-stub-fn]
+  (if-let [left-sp (get-stub-output left-stub)]
+    (make-pair-stub2 subsuming-sp left-sp (right-stub-fn (output-set left-sp)))
+   (let [nm [:Pair1 (stub-name left-stub) right-name]
+         is (input-set left-stub)
+         ret (traits/reify-traits [summaries/or-summarizable (simple-stub nm is)])]
+     (connect-subsuming! ret subsuming-sp)
+     (connect-and-watch-stub! ret left-stub
+       (fn [lo]
+         (connect-and-watch-stub-up! ret
+           (make-pair-stub2 subsuming-sp lo (right-stub-fn (output-set lo)))
+           #(set-stub-output! ret %))))
+     ret)))
+
+
+;; Experimental version -- switched order.
+(defn- make-left-recursive-fs-seq-stub
+  ([inp-set fs] (make-left-recursive-fs-seq-stub inp-set fs (map fs/fs-name fs)))
+  ([inp-set [first-fs & rest-fs] fs-names]
+     (loop [left-stub (get-atomic-stub nil inp-set first-fs) rest-fs rest-fs fs-names (rest fs-names)]
+       (if (empty? rest-fs)
+         left-stub
+         (recur (make-pair-stub1 nil left-stub (first fs-names) #(get-atomic-stub nil % (first rest-fs)))
+                (rest rest-fs) (rest fs-names))))))
+
+(defn- make-right-recursive-fs-seq-stub
+  ([inp-set fs] (make-right-recursive-fs-seq-stub inp-set fs (map fs/fs-name fs)))
+  ([inp-set [first-fs & rest-fs] fs-names]
+     (let [left-stub (get-atomic-stub nil inp-set first-fs)]
+       (if (empty? rest-fs)
+         left-stub
+         (make-pair-stub1 nil left-stub (rest fs-names)
+                          #(make-right-recursive-fs-seq-stub % rest-fs (rest fs-names)))))))
+
+(defn- make-fs-seq-stub [inp-set fs]
+  ((if *left-recursive* make-left-recursive-fs-seq-stub make-right-recursive-fs-seq-stub)
+   inp-set fs))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Planning ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(defn- get-root-subproblem [inp-set fs]
+  (let [root-stub (make-atomic-stub nil nil inp-set fs)]
+    (dotimes [_ 2] (evaluate! root-stub))
+    (get-stub-output! root-stub)))
+
+(def *lazy-cache* false)
+(def *no-subsumption* false)
+(def *assume-consistency* false) ;; Don't propagate lazy increases.
+
+;; TODO: sa options...
+(defn implicit-dash-a*
+  [henv & {gather :gather d :d   s :s    choice-fn :choice-fn local? :local?  dir :dir :as m
+      :or {gather true   d true s :eager choice-fn last       local? true     dir :right}}]
+  (assert (every? #{:gather :d :s :choice-fn :local? :dir} (keys m)))
+  (assert (contains? #{:left :right} dir))
+  (assert (contains? #{nil false :eager :deliberate} s))
+  (when s (assert d))
+  (when d (assert gather))
+;  (assert (contains? #{:uncached :lazy :eager  :eager-nosub :eager-nokids} c))
+  (binding [*collect-equal-outputs* gather
+            *decompose-cache*       (when d (HashMap.))
+            *state-abstraction*     s
+            *left-recursive*        (= dir :left)
+ ;            summaries/*cache-method* c
+            ]
+    (summaries/solve
+     (tree-summarizer (apply get-root-subproblem (fs/make-init-pair henv)))
+     choice-fn local? evaluate!
+     #(let [n (second (subproblem-name %))] (when-not (= (first n) :noop) n)))))
+
+;; (do (use '[angelic env hierarchy] 'angelic.domains.nav-switch 'angelic.search.implicit.fah-astar-expand 'angelic.search.implicit.fah-astar-eval 'angelic.search.implicit.dash-astar 'angelic.domains.discrete-manipulation) (require '[angelic.search.explicit.hierarchical :as his]))
+
+;; (do (use '[angelic env hierarchy] 'angelic.domains.nav-switch  'angelic.search.implicit.dash-astar 'angelic.domains.discrete-manipulation) (require '[angelic.search.explicit.hierarchical :as his]))
+
+; (do (def s summaries/summarize) (def sc summary/children) (def nc summaries/node-ordinary-children) (def src summary/source))
+;;(dotimes [_ 1] (reset! summaries/*summary-count* 0) (debug 0 (time (let [h (make-nav-switch-hierarchy (make-random-nav-switch-env 2 1 0) true)]  (println (run-counted #(second (implicit-dash-a* h))) @summaries/*summary-count*)))))
+
+
+;; (dotimes [_ 1] (reset! summaries/*summary-count* 0) (debug 0 (let [h (make-discrete-manipulation-hierarchy  (make-discrete-manipulation-env [5 3] [1 1] [ [ [2 2] [3 2] ] ] [ [:a [2 2] [ [3 2] [3 2] ] ] ] 1))]  (time (println (run-counted #(identity (implicit-dash-a* h))) @summaries/*summary-count*)) )))
+
+
+;;(dotimes [_ 1] (reset! summaries/*summary-count* 0) (reset! *out-count* 0) (debug 0 (let [h (make-discrete-manipulation-hierarchy (make-random-hard-discrete-manipulation-env 2 3))]  (time (println (run-counted #(identity (implicit-dash-a* h))) @summaries/*summary-count* @*out-count*)) (time (println (run-counted #(identity (his/explicit-simple-dash-a* h ))) @summaries/*summary-count* @*out-count*)) )))
+
+; (dotimes [_ 1] (reset! summaries/*summary-count* 0) (reset! *out-count* 0) (debug 0 (let [h (make-discrete-manipulation-hierarchy (make-random-discrete-manipulation-env 4 3))]  (time (println (run-counted #(identity (implicit-dash-a* h))) @summaries/*summary-count* @*out-count*)) )))
+
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Graveyard ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(comment
+  (defn pseudo-solve [root-sp]
+   (summaries/pseudo-solve root-sp summary/+worst-simple-summary+ (complement summaries/expanded?)
+                           #(if (evaluated? %) (do (assert (not (summaries/expanded? %))) (child-keys %)) (evaluate! %))))
+
+
+  (defn implicit-fah-a*-eval-pseudo [henv]
+  (->> (fs/make-init-pair henv)
+       (apply make-simple-atomic-subproblem nil)
+       subproblem/pseudo-solve)))
+
+
+


boot alda task

boot alda task

This is a workaround for Windows users, while we figure out how to get the `alda` executable script to work for Windows. (see README)

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/jtbeckha/alda.git/'


ns world creates simple 2d world

ns world creates simple 2d world

error: pathspec 'src/cas/world.cljs' did not match any file(s) known to git

--- src/cas/world.cljs
+++ src/cas/world.cljs
@@ -0,0 +1,21 @@
+(ns cas.world)
+
+(def tile-colors {:stone [125 117 114]
+                  :dirt [125 97 87]
+                  :grass [96 125 87]
+                  :sky [87 115 125]})
+
+(defn tile
+  [kind]
+  {:kind kind :color (tile-colors kind)})
+
+(defn new-simple-world
+  [x y stone-to-dirt dirt-to-grass grass-to-sky]
+  (letfn [(new-row [size kind]
+            (vec (repeatedly size #(tile kind))))
+          (kind [level] (let [level (dec (- y level))]
+            (cond (< level stone-to-dirt) :stone
+                  (< level dirt-to-grass) :dirt
+                  (< level grass-to-sky) :grass
+                  :else :sky)))]
+    (vec (map #(new-row x (kind %)) (range y)))))


squash

squash

error: pathspec 'src/clj/xvsy/macros.clj' did not match any file(s) known to git

--- src/clj/xvsy/macros.clj
+++ src/clj/xvsy/macros.clj
@@ -0,0 +1,41 @@
+(ns xvsy.macros)
+
+(defmacro remap
+  "\"restructures\" a map. For example:
+  (let [a 1 b 2 c 3]
+  (remap a b c))
+  => {:a 1 :b 2 :c3}"
+  ([a]
+   `(hash-map (keyword '~a) ~a))
+  ([a b]
+   `(hash-map (keyword '~a) ~a (keyword '~b) ~b))
+  ([a b c]
+   `(hash-map (keyword '~a) ~a (keyword '~b) ~b (keyword '~c) ~c))
+  ([a b c d]
+   `(hash-map (keyword '~a) ~a (keyword '~b) ~b (keyword '~c) ~c
+      (keyword '~d) ~d))
+  ([a b c d e]
+   `(hash-map (keyword '~a) ~a (keyword '~b) ~b (keyword '~c) ~c
+      (keyword '~d) ~d (keyword '~e) ~e))
+  ([a b c d e f]
+   `(hash-map (keyword '~a) ~a (keyword '~b) ~b (keyword '~c) ~c
+      (keyword '~d) ~d (keyword '~e) ~e (keyword '~f) ~f)))
+
+(defmacro doall-time
+  [name & body]
+  `(do
+     (print ~name)
+     (let [res# ~@body]
+       (if (coll? res#)
+         (time (doall res#))
+         (do (print \newline) res#)))))
+
+(defn kw->var
+  [kw]
+  (intern 'xvsy.conf (symbol (str \* (name kw) \*))))
+
+(defmacro with-conf
+  [bindings & body]
+  (let [starred-vars (map kw->var (keys bindings))
+        starred-bindings (zipmap starred-vars (vals bindings))]
+    `(clojure.core/with-bindings ~starred-bindings ~@body)))


Update nrepl dep (fixes #124)

Update nrepl dep (fixes #124)

--- boot/core/src/boot/repl.clj
+++ boot/core/src/boot/repl.clj
@@ -2,7 +2,7 @@
   (:require [boot.util :as util]))

 (def ^:dynamic *default-dependencies*
-  (atom '[[org.clojure/tools.nrepl "0.2.6" :exclusions [[org.clojure/clojure]]]]))
+  (atom '[[org.clojure/tools.nrepl "0.2.7" :exclusions [[org.clojure/clojure]]]]))

 (def ^:dynamic *default-middleware*
   (atom (if-not @util/*colorize?* [] ['boot.from.io.aviso.nrepl/pretty-middleware])))


Better way to avoid unnecessary call

Better way to avoid unnecessary call

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/election-notification-works.git/'


Add more examples

Add more examples

error: pathspec 'src/clojure_walkthrough/jocj/ch03_05.clj' did not match any file(s) known to git

--- src/clojure_walkthrough/jocj/ch03_05.clj
+++ src/clojure_walkthrough/jocj/ch03_05.clj
@@ -0,0 +1,24 @@
+(ns clojure-walkthrough.jocj.ch03-05
+  (:require [clojure.data.json :as json]
+            [clojure.xml :as xml-core])
+  (:gen-class))
+
+;; See: https://github.com/clojure/data.json
+(def sample-json
+  (json/write-str {:a 1 :b 2}))
+
+sample-json ;; "{\"a\":1,\"b\":2}"
+
+(json/read-str sample-json) ;; {"a" 1, "b" 2}
+
+;;  e.g. 3.8:
+(declare load-totals)
+
+(defn import-xml-transactions-from-bank [url]
+  (let [xml-document (xml-core/parse url)]
+    ;; more code here
+    ))
+
+(defn totals-by-day [start-date end-date]
+  (let [expenses-by-day (load-totals start-date end-date)]
+    (json/json-str expense-by-day)))


STORM-585 is fixed: Performance improvement in none grouping

--- storm-core/src/clj/backtype/storm/daemon/executor.clj
+++ storm-core/src/clj/backtype/storm/daemon/executor.clj
@@ -80,7 +80,7 @@
       :none
         (fn [task-id tuple]
           (let [i (mod (.nextInt random) num-tasks)]
-            (.get target-tasks i)
+            (get target-tasks i)
             ))
       :custom-object
         (let [grouping (thrift/instantiate-java-object (.get_custom_object thrift-grouping))]


Rework the way field flattening happens in annotate :yum:

--- src/metabase/driver/query_processor/annotate.clj
+++ src/metabase/driver/query_processor/annotate.clj
@@ -44,34 +44,54 @@
   (assoc field :field-name (keyword (apply str (->> (rest (i/qualified-name-components field))
                                                     (interpose "."))))))

-(defn- flatten-collect-fields [form]
-  (let [fields (transient [])]
-    (clojure.walk/prewalk (fn [f]
-                            (cond
-                              (= (type f) metabase.driver.query_processor.interface.Field)
-                              (do
-                                (conj! fields f)
-                                ;; HACK !!!
-                                ;; Nested Mongo fields come back inside of their parent when you specify them in the fields clause
-                                ;; e.g. (Q fields venue...name) will return rows like {:venue {:name "Kyle's Low-Carb Grill"}}
-                                ;; Until we fix this the right way we'll just include the parent Field in the :query-fields list so the pattern
-                                ;; matching works correctly.
-                                ;; (This hack was part of the old annotation code too, it just sticks out better because it's no longer hidden amongst the others)
-                                (when (:parent f)
-                                  (conj! fields (:parent f))))
-
-                              ;; For a DateTimeField we'll flatten it back into regular Field but include the :unit info for the frontend
-                              ;; Recurse so this fn will handle the resulting Field normally
-                              (= (type f) metabase.driver.query_processor.interface.DateTimeField)
-                              (recur (assoc (:field f)
-                                            :unit (:unit f)))
-
-                              :else f))
-                          form)
-    (->> (persistent! fields)
-         distinct
-         (map field-qualify-name)
-         (mapv (u/rpartial dissoc :parent :parent-id :table-name)))))
+(defn- collect-fields
+  "Return a sequence of all the `Fields` inside THIS, recursing as needed for collections.
+   For maps, add or `conj` to property `:path`, recording the keypath used to reach each `Field.`
+
+     (collect-fields {:name \"id\", ...})     -> [{:name \"id\", ...}]
+     (collect-fields [{:name \"id\", ...}])   -> [{:name \"id\", ...}]
+     (collect-fields {:a {:name \"id\", ...}) -> [{:name \"id\", :path [:a], ...}]"
+  [this]
+  (condp instance? this
+    clojure.lang.IPersistentMap
+    (for [[k v] (seq this)
+          field (collect-fields v)]
+      (update field :path conj k))
+
+    clojure.lang.Sequential
+    (mapcat collect-fields this)
+
+    metabase.driver.query_processor.interface.Field
+    (if-let [{:keys [parent]} this]
+      ;; Nested Mongo fields come back inside of their parent when you specify them in the fields clause
+      ;; e.g. (Q fields venue...name) will return rows like {:venue {:name "Kyle's Low-Carb Grill"}}
+      ;; Until we fix this the right way we'll just include the parent Field in the :query-fields list so the pattern
+      ;; matching works correctly.
+      [this parent]
+      [this])
+
+    ;; For a DateTimeField we'll flatten it back into regular Field but include the :unit info for the frontend
+    metabase.driver.query_processor.interface.DateTimeField
+    (recur (assoc (:field this) :unit (:unit this)))
+
+    nil))
+
+(defn- flatten-fields
+  "Flatten a group of fields, keeping those which are more important when duplicates exist."
+  [fields]
+  (let [path-importance (fn [{[k] :path}]
+                          (cond
+                            (= k :breakout) 0     ; lower number = higher importance, because `sort` is ascending
+                            (= k :fields)   1     ; more important versions of fields are the ones we'll actually see in results,
+                            :else           2))]  ; so look at each field's :path. For now, it's enough just to look at the first element.
+    (distinct (sort-by path-importance fields)))) ; this is important so we don't use return the wrong version of a Field (e.g. with the wrong unit)
+
+(defn- flatten-collect-fields
+  "Collect fields from COLL, and remove duplicates."
+  [coll]
+  (for [field (flatten-fields (collect-fields coll))]
+    (dissoc (field-qualify-name field)
+            :parent :parent-id :table-name :path)))  ; remove keys we don't need anymore

 (defn- flatten-collect-ids-domain [form]
   (apply fd/domain (sort (map :field-id (flatten-collect-fields form)))))


optimization routines for clojure

optimization routines for clojure

git-svn-id: 03a8048b5ee8463be5048a3801110fb50f378627@5918 d0ab736e-dc22-4aeb-8dc9-08def0aa14fd

error: pathspec 'clojure/optimization.clj' did not match any file(s) known to git

--- clojure/optimization.clj
+++ clojure/optimization.clj
@@ -0,0 +1,28 @@
+(ns optimization
+  (:import [org.apache.commons.math.optimization GoalType]
+           [org.apache.commons.math.optimization.univariate BrentOptimizer]
+           [org.apache.commons.math.optimization.direct NelderMead]
+           [org.apache.commons.math.analysis UnivariateRealFunction MultivariateRealFunction]))
+
+(defn brent-min
+  "Find the minimum of univariate function f
+  using Brent's method."
+  [f xmin xmax]
+  (.optimize
+    (BrentOptimizer.)
+    (reify UnivariateRealFunction
+      (value [_ x] (f x)))
+    GoalType/MINIMIZE xmin xmax))
+
+
+(defn nelder-mead-min
+  "Find the minimum of multivariate function f
+  using the Nelder-Mead method."
+  [f stepsizes]
+  (->
+    (.optimize
+      (NelderMead.)
+      (reify MultivariateRealFunction
+        (value [_ x] (apply f x)))
+      GoalType/MINIMIZE (double-array stepsizes))
+    .getPoint vec))


Only adapt Object methods that actually belong to Object

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/shaunstanislaus/cljs2go.git/'


Indentation

Indentation

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/election-mail-works.git/'


added leiningen task.

added leiningen task.

error: pathspec 'leiningen/midje.clj' did not match any file(s) known to git

--- leiningen/midje.clj
+++ leiningen/midje.clj
@@ -0,0 +1,70 @@
+;; -*- indent-tabs-mode: nil -*-
+
+(ns leiningen.midje
+  (:refer-clojure :exclude [test])
+  (:use [leiningen.util.ns :only [namespaces-in-dir]]
+        [leiningen.compile :only [eval-in-project]]))
+
+(defn require-namespaces-form [namespaces]
+  `(do
+     (require 'clojure.test)
+     (require 'clojure.string)
+
+     ;; This turns off "Testing ...." lines, which I hate, especially
+     ;; when there's no failure output.
+     (defmethod clojure.test/report :begin-test-ns [m#])
+
+     (alter-var-root (var clojure.test/*report-counters*)
+		     (fn [_#] (ref clojure.test/*initial-report-counters*)))
+     (doseq [n# '~namespaces] (require n#))
+
+     (let [midje-passes#    (:pass @clojure.test/*report-counters*)
+	   midje-fails#     (:fail @clojure.test/*report-counters*)
+           midje-failure-message#
+	      (condp = midje-fails#
+		  0 (format "All claimed facts (%d) have been confirmed." midje-passes#)
+		  1 (format "FAILURE: %d fact was not confirmed." midje-fails#)
+		  (format "FAILURE: %d facts were not confirmed." midje-fails#))
+	   potential-consolation#
+	       (condp = midje-passes#
+		   0 ""
+		   1 "(But 1 was.)"
+		   (format "(But %d were.)" midje-passes#))
+	   midje-consolation#
+	           (if (> midje-fails# 0) potential-consolation# "")
+
+	   ; Stashed clojure.test output
+	   clojure-test-output-catcher#
+	           (java.io.StringWriter.)
+	   clojure-test-result#
+   	           (binding [clojure.test/*test-out* clojure-test-output-catcher#]
+		     (apply ~'clojure.test/run-tests '~namespaces))
+	   clojure-test-output#
+    	           (-> clojure-test-output-catcher# .toString clojure.string/split-lines)]
+
+
+       (when (> (+ (:fail clojure-test-result#) (:error clojure-test-result#))
+		0)
+	 ;; For some reason, empty lines are swallowed, so I use >>> to
+         ;; demarcate sections.
+	 (println ">>> Output from clojure.test tests:")
+	 (dorun (map println (drop-last 2 clojure-test-output#))))
+
+       (when (> (:test clojure-test-result#) 0)
+	 (println ">>> clojure.test summary:")
+	 (dorun (map println (take-last 2 clojure-test-output#)))
+	 (println ">>> Midje summary:"))
+
+       (println midje-failure-message# midje-consolation#)
+
+       ;; A non-nil return value is printed, so I'll just exit here.
+       (System/exit (+ midje-fails#
+                       (:error clojure-test-result#)
+                       (:fail clojure-test-result#))))))
+
+(defn midje [project & namespaces]
+  (let [desired-namespaces  (if (empty? namespaces)
+                              (concat (namespaces-in-dir (:test-path project))
+                                      (namespaces-in-dir (:source-path project)))
+                              (map symbol namespaces))]
+    (eval-in-project project (require-namespaces-form desired-namespaces))))


fix dividing by zero in metadata sync

fix dividing by zero in metadata sync

--- src/metabase/driver/generic_sql/sync.clj
+++ src/metabase/driver/generic_sql/sync.clj
@@ -165,12 +165,13 @@
     ;; Otherwise we'll have to select *all* values of the Field and sum their counts in Clojure-land
     (do (log/warn (format "WARNING: *sql-string-length-fn* is not bound for the %s driver. We cannot efficiently determine the average length of text fields."
                           (-> korma-table :db :options :subprotocol)))
-        (let [values (select korma-table (fields [(keyword field-name) :value]))
-              length-sum (->> values
-                              (map :value)
-                              (map count)
-                              (reduce +))]
-          (int (math/round (/ length-sum (count values))))))))
+        (let [values (select korma-table (fields [(keyword field-name) :value]))]
+          (if-not (seq values) 0
+                  (let [length-sum (->> values
+                                        (map :value)
+                                        (map count)
+                                        (reduce +))]
+                    (int (math/round (/ length-sum (count values))))))))))

 (defn- check-for-large-average-length
   "Check a Field to see if it has a large average length and should be marked as `preview_display = false`.
@@ -195,11 +196,12 @@
   [korma-table {field-name :name}]
   (let [total-non-null-count (-> (select korma-table
                                          (aggregate (count :*) :count)
-                                         (where {(keyword field-name) [not= nil]})) first :count)
-        url-count (-> (select korma-table
-                              (aggregate (count :*) :count)
-                              (where {(keyword field-name) [like "http%://_%.__%"]})) first :count)] ; simple SQL equivalent of regex #"^https?://.+\..{2,}$"
-    (float (/ url-count total-non-null-count))))
+                                         (where {(keyword field-name) [not= nil]})) first :count)]
+    (if (= total-non-null-count 0) 0
+        (let [url-count (-> (select korma-table
+                                    (aggregate (count :*) :count)
+                                    (where {(keyword field-name) [like "http%://_%.__%"]})) first :count)]
+          (float (/ url-count total-non-null-count))))))

 (defn- check-for-urls
   "Check a Field to see if the majority of its *NON-NULL* values are URLs; if so, mark it as `special_type = :url`.


Use derefed async transactions for create-identifiers

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/scheduled-message-works.git/'


POST to rails /teams from teams/create-team

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/physion/ovation-webapi.git/'


Saioa atoma zuzenean amaitu

Saioa atoma zuzenean amaitu

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/lnmnd/magnet.bez.git/'


added hoptree test namespace

added hoptree test namespace

error: pathspec 'test/forma/hoptree_test.clj' did not match any file(s) known to git

--- test/forma/hoptree_test.clj
+++ test/forma/hoptree_test.clj
@@ -0,0 +1,2 @@
+(ns forma.hoptree-test
+  (:use [forma.hoptree] :reload))


using fill-in-blanks for everything

using fill-in-blanks for everything

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/croeder/clojure-koans-work.git/'


Add intro to atoms.

Add intro to atoms.

error: pathspec 'test/com/nomistech/clojure_the_language/intro_to_state.clj' did not match any file(s) known to git

--- test/com/nomistech/clojure_the_language/intro_to_state.clj
+++ test/com/nomistech/clojure_the_language/intro_to_state.clj
@@ -0,0 +1,64 @@
+(ns com.nomistech.clojure-the-language.intro-to-state
+  (:require [midje.sweet :refer :all]))
+
+;;;; ___________________________________________________________________________
+;;;; Atoms: `atom`, `reset!` and `swap!`
+
+(def my-atom-1 (atom 0))
+
+(fact (deref my-atom-1) => 0)
+(fact @my-atom-1 => 0)
+
+(reset! my-atom-1 100)
+(fact @my-atom-1 => 100)
+
+(swap! my-atom-1 inc)
+(fact @my-atom-1 => 101)
+
+(swap! my-atom-1 + 10 20 30)
+(fact @my-atom-1 => 161)
+
+;; Maps in atoms
+
+(def my-atom-2 (atom {}))
+
+(swap! my-atom-2 assoc :first-name "Alice")
+(fact @my-atom-2 => {:first-name "Alice"})
+
+(swap! my-atom-2 assoc :first-name "Bob")
+(fact @my-atom-2 => {:first-name "Bob"})
+
+(swap! my-atom-2 assoc-in [:address :line-1] "78 Green Lane")
+(swap! my-atom-2 assoc-in [:address :line-2] "New Town")
+(fact @my-atom-2 => {:first-name "Bob"
+                     :address {:line-1 "78 Green Lane"
+                               :line-2 "New Town"}})
+
+;;;; ___________________________________________________________________________
+;;;; Atoms and concurrency
+
+(def atom-to-demo-competing-updates (atom 0))
+
+(def n-competitors 100)
+
+(defn demo-competition-to-modify-atom []
+  (let [n-attempts-atom (atom 0)
+        futures         (for [i (range n-competitors)]
+                          (future (swap! atom-to-demo-competing-updates
+                                         (fn [n]
+                                           (swap! n-attempts-atom inc)
+                                           (Thread/sleep (rand-int 100))
+                                           (inc n)))))]
+    (loop []
+      (println @atom-to-demo-competing-updates)
+      (when (not-every? realized? futures)
+        (Thread/sleep 1000)
+        (recur)))
+    (println "Finished -- n-attempts =" @n-attempts-atom)
+    [@atom-to-demo-competing-updates
+     @n-attempts-atom]))
+
+(fact "About concurrency and atoms"
+  (let [[final-value n-attempts] (demo-competition-to-modify-atom)]
+    (fact final-value => n-competitors)
+    (fact (> n-attempts n-competitors) => truthy)))


Allow using seesaw.core/select when AWT components are being used

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/bsmr-clojure/Nightcode.git/'


Passing entity information from game screen to overlay screen for use in making labels.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Yoshiyuka/cthulhu.git/'


place a script temporarily on the target machine and run it

error: pathspec 'plugins/matross/tasks/script.clj' did not match any file(s) known to git

--- plugins/matross/tasks/script.clj
+++ plugins/matross/tasks/script.clj
@@ -0,0 +1,35 @@
+(ns matross.tasks.script
+  (:require [matross.tasks.core :refer [deftask run-task]]
+            [matross.tasks.template :as template]
+            [matross.tasks.temp-file :refer [with-temp-files]]))
+
+
+(def defaults {:template true
+               :vars {}
+               :env {}})
+
+(defn get-script [conf]
+  (if (:file conf)
+    (slurp (:file conf))
+    (get conf :inline "")))
+
+(defn template-conf [conf src dest]
+  (-> conf
+      (assoc :type :template)
+      (assoc :inline src)
+      (assoc :dest (clojure.string/trim-newline dest))
+      (update-in [:vars] #(if (:template conf) %1 {}))))
+
+(deftask :script [conn conf]
+  (comment
+    :file a file to render
+    :inline a string to render (optional, instead of :file)
+    :template boolean whether or not to template the script (default true)
+    :env environment variables to expose to the script
+    :vars map of vars for templating)
+  (with-temp-files conn [script]
+    (let [conf (merge defaults conf)
+          src (get-script conf)
+          final (run-task conn (template-conf conf src script))]
+      (run-task conn {:type :command :command (str "chmod +x " script)})
+      (run-task conn {:type :command :command script}))))


combineTiles.clj: new file

combineTiles.clj: new file

error: pathspec 'clojure/org/gavrog/clojure/combineTiles.clj' did not match any file(s) known to git

--- clojure/org/gavrog/clojure/combineTiles.clj
+++ clojure/org/gavrog/clojure/combineTiles.clj
@@ -0,0 +1,14 @@
+(ns org.gavrog.clojure.combineTiles
+  (:use (org.gavrog.clojure
+          [generators :only [make-backtracker results]]
+          [delaney])))
+
+(defn- components-with-multiplicities [ds]
+  (let [idcs (indices ds)]
+    (frequencies (for [D (orbit-reps ds idcs)] (canonical (orbit ds idcs D))))))
+
+(defn combine-tiles [ds]
+  (make-backtracker
+    {:root []
+     :extract (fn [[]])
+     :children (fn [[]])}))


Remove .checkError after printing each element of a reducible

This means a .flush after each (possibly tiny) element of a
collection, which often amounts in a huge overhead because of
chunking, as described in #113.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/meowcakes/ring.git/'


Restore aviso.nrepl namespace, fixes repl task crashing on start

error: pathspec 'boot/pod/src/boot/from/io/aviso/nrepl.clj' did not match any file(s) known to git

--- boot/pod/src/boot/from/io/aviso/nrepl.clj
+++ boot/pod/src/boot/from/io/aviso/nrepl.clj
@@ -0,0 +1,10 @@
+(ns boot.from.io.aviso.nrepl
+  "nREPL middleware to enable pretty exception reportinging in the REPL."
+  {:boot/from :AvisoNovate/pretty:0.1.11}
+  (:use [boot.from.io.aviso.repl]))
+
+(defn pretty-middleware
+  "nREPL middleware that simply ensures that pretty exception reporting is installed."
+  [handler]
+  (install-pretty-exceptions)
+  handler)


Enter key handler was added

Enter key handler was added

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/abtv/personal-aggregator.git/'


Don't log anything in question groups spec.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/couragelabs/coachbot.git/'


read input & print output

read input & print output

error: pathspec 'src/hackerrank/fp/Evaluating' did not match any file(s) known to git
error: pathspec 'e^x.clj' did not match any file(s) known to git


removed standalone config from entities

removed standalone config from entities

--- src/ruuvi_server/models/entities.clj
+++ src/ruuvi_server/models/entities.clj
@@ -1,10 +1,8 @@
 (ns ruuvi-server.models.entities
   (:use korma.db)
   (:use korma.core)
-  (:use ruuvi-server.standalone.config)
   (:use [clojure.tools.logging :only (debug info warn error)])
   )
-

 (info "Mapping entities")


Cleaned out cruft.

Cleaned out cruft.


Initial foray into grabbing lowest price from ccc.

error: pathspec 'src/az_wish/ccc.clj' did not match any file(s) known to git

--- src/az_wish/ccc.clj
+++ src/az_wish/ccc.clj
@@ -0,0 +1,15 @@
+(ns core/ccc
+  (:require [net.cgrand.enlive-html :as html]))
+
+(defn- fetch-url [url]
+  (html/html-resource (java.net.URL. url)))
+
+;; http://camelcamelcamel.com/product/1941222226 ... redirects to ...
+;; http://camelcamelcamel.com/Mastering-Clojure-Macros-Cleaner-Smarter/product/1941222226
+
+(def direct (fetch-url "http://camelcamelcamel.com/product/1941222226"))
+
+(def az-lowest (second (html/select direct [:table.product_pane :tr.lowest_price :td])))
+;; And the next td is the date of that price
+
+(def price (-> az-lowest :content first))


Mount the pedestal app in Immutant [IMMUTANT-253]

Currently, only mounting at the root context is supported.

error: pathspec 'integration-tests/apps/pedestal/hello/src/immutant/init.clj' did not match any file(s) known to git

--- integration-tests/apps/pedestal/hello/src/immutant/init.clj
+++ integration-tests/apps/pedestal/hello/src/immutant/init.clj
@@ -0,0 +1,6 @@
+(ns immutant.init
+  (:require [immutant.web             :as web]
+            [io.pedestal.service.http :as bootstrap]
+            [hello.service            :as service]))
+
+(web/start-servlet "/" (::bootstrap/servlet (bootstrap/create-servlet service/service)))


Add 'floor' intrinsic

Add 'floor' intrinsic

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/kkroening/jackal.git/'


Enumerate child components

Enumerate child components


Datomic interface.

Datomic interface.

error: pathspec 'src/onyx/coordinator/log/datomic.clj' did not match any file(s) known to git

--- src/onyx/coordinator/log/datomic.clj
+++ src/onyx/coordinator/log/datomic.clj
@@ -0,0 +1,27 @@
+(ns onyx.coordinator.log.datomic
+  (:require [onyx.coordinator.extensions :as extensions]))
+
+(defmethod extensions/mark-peer-born :datomic
+  [log peer])
+
+(defmethod extensions/mark-peer-dead :datomic
+  [log peer])
+
+(defmethod extensions/mark-offered :datomic
+  [log])
+
+(defmethod extensions/plan-job :datomic
+  [log job])
+
+(defmethod extensions/ack :datomic
+  [log task])
+
+(defmethod extensions/evict :datomic
+  [log task])
+
+(defmethod extensions/complete :datomic
+  [log task])
+
+(defmethod extensions/next-task :datomic
+  [log])
+


util class for edn added

util class for edn added

error: pathspec 'src/photosure/client/util.cljs' did not match any file(s) known to git

--- src/photosure/client/util.cljs
+++ src/photosure/client/util.cljs
@@ -0,0 +1,20 @@
+(ns photosure.client.util
+  (:require [cljs.reader :as reader]
+            [goog.events :as events])
+  (:import [goog.net XhrIo]
+           [goog.events EventType]))
+
+(def ^:private meths
+  {:get "GET"
+   :put "PUT"
+   :post "POST"
+   :delete "DELETE"})
+
+(defn edn-xhr [{:keys [method url data on-complete]}]
+  (let [xhr (XhrIo.)]
+    (events/listen xhr EventType.COMPLETE
+                   (fn [e]
+                     (on-complete (reader/read-string (.getResponseText xhr)))))
+    (. xhr
+       (send url (meths method) (when data (pr-str data))
+             #js {"Content-Type" "application/edn"}))))


system/utils has been moved to cljc section

error: pathspec 'core/src/cljc/hellhound/system/utils.cljc' did not match any file(s) known to git

--- core/src/cljc/hellhound/system/utils.cljc
+++ core/src/cljc/hellhound/system/utils.cljc
@@ -0,0 +1,9 @@
+(ns hellhound.system.utils
+  "TODO"
+  (:import (clojure.lang IPersistentMap
+                         PersistentVector)))
+
+(defn ^PersistentVector get-components
+  "Returns the components catalog of the given `system`."
+  [^IPersistentMap system]
+  (:components system))


Stub for new test module: config-test

Stub for new test module: config-test

error: pathspec 'test/arachnida/config_test.clj' did not match any file(s) known to git

--- test/arachnida/config_test.clj
+++ test/arachnida/config_test.clj
@@ -0,0 +1,16 @@
+;
+;  (C) Copyright 2015  Pavel Tisnovsky
+;
+;  All rights reserved. This program and the accompanying materials
+;  are made available under the terms of the Eclipse Public License v1.0
+;  which accompanies this distribution, and is available at
+;  http://www.eclipse.org/legal/epl-v10.html
+;
+;  Contributors:
+;      Pavel Tisnovsky
+;
+
+(ns arachnida.config-test
+  (:require [clojure.test :refer :all]
+            [arachnida.config :refer :all]))
+


making tests pass

making tests pass

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/physion/ovation-webapi.git/'


[WM] set unique test port

[WM] set unique test port

Hopefully unique?

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/election-authority-http-api.git/'


Add simple test for simulation run

Add simple test for simulation run

error: pathspec 'test/clj_gatling/simulation_test.clj' did not match any file(s) known to git

--- test/clj_gatling/simulation_test.clj
+++ test/clj_gatling/simulation_test.clj
@@ -0,0 +1,20 @@
+(ns clj-gatling.simulation-test
+  (:use clojure.test)
+  (:require [clj-gatling.simulation :as simulation]))
+
+(defn run-request [id] "OK")
+
+(def scenario
+  {:name "Test scenario"
+   :requests [{:name "Request1" :fn run-request}
+              {:name "Request2" :fn run-request}]})
+
+(defn get-result [requests request-name]
+  (:result (first (filter #(= request-name (:name %)) requests))))
+
+(deftest simulation-returns-result-when-run-with-one-user
+  (let [result (first (simulation/run-simulation scenario 1))]
+    (is (= "Test scenario" (:name result)))
+    (is (= "OK" (get-result (:requests result) "Request1")))
+    (is (= "OK" (get-result (:requests result) "Request2")))))
+


Make it look pretty

Make it look pretty

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/starcity-properties/odin.git/'


Tokenaren oharrak

Tokenaren oharrak

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/lnmnd/magnet.zer.git/'


test fix

test fix

--- test/metabase/models/common_test.clj
+++ test/metabase/models/common_test.clj
@@ -20,6 +20,8 @@
 ;; creator can read + write
 (expect #{:read :write}
   (binding [*current-user-id* 100]
-    (user-permissions {:creator_id 100})))
+    (user-permissions {:creator_id 100
+                       :organization_id 12
+                       :public_perms 0})))

 ;; TODO - write tests for the rest of the `user-permissions`


Initial flow ns?

Initial flow ns?

error: pathspec 'src/cljc/seria/flow.cljc' did not match any file(s) known to git

--- src/cljc/seria/flow.cljc
+++ src/cljc/seria/flow.cljc
@@ -0,0 +1,10 @@
+(ns seria.flow)
+
+"Extensions:
+ - automatic delta groups and stuff
+   :autodiff? to enable
+   :group to select group
+   incremental strategy: every n. is full, inbetween is diffed
+     with previous full
+   reserve 2 bytes for delta group
+   "


Add simple mic/input pitch-controlled synth example

error: pathspec 'src/overtone/examples/instruments/pitch_controller.clj' did not match any file(s) known to git

--- src/overtone/examples/instruments/pitch_controller.clj
+++ src/overtone/examples/instruments/pitch_controller.clj
@@ -0,0 +1,15 @@
+(ns overtone.examples.instruments.pitch-controller
+  (:use overtone.live))
+
+;; Fire off this synth and connect an instrument/mic.
+;; The pitch will be detected and used to control the saw waves
+
+(defsynth pitch-controlled-saws
+  [out-bus 0]
+  (let [p   (pitch (sound-in) )
+        p   (/ p 4)
+        p   (lag p 1)]
+    (out out-bus (saw [p (+ p (* p 0.01))]))))
+
+;;(pitch-controlled-saws)
+;;(stop)


Back to running.

Back to running.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/inchingforward/eon.git/'


Added list all links interactor

Added list all links interactor

error: pathspec 'src/clj/squad_share/interactors/list_all_links.clj' did not match any file(s) known to git

--- src/clj/squad_share/interactors/list_all_links.clj
+++ src/clj/squad_share/interactors/list_all_links.clj
@@ -0,0 +1,12 @@
+(ns squad_share.interactors.list-all-links
+     (:require
+       [clojure.core.async :refer [go <!!]]
+       [postgres.async :as pg]
+       [squad-share.config :as config]))
+
+(defn run!
+      [context]
+      (let [result (<!! (pg/select config/db {:table "squadshare.links"}))]
+           )
+
+      )


Solve 14 in Clojure

Solve 14 in Clojure

error: pathspec 'Problem014/Clojure/solution_1.clj' did not match any file(s) known to git


Breaking out go-static-field?

Breaking out go-static-field?

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/shaunstanislaus/cljs2go.git/'


finish vertex clipping example

finish vertex clipping example

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/aamedina/gltut.git/'


Removed last reference of SQLite

Removed last reference of SQLite

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/acessocard/microscope.git/'


Erantzunak azpian

Erantzunak azpian

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/lnmnd/magnet.bez.git/'


RSeq tests.

RSeq tests.


When an exception bubbles out of the router loop, it now restarts itself. Previously the  the router loop was permanently broken by an exception. This change makes figwheel debugging work much more nicely in some circumstances. Plus it means that in production, apps have a chance at recovery from UHE

--- src/re_frame/router.cljs
+++ src/re_frame/router.cljs
@@ -3,7 +3,7 @@
   (:require-macros [cljs.core.async.macros :refer [go-loop go]])
   (:require [reagent.core        :refer [flush]]
             [re-frame.handlers   :refer [handle]]
-            [re-frame.utils      :refer [warn]]
+            [re-frame.utils      :refer [warn error]]
             [cljs.core.async     :refer [chan put! <! timeout]]))

 ;; -- The Event Conveyor Belt  --------------------------------------------------------------------
@@ -13,6 +13,12 @@
 ;;
 (def ^:private event-chan (chan))    ;; TODO: set buffer size?

+(defn purge-chan
+  "read all pending events from the channel and drop them on the floor"
+  []
+  #_(loop []                          ;; TODO commented out until poll! is a part of the core.asyc API
+    (when (go (poll! event-chan))     ;; progress: https://github.com/clojure/core.async/commit/d8047c0b0ec13788c1092f579f03733ee635c493
+      (recur))))

 ;; -- router loop ---------------------------------------------------------------------------------
 ;;
@@ -27,13 +33,34 @@
 ;; Example usage (notice the ":flush-dom" metadata):
 ;;   (dispatch ^:flush-dom  [:event-id other params])
 ;;
-(go-loop []
-         (let [event-v  (<! event-chan)                   ;; wait for an event
-               _        (if (:flush-dom (meta event-v))   ;; check the event for metadata
-                          (do (flush) (<! (timeout 20)))  ;; wait just over one annimation frame (16ms), to rensure all pending GUI work is flushed to the DOM.
-                          (<! (timeout 0)))]              ;; just in case we are handling one dispatch after an other, give the browser back control to do its stuff
-           (handle event-v)
+
+(defn router-loop
+  []
+  (go-loop []
+           (let [event-v  (<! event-chan)                   ;; wait for an event
+                 _        (if (:flush-dom (meta event-v))   ;; check the event for metadata
+                            (do (flush) (<! (timeout 20)))  ;; wait just over one annimation frame (16ms), to rensure all pending GUI work is flushed to the DOM.
+                            (<! (timeout 0)))]              ;; just in case we are handling one dispatch after an other, give the browser back control to do its stuff
+             (try
+               (handle event-v)
+
+               ;; Unhandled exceptions from event handlers must be managed as follows:
+               ;;   - call the standard logging function "error"
+               ;;   - allow them to continue to bubble up because the app, in production,
+               ;;     may have hooked window.onerror and perform special processing.
+               ;;   - But an exception which bubbles out will break the enclosing go-loop.
+               ;;     So we'll need to start another one.
+               (catch js/Object e
+                 (do
+                   ;; try to recover from this (probably uncaught) error as best we can
+                   (purge-chan)        ;; get rid of any pending events
+                   (router-loop)       ;; Exception throw will cause termination of go-loop. So, start another.
+
+                   (throw e)))))        ;; re-throw so the rest of the app's infrastructure (window.onerror?) gets told
            (recur)))
+
+;; start event processing
+(router-loop)

 ;; -- dispatch ------------------------------------------------------------------------------------
@@ -46,7 +73,7 @@
   "
   [event-v]
   (if (nil? event-v)
-    (warn "re-frame: \"dispatch\" is ignoring a nil event.")     ;; nil would close the channel
+    (error "re-frame: \"dispatch\" is ignoring a nil event.")     ;; nil would close the channel
     (put! event-chan event-v))
   nil)   ;; Ensure nil return. See https://github.com/Day8/re-frame/wiki/Beware-Returning-False


use :use to import utility methods directly into document namespace and shorten method implementations

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/colophon/clarango.git/'


display correct time on webcam page

display correct time on webcam page

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/20centaurifux/my-website.git/'


Let's not try to be too clever with testify here.