Client-API: convert id values to strings. Fix #12.

--- src/ruuvi_server/client_api.clj
+++ src/ruuvi_server/client_api.clj
@@ -40,8 +40,29 @@
   (let [selected-data (select-keys event-data
                                    [:id :event_time :tracker_id
                                     :created_on])
-        renamed-data (rename-keys selected-data
-                                  {:created_on :store_time})
+        renamed-data (util/modify-map selected-data
+                                 {:created_on :store_time}
+                                 {:id (fn [id] (str id))
+                                  :tracker_id (fn [id] (str id))})
+        location-data (select-location-data
+                       (get (event-data :event_locations)
+                            0))
+        extension-data (select-extension-data
+                        (event-data :event_extension_values))]
+
+    (util/remove-nil-values (merge renamed-data
+                                   {:location location-data
+                                    :extension_values extension-data}))
+    ))
+
+(defn- select-event-data [event-data]
+  (let [selected-data (select-keys event-data
+                                   [:id :event_time :tracker_id
+                                    :created_on])
+        renamed-data (util/modify-map selected-data
+                                 {:created_on :store_time}
+                                 {:id (fn[id] (str id))
+                                  :tracker_id (fn[id] (str id ))})
         location-data (select-location-data
                        (get (event-data :event_locations)
                             0))
@@ -59,8 +80,9 @@

 (defn- select-tracker-data [data-map]
   (let [selected (select-keys data-map [:id :tracker_code :name
-                                        :latest_activity :created_on])]
-    (util/remove-nil-values selected)))
+                                        :latest_activity :created_on])
+        renamed (util/modify-map selected nil {:id (fn [id] (str id))})]
+    (util/remove-nil-values renamed)))

 (defn- select-trackers-data [data-map]
   {:trackers (map select-tracker-data (data-map :trackers))})


Finally fixed password

Finally fixed password

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/OttoJursch/sched-system.git/'


prefer `remove` to a negated `filter`

prefer `remove` to a negated `filter`

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/email-works.git/'


Fixed Game Over screen.

Fixed Game Over screen.

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/'


comment out rereduced helper (not presently in use)

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/'


make first added credit card default source

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/'


Adds annotation schemata and prototype endpoint

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/'


Profile component

Profile component

error: pathspec 'src/trak/ui/components/profile.cljs' did not match any file(s) known to git

--- src/trak/ui/components/profile.cljs
+++ src/trak/ui/components/profile.cljs
@@ -0,0 +1,39 @@
+(ns trak.ui.components.profile
+  (:require [rum.core :as rum]
+            [trak.utils :as utils]
+            [trak.db :as db]
+            [trak.globals :as globals]
+            [trak.ui.components :as components]))
+
+
+;(rum/defc profile-login []
+;  (components/link
+;    {:href (globals/spotify-authorization-link "user-read-private user-read-email") :class-name "btn btn-primary"}
+;    "Log in"))
+;
+;(rum/defc profile [me]
+;  [:div [:h2 (:me/display_name me)] (:me/country me)])
+;
+;(rum/defc profile-base [*db]
+;  (let [me (db/me *db)]
+;    (utils/info me (:me/status me))
+;    (cond
+;      (= :logged-out (:me/status me)) (profile-login)
+;      (= :logged-in (:me/status me)) (profile me)
+;      (= :loading (:me/status me)) [:div "Loading..."])))
+
+
+(defn profile-playlists [db]
+  (let [playlists (db/playlists db :me)]
+    (map (fn [playlist]
+           [:li.nav-item {:key (:playlist/id playlist)}
+            (components/icon "web")
+            (components/link {:href (str "/playlists/" (:playlist/id playlist))}
+                             (:playlist/name playlist))])
+         playlists))
+  )
+
+(rum/defc profile [db]
+  (utils/info (profile-playlists db))
+  [:ul.sidebar-nav.nav
+   [:li.nav-item.active "Playlists" [:ul.nav (profile-playlists db)]]])


Test description fix

Test description fix

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/voter-registration-http-api.git/'


Add idea re. expanding body coercions

Add idea re. expanding body coercions

--- src/yada/body.clj
+++ src/yada/body.clj
@@ -250,3 +250,7 @@
 (defmethod render-error :default
   [status error representation {:keys [id options]}]
   nil)
+
+
+;; Expand on the idea that errors, org/markdown files, etc. can
+;; themselves be resources, yielding multiple representations.


Add missing projects repository impl.

Add missing projects repository impl.

error: pathspec 'src/uxbox/repo/projects.cljs' did not match any file(s) known to git

--- src/uxbox/repo/projects.cljs
+++ src/uxbox/repo/projects.cljs
@@ -0,0 +1,27 @@
+;; This Source Code Form is subject to the terms of the Mozilla Public
+;; License, v. 2.0. If a copy of the MPL was not distributed with this
+;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;;
+;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
+
+(ns uxbox.repo.projects
+  "A main interface for access to remote resources."
+  (:refer-clojure :exclude [do])
+  (:require [httpurr.client.xhr :as http]
+            [httpurr.status :as http.status]
+            [promesa.core :as p :include-macros true]
+            [beicon.core :as rx]
+            [uxbox.repo.core :as urc]
+            [uxbox.state :as ust]))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Login
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defmethod urc/-do :fetch/projects
+  [type data]
+  (urc/req! {:url (str urc/+uri+ "/projects") :method :get}))
+
+(defmethod urc/-do :fetch/pages
+  [type data]
+  (urc/req! {:url (str urc/+uri+ "/pages") :method :get}))


Fix accidental debugging commit.

Fix accidental debugging commit.

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/crispy-tatertot.git/'


[WM] use doseq instead of for for side-effects

"for is lazy, doseq is eager" - repeating this to myself

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/'


Add ip resolver to get lat/long.

Add ip resolver to get lat/long.

error: pathspec 'src/forecast/repository/ip_locator.clj' did not match any file(s) known to git

--- src/forecast/repository/ip_locator.clj
+++ src/forecast/repository/ip_locator.clj
@@ -0,0 +1,22 @@
+(ns forecast.repository.ip-locator
+  (:require [clj-http.client :as client]
+            [cheshire.core :refer [parse-string]]
+            [clojure.string :refer [split]]
+            ))
+
+(defn ip->location
+  [ip]
+  (try
+    (let [url (str "http://ipinfo.io/" ip)
+          response (client/get url {:accept :json :socket-timeout 1000 :conn-timeout 1000})]
+      (if (= (:status response) 200)
+        (->
+         ((parse-string (:body response)) "loc")
+         (split #",")
+         ((fn [v] {:latitude (read-string (first v)) :longitude (read-string (second v))}))
+         )
+        response
+        ))
+    (catch Exception e {:error (str e)})))
+
+;; (prn (ip->location "8.8.8.8"))


Start to wrap tests around JlineInputReader

error: pathspec 'test/reply/reader/jline/jline_input_reader_test.clj' did not match any file(s) known to git

--- test/reply/reader/jline/jline_input_reader_test.clj
+++ test/reply/reader/jline/jline_input_reader_test.clj
@@ -0,0 +1,43 @@
+(ns reply.reader.jline.jline-input-reader-test
+  (:use [midje.sweet])
+  (:import [reply.reader.jline JlineInputReader]))
+
+(defprotocol LineReader
+  (readLine [_]))
+
+(defrecord FakeJlineReader [f]
+  LineReader
+  (readLine [this] (f)))
+
+(defn fake-reader
+  ([input-fn] (fake-reader input-fn #()))
+  ([input-fn set-empty-prompt]
+    (let [jline-reader (FakeJlineReader. input-fn)]
+      (JlineInputReader. {:jline-reader jline-reader
+                          :set-empty-prompt set-empty-prompt}))))
+
+(fact "reading nothing gives nothing"
+  (.read (fake-reader (constantly nil))) => -1)
+
+(fact "reading an empty line gives a newline"
+  (.read (fake-reader (constantly ""))) => 10)
+
+(let [reader (fake-reader (constantly "abcd"))]
+  (fact "reading a few characters works"
+    (for [i (range 5)]
+      (.read reader)) => [97 98 99 100 10]))
+
+(let [times-readLine-called (atom 0)
+      reader (fake-reader (constantly "") #(swap! times-readLine-called inc))]
+  (facts "it calls for more input on a newline"
+    (for [i (range 3)]
+      (.read reader)) => [10 10 10]
+    @times-readLine-called => 3))
+
+(let [times-readLine-called (atom 0)
+      reader (fake-reader (constantly "ab") #(swap! times-readLine-called inc))]
+  (facts "no more calls to readLine than are necessary"
+    (for [i (range 10)]
+      (.read reader)) => [97 98 10 97 98 10 97 98 10 97]
+    @times-readLine-called => 4))
+


Add test for post-layout

Add test for post-layout

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/magoyette/marcandregoyette.com.git/'


add bookmarks.cljs

add bookmarks.cljs

error: pathspec 'src_cljs/bookmarks/bookmarkslist.cljs' did not match any file(s) known to git

--- src_cljs/bookmarks/bookmarkslist.cljs
+++ src_cljs/bookmarks/bookmarkslist.cljs
@@ -0,0 +1,4 @@
+(ns bookmarks.bookmarkslist
+  (:require [bookmarks.helpers :as he]))
+
+


Formatting.

Formatting.

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/monument.git/'


Sample test for the service routing

Sample test for the service routing

error: pathspec 'application/test/spira/service/routes_fixture.clj' did not match any file(s) known to git

--- application/test/spira/service/routes_fixture.clj
+++ application/test/spira/service/routes_fixture.clj
@@ -0,0 +1,30 @@
+;; Copyright (C) 2013 Anders Sundman <anders@4zm.org>
+;;
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+(ns spira.service.routes-service
+  (:require [clojure.test :refer :all]
+            [spira.service.routes :refer :all]))
+
+(def http-req-ok 200)
+
+(def test-req
+  {:request-method :get
+   :uri "/api/fu" :headers []
+   :params []})
+
+(deftest test-fu
+  (testing "Testing the /api/fu route"
+    (is (= http-req-ok (:status (app-routes test-req))))
+    ))


Added a Jetty wrapper.

Added a Jetty wrapper.

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

--- src/appengine_magic/jetty.clj
+++ src/appengine_magic/jetty.clj
@@ -0,0 +1,37 @@
+(ns appengine-magic.jetty
+  (:use [ring.util.servlet :only [servlet]])
+  (:import org.mortbay.jetty.handler.ContextHandlerCollection
+           org.mortbay.jetty.Server
+           [org.mortbay.jetty.servlet Context ServletHolder]))
+
+
+(defn- proxy-multihandler
+  "Returns a Jetty Handler implementation for the given map of relative URLs to
+   handlers. Each handler may be a Ring handler or an HttpServlet instance."
+  [handlers]
+  (let [all-contexts (ContextHandlerCollection.)]
+    (doseq [[relative-url handler] handlers]
+      (let [context (Context. all-contexts relative-url)
+            handler-servlet (if (instance? HttpServlet handler)
+                                handler
+                                (servlet handler))
+            servlet-holder (ServletHolder. handler-servlet)]
+        (.addServlet context servlet-holder "/*")))
+    all-contexts))
+
+
+;;; TODO: When Clojure 1.2 comes out, change this to use the destructuring
+;;; syntax for keyword arguments.
+(defn #^Server start [handlers {:keys [port join?] :or {port 8080 join? true}}]
+  (let [server (Server. port)]
+    (doto server
+      (.setHandler (if (map? handlers)
+                       (proxy-multihandler handlers)
+                       (proxy-multihandler {"/" handlers})))
+      (.start))
+    (when join? (.join server))
+    server))
+
+
+(defn stop [#^Server server]
+  (.stop server))


Missed cond

Missed cond

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/'


bump versions in profiles.clj

bump versions in profiles.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/sw1nn/dotfiles.git/'


exception handling is done by multimethod now in core_utility

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/'


Begin universe refactor

Begin universe refactor

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

--- src/cljs/threed/universe.cljs
+++ src/cljs/threed/universe.cljs
@@ -0,0 +1,6 @@
+(ns threed.universe)
+
+(defrecord Universe [positions])
+
+(defn universe []
+  (map->Universe {:positions []}))


Added namespace to support attribute operations

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

--- src/clojure/alfresco/attr.clj
+++ src/clojure/alfresco/attr.clj
@@ -0,0 +1,86 @@
+;
+; Copyright (C) 2014 Peter Monks
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+;     http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+
+(ns alfresco.attr
+  (:require [clojure.string :as s]
+            [alfresco.core  :as c]
+            [alfresco.nodes :as n])
+  (:import [java.io Serializable]
+           [org.alfresco.service.cmr.attributes AttributeService
+                                                AttributeService$AttributeQueryCallback]))
+
+(defn ^AttributeService attribute-service
+  "The attribute service bean."
+  []
+  (.getAttributeService (c/alfresco-services)))
+
+(defn- construct-keys
+  "Constructs keys in the format expected by the native attribute service."
+  ([namespace]         (into-array Serializable [namespace]))
+  ([namespace name]    (into-array Serializable [namespace name]))
+  ([namespace name id] (into-array Serializable [namespace name id])))
+
+(defn- split-keys
+  "Splits keys from the native attribute service into a vector of three elements (some of which may be nil)."
+  [keys]
+  (condp = (alength keys)
+    1 [(aget keys 0) nil           nil]
+    2 [(aget keys 0) (aget keys 1) nil]
+    3 [(aget keys 0) (aget keys 1) (aget keys 2)]))
+
+(defn- handle-attribute
+  [result attr-id value keys]
+  (let [[namespace name id] (split-keys keys)]
+    (conj result { :namespace namespace
+                   :name      name
+                   :id        id
+                   :value     value })))
+
+(defn- list-attrs-impl
+  "Private implementation of list-attrs."
+  [keys]
+  (let [result   (atom [])
+        callback (proxy [AttributeService$AttributeQueryCallback] []
+                   (handleAttribute [attr-id value keys]
+                     (swap! result handle-attribute attr-id value keys)
+                     true))
+        _        (.getAttributes (attribute-service) callback keys)]
+    @result))
+
+(defn exists?
+  "Does the given attribute exist?"
+  [namespace name id]
+  (.exists (attribute-service) (construct-keys namespace name id)))
+
+(defn list-attrs
+  "List all attributes in the given namespace, or namespace+name."
+  ([namespace]      (list-attrs-impl (construct-keys namespace)))
+  ([namespace name] (list-attrs-impl (construct-keys namespace name))))
+
+(defn get-attr
+  "Retrieves the current value of the given attribute."
+  [namespace name id]
+  (.getAttribute (attribute-service) (construct-keys namespace name id)))
+
+(defn set-attr!
+  "Unconditionally sets the value of the given attribute, creating it if it doesn't already exist."
+  [namespace name id value]
+  (.setAttribute (attribute-service) value (construct-keys namespace name id)))
+
+(defn delete!
+  "Deletes one or more attributes from the system."
+  ([namespace]         (.removeAttributes (attribute-service) (construct-keys namespace)))
+  ([namespace name]    (.removeAttributes (attribute-service) (construct-keys namespace name)))
+  ([namespace name id] (.removeAttribute  (attribute-service) (construct-keys namespace name id))))


Fixed merge error in drpc.clj

Fixed merge error in drpc.clj

--- storm-core/src/clj/backtype/storm/daemon/drpc.clj
+++ storm-core/src/clj/backtype/storm/daemon/drpc.clj
@@ -208,10 +208,10 @@
           ;; invocations that will unblock those threads
           handler-server (when (> drpc-port 0)
                            (ThriftServer. conf
-                             (DistributedRPC$Processor. service-handler)
+                             (DistributedRPC$Processor. drpc-service-handler)
                              ThriftConnectionType/DRPC))
           invoke-server (ThriftServer. conf
-                          (DistributedRPCInvocations$Processor. service-handler)
+                          (DistributedRPCInvocations$Processor. drpc-service-handler)
                           ThriftConnectionType/DRPC_INVOCATIONS)
           http-creds-handler (AuthUtils/GetDrpcHttpCredentialsPlugin conf)]
       (.addShutdownHook (Runtime/getRuntime) (Thread. (fn []


aldatu-erabiltzailea! atera

aldatu-erabiltzailea! atera

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/'


formatting

formatting

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/notification-works.git/'


Add a build-id to server messages

Add a build-id to server messages

--- sidecar/src/figwheel_sidecar/core.clj
+++ sidecar/src/figwheel_sidecar/core.clj
@@ -62,10 +62,16 @@
             (println "Figwheel: there was a problem running the open file command - " command))
           )))))

+(defn add-build-id [{:keys [build-id]} msg]
+  (if build-id
+    (assoc msg :build-id build-id)
+    msg))
+
 (defn message* [opts msg-name data]
   (merge data
-         { :msg-name msg-name
-           :project-id (:unique-id opts)}))
+         (add-build-id opts
+                       { :msg-name msg-name
+                         :project-id (:unique-id opts)})))

 (defn setup-file-change-sender [{:keys [file-change-atom compile-wait-time] :as server-state}
                                 wschannel]
@@ -224,7 +230,7 @@
   (keep
    #(when (file-changed? st %)
       { :dependency-file true
-        :file (remove-resource-path st %)})
+        :file (remove-resource-path st %) })
    (dependency-files st)))

 (defn make-sendable-file
@@ -233,9 +239,7 @@
   (let [n (-> nm name underscore)]
     { :file (ns-to-server-relative-path st n)
       :namespace (cljs.compiler/munge n)
-      :meta-data (meta nm)}
-    ))
-
+      :meta-data (meta nm) }))

 ;; I would love to just check the compiled javascript files to see if
 ;; they changed and then just send them to the browser. There is a
@@ -332,6 +336,8 @@
   (doseq [df (dependency-files state)]
     (file-changed? state df))
   (:file-md5-atom state))
+
+

 (defn create-initial-state [{:keys [root name version resource-paths
                                     css-dirs ring-handler http-server-root


fix replace! usage

fix replace! usage

--- labs/architecture-examples/om/src/todomvc/item.cljs
+++ labs/architecture-examples/om/src/todomvc/item.cljs
@@ -17,7 +17,7 @@
     (if-not (string/blank? val)
       (go
         (>! (:save chans) [todo val])
-        (om/replace! todo :title (:edit-text todo)))
+        (om/replace! todo [:title] (:edit-text todo)))
       (put! (:destroy chans) todo))
     false))

@@ -27,23 +27,25 @@
     (let [node (dom/get-node owner "editField")]
       (.focus node)
       (.setSelectionRange (.. node -value -length) (.. node -value -length))))
-  (om/replace! todo :edit-text (:title todo)))
+  (om/replace! todo [:edit-text] (:title todo)))

 (defn handle-key-down [e todo opts]
   (if (identical? (.-keyCode e) ESCAPE_KEY)
-    (om/replace! todo :edit-text (:title todo))
+    (om/replace! todo [:edit-text] (:title todo))
     (handle-submit e todo opts)))

 (defn handle-change [e todo]
-  (om/replace! todo :edit-text (.. e -target -value)))
+  (om/replace! todo [:edit-text] (.. e -target -value)))

-(defn todo-item [{:keys [completed editing] :as todo} {:keys [chans editing]}]
+(defn todo-item [{:keys [id completed] :as todo} {:keys [chans editing]}]
   (reify
     dom/IRender
     (-render [_ owner]
-      (let [m {:owner owner :chans chans}]
-        (dom/li #js {:className (str (and completed "completed") " "
-                                     (and editing "editing"))}
+      (let [m {:owner owner :chans chans}
+            classes (cond-> []
+                      completed (conj "completed")
+                      (= id editing) (conj "editing"))]
+        (dom/li #js {:className (string/join classes " ")}
           (dom/div #js {:className "view"}
             (dom/input #js {:className "toggle"
                             :type "checkbox"


fix error message

fix error message

--- src/metabase/driver/postgres/sync.clj
+++ src/metabase/driver/postgres/sync.clj
@@ -59,6 +59,6 @@
                          :table_id id
                          :name column_name
                          :base_type (or (column->base-type (keyword type_name))
-                                        (throw (Exception. (str "Column " column_name "has an unknown type: " type_name
-                                                                ". Please add the type mapping to metabase.driver.postgres.sync.")))))))
+                                        (throw (Exception. (str "Column '" column_name "' has an unknown type: '" type_name
+                                                                "'. Please add the type mapping to metabase.driver.postgres.sync.")))))))
               @jdbc-columns)))


More efficiently highlight paths.

More efficiently highlight paths.

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/cstorey/nrod.git/'


simplifying meditations macro

simplifying meditations macro

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/'


Clojure Collector: bump lein-ring to 0.12.4 (closes #3783)

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/liveintent-berlin/snowplow.git/'


modern keyword generator

modern keyword generator

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/yokalona/threen.git/'


comment re: defwarp idea

comment re: defwarp idea

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/'


cached-rf core-helper

cached-rf core-helper


source-section heading comments

source-section heading comments


Extract typekit JS, add google analytics JS

--- src/clojars/web/common.clj
+++ src/clojars/web/common.clj
@@ -24,6 +24,18 @@
     (link-to {:target "_blank"}
              "http://www.bendyworks.com/"
              (image "/images/bendyworks_logo_white.png" "Bendyworks Inc."))]])
+
+(defn google-analytics-js []
+  [:script "(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+  ga('create', 'UA-51806851-1', 'clojars.org');
+  ga('send', 'pageview');"])
+
+(defn typekit-js []
+  [:script "try{Typekit.load();}catch(e){}"])

 (defn html-doc [account title & body]
   (html5
@@ -43,7 +55,8 @@
          ;; more info: http://getbootstrap.com/css/#grid
          ["reset.css" "vendor/bootstrap/bootstrap.css" "screen.css"])
     (include-js "//use.typekit.net/zhw0tse.js")
-    [:script "try{Typekit.load();}catch(e){}"]
+    (typekit-js)
+    (google-analytics-js)
     (raw (when-ie (include-js "/js/html5.js")))]
    [:body.container-fluid
     [:div#content-wrapper


add upgrade to reassign

add upgrade to reassign

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/'


add ns to parse md to hiccup, make cljs changelog

error: pathspec 'src/braid/server/markdown.clj' did not match any file(s) known to git

--- src/braid/server/markdown.clj
+++ src/braid/server/markdown.clj
@@ -0,0 +1,48 @@
+(ns braid.server.markdown
+  (:require [instaparse.core :as insta]
+            [clojure.java.io :as io]))
+
+(def markdown-parser
+  "Simple markdown parser. Only parsing enough to handle CHANGELOG.md, so lots
+  is probably missing"
+  (insta/parser
+    "S ::= ( <#'^'> LINE <#'\\n|$'> )*
+    <LINE> ::= ( ( HEADER | LIST ) / PLAIN_LINE )
+    DOT ::= #'.'
+    TEXT ::= #'.*'
+    HEADER ::= #'\\#+' TEXT
+    LIST ::= ( LIST_LINE <'\\n'> ) +
+    LIST_LINE ::= <#'\\s*(-|\\*)'> TEXT
+    PLAIN_LINE ::= TEXT (* TODO: add inline things *)
+    "))
+
+(defn markdown->hiccup
+  "Parse markdown into hiccup."
+  [md-str]
+  (->> (markdown-parser md-str)
+       (insta/transform {:HEADER (fn [delim rst]
+                                   [(keyword (str "h" (count delim)))
+                                    rst]
+                                   )
+                         :TEXT identity
+                         :LIST (fn [& args]
+                                 (vec (cons :ul args)))
+                         :LIST_LINE (fn [txt] [:li txt])
+                         ; TODO: group plain lines into paragraphs
+                         :PLAIN_LINE identity
+                         :S (fn [& args]
+                              (vec (cons :div args)))
+                         })))
+
+(defn generate-changelog
+  []
+  (let [changelog-hiccup (markdown->hiccup (slurp "CHANGELOG.md"))]
+    (with-open [out-f (io/writer "src/braid/client/ui/views/pages/changelog.cljs")]
+      (.write out-f "; THIS FILE IS AUTOMATICALLY GENERATED FROM CHANGELOG.md\n")
+      (.write out-f "; DO NOT EDIT DIRECTLY\n\n")
+      (.write out-f (str '(ns braid.client.ui.views.pages.changelog) "\n"))
+      (.write out-f (str (list 'defn 'changelog-view []
+                           [:div.page.changelog
+                            [:div.title "Changelog"]
+                            [:div.content
+                             changelog-hiccup]]))))))


Add Bundler dependencies parser

Add Bundler dependencies parser

error: pathspec 'src/hu/ssh/github_changelog/dependencies/bundler.clj' did not match any file(s) known to git

--- src/hu/ssh/github_changelog/dependencies/bundler.clj
+++ src/hu/ssh/github_changelog/dependencies/bundler.clj
@@ -0,0 +1,22 @@
+(ns hu.ssh.github-changelog.dependencies.bundler
+  (:require
+    [clojure.string :refer [split-lines]]))
+
+(defn- get-specs [file]
+  (->> (split-lines file)
+       (drop-while #(not= % "  specs:"))
+       (drop 1)
+       (take-while seq)))
+
+(defn- parse-spec [spec]
+  {:gem (second spec) :version (nth spec 2)})
+
+(defn- parse-specs [specs]
+  (->> (map #(re-matches #"^\s{4}(\S+) \((.*)\)$" %) specs)
+       (remove empty?)
+       (map parse-spec)))
+
+(defn parse [file]
+  (->> (slurp file)
+       get-specs
+       parse-specs))


Add datomic task - don't generate with template yet.

error: pathspec 'src/leiningen/new/onyx_app/src/onyx_app/tasks/datomic.clj' did not match any file(s) known to git

--- src/leiningen/new/onyx_app/src/onyx_app/tasks/datomic.clj
+++ src/leiningen/new/onyx_app/src/onyx_app/tasks/datomic.clj
@@ -0,0 +1,37 @@
+(ns {{app-name}}.tasks.datomic
+    (:require [taoensso.timbre :refer [info]]))
+
+(defn add-log-input
+  "Instrument a job with a Datomic log input lifecycles and catalog entries."
+  [job task opts]
+  (-> job
+      (update :catalog conj (merge {:onyx/name task
+                                    :onyx/plugin :onyx.plugin.datomic/read-log
+                                    :onyx/type :input
+                                    :onyx/medium :datomic
+                                    ;; Parameters to be supplied in opts
+                                    ;:onyx/batch-size 20
+                                    ;:datomic/uri db-uri
+                                    ;:datomic/log-start-tx <<OPTIONAL_TX_START_INDEX>>
+                                    ;:datomic/log-end-tx <<OPTIONAL_TX_END_INDEX>>
+                                    ;:checkpoint/force-reset? true
+                                    :onyx/max-peers 1
+                                    :onyx/doc "Reads a sequence of datoms from the d/log API"}
+                                   opts))
+      (update :lifecycles conj {:lifecycle/task task
+                                :lifecycle/calls :onyx.plugin.datomic/read-log-calls})))
+
+(defn add-writer
+  "Instrument a job with a Datomic writer catalog entry and lifecycle"
+  [job task opts]
+  (-> job
+      (update :catalog conj (merge {:onyx/name task
+                                    :onyx/plugin :onyx.plugin.datomic/write-datoms
+                                    :onyx/type :output
+                                    :onyx/medium :datomic
+                                    ;:datomic/uri db-uri
+                                    ;:onyx/batch-size batch-size
+                                    :onyx/doc "Transacts segments to storage"}
+                              opts))
+      (update :lifecycles conj {:lifecycle/task task
+                                :lifecycle/calls :onyx.plugin.datomic/write-tx-calls}})))


Add leiningen config

Add leiningen config


aoc2020 day13

aoc2020 day13

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

--- 2020/src/day13.clj
+++ 2020/src/day13.clj
@@ -0,0 +1,35 @@
+(ns day13
+  (:require [clojure.pprint :refer [pprint]]))
+
+(def test-input [939 [7 13 "x" "x" 59 "x" 31 19]])
+(def input [1008713 [13 "x" "x" 41 "x" "x" "x" "x" "x" "x" "x" "x" "x" 467 "x" "x" "x" "x" "x" "x" "x" "x" "x" "x" "x" 19 "x" "x" "x" "x" 17 "x" "x" "x" "x" "x" "x" "x" "x" "x" "x" "x" 29 "x" 353 "x" "x" "x" "x" "x" 37 "x" "x" "x" "x" "x" "x" "x" "x" "x" "x" "x" "x" "x" "x" "x" "x" 23]])
+
+
+(defn part-1 [input]
+  (let [[ts bus-ids] input
+        [bus-id time] (->> bus-ids
+                           (filter #(not= "x" %))
+                           (map #(vector % (* % (quot (+ ts %) %))))
+                           (sort-by second)
+                           first)]
+    (* bus-id (- time ts))))
+
+
+(pprint (part-1 test-input))
+(pprint (part-1 input))
+
+(defn part-2 [input]
+ (let [input' (->> input
+                   second
+                   (map-indexed vector)
+                   (filter #(not= "x" (second %))))]
+   (first
+    (reduce (fn [[t step] [i n]]
+              (let [t' (->> (iterate #(+ step %) t)
+                            (filter #(zero? (rem (+ % i) n)))
+                            first)]
+                [t' (* step n)]))
+            input'))))
+
+(pprint (part-2 test-input))
+(pprint (part-2 input))


Upgrade datomic to 0.9.5394

Upgrade datomic to 0.9.5394

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/'


move plugins under :dev profile so they don't get built into standalone jar

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/'


fix deps datomic-client problem

fix deps datomic-client problem

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/MitchellJThomas/medir.git/'


Exclude openid4java dependency via friend.

We don't currently use OpenID and openid4java's depdendency on
Google Guice's maven repository has been causing build failures.

--- project.clj
+++ project.clj
@@ -16,7 +16,8 @@
                  [org.apache.commons/commons-email "1.2"]
                  [net.cgrand/regex "1.0.1" :exclusions [org.clojure/clojure]]
                  [clj-time "0.3.8"]
-                 [com.cemerick/friend "0.0.8"]
+                 [com.cemerick/friend "0.0.8"
+                  :exclusions [org.openid4java/openid4java-nodeps]]
                  [clj-stacktrace "0.2.4"]]
   :profiles {:test {:resource-paths ["test-resources"]
                     :dependencies [[kerodon "0.0.6"]


Start 0.2.17-SNAPSHOT.

Start 0.2.17-SNAPSHOT.

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject sablono "0.2.16"
+(defproject sablono "0.2.17-SNAPSHOT"
   :description "Lisp style templating for Facebook's React."
   :url "http://github.com/r0man/sablono"
   :author "Roman Scherer"


Swap order of imports to help git with merging

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/'


bump version

bump version

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject storm "0.8.1-wip2"
+(defproject storm "0.8.1-wip3-SNAPSHOT"
   :source-path "src/clj"
   :test-path "test/clj"
   :java-source-path "src/jvm"


var change

var change

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/clojure-ml/cml.git/'


login form

login form

error: pathspec 'src/cljs/swarmpit/component/user/login.cljs' did not match any file(s) known to git

--- src/cljs/swarmpit/component/user/login.cljs
+++ src/cljs/swarmpit/component/user/login.cljs
@@ -0,0 +1,48 @@
+(ns swarmpit.component.user.login
+  (:require [swarmpit.material :as material :refer [svg]]
+            [rum.core :as rum]))
+
+(defonce state (atom {:email    ""
+                      :password ""}))
+
+(defn- update-item
+  "Update form item configuration"
+  [k v]
+  (swap! state assoc k v))
+
+(defn- form-email [value]
+  (material/theme
+    (material/text-field
+      #js {:id                "loginEmail"
+           :floatingLabelText "Email"
+           :value             value
+           :onChange          (fn [e v] (update-item :email v))})))
+
+(defn- form-password [value]
+  (material/theme
+    (material/text-field
+      #js {:id                "loginPassword"
+           :floatingLabelText "Password"
+           :type              "password"
+           :value             value
+           :onChange          (fn [e v] (update-item :password v))})))
+
+(defn- form-button []
+  (material/theme
+    (material/raised-button
+      #js {:className "login-btn"
+           :label     "Login"
+           :primary   true})))
+
+(rum/defc form < rum/reactive []
+  (let [{:keys [email
+                password]} (rum/react state)]
+    [:div.login-back
+     [:div.login
+      (form-email email)
+      (form-password password)
+      (form-button)]]))
+
+(defn mount!
+  []
+  (rum/mount (form) (.getElementById js/document "layout")))


Add new valuta function/data

Add new valuta function/data

error: pathspec 'src/clj_simple_chart/ssb/valuta2.clj' did not match any file(s) known to git

--- src/clj_simple_chart/ssb/valuta2.clj
+++ src/clj_simple_chart/ssb/valuta2.clj
@@ -0,0 +1,30 @@
+(ns clj-simple-chart.ssb.valuta2
+  (:require [clj-http.client :as client]
+            [clj-simple-chart.csv.csvmap :as csv]
+            [clojure.set :as set]
+            [clojure.string :as str]))
+
+(def valuta-url
+  (str "https://data.norges-bank.no/api/data/EXR/M..NOK.SP"
+       "?startPeriod=1900-01-01&endPeriod=2119-09-21"
+       "&format=csv&locale=no"))
+
+(defonce resp (client/get valuta-url))
+
+(def data (->> (csv/csv-map-assert-columns (:body resp) [] :separator \;)
+               :data
+               (filter #(= "USD" (:BASE_CUR %)))
+               (mapv #(set/rename-keys % {:OBS_VALUE :usd
+                                          :TIME_PERIOD :dato}))
+               (mapv #(select-keys % [:usd :dato]))
+               (mapv #(update % :usd (fn [x] (Double/valueOf (str/replace x "," ".")))))
+               (sort-by :dato)))
+
+(def one-usd-numeric-12-mma
+  (->> data
+       (map-indexed (fn [idx x] (assoc x :prev-rows (take-last 12 (take (inc idx) data)))))
+       (filter #(= 12 (count (:prev-rows %))))
+       (mapv #(assoc % :usd (/ (reduce + 0 (mapv :usd (:prev-rows %))) 12)))
+       (mapv #(dissoc % :prev-rows))))
+
+(def one-usd-date-to-nok (reduce (fn [o v] (assoc o (:dato v) (:usd v))) {} one-usd-numeric-12-mma))


remove console log

remove console log


Add flow-controls examples

Add flow-controls examples

error: pathspec 'src/clojure/cjfn/07_control_flow.clj' did not match any file(s) known to git

--- src/clojure/cjfn/07_control_flow.clj
+++ src/clojure/cjfn/07_control_flow.clj
@@ -0,0 +1,197 @@
+(ns cjfn.07-control-flow
+  (:require [clojure.java.io :as io]))
+
+;; if-do
+(if (even? 5)
+  (do
+    (println "even")
+    true)
+  (do (println "odd")
+      false)) ;; false
+
+;; if-let
+(if-let [x (even? 3)]
+  (str "x is :" x)
+  (str "some odd value")) ;; "some odd value"
+
+;; Empty list is truthy
+(if ()
+  "I am empty and is truthy!"
+  "I am empty and is falsey") ;; "I am empty and is truthy!"
+
+;; Note:
+(filter even? [1 3 5]) ;; () ;; which is truthy!
+
+(seq (filter even? [1 3 5])) ;; nil ;; which is falsey!
+1
+(defn show-evens [cols]
+  (if-let [evens (seq (filter even? cols))]
+    (str "The evens numbers are: " evens)
+    (str "There were no evens in : " cols)))
+
+;; if we have the condition
+(show-evens [1 2 3 4 5 6 7 8 9 10]) ;; "The evens numbers are: (2 4 6 8 10)"
+
+;; If we have no matching number
+(show-evens '[1 3 5 7]) ;; "There were no evens in : [1 3 5 7]"
+
+;; 07-09: cond
+(defn what-am-i [x]
+  (cond
+    (< x 2) "x is less than 2"
+    (< x 10) "x is less than 10"
+    :else "x is greater than or equal to 10"))
+
+(what-am-i 1) ;; "x is less than 2"
+(what-am-i 3) ;; "x is less than 10"
+(what-am-i 11);; "x is greater than or equal to 10"
+
+;; 07-10: condp, shared predicate
+(defn describe-number [x]
+  (condp = x
+    5 "x is 5"
+    10 "x is 10"
+    "x is neither 5 nor 10"))
+
+(describe-number 10) ;; "x is 10"
+(describe-number 5)  ;; "x is 5"
+(describe-number 20) ;; "x is neither 5 nor 10"
+
+;; 07-11: cases
+
+(defn case-demo [x]
+  (case x
+    5 "x is 5"
+    10 "x is 10"
+    "x is neither 5 nor 10"))
+
+(case-demo 10) ;;"x is 10"
+(case-demo 5)  ;;"x is 5"
+(case-demo 30) ;;"x is neither 5 nor 10"
+
+;; 07-12: demo
+(defn str-binary [n]
+  (cond
+    (= n 0) "zero"
+    (= n 1) "one"
+    :else "unknown"))
+
+(str-binary 0) ;; "zero"
+(str-binary 1) ;; "one"
+(str-binary 3) ;; "unknown"
+
+(defn str-binary-p [n]
+  (condp = n
+    0 "zero"
+    1 "one"
+    "unknown"))
+
+(str-binary-p 0) ;; "zero"
+(str-binary-p 1) ;; "one"
+(str-binary-p 20);; "unknown"
+
+(defn str-binary-case [n]
+  (case n
+    0 "zero"
+    1 "one"
+    "unknown"))
+
+(str-binary-case 1)  ;; "one"
+(str-binary-case 0)  ;; "zero"
+(str-binary-case 30) ;; "unknown"
+
+;; 07-14: doseq
+(doseq [n (range 3)]
+  ;; comes with side-effect
+  (println n))
+
+(doseq [x (range 3)
+        y (range 5)]
+  (println x y))
+
+;; 07-15: dotimes
+(dotimes [i 3]
+  (println i)) ;; will print 0, 1, 2
+
+;; 07-17: for for sequence permutation
+(for [x [0 1]
+      y [2 3]]
+  [x y]) ;; ([0 2] [0 3] [1 2] [1 3])
+
+;; 07-18: loop/recur
+(loop [i 0]
+  (if (< i 10)
+    (recur (inc i))
+    i)) ;; 10
+
+;; 7-19: defn/recur
+(defn increase [i]
+  "Increment a number less than 10 to at most 10,
+  otherwise just return that number"
+  (if (< i 10)
+    (recur (inc i))
+    i))
+
+(increase 1)  ;; 10
+(increase 3)  ;; 10
+(increase 20) ;; 20
+
+;; 07-21: recur for recursively function
+(defn factorial-with-problem
+  "Factorial that will not work well with large number"
+  ([n] (factorial 1 n))
+  ([acc n]
+   (if (zero? n)
+     acc
+     (factorial (* acc n) (dec n)))))
+
+(factorial-with-problem 5) ;; 120
+
+;; (factorial-with-problem 100) ;; => StackOverflow
+
+;; Note: still have the problem with large number
+;; See: http://noahlz.github.io/factorials/factorials.core.html
+
+;; (defn factorial-ok
+;;   "Factorial that work with larger number"
+;;   ([n] (factorial-ok 1 n))
+;;   ([acc n]
+;;    (if (zero? n)
+;;      acc
+;;      (recur (* acc n) (dec n)))))
+;; (factorial-ok 100)
+
+;; (defn factorial-with-recur [n]
+;;   (loop [current n
+;;          next (dec current)
+;;          total 1]
+;;     (if (> current 1)
+;;        (recur next (dec next) (* total current))
+;;        total)))
+
+;; (factorial-with-recur 5)  ;;
+;; (factorial-with-recur 20) ;; 2432902008176640000
+
+;; 07-22: Exception handling
+(defn try-exception [x y]
+  (try
+    (/ x y)
+    (catch ArithmeticException e
+      "devided by zero!")
+    (finally
+      (println "Cleanup.."))))
+
+(try-exception 1 2) ;; 1/2
+(try-exception 1 0) ;; "devided by zero!"
+
+;; 07-23: thowing exceptions
+(try
+  (throw (Exception. "Something went wrong"))
+  (catch Exception e (.getMessage e))) ;; "Something went wrong"
+
+;; 07-24: with-open
+(require '[clojure.java.io :as io])
+
+;; resource will be closed automatically
+(with-open [f (io/writer "/tmp/new")]
+  (.write f "some-text"))


Rough fleshing out of pin-ctrl-simulator implementation

error: pathspec 'src/clj_bots/pin_ctrl_simulator/implementation.clj' did not match any file(s) known to git

--- src/clj_bots/pin_ctrl_simulator/implementation.clj
+++ src/clj_bots/pin_ctrl_simulator/implementation.clj
@@ -0,0 +1,152 @@
+(ns clj-bots.pin-ctrl-simulator.implementation
+  (:require [clj-bots.pin-ctrl
+             [protocols :as pcp]
+             [implementation :as impl]]
+            [clojure.core.async :as async :refer [chan >!! <!! go <! >! go-loop]]))
+
+(def full-available-modes
+  #{:input :output :input-rising :input-falling :input-both :ain :aout :pwm})
+
+(def available-modes
+  #{:gpio :ain :aout :pwm})
+
+(def mode-mapping
+  {:gpio [:input :output :input-rising :input-falling :input-both]
+   :ain  [:ain]
+   :aout [:aout]
+   :pwm  [:pwm]})
+
+(declare current-pin-modes)
+
+(defmulti read-pin*
+  "Inner method for reading from a pin; dispatches on pin mode"
+  (fn [board pin-n]
+    (get (current-pin-modes board) pin-n)))
+
+(declare current-pin-mode writeable-pin? ok-val?)
+
+(defrecord SimBoard
+  [pin-state pin-modes edge-channels config]
+  pcp/PBoard
+  (pin-modes [_] (:pin-modes config))
+  (current-pin-modes [_] @pin-modes)
+  (get-config [_] config)
+  (update-config [this f] (update-in this [:config] f))
+
+  pcp/POverwireBoard
+  (reset-board! [_]
+    (if (= (:board-class config) :overwire)
+      (do (reset! pin-modes)
+          (reset! pin-state))
+      (println "This option is not available for onboard boards")))
+
+  pcp/PPinConfigure
+  (set-mode! [_ pin-n mode]
+    (swap! pin-modes assoc pin-n mode))
+
+  pcp/PReadablePin
+  (read-value [board pin-n]
+    (read-pin* board pin-n))
+
+  pcp/PAinPin
+  (read-raw-value [board pin-n]
+    (assert (= (current-pin-mode board pin-n) :ain)
+            "Only :ain pins have raw values")
+    (get @pin-state pin-n))
+
+  pcp/PWriteablePin
+  (write-value! [board pin-n val]
+    (assert (writeable-pin? board pin-n)
+            (str "Pins of mode " (current-pin-mode board pin-n) " are not writeable"))
+    (assert (ok-val? board pin-n val)
+            (str "The value " val " is not an acceptable value for pins of type " (current-pin-mode board pin-n)))
+    (swap! pin-state pin-n val))
+
+  pcp/PEdgeDetectablePin
+  (set-edge! [board pin-n edge buffer]
+    (if (= :none edge)
+      (swap! edge-channels dissoc pin-n)
+      (let [[c m] (or (get @edge-channels pin-n)
+                      (let [c (chan buffer)]
+                        [c (async/mult c)]))
+            match (case edge
+                    (:rising "rising")   #{:high}
+                    (:falling "falling") #{:low}
+                    (:both "both")       #{:high :low})]
+        (swap! edge-channels assoc pin-n [c m]
+        (add-watch pin-state
+                   ; May have to have board ids involved in this scheme for overwire;
+                   ; should have global registry of these board ids XXX
+                   (symbol (str "edge-detection-watch-simulator" pin-n))
+                   (fn [_ _ _ new-val]
+                     (when (match new-val)
+                       (>!! c new-val))))))))
+  (get-edge-mult [board pin-n]
+    (second (get @edge-channels pin-n))))
+
+(defmethod read-pin* :input
+  [board pin-n]
+  (get (deref (:pin-state board)) pin-n))
+
+(defmethod read-pin* :output
+  [board pin-n]
+  (get (deref (:pin-state board)) pin-n))
+
+(defn get-bits
+  [board pin-n]
+  (get-in board [:config :analog-bits pin-n]))
+
+(defmethod read-pin* :ain
+  [board pin-n]
+  (double (/ (get (deref (:pin-state board)) pin-n)
+             (get-bits board pin-n))))
+
+
+(defn current-pin-mode
+  [board pin-n]
+  (get (current-pin-modes board) pin-n))
+
+(defn writeable-pin?
+  [board pin-n]
+  (#{:output :aout} (current-pin-mode board pin-n)))
+
+(defn ok-val?
+  [board pin-n val]
+  (case (current-pin-mode board pin-n)
+    :output (#{0 1 \0 \1 :high :low} val)
+    :aout   (fn [n]
+              (and (integer? n)
+                   (>= n 0)
+                   (< (Math/pow 2 (get-bits board pin-n)))))
+    false))
+
+(defn sim-board
+  [config]
+  (SimBoard.
+    (atom {})
+    (atom {})
+    (atom {})
+    config))
+
+(defn random-config
+  [n-pins]
+  {:pin-modes
+   (into {}
+         (for [i (range n-pins)]
+           [[(rand-nth [:P8 :P9]) i]
+            (filterv
+              (fn [_] (> (rand) 0.68))
+              available-modes)]))})
+
+(def implementation
+  (reify
+    Object
+    (toString [_]
+      "<BoardSimulator>")
+    pcp/PPinCtrlImplementation
+    (create-board [_ config]
+      (sim-board config))
+    (default-config [_]
+      (pcp/default-config 100))))
+
+


use plan name instead

use plan name instead


Clean up reports

Clean up reports

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/mtravers/incidents.git/'


fix resolver errors during development

fix resolver errors during development


Add check for eraser

Add check for eraser

--- src-clj/acha/achievement.clj
+++ src-clj/acha/achievement.clj
@@ -150,7 +150,7 @@
 (def eraser
   (make-loc-scanner
     [:eraser
-    (fn [loc] (nil? (:added loc 0)))]))
+    (fn [loc] (= 0 (:added loc 0)))]))

 (def massive
   (make-loc-scanner


add test conditions that the authority id's remain constant


add somewhat complete app ns (old examples)

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

--- src/clojocular/app.clj
+++ src/clojocular/app.clj
@@ -0,0 +1,110 @@
+(ns clojocular.app
+  (:require [clojocular.utils :as utils])
+  (:import [org.lwjgl.opengl GL11]
+           org.lwjgl.opengl.GLContext
+           [java.awt Rectangle]
+           [org.lwjgl.opengl ContextAttribs PixelFormat]
+           [org.saintandreas.gl FrameBuffer MatrixStack OpenGL]
+           [org.saintandreas.gl.app LwjglApp]
+           [org.saintandreas.gl.buffers VertexArray]
+           [org.saintandreas.math Matrix4f]
+
+           [com.oculusvr.capi EyeRenderDesc FovPort HmdDesc OvrLibrary
+            OvrVector2i Posef RenderAPIConfig Texture TextureHeader]
+           com.oculusvr.capi.OvrLibrary$ovrRenderAPIType
+           com.oculusvr.capi.FovPort$ByValue
+           com.oculusvr.capi.OvrLibrary$ovrHmd
+           com.oculusvr.capi.OvrLibrary$ovrHmdType
+           ))
+
+(comment
+ (let [projections [(Matrix4f.) (Matrix4f.)]]
+   projections))
+
+(def ipd (. OvrLibrary OVR_DEFAULT_IPD))
+
+(def get-hmd
+  (memoize (fn [] (OvrLibrary$ovrHmd/createDebug OvrLibrary$ovrHmdType/ovrHmd_DK1))))
+
+(comment
+ (. OvrLibrary/INSTANCE ovr_Initialize)
+ (get-hmd)
+ (.getDesc (get-hmd)))
+
+; (OvrLibrary$ovrHmd.)
+; (. (OvrLibrary$ovrHmd.) destroy)
+; (. (get-hmd) destroy)
+
+(comment
+ (.getFloat (get-hmd) OvrLibrary/OVR_KEY_IPD ipd))
+
+; (.startSensor hmd 0 0)
+; (.WindowsPos hmd-desc)
+; (get (.EyeRenderOrder hmd-desc) 0)
+; (get (.EyeRenderOrder hmd-desc) 1)
+; (.beginEyeRender (get-hmd) 0)
+; (.beginEyeRender (get-hmd) 1)
+
+; (GL11/glViewport 0 0 10 10)
+
+(defn target-rect [hmd-desc]
+  (System/setProperty "org.lwjgl.opengl.Window.undecorated" "true")
+  (let [pixel-format (.withDepthBits (.withSamples (PixelFormat.) 4) 16)
+        context-attributes (-> (ContextAttribs. 4 4)
+                               (.withForwardCompatible true)
+                               (.withProfileCore true)
+                               (.withDebug true))
+        target-rect (Rectangle. (.x (.WindowsPos hmd-desc))
+                                (.y (.WindowsPos hmd-desc))
+                                (.w (.Resolution hmd-desc))
+                                (.h (.Resolution hmd-desc)))]
+    target-rect))
+
+; (target-rect hmd-desc)
+
+; (. (OvrLibrary/INSTANCE) ovrMatrix4f_Projection)
+; (. OvrLibrary INSTANCE ovrMatrix4f_Projection)
+
+; TODO Debug
+(comment
+ (System/setProperty "org.lwjgl.util.Debug" "true"))
+; TODO Debug
+
+; (useContext nil)
+(proxy [LwjglApp] []
+  (setupDisplay
+    ([] (proxy-super
+         setupDisplay
+         (target-rect (.getDesc (get-hmd))))))
+  (initGl
+    ([]
+     (let [hmd (get-hmd)
+           hmd-desc (.getDesc hmd)
+           fov-ports
+           (for [eye [0 1]
+                 :let [default-eye-fov (get (. hmd-desc DefaultEyeFov) eye)
+                       fov-port
+                       (doto (FovPort$ByValue.)
+                         (-> .DownTan (set! (.DownTan default-eye-fov)))
+                         (-> .UpTan (set! (.UpTan default-eye-fov)))
+                         (-> .LeftTan (set! (.LeftTan default-eye-fov)))
+                         (-> .RightTan (set! (.RightTan default-eye-fov))))
+                       projection (. (OvrLibrary/INSTANCE)
+                                     ovrMatrix4f_Projection
+                                     fov-port 0.1 10000 (byte 1))
+                       eth (let [texture-size (.getFovTextureSize hmd eye fov-port 1.0)]
+                             (doto (.Header (Texture.))
+                               (-> .TextureSize (set! texture-size))
+                               (-> .RenderViewport .Size (set! texture-size))
+                               (-> .RenderViewport .Pos (set! (OvrVector2i. 0 0)))
+                               (-> .API (set! OvrLibrary$ovrRenderAPIType/ovrRenderAPI_OpenGL))))
+                       frame-buffer (FrameBuffer. (.w (.TextureSize eth))
+                                                  (.h (.TextureSize eth)))
+                       eye-texture-id (.id (.getTexture frame-buffer))
+                       ]]
+             ; eth
+             ; frame-buffer
+             eye-texture-id
+             ; [projection fov-port]
+                )]
+          fov-ports))))


Send them as a separate user.

Send them as a separate user.

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/'


Add Alan Dipert's implementation of Kahn's topological sort algorithm.

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/cstorey/nrod.git/'


Add some basic hipchat tests

Add some basic hipchat tests

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

--- test/riemann/hipchat_test.clj
+++ test/riemann/hipchat_test.clj
@@ -0,0 +1,55 @@
+(ns riemann.hipchat-test
+  (:use riemann.hipchat
+        clojure.test)
+  (:require [riemann.logging :as logging]))
+
+(def api-key (System/getenv "HIPCHAT_API_KEY"))
+(def room (System/getenv "HIPCHAT_ALERT_ROOM"))
+(def alert_user "Riemann_HC_Test")
+
+(when-not api-key
+  (println "export HIPCHAT_API_KEY=\"...\" to run these tests."))
+
+(when-not room
+  (println "export HIPCHAT_ALERT_ROOM=\"...\" to run these tests."))
+
+(logging/init)
+
+(deftest good_event
+  (let [hc (hipchat {:token api-key :room room :from alert_user :notify 0})]
+    (hc {:host "localhost"
+         :service "hipchat test good"
+         :metric 42
+         :state "ok"})))
+
+(deftest error_event
+  (let [hc (hipchat {:token api-key :room room :from alert_user :notify 0})]
+    (hc {:host "localhost"
+         :service "hipchat test error"
+         :metric 43
+         :state "error"})))
+
+(deftest critical_event
+  (let [hc (hipchat {:token api-key :room room :from alert_user :notify 0})]
+    (hc {:host "localhost"
+         :service "hipchat test critical"
+         :metric 44
+         :state "critical"})))
+
+(deftest yellow
+  (let [hc (hipchat {:token api-key :room room :from alert_user :notify 0})]
+    (hc {:host "localhost"
+         :service "hipchat test yellow"
+         :metric 45
+         :state "unknown"})))
+
+(deftest multiple_events
+  (let [hc (hipchat {:token api-key :room room :from alert_user :notify 0})]
+    (hc [{:host "localhost"
+          :service "hipchat multi 1"
+          :metric 46
+          :state "ok"}
+         {:host "localhost"
+          :service "hipchat multi 2"
+          :metric 47
+          :state "ok"}])))


Actually, let's use the in-memory store

Actually, let's use the in-memory store

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/ben-biddington/solace.git/'


CMR-2148: Moved migration to avoid conflict

error: pathspec 'metadata-db-app/src/migrations/025_create_groups_table.clj' did not match any file(s) known to git

--- metadata-db-app/src/migrations/025_create_groups_table.clj
+++ metadata-db-app/src/migrations/025_create_groups_table.clj
@@ -0,0 +1,54 @@
+(ns migrations.025-create-groups-table
+  (:require [clojure.java.jdbc :as j]
+            [config.migrate-config :as config]
+            [config.mdb-migrate-helper :as h]))
+
+(def ^:private groups-column-sql
+  "id NUMBER,
+  concept_id VARCHAR(255) NOT NULL,
+  native_id VARCHAR(1030) NOT NULL,
+  provider_id VARCHAR(10),
+  metadata BLOB NOT NULL,
+  format VARCHAR(255) NOT NULL,
+  revision_id INTEGER DEFAULT 1 NOT NULL,
+  revision_date TIMESTAMP WITH TIME ZONE DEFAULT SYSTIMESTAMP NOT NULL,
+  deleted INTEGER DEFAULT 0 NOT NULL,
+  user_id VARCHAR(30)")
+
+(def ^:private groups-constraint-sql
+  (str "CONSTRAINT cmr_groups_pk PRIMARY KEY (id), "
+       ;; Unique constraint on provider-id, native id and revision id
+       "CONSTRAINT cmr_groups_pnid_rev UNIQUE (provider_id, native_id, revision_id)
+       USING INDEX (create unique index cmr_groups_nr_i ON cmr_groups (provider_id, native_id, revision_id)), "
+
+       ;; Unique constraint on provider-id, concept id and revision id
+       "CONSTRAINT cmr_groups_pcid_rev UNIQUE (provider_id, concept_id, revision_id)
+       USING INDEX (create unique index cmr_groups_cr_i ON cmr_groups (provider_id, concept_id, revision_id))"))
+
+(defn- create-groups-table
+  []
+  (h/sql (format "CREATE TABLE METADATA_DB.cmr_groups (%s, %s)" groups-column-sql groups-constraint-sql)))
+
+
+(defn- create-groups-indices
+  []
+  (h/sql "CREATE INDEX cmr_groups_crdi ON cmr_groups (concept_id, revision_id, deleted)"))
+
+(defn- create-groups-sequence
+  []
+  (h/sql "CREATE SEQUENCE cmr_groups_seq"))
+
+(defn up
+  "Migrates the database up to version 24."
+  []
+  (println "migrations.024-setup-groups-table up...")
+  (create-groups-table)
+  (create-groups-indices)
+  (create-groups-sequence))
+
+(defn down
+  "Migrates the database down from version 24."
+  []
+  (println "migrations.024-setup-groups-table down...")
+  (h/sql "DROP SEQUENCE METADATA_DB.cmr_groups_seq")
+  (h/sql "DROP TABLE METADATA_DB.cmr_groups"))


Delete 3scale client tests

Delete 3scale client tests

It's so simple now there's hardly anything worth testing. Yay!

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/'


fix selected behavior

fix selected behavior

--- labs/architecture-examples/om/src/todomvc/app.cljs
+++ labs/architecture-examples/om/src/todomvc/app.cljs
@@ -48,7 +48,8 @@
                          #js {:id "clear-completed"
                               :onClick #(put! (:clear chans) (now))}
                          (str "Clear completed " completed)))
-        selected (zipmap [:all :active :completed] (repeat "select"))]
+        selected (-> (zipmap [:all :active :completed] (repeat ""))
+                     (assoc showing "selected"))]
     (dom/component
       (dom/footer #js {:id "footer"}
         (dom/span #js {:id "todo-count"}
@@ -56,13 +57,13 @@
           (str " " (pluralize active "item") " left"))
         (dom/ul #js {:id "filters"}
           (dom/li nil
-            (dom/a #js {:href "#/" :className (selected showing)}
+            (dom/a #js {:href "#/" :className (selected :all)}
               "All"))
           (dom/li nil
-            (dom/a #js {:href "#/active" :className (selected showing)}
+            (dom/a #js {:href "#/active" :className (selected :active)}
               "Active"))
           (dom/li nil
-            (dom/a #js {:href "#/completed" :className (selected showing)}
+            (dom/a #js {:href "#/completed" :className (selected :completed)}
               "Completed"))
           clear-button)))))

@@ -123,7 +124,8 @@
                          :onKeyDown #(handle-new-todo-keydown % app owner)})
                   (om/render main app [:todos] chans)
                   (om/render footer app []
-                    {:active active :completed completed :chans chans})]))))))
+                    {:active active :completed completed
+                     :chans chans :showing :all})]))))))

 (om/root app-state todo-app (.getElementById js/document "todoapp"))


Hide footer and toggle-all when there are no todo items

--- labs/architecture-examples/om/src/todomvc/app.cljs
+++ labs/architecture-examples/om/src/todomvc/app.cljs
@@ -47,9 +47,12 @@
     :active (not (:completed todo))
     :completed (:completed todo)))

-(defn main [{:keys [showing] :as app} opts]
+(defn main [{:keys [showing todos] :as app} opts]
   (om/component
-    (dom/section #js {:id "main"}
+    (dom/section #js {:id "main"
+                      :style (if (empty? todos)
+                               #js {:display "none"}
+                               #js {})}
       (dom/input #js {:id "toggle-all" :type "checkbox"
                       :onChange #(toggle-all % app)})
       (dom/ul #js {:id "todo-list"}
@@ -74,7 +77,10 @@
         sel (-> (zipmap [:all :active :completed] (repeat ""))
                 (assoc showing "selected"))]
     (om/component
-      (dom/footer #js {:id "footer"}
+      (dom/footer #js {:id "footer"
+                       :style (if (empty? todos)
+                                #js {:display "none"}
+                                #js {})}
         (dom/span #js {:id "todo-count"}
           (dom/strong nil count)
           (str " " (pluralize count "item") " left"))


Refactor electorates-from-election

Refactor electorates-from-election

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/'


finished most difficult transactional test

--- test/clj/backtype/storm/transactional_test.clj
+++ test/clj/backtype/storm/transactional_test.clj
@@ -18,7 +18,7 @@

 ;;  what about testing that the coordination is done properly?
 ;;  can check that it receives all the prior tuples before finishbatch is called in the full topology
-;;  should test that it commits even when receiving no tuples (and test that finishBatch is called before commit in this case)
+;;

 ;; * Test that it repeats the meta for a partitioned state (test partitioned emitter on its own)
@@ -284,16 +284,6 @@
         (.close state)
         ))))

-
-
-;; * Test that commit isn't considered successful until the entire tree has been completed (including tuples emitted from commit method)
-;;      - test the full topology (this is a test of acking/anchoring)
-;; * Test that batch isn't considered processed until the entire tuple tree has been completed
-;;      - test the full topology (this is a test of acking/anchoring)
-;; * Test that it picks up where it left off when restarting the topology
-;;      - run topology and restart it
-
-
 (defn mk-transactional-source []
   (HashMap.))

@@ -332,7 +322,7 @@
      (RegisteredGlobalState/clearState id#)
     ))

-;; cluster-map topology :mock-sources {} :storm-conf {}
+
 (deftest test-transactional-topology
   (with-tracked-cluster [cluster]
     (with-controller-bolt [controller collector tuples]
@@ -378,8 +368,7 @@
                                {0 [["dog" 3]
                                    ["cat" 4]
                                    ["apple" 1]
-                                   ["dog" 3]
-                                   ["banana" 0]]
+                                   ["dog" 3]]
                                 1 [["cat" 1]
                                    ["mango" 4]]
                                 2 [["happy" 11]
@@ -405,6 +394,17 @@
                          (doseq [t to-ack]
                            (.ack @collector t)))))

+       (bind fail-tx! (fn [txid]
+                        (let [[to-fail not-to-fail] (separate
+                                                     #(-> %
+                                                          (.getValue 0)
+                                                          .getTransactionId
+                                                          (= txid))
+                                                     @tuples)]
+                          (reset! tuples not-to-fail)
+                          (doseq [t to-fail]
+                            (.fail @collector t)))))
+
        ;; only check default streams
        (bind verify! (fn [expected]
                        (let [results (-> topo-info :capturer .getResults)]
@@ -418,8 +418,6 @@
                          )))

        (tracked-wait topo-info 2)
-       (println "Controlled: " @tuples)
-       (println "Captured:" (-> topo-info :capturer .getResults))
        (verify! {"sum" [[1 "dog" 3]
                         [1 "cat" 5]
                         [1 "mango" 6]
@@ -440,31 +438,75 @@
                            [1 "cat" 2]
                            [1 "mango" 2]
                            [1 "happy" 2]]})
+
+       (add-transactional-data data
+                               {0 [["a" 1]
+                                   ["b" 2]
+                                   ["c" 3]]
+                                1 [["d" 4]
+                                   ["c" 1]]
+                                2 [["a" 2]
+                                   ["e" 7]
+                                   ["c" 11]]
+                                3 [["a" 2]]})
+
        (ack-tx! 1)
+       (tracked-wait topo-info 1)
+       (verify! {"sum" [[3 "a" 5]
+                        [3 "b" 2]
+                        [3 "d" 4]
+                        [3 "c" 1]
+                        [3 "e" 7]]
+                 "count" []
+                 "count2" []})
+       (ack-tx! 3)
+       (ack-tx! 2)
+       (tracked-wait topo-info 1)
+       (verify! {"sum" []
+                 "count" [[2 "apple" 1]
+                          [2 "dog" 1]
+                          [2 "zebra" 1]]
+                 "count2" [[2 "apple" 2]
+                           [2 "dog" 2]
+                           [2 "zebra" 2]]})
+
+       (fail-tx! 2)
+       (tracked-wait topo-info 1)
+
+       (verify! {"sum" [[2 "apple" 1]
+                        [2 "dog" 3]
+                        [2 "zebra" 1]]
+                 "count" []
+                 "count2" []})
+       (ack-tx! 2)
+       (tracked-wait topo-info 1)

-       ;; ack the commit
-       ;; check that third batch is emitted
-       ;; ack the third batch
-       ;; check that the fourth batch is emitted
-       ;; ack the second batch
-       ;; check that the second batch is committed
-       ;; fail the commit
-       ;; check that second batch is emitted again
-       ;; ack the second batch
-       ;; commit the second batch...
-       ;; check that third batch is committed
+       (verify! {"sum" []
+                 "count" [[2 "apple" 1]
+                          [2 "dog" 1]
+                          [2 "zebra" 1]]
+                 "count2" [[2 "apple" 2]
+                           [2 "dog" 2]
+                           [2 "zebra" 2]]})

-       ;;       (println (read-tuples results "count"))
+       (ack-tx! 2)
+
+       (tracked-wait topo-info 2)
+       (verify! {"sum" [[4 "c" 14]]
+                 "count" [[3 "a" 3]
+                          [3 "b" 1]
+                          [3 "d" 1]
+                          [3 "c" 1]
+                          [3 "e" 1]]
+                 "count2" [[3 "a" 2]
+                           [3 "b" 2]
+                           [3 "d" 2]
+                           [3 "c" 2]
+                           [3 "e" 2]]})
+
        (-> topo-info :capturer .getAndClearResults)
        ))))

-{0 [["dog" 3]
-    ["cat" 4]
-    ["apple" 1]
-    ["dog" 3]
-    ["banana" 0]]
- 1 [["cat" 1]
-    ["mango" 4]]
- 2 [["happy" 11]
-    ["mango" 2]
-    ["zebra" 1]]}
+;; TODO: should test that it commits even when receiving no tuples (and test that finishBatch is called before commit in this case)
+;; TODO: ;; * Test that it picks up where it left off when restarting the topology
+;;      - run topology and restart it


SVG records and protocols

SVG records and protocols

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

--- src/clj/brutha/svg.clj
+++ src/clj/brutha/svg.clj
@@ -0,0 +1,89 @@
+(ns brutha.svg
+  (:require [brutha.scene :as bs]
+            [brutha.layer :as bl]
+            [brutha.view :as bv]
+            [brutha.geo :as geo]
+            [brutha.shape :as bsh])
+  (:import [brutha.shape RefShape TransformedShape]))
+
+(defprotocol ISvg
+  (-dims [s])
+  (-defs [s])
+  (-shapes [s]))
+
+(defn svg? [s]
+  (satisfies? ISvg s))
+
+(defprotocol IShape
+  (-shape [s]))
+
+(extend-protocol IShape
+  RefShape
+  (-shape [s]
+    (bsh/id s))
+  TransformedShape
+  (-shape [s]
+    (-shape (:shape s))))
+
+(defn shape? [s]
+  (satisfies? IShape s))
+
+(defrecord SvgShape [id shape]
+  bsh/IShape
+  (-position [_]
+    [0 0])
+  (-id [_]
+    id)
+  (-scale [_]
+    [1 1])
+  IShape
+  (-shape [_]
+    shape))
+
+(defn shape
+  ([s]
+     (shape s nil))
+  ([s id]
+     (->SvgShape id s)))
+
+(defrecord SvgGroup [shapes]
+  bsh/IShape
+  (-position [_]
+    [0 0])
+  (-scale [_]
+    [1 1])
+  (-id [_]
+    nil)
+  IShape
+  (-shape [_]
+    shapes))
+
+(defn group [shapes]
+  (->SvgGroup shapes))
+
+(defrecord Svg [scene defs]
+  ISvg
+  (-dims [_]
+    (let [v (bs/view scene)
+          b (bv/bounds v)]
+      (geo/dims b)))
+  (-defs [_]
+    (vals defs))
+  (-shapes [_]
+    (->> scene
+        bs/layers
+        (map bl/shapes)
+        group))
+  bs/IScene
+  (-view [_]
+    (bs/view scene))
+  (-layers [_]
+    (bs/layers scene))
+  (-add-shape [s sh z]
+    (update-in s [:scene] bs/add-shape sh z)))
+
+(defn svg
+  ([s]
+     (svg s {}))
+  ([s d]
+     (->Svg s d)))


Do not publish messages inside atom swap

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/'


117 initial ns added

117 initial ns added

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

--- src/etaoin/element.clj
+++ src/etaoin/element.clj
@@ -0,0 +1,12 @@
+(ns etaoin.element)
+
+(defrecord Element [id])
+
+(defn el? [el]
+  (instance? Element el))
+
+(defn el [id]
+  (->Element id))
+
+(defn id [el]
+  (:id el))


Always return a promise from attribute-info-async

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/leif47/immutabledb-experimental.git/'


Fix: reintroduce style needed for ellipsis in...

... item texts. Without this fix, the item boxes would just grow and
grow as the amount of text increased, pushing the static sidebar on
the left out of the browser.

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/Reefersleep/sleepydo.git/'


Use pre-calcuated coordinates when build quad-tree.


implements has-verified-financials

implements has-verified-financials

and moves the meat of `bank-accounts` into a helper function, since that
information is needed by more than one resolver.

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/'


replace dummy property data in catalogs view


add namespace for calling dokkaa APIs

add namespace for calling dokkaa APIs

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

--- src/cljs/dokkaa_builder/api.cljs
+++ src/cljs/dokkaa_builder/api.cljs
@@ -0,0 +1,5 @@
+(ns dokkaa-builder.api
+  (:require [cljs-http.client :as http]))
+
+(defn apps [& {:keys [host token]}]
+  (http/get (str "http://" host "/apps/") {:query-params {:token token}}))


changed timeout for clojbot insult module

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/m1dnight/clojbot.git/'


fixed typo

fixed typo

--- src/leiningen/new/cryogen/src/cryogen/compiler.clj
+++ src/leiningen/new/cryogen/src/cryogen/compiler.clj
@@ -65,7 +65,7 @@
          :toc (if (:toc page-meta) (generate-toc content))}
         (if is-post?
           {:date          (parse-post-date file-name)
-           :archive-group (.format (java.text.SimpleDateFormat. "yyyy MMMM" (java.util.Locale "en")) (parse-post-date file-name))
+           :archive-group (.format (java.text.SimpleDateFormat. "yyyy MMMM" (java.util.Locale. "en")) (parse-post-date file-name))
            :uri           (post-uri file-name config)
            :tags          (set (:tags page-meta))}
           {:uri        (page-uri file-name config)


check for nil :open-file-command

check for nil :open-file-command

fixes #412

Also logging the unavailability of the :open-file-command.

--- sidecar/src/figwheel_sidecar/components/figwheel_server.clj
+++ sidecar/src/figwheel_sidecar/components/figwheel_server.clj
@@ -23,8 +23,6 @@
   (-send-message [this channel-id msg-data callback])
   (-connection-data [this])
   (-actual [this]))
-
-

 (defn get-open-file-command [open-file-command {:keys [file-name file-line file-column]}]
   (when open-file-command
@@ -53,7 +51,7 @@

 (defn exec-open-file-command [{:keys [open-file-command] :as server-state} msg]
   (when-let [msg (#'validate-file-selected-msg msg)]
-    (let [command (get-open-file-command open-file-command msg)]
+    (if-let [command (get-open-file-command open-file-command msg)]
       (try
         (let [result (apply shell/sh command)]
           (if (zero? (:exit result))
@@ -69,7 +67,9 @@
         (catch Exception e
           (println "Figwheel: there was a problem running the open file command - "
                    command)
-          (println (.getMessage e)))))))
+          (println (.getMessage e))))
+      (println "Figwheel: Can't open " (pr-str (vals (select-keys msg [:file-name :file-line :file-column])))
+               "No :open-file-command supplied in the config."))))

 ;; should make this extendable with multi-method
 (defn handle-client-msg [{:keys [browser-callbacks log-writer] :as server-state} data]


Add first round of self-tests

Add first round of self-tests

error: pathspec 'src/test/clojure/com/stuartsierra/lazytest_spec.clj' did not match any file(s) known to git

--- src/test/clojure/com/stuartsierra/lazytest_spec.clj
+++ src/test/clojure/com/stuartsierra/lazytest_spec.clj
@@ -0,0 +1,87 @@
+(ns com.stuartsierra.lazytest-spec
+  (:use [com.stuartsierra.lazytest
+         :only (describe spec spec?
+                         is given defcontext
+                         context? ok? success?
+                         pending? error? container?)]))
+
+(defcontext dummy-context-1 [] 1)
+
+(defcontext is-without-givens []
+  (is (= 1 1) "hello" (= 1 2)))
+
+(defcontext is-with-givens []
+  (given [x dummy-context-1]
+         (is (= x 1) "hello" (= x 2))))
+
+(spec is-spec "The 'is' macro"
+      (given [it is-without-givens]
+             (spec "without any givens"
+                   (is "should create a spec"
+                       (spec? it)
+
+                       "should create an invokable fn"
+                       (instance? clojure.lang.IFn it)
+
+                       "should attach :doc string metadata to assertions"
+                       (= "hello" (:doc (meta (second (:children it)))))
+
+                       "should attach :form metadata to assertions"
+                       (= '(= 1 1) (:form (meta (first (:children it))))))
+
+                   (spec "should have children"
+                         (is (seq (:children it))
+
+                             "that are specs"
+                             (every? spec? (:children it))
+
+                             "that are invokable IFns"
+                             (every? #(instance? clojure.lang.IFn %) (:children it))
+
+                             "as many as there are expressions"
+                             (= 2 (count (:children it)))))))
+
+      (given [it is-with-givens]
+             (spec "with givens"
+                   (is "should create a spec"
+                       (spec? it)
+
+                       "should create an invokable IFns"
+                       (instance? clojure.lang.IFn it)
+
+                       "should attach :doc string metadata to assertions"
+                       (= "hello" (:doc (meta (second (:children it)))))
+
+                       "should attach :form metadata to assertions"
+                       (= '(= x 1) (:form (meta (first (:children it))))))
+
+                   (spec "should have children"
+                         (is (seq (:children it))
+
+                             "that are specs"
+                             (every? spec? (:children it))
+
+                             "that are invokable IFns"
+                             (every? #(instance? clojure.lang.IFn %) (:children it))
+
+                             "as many as there are expressions"
+                             (= 2 (count (:children it)))
+
+                             (spec "with contexts"
+                                   (is (seq (:contexts (first (:children it))))
+                                       "that are Context objects"
+                                       (every? context? (:contexts (first (:children it)))))))))))
+
+(comment
+  (spec assertions-spec "Assertions, when invoked"
+        (given [it is-without-givens]
+               (spec "should return an object"
+                     (is (not (nil? ((:first (:children it)))))
+                         "that supports success?"
+                         (ok? (success? ((:first (:children it)))))
+                         "that supports pending?"
+                         (ok? (pending? ((:first (:children it)))))
+                         "that supports error?"
+                         (ok? (error? ((:first (:children it)))))
+                         "that supports container?"
+                         (ok? (container? ((:first (:children it))))))))))


Updated ring-jetty-adapter dependency versions

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/'


migrations poc

migrations poc

error: pathspec 'src/clj/swarmpit/couchdb/migration.clj' did not match any file(s) known to git

--- src/clj/swarmpit/couchdb/migration.clj
+++ src/clj/swarmpit/couchdb/migration.clj
@@ -0,0 +1,27 @@
+(ns swarmpit.couchdb.migration)
+
+(defn init [] (print"init"))
+
+(defn some-migration [] (print "some"))
+
+(def migrations
+  [init
+   some-migration
+   println])
+
+(defn fname [fx]
+   (->> (str fx)
+        (clojure.repl/demunge)
+        (re-find #"(?<=\/).*(?=@)")))
+
+(defn namef [name]
+   (-> name (symbol) (resolve)))
+
+(defn migrate []
+  (doseq [migration (->> migrations
+                         (map fname)
+                         (map namef))]
+    (migration)))
+
+
+


revert last commit

revert last commit

--- cljs-client/cljsinfo_client/threading_macro.cljs
+++ cljs-client/cljsinfo_client/threading_macro.cljs
@@ -439,7 +439,7 @@
   (set-html! "bubblesContainer" (bubble-links a))
   (set-html! "bigScreen" (big-screen-chars a))
   (let [max-y (max-y-value-in-frames (:frames a))
-        big-screen-height (* (inc max-y) reg-y-unit)]
+        big-screen-height (+ (* max-y reg-y-unit) (half reg-y-unit))]
     (.height ($ "#bigScreen") big-screen-height)))

 (defn- on-change-animation [_kwd _atom old-a new-a]


tracker api fields are no longer mandatory

--- src/ruuvi_server/tracker_api.clj
+++ src/ruuvi_server/tracker_api.clj
@@ -14,11 +14,11 @@
 (defn- map-api-event-to-internal
   "Converts incoming data to internal presentation."
   [params]
-  (let [date-time (parse/parse-timestamp (params :time))
-        latitude (parse/parse-coordinate (params :latitude))
-        longitude (parse/parse-coordinate (params :longitude))
-        accuracy (parse/parse-decimal (params :accuracy))
-        altitude (parse/parse-decimal (params :altitude))
+  (let [date-time (when (params :time) (parse/parse-timestamp (params :time)))
+        latitude (when (params :latitude) (parse/parse-coordinate (params :latitude)))
+        longitude (when (params :longitude) (parse/parse-coordinate (params :longitude)))
+        accuracy (when (params :accuracy) (parse/parse-decimal (params :accuracy)))
+        altitude (when (params :altitude) (parse/parse-decimal (params :altitude)))
         ]
     (merge params {:event_time date-time
                    :latitude latitude


Misc. test tweaks

Misc. test tweaks

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/'


fix typo

fix typo


[TH JE] added deadlines to email context, updated template on S3


add infix

add infix

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/carolove/clojure-ring-app.git/'


Don't escape full message

Don't escape full message

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/'


check for all known referendum keys

check for all known referendum keys


fix using 'false' as a filter value

fix using 'false' as a filter value

--- src/metabase/driver/query_processor/expand.clj
+++ src/metabase/driver/query_processor/expand.clj
@@ -415,13 +415,13 @@
                                      :min   (ph lon-field lon-min)
                                      :max   (ph lon-field lon-max)}})

-  ["BETWEEN" (field-id :guard Field?) (min :guard identity) (max :guard identity)]
+  ["BETWEEN" (field-id :guard Field?) (min :guard (complement nil?)) (max :guard (complement nil?))]
   (map->Filter:Between {:filter-type :between
                         :field       (ph field-id)
                         :min-val     (ph field-id min)
                         :max-val     (ph field-id max)})

-  [(filter-type :guard (partial contains? #{"=" "!=" "<" ">" "<=" ">="})) (field-id :guard Field?) (val :guard identity)]
+  [(filter-type :guard (partial contains? #{"=" "!=" "<" ">" "<=" ">="})) (field-id :guard Field?) (val :guard (complement nil?))]
   (map->Filter:Field+Value {:filter-type (keyword filter-type)
                             :field       (ph field-id)
                             :value       (ph field-id val)})


Add basic production data for NCS

Add basic production data for NCS

error: pathspec 'src/clj_simple_chart/ncs/production_monthly_field.clj' did not match any file(s) known to git

--- src/clj_simple_chart/ncs/production_monthly_field.clj
+++ src/clj_simple_chart/ncs/production_monthly_field.clj
@@ -0,0 +1,59 @@
+(ns clj-simple-chart.ncs.production-monthly-field
+  (:require [clojure.test :as test]
+            [clj-http.client :as client]
+            [clj-simple-chart.csv.csvmap :as csv])
+  (:import (java.time YearMonth)))
+
+(def field-monthly-production-url "http://factpages.npd.no/ReportServer?/FactPages/TableView/field_production_monthly&rs:Command=Render&rc:Toolbar=false&rc:Parameters=f&rs:Format=CSV&Top100=false&IpAddress=80.213.237.130&CultureCode=en")
+(defonce raw-data (-> field-monthly-production-url
+                      (client/get)
+                      (:body)
+                      (csv/csv-map)))
+
+(test/is (= (:columns raw-data) [:prfInformationCarrier
+                                 :prfYear
+                                 :prfMonth
+                                 :prfPrdOilNetMillSm3
+                                 :prfPrdGasNetBillSm3
+                                 :prfPrdNGLNetMillSm3
+                                 :prfPrdCondensateNetMillSm3
+                                 :prfPrdOeNetMillSm3
+                                 :prfPrdProducedWaterInFieldMillSm3
+                                 :prfNpdidInformationCarrier]))
+
+(def numeric-columns [:prfYear
+                      :prfMonth
+                      :prfPrdOilNetMillSm3
+                      :prfPrdGasNetBillSm3
+                      :prfPrdNGLNetMillSm3
+                      :prfPrdCondensateNetMillSm3
+                      :prfPrdOeNetMillSm3
+                      :prfPrdProducedWaterInFieldMillSm3])
+
+(def data (->> raw-data
+               :data
+               (remove #(= "33/9-6 DELTA" (:prfInformationCarrier %)))
+               (csv/read-string-columns numeric-columns)
+               (csv/number-or-nil-columns numeric-columns)
+               (map #(assoc % :date (str (format "%04d-%02d" (:prfYear %) (:prfMonth %)))))
+               (map #(assoc % :days-in-month (. (YearMonth/of (:prfYear %) (:prfMonth %)) lengthOfMonth)))
+               (map #(dissoc % :prfNpdidInformationCarrier))
+               (sort-by :date)
+               (vec)))
+
+(def field-names (->> data
+                      (mapv :prfInformationCarrier)
+                      (distinct)
+                      (sort)
+                      (vec)))
+
+(test/is (some #{"ÅSGARD"} field-names))
+(test/is (some #{"ØST FRIGG"} field-names))
+(test/is (some #{"STATFJORD"} field-names))
+(test/is (some #{"EKOFISK"} field-names))
+(test/is (some #{"TROLL"} field-names))
+(test/is (some #{"SINDRE"} field-names))
+(test/is (some #{"GINA KROG"} field-names))
+(test/is (some #{"TYRIHANS"} field-names))
+(test/is (some #{"REV"} field-names))
+(test/is (some #{"GULLFAKS"} field-names))


simulate a STM thread starving

simulate a STM thread starving

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

--- src/language/threadStarve.clj
+++ src/language/threadStarve.clj
@@ -0,0 +1,59 @@
+(ns language.threadStarve
+  (:import (java.lang Thread)))
+
+(def counter (ref 0))
+
+(def a1 (agent :a1))
+
+(def a2 (agent :a2))
+
+(defn start-agents [msg a1-sleep a2-sleep]
+  (send a1 msg a1-sleep) (send a2 msg a2-sleep))
+
+(defn debug
+  [msg]
+  (print (str msg \n)) (.flush *out*))
+
+(defn debug!
+  [msg]
+  (io! (print (str msg \n)) (.flush *out*)))
+
+(defn starve-out [tag sleep-for]
+  (let [retries (atom 0)]
+    (dosync
+     (let [c @counter]
+       (when-not (zero? @retries)
+         (debug (str ":starveout " tag
+                     " :retry " @retries
+                     " :counter " c)))
+       (swap! retries inc)
+       (Thread/sleep sleep-for)
+       (ref-set counter (inc c))
+       (send *agent* starve-out sleep-for)
+       tag))))
+
+(defn starve-safe [tag sleep-for]
+  (let [retries (atom 0)]
+
+    (dosync (let [c @counter]
+              (swap! retries inc)
+              (Thread/sleep sleep-for)
+              (ref-set counter (inc c))))
+    (when-not (zero? @retries)
+      (debug! (str ":safe-starve " tag
+                   " :retry " @retries
+                   " :counter " @counter)))
+    (send *agent* starve-safe sleep-for)
+    tag))
+
+;(start-agents starve-out 50 1000)
+
+(start-agents starve-safe 50 1000)
+
+;(shutdown-agents)
+;;;;;;;;;;;;;;;;;;;;;;;;;tips;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(defn uuu [x] (+ x 1))
+uuu
+(str uuu)


Simplify twilio-recognizable-message?

Simplify twilio-recognizable-message?

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/'


beginnings of a demo domain

beginnings of a demo domain

error: pathspec 'src/main/java/org/dada/demo/whales.clj' did not match any file(s) known to git

--- src/main/java/org/dada/demo/whales.clj
+++ src/main/java/org/dada/demo/whales.clj
@@ -0,0 +1,83 @@
+(ns org.dada.whales
+    ;;(:refer org.dada.core)
+    )
+
+(import (clojure.lang DynamicClassLoader))
+(defn make-class [factory name superclass & properties]
+  (. #^DynamicClassLoader
+     (deref clojure.lang.Compiler/LOADER)
+     (defineClass name
+       (.create
+	factory
+	name
+	(. superclass getCanonicalName)
+	(if (empty? properties)
+	  nil
+	  (into-array (map (fn [pair]
+			       (let [array (make-array String 2)]
+				 (aset array 0 (.getCanonicalName (first pair)))
+				 (aset array 1 (first (rest pair)))
+				 array))
+			   properties)))))))
+
+(import org.dada.asm.ClassFactory)
+(def factory (new ClassFactory))
+
+(do
+  (def Cetacea (make-class factory "org.dada.whales.Cetacea" Object [(Float/TYPE) "length"] [(Float/TYPE) "weight"]))
+  (def Mysticeti (make-class factory "org.dada.whales.Mysticeti" Cetacea))
+  (def Balaenopteridae (make-class factory "org.dada.whales.Balaenopteridae" Mysticeti))
+  (def Eschrichtiidae (make-class factory "org.dada.whales.Eschrichtiidae" Mysticeti))
+  (def Neobalaenidae (make-class factory "org.dada.whales.Neobalaenidae" Mysticeti))
+  (def Balaenidae (make-class factory "org.dada.whales.Balaenidae" Mysticeti))
+  (def Odontoceti (make-class factory "org.dada.whales.Odontoceti" Cetacea))
+  (def Physeteroidea (make-class factory "org.dada.whales.Physeteroidea" Odontoceti))
+  (def Zyphiidae (make-class factory "org.dada.whales.Zyphiidae" Odontoceti))
+  (def Delphinidae (make-class factory "org.dada.whales.Delphinidae" Odontoceti))
+  )
+
+
+;; mysticeti				; Baleen Whales
+;;  balaenidae                          ; Right, Bowhead Whales
+;;  balaenopteridae                     ; Rorqual Whales-Blue, Minke, Bryde's, Eden, Humpback
+;;  eschrichtiidae                      ; Gray Whales
+;;  neobalaenidae                       ; Pygmy Right Wale
+;; odontoceti				; Toothed Whales
+;;  physeteroidea			; Sperm Whales
+;;  zyphiidae                           : Beaked Whales
+;;  delphinidae                         ; Orca, Dolphins
+
+
+(def types '(
+		     "blue whale"
+	     "sei whale"
+	     "bottlenose dolphine"
+	     "killer whale"
+	     "false killer whale"
+	     "amazon river dolphin"
+	     "narwhal"
+	     "sperm whale"
+	     "pilot whale"
+	     "beluga whale"
+	     "humpback whale"
+	     "fin whale"
+	     "right whale"
+	     "bowhead whale"
+	     "brydes whale"
+	     "minke whale"
+	     "gray whale"
+	     "spinner dolphin"
+	     "melon headed whale"
+	     "beaked whale"
+	     ))
+
+(defn rnd [seq] (nth seq (rand-int (count seq))))
+
+(rnd types)
+
+
+;; IDEAS
+
+;; spotting - whale-id, time, coordinates, weight, length
+;; birth - whale-id time, weight, length, location
+;; death - id, time, weight, length


Fix typo in namespace

Fix typo in namespace

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/mistsys/mist-kwt.git/'