fix failing test (:note-length is no longer an attribute)

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


add roundtrip test

add roundtrip test

error: pathspec 'test/transit/roundtrip/core.cljs' did not match any file(s) known to git

--- test/transit/roundtrip/core.cljs
+++ test/transit/roundtrip/core.cljs
@@ -0,0 +1,10 @@
+(ns transit.roundtrip.core
+  (:require [transit.core :as t]))
+
+(def transport (or (aget (.-argv js/process) 2) :json))
+(def r (t/reader transport))
+(def w (t/writer transport))
+
+(.on (.-stdin js/process) "data"
+  (fn [data err]
+    (.write (.-stdout js/process) (.write w (.read r data)))))


This parser parses but nothing else!

This parser parses but nothing else!

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

--- src/doctopus/parsers/markdown.clj
+++ src/doctopus/parsers/markdown.clj
@@ -0,0 +1,13 @@
+(ns doctopus.markdown
+  (:require [markdown.core :as md]))
+
+(defn parse-mardown-file
+  "Read a file and parse the contents from markdown to html"
+  [file]
+  {:pre [(re-find #"(?i)[md|markdown|mdown]$" file)]}
+  (let [text-string (slurp file)]
+    (md/md-to-html-string text-string)))
+
+(defn parse-to-file
+  "Parse a file and write the output string to a new file"
+  [source-file destination-root])


test fix

test fix


Update macros.clj

Update macros.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/parenode/clojure-cup-2015.git/'


Set source url to new document

Set source url to new document

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/tokenmill/clj-gate.git/'


handler for weight

handler for weight

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


Restored space between similar quotes

Restored space between similar quotes

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/hudren/ebook-novel.git/'


was doing this wrong, increased complexity tremendously

--- sidecar/src/figwheel_sidecar/core.clj
+++ sidecar/src/figwheel_sidecar/core.clj
@@ -244,20 +244,12 @@
    (dependency-files st)))

 (def ^:dynamic *transitive-dep-cache* false)
-(declare transitive-dependents)
-
-;; mutual recursion
-(defn transitive-dependents* [n]
-  (let [deps (ana/ns-dependents n)]
-    (if (empty? deps)
-      #{}
-      (set (concat deps (mapcat transitive-dependents deps))))))

 (defn transitive-dependents [nm]
   (let [cached (get-in @*transitive-dep-cache* (name nm))]
     (if (not (nil? cached))
       cached
-      (let [res (transitive-dependents* nm)]
+      (let [res (set (ana/ns-dependents nm))]
         (swap! *transitive-dep-cache* assoc (name nm) res)
         res))))

@@ -285,7 +277,7 @@
     (false? (:recompile-dependents state))
     (concat changed-ns-syms' (find-figwheel-always))
     :else
-    (let [changed-ns-syms       (set changed-ns-syms')
+    (let [changed-ns-syms       (set (map (fn [n] (:name (ana-api/find-ns n))) changed-ns-syms'))
           dependants            (set (mapcat
                                       transitive-dependents
                                       changed-ns-syms))


Models using korma

Models using korma

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

--- src/swartz/models.clj
+++ src/swartz/models.clj
@@ -0,0 +1,22 @@
+(ns swartz.models
+  (:use korma.db
+        korma.core))
+
+(defdb db (postgres {:db "swartz"
+                     :user "austin"
+                     :password "notasecurepass"}))
+
+(declare users posts comments)
+
+(defentity users
+  (has-many posts))
+
+(defentity posts
+  (belongs-to users)
+  (has-many comments))
+
+(defentity comments
+  (belongs-to users)
+  (belongs-to posts)
+  (belongs-to comments)
+  (has-many comments))


beginnings of a microbench suite

beginnings of a microbench suite

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


fix parenthesis in test

fix parenthesis in test

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


more Trailing String

more Trailing String

Clojure

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/nikai3d/ce-challenges.git/'


test fix

test fix

--- src/metabase/driver/mongo/query_processor.clj
+++ src/metabase/driver/mongo/query_processor.clj
@@ -26,6 +26,7 @@
            (metabase.driver.query_processor.interface DateTimeField
                                                       DateTimeValue
                                                       Field
+                                                      OrderByAggregateField
                                                       Value)))

 (declare apply-clause
@@ -100,6 +101,18 @@
    (field->name this "."))
   ([this separator]
    (apply str (interpose separator (rest (qualified-name-components this))))))
+
+(defmethod field->name OrderByAggregateField
+  ([this]
+   (field->name this nil))
+  ([this _]
+   (let [{:keys [aggregation-type]} (:aggregation (:query *query*))]
+     (case aggregation-type
+       :avg      "avg"
+       :count    "count"
+       :distinct "count"
+       :stddev   "stddev"
+       :sum      "sum"))))

 (defmethod field->name DateTimeField
   ([this]


Add Chapter 1 code

Add Chapter 1 code

error: pathspec 'clojure-lang/src/clojure_lang/chapter01.clj' did not match any file(s) known to git

--- clojure-lang/src/clojure_lang/chapter01.clj
+++ clojure-lang/src/clojure_lang/chapter01.clj
@@ -0,0 +1,84 @@
+(ns clojure-lang.chapter01
+  (:require [clojure.string :refer [split]]
+            [cheshire.core :as cc]
+            [taoensso.carmine :as car]
+            [clj-time.coerce :as ctc]
+            [clj-time.core :as ct]
+            [clojure-lang.util :refer [wcar*]]))
+
+
+(def ONE-WEEK-IN-SECONDS (* 7 86400))
+(def VOTE-SCORE 432)
+(def ARTICLES-PER-PAGE 25)
+
+;; 1.3.1 Voting an articles
+
+(defn article-vote
+  [user article]
+  (let [cutoff (- (ctc/to-long (ct/now))
+                  ONE-WEEK-IN-SECONDS)
+        last-vote-time (Long/parseLong (wcar* (car/zscore "time:" article)))]
+    (when (or (not last-vote-time)
+              (> last-vote-time cutoff))
+      (let [article-id (last (split article #":"))]
+        (when (wcar* (car/sadd (str "voted:" article-id) user))
+          (wcar* (car/zincrby "score:" VOTE-SCORE article))
+          (wcar* (car/hincrby article "votes" 1)))))))
+
+
+;; 1.3.2 Posting and fetching articles
+
+(defn post-article
+  [user title link]
+  (let [article-id (wcar* (car/incr "article:"))
+        voted (str "voted:" article-id)
+        time (ctc/to-long (ct/now))
+        article (str "article:" article-id)
+        article-object {:title title
+                        :link link
+                        :poster user
+                        :time time
+                        :votes 1}]
+    (wcar* (car/sadd voted user))
+    (wcar* (car/expire voted ONE-WEEK-IN-SECONDS))
+    (wcar* (car/hmset article :title title :link link :poster user :time time :votes 1))
+    (wcar* (car/zadd "score:" (+ time VOTE-SCORE) article))
+    (wcar* (car/zadd "time:" time article))
+    article))
+
+
+(defn get-articles
+  ([page]
+   (get-articles page "score:"))
+  ([page order]
+   (let [start (* ARTICLES-PER-PAGE
+                  (dec page))
+         end (dec (+ start ARTICLES-PER-PAGE))
+         ids (wcar* (car/zrevrange order start end))]
+     (mapv (fn [id]
+             (->> (wcar* (car/hgetall id))
+                  (into ["id" id])
+                  (apply array-map)))
+           ids))))
+
+
+;; 1.3.3 Grouping Articles
+
+(defn add-remove-groups
+  [article-id to-add to-remove]
+  (let [article (str "article:" article-id)]
+    (doseq [group to-add]
+      (wcar* (car/sadd (str "group:" group) article)))
+    (doseq [group to-remove]
+      (wcar* (car/srem (str "group:" group) article)))))
+
+
+(defn get-group-articles
+  ([group page]
+   (get-group-articles group page "score:"))
+  ([group page order]
+   (let [grouped-key (str order group)]
+     (when-not (wcar* (car/exists grouped-key))
+       (wcar* (car/zinterstore* grouped-key [(str "group:" + group) order] "max"))
+       (wcar* (car/expire grouped-key 60)))
+     (get-articles page grouped-key))))


Make ping responses text/plain

Make ping responses text/plain

Otherwise they default to application/edn and show up as base64-encoded binary in some dev tools.

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


:no_mouth:

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


turkey day achievement

turkey day achievement

--- src-clj/acha/achievement.clj
+++ src-clj/acha/achievement.clj
@@ -185,15 +185,26 @@
            cal (Calendar/getInstance)
            _ (.setTime cal time)
            commit-day (.get cal Calendar/DAY_OF_YEAR)]
-       (when (= [1024] [commit-day])
+       (when (= 1024 commit-day)
          {:username (:author commit-info)
           :time time})))])

-; TODO date achievements
 (def turkey-day
   [:turkey-day
    (fn [commit-info]
-     nil)])
+     (let [time (:time commit-info)
+           ; TODO Correct timezone
+           cal (Calendar/getInstance)
+           _ (.setTime cal time)
+           commit-day (.get cal Calendar/DAY_OF_WEEK)
+           commit-month (.get cal Calendar/MONTH)
+           commit-month-day (.get cal Calendar/DAY_OF_MONTH)]
+       (when (and (= [10 3] [commit-month commit-day])
+             (and (>= commit-month-day 22) (<= commit-month-day 28)))
+         {:username (:author commit-info)
+          :time time})))])
+
+; TODO date achievements
 (def owl
   [:owl
    (fn [commit-info]


adding messages namespace and values

adding messages namespace and values

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

--- src/cljs/ohds/messages.cljs
+++ src/cljs/ohds/messages.cljs
@@ -0,0 +1,31 @@
+(ns ohds.messages)
+
+
+;;; Login
+(defrecord FieldworkerLogin [])
+(defrecord AdminLogin [])
+
+;;; Search
+(defrecord LocationHierarchySelect [])
+
+;;; Create
+(defrecord NewLocation [])
+(defrecord NewIndividual [])
+(defrecord NewResidency [])
+(defrecord NewRelationship [])
+(defrecord NewMembership [])
+
+(defrecord NewUser [])
+(defrecord NewFieldworker [])
+
+
+;;; Update
+(defrecord UpdateIndividual [])
+(defrecord UpdateLocation [])
+(defrecord UpdateResidency [])
+(defrecord UpdateRelationship [])
+(defrecord UpdateMembership [])
+
+(defrecord UpdateUser [])
+(defrecord UpdateFieldworker [])
+


THA add photo tab place holder

THA add photo tab place holder

error: pathspec 'src/hatti/views/photos.cljs' did not match any file(s) known to git

--- src/hatti/views/photos.cljs
+++ src/hatti/views/photos.cljs
@@ -0,0 +1,12 @@
+(ns hatti.views.photos
+  (:require [om.core :as om :include-macros true]
+            [sablono.core :refer-macros [html]]
+            [hatti.views :refer [photos-page]]))
+
+(defmethod photos-page :default
+  [{:keys [dataset-info]} owner]
+  "Om component for the photos page."
+  (om/component
+   (html
+    [:div.container
+     [:p "This is the default photos page holder."]])))


fix up session DELETE (logout) endpoint.

--- src/metabase/api/session.clj
+++ src/metabase/api/session.clj
@@ -15,15 +15,14 @@
       (ins Session
         :id session-id
         :user_id (:id user))
-      ;; TODO - figure out how to apply session to client.  cookies??
       {:id session-id})))

-(defendpoint DELETE "/" [:as {{:keys [session_id] :as body} :body}]
-  (check-400 session_id)
-  (let-400 [session (sel :one Session :id session_id)]
-    (del Session :id session_id)))
-;; TODO - do we need to remove any cookies??
+(defendpoint DELETE "/" [:as {params :params}]
+  (let [session_id (:session_id params)]
+    (check-400 session_id)
+    (let-400 [session (sel :one Session :id session_id)]
+      (del Session :id session_id))))

 (define-routes)


add a try/catch when we update the sample dataset so that failures don't cascade to other code.

--- src/metabase/sample_data.clj
+++ src/metabase/sample_data.clj
@@ -34,4 +34,7 @@
 (defn update-sample-dataset-if-needed! []
   ;; TODO - it would be a bit nicer if we skipped this when the data hasn't changed
   (when-let [db (db/sel :one Database :is_sample true)]
-    (driver/sync-database! db)))
+    (try
+      (driver/sync-database! db)
+      (catch Throwable e
+        (log/error (format "Failed to update sample dataset: %s" (.getMessage e)))))))


Add job flow for phase 2 tnseq

Add job flow for phase 2 tnseq

error: pathspec 'Jobs/tnseq-phase-2-job-template.clj' did not match any file(s) known to git

--- Jobs/tnseq-phase-2-job-template.clj
+++ Jobs/tnseq-phase-2-job-template.clj
@@ -0,0 +1,10 @@
+
+{:nodes
+ {:ph2
+  {:name "tnseq-phase2",
+   :type "tool",
+   :args []}
+  :prn1 {:type "func",
+         :name "prn"}},
+ :edges
+ {:ph2 [:prn1]}}


Towards streaming events

Towards streaming events

error: pathspec 'src/zoo_live/model/event.clj' did not match any file(s) known to git

--- src/zoo_live/model/event.clj
+++ src/zoo_live/model/event.clj
@@ -0,0 +1,4 @@
+(ns zoo-live.model.event)
+
+(defn query
+  [])


drop type hints

drop type hints


Associative抽象

Associative抽象

error: pathspec 'src/learnclojure/chapt3/core4.clj' did not match any file(s) known to git

--- src/learnclojure/chapt3/core4.clj
+++ src/learnclojure/chapt3/core4.clj
@@ -0,0 +1,22 @@
+(ns learnclojure.chapt3.core4)
+;;Associative抽象
+;;关系型数据结构Associative接口抽象的是把一个key和一个value关联起来的数据结构
+;;这个接口有四个操作：
+;;1.assoc 它向集合中添加一个新的key到value的映射
+;;2.dissoc 从集合中移除指定的key到value的映射
+;;3.get 从集合中取出指定key的value
+;;4.contains？ 是一个谓词，集合中包含指定key的时候返回true，否则返回false
+
+;;最正宗的关系型数据结构是map，它也是clojure提供的最有用的数据结构
+(def m {:a 1,:b,2,:c 3})
+(get m :a)
+(get m :d)
+(get m :d "not found")
+(assoc m :d 4)
+(dissoc m :b)
+;;assoc和dissoc还可以增加和删除多个键值对
+(assoc m
+  :x 4
+  :y 5
+  :z 6)
+(dissoc m :a :c)


health e resource-status no manager

health e resource-status no manager

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


added random name generator

added random name generator

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

--- src/sushi_machine/random_name.clj
+++ src/sushi_machine/random_name.clj
@@ -0,0 +1,84 @@
+(ns sushi-machine.random-name)
+
+(def adjektiv ["hedonistisk"
+               "morsom"
+               "teit"
+               "sexy"
+               "genial"
+               "psykotisk"
+               "esende"
+               "barsk"
+               "deilig"
+               "snodig"
+               "modig"
+               "flau"
+               "allmektig"
+               "stygg"
+               "gul"
+               "klok"
+               "syk"
+               "klein"
+               "skitten"
+               "farlig"
+               "blind"
+               "kvalm"
+               "lysten"
+               "full"
+               "desperat"
+               "sint"
+               "ond"
+               "skarp"
+               "lat"])
+
+(def substantiv ["rev"
+                 "elg"
+                 "sau"
+                 "munk"
+                 "nisse"
+                 "mor"
+                 "trikk"
+                 "bybane"
+                 "ku"
+                 "katt"
+                 "ugle"
+                 "kodemann"
+                 "politiker"
+                 "dust"
+                 "maskin"
+                 "automat"
+                 "kollega"
+                 "nabo"
+                 "mann"
+                 "dame"
+                 "programmerer"
+                 "selger"])
+
+(def verb ["hopper"
+           "sniker"
+           "smyger"
+           "snoker"
+           "titter"
+           "danser"
+           "koder"
+           "knoter"
+           "synger"
+           "soper"
+           "spiser"
+           "suger"
+           "brygger"
+           "bader"
+           "stripper"
+           "koker"
+           "fjaser"
+           "bakser"
+           "mikser"
+           "jukser"
+           "baker"
+           "drikker"
+           "sniffer"
+           "hoster"])
+
+(defn gen-random-name []
+  (->> [adjektiv substantiv verb]
+       (map rand-nth)
+       (clojure.string/join '-)))


unit test for contains-many? fn.

unit test for contains-many? fn.

--- test/metabase/test_util.clj
+++ test/metabase/test_util.clj
@@ -1,6 +1,17 @@
 (ns metabase.test-util
   (:require [expectations :refer :all]
             [metabase.util :refer :all]))
+
+
+;; tests for CONTAINS-MANY?
+
+(let [m {:a 1 :b 1 :c 2}]
+  (expect true (contains-many? m :a))
+  (expect true (contains-many? m :a :b))
+  (expect true (contains-many? m :a :b :c))
+  (expect false (contains-many? m :a :d))
+  (expect false (contains-many? m :a :b :d)))
+

 ;;; tests for SELECT-NON-NIL-KEYS


test resources

test resources

error: pathspec 'test/infinitelives/pixi/resources_test.cljs' did not match any file(s) known to git

--- test/infinitelives/pixi/resources_test.cljs
+++ test/infinitelives/pixi/resources_test.cljs
@@ -0,0 +1,8 @@
+(ns infinitelives.pixi.resources-test
+  (:require [cljs.test :refer-macros [deftest is]]
+            [infinitelives.pixi.resources :as resources]))
+
+(comment (deftest make
+           (is (canvas/make :engine :canvas))
+           (is (canvas/make :engine :auto))
+           (remove-all-dom-canvas)))


add some minimal tests about with-timeout macro

error: pathspec 'test/open_company/unit/resources/common.clj' did not match any file(s) known to git

--- test/open_company/unit/resources/common.clj
+++ test/open_company/unit/resources/common.clj
@@ -0,0 +1,9 @@
+(ns open-company.unit.resources.common
+  (:require [open-company.resources.common :as co]
+            [midje.sweet :refer :all]))
+
+(facts "about with-timeout macro"
+  (let [s "result"]
+    (co/with-timeout 100 s) => s
+    (co/with-timeout 100 (do (Thread/sleep 90) s) => s)
+    (co/with-timeout 100 (do (Thread/sleep 110) s)) => (throws Exception)))


Add a reminder

Add a reminder

--- examples/todomvc/src/todomvc/core.cljs
+++ examples/todomvc/src/todomvc/core.cljs
@@ -15,6 +15,6 @@

 (defn ^:export main
   []
-  (dispatch [:initialise-db])
+  (dispatch [:initialise-db])       ;; remember this is async
   (reagent/render [todomvc.views/top-panel]
                   (.getElementById js/document "app")))


Consistent naming

Consistent naming

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


Ability to buil shen,clj out of Platorms/Clojure in the Shen distro

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


Create iolist.clj

Create iolist.clj

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

--- src/iyye/iolist.clj
+++ src/iyye/iolist.clj
@@ -0,0 +1,34 @@
+; Iyye - AI agent
+; Copyright (C) 2016-2017  Sasha Yumzya
+
+; This program is free software: you can redistribute it and/or modify
+; it under the terms of the GNU Affero 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 Affero General Public License for more details.
+
+; You should have received a copy of the GNU Affero General Public License
+; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+(ns iyye.iolist
+  (:require [extras.lispychat :as lispychat]
+            [clojure.tools.logging :as log]))
+
+(def AvatarsIOList (ref ()))
+
+(defn init-avatars-list []
+  (dosync
+    (alter AvatarsIOList conj lispychat/lispy-chat-IO)))
+
+(defn init-io []
+  (letfn [(start-all [l]
+            (for [func (map :start-function l) :when func] (func)))]
+    (do [
+      (init-avatars-list)
+      (start-all @AvatarsIOList)
+      (start-all (:inputs-list @AvatarsIOList))
+      (start-all (:outputs-list @AvatarsIOList))])))


Add robot simulator assignments

Add robot simulator assignments

error: pathspec 'assignments/clojure/robot-simulator/test.clj' did not match any file(s) known to git

--- assignments/clojure/robot-simulator/test.clj
+++ assignments/clojure/robot-simulator/test.clj
@@ -0,0 +1,27 @@
+(load-file "robot.clj")
+
+(def robbie (robot {:x -2 :y 1} :east))
+(assert (= :east (:bearing robbie)))
+(assert (= {:x -2 :y 1} (:coordinates robbie)))
+
+(assert (= :north (turn-right :west)))
+(assert (= :west  (turn-left :north)))
+
+(assert (= :west (:bearing (simulate "RLAALAL" robbie))))
+(assert (= {:x 0 :y 2} (:coordinates (simulate "RLAALAL" robbie))))
+
+(def clutz  (robot {:x 0 :y  0} :north))
+(def sphero (robot {:x 2 :y -7} :east))
+(def roomba (robot {:x 8 :y  4} :south))
+
+(let [clutz (simulate "LAAARALA" clutz)]
+  (assert (= :west (:bearing clutz)))
+  (assert (= {:x -4 :y 1} (:coordinates clutz))))
+
+(let [sphero (simulate "RRAAAAALA" sphero)]
+  (assert (= :south (:bearing sphero)))
+  (assert (= {:x -3 :y -8} (:coordinates sphero))))
+
+(let [roomba (simulate "LAAARRRALLLL" roomba)]
+  (assert (= :north (:bearing roomba)))
+  (assert (= {:x 11 :y 5} (:coordinates roomba))))


Clojure: started on new experimental p-graph morphism detection code

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

--- clojure/org/gavrog/clojure/pgraph_morphisms.clj
+++ clojure/org/gavrog/clojure/pgraph_morphisms.clj
@@ -0,0 +1,15 @@
+(ns org.gavrog.clojure.pgraph-morphisms
+  (:import (org.gavrog.joss.pgraphs.io Net)
+           (org.gavrog.joss.geometry Operator)))
+
+(defn nets [filename]
+  (iterator-seq (Net/iterator filename)))
+
+(defn identity-matrix [net]
+  (Operator/identity (.getDimension net)))
+
+(defn node-signatures [net]
+  (let [mod-1 (fn [[v p]] [v (.modZ p)])
+        pos (into {} (map mod-1 (.barycentricPlacement net)))
+        by-pos (group-by pos (.nodes net))]
+    by-pos))


Add signing root namespace.

Add signing root namespace.

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

--- src/clojure/buddy/sign/generic.clj
+++ src/clojure/buddy/sign/generic.clj
@@ -0,0 +1,69 @@
+;; Copyright 2013 Andrey Antukh <niwi@niwi.be>
+;;
+;; 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 buddy.sign.generic
+  (:require [buddy.codecs :refer :all]
+            [buddy.crypto.core :refer :all]
+            [clojure.string :refer [split]]
+            [taoensso.nippy :as nippy]))
+
+(defn- make-signature
+  [s pkey salt]
+  (-> (hmac-sha256 s pkey {:salt salt})
+      (bytes->hex)))
+
+(defn- make-stamped-signature
+  [s pkey salt sep stamp]
+  (let [candidate (str s stamp)
+        signature (make-signature candidate pkey salt)]
+    (format "%s%s%s" signature sep stamp)))
+
+(defn sign
+  "Given a string and secret key,
+  return a signed and prefixed string."
+  ([s, pkey & [{:keys [sep salt]
+                :or {sep ":" salt "clj"}
+                :as opts}]]
+   (let [stamp     (str->base64 (str (timestamp)))
+         signature (make-stamped-signature s pkey salt sep stamp)]
+     (format "%s%s%s" s sep signature))))
+
+(defn unsign
+  "Given a signed string and private key with string
+  was preoviously signed and return unsigned value
+  if the signature is valed else nil."
+  ([s pkey & [{:keys [sep salt max-age]
+               :or {sep ":" salt "clj" max-age nil}}]]
+   (let [[value sig stamp] (split s (re-pattern sep))
+         candidate (str value stamp)]
+     (when (= sig (make-signature candidate pkey salt))
+       (if-not (nil? max-age)
+         (let [old-stamp-value (Integer/parseInt (base64->str stamp))
+               age             (- (timestamp) old-stamp-value)]
+           (if (> age max-age) nil value))
+        value)))))
+
+(defn dumps
+  "Sign a complex data strucutres using
+  serialization as intermediate step."
+  [data & args]
+  (let [encoded (bytes->base64 (nippy/freeze data))]
+    (apply sign encoded (vec args))))
+
+(defn loads
+  "Unsign data signed with dumps."
+  [s & args]
+  (let [unsigned (apply unsign s (vec args))]
+    (when-not (nil? unsigned)
+      (nippy/thaw (base64->bytes unsigned)))))


removed outdated comments

removed outdated comments

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


Problem 138.

Problem 138.

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

--- src/project_euler/problem_0138.clj
+++ src/project_euler/problem_0138.clj
@@ -0,0 +1,58 @@
+(ns project-euler.problem_0138)
+
+;; Consider the isosceles triangle with base length, b = 16, and legs, L = 17.
+
+;; By using the Pythagorean theorem it can be seen that the height of the triangle,
+;; h = √(172 − 82) = 15, which is one less than the base length.
+
+;; With b = 272 and L = 305, we get h = 273, which is one more than the base length,
+;; and this is the second smallest isosceles triangle with the property that h = b ± 1.
+
+;; Find ∑ L for the twelve smallest isosceles triangles for which h = b ± 1 and b, L are positive integers.
+
+;;========================================================================================================
+
+(defn int-sqrt? [x]
+  (let [sqrt-x (Math/round (Math/sqrt x))]
+    (== x (*' sqrt-x sqrt-x))))
+
+(defn solution-from [hb]
+  (->> (iterate inc hb)
+       (mapcat (fn [hb] (let [b (* hb 2)]
+                          [(+ (* hb hb) (* (dec b) (dec b)))
+                           (+ (* hb hb) (* (inc b) (inc b)))])))
+       (filter int-sqrt?)
+       (map (fn [h2] (int (Math/round (Math/sqrt h2)))))
+       first))
+
+(defn solution' []
+  (loop [hb 8
+         n 0
+         ls []
+         prev-l 1]
+    (if (== n 7)
+      ls
+      (let [l (solution-from hb )]
+        (recur (bigint (/ (*' hb l) prev-l))
+               (inc n)
+               (conj ls l)
+               l
+               ))
+      )))
+
+;; After observation of the FIRST solutions:
+
+(defn solution []
+  (loop [k 1
+         l 17
+         n 0
+         ls []]
+    (if (== 12 n)
+      (apply + ls)
+      (let [m (-' (*' 18 l) k)]
+        (recur l
+               m
+               (inc n)
+               (conj ls l))))))
+
+;; 1118049290473932


forgot to add this to repogit add src/aerobio/validate/datasets.clj

error: pathspec 'src/aerobio/validate/datasets.clj' did not match any file(s) known to git

--- src/aerobio/validate/datasets.clj
+++ src/aerobio/validate/datasets.clj
@@ -0,0 +1,138 @@
+(ns aerobio.validate.datasets
+  (:require
+   [clojure.pprint :refer [pprint]]
+
+   [clojure.spec.alpha :as s]
+   [phrase.alpha :as p
+    :refer [defphraser phrase phrase-first]]
+
+   [clojure.string :as cljstr]
+   [aerial.utils.string :as str]
+   [aerial.fs :as fs]
+
+   [aerobio.params :as pams]
+   [aerobio.validate.common :as vc
+    :refer [validate-msg make-validator bases? cols->maps]]
+   [aerobio.htseq.common :as ac]))
+
+
+;;; phase-0 checks. Need to ensure 'experiment' directory exists and
+;;; has the path holding the bcl files
+
+(defn expexists? [EID]
+  (fs/directory?
+   (fs/join (pams/get-params :nextseq-base) EID)))
+
+(defn bclfiles? [EID]
+  (fs/directory?
+   (fs/join (pams/get-params :nextseq-base)
+            EID
+            (pams/get-params :nextseq-fqdir))))
+
+(s/def ::expexists? expexists?)
+(s/def ::bclfiles? bclfiles?)
+(s/def ::phase0-chks (s/and ::expexists? ::bclfiles?))
+
+(p/defphraser expexists?
+  [_ problem]
+  (format "Experiment '%s' does not exist!"
+          (-> problem :val)))
+
+(p/defphraser bclfiles?
+  [_ problem]
+  (format "Experiment '%s' does not have any registered bcl files!"
+          (-> problem :val)))
+
+(def validate-expexists (make-validator ::expexists?))
+(def validate-bclfiles (make-validator ::bclfiles?))
+(def validate-phase-0 (make-validator ::phase0-chks :sep "\n"))
+
+
+
+
+;;; phase-1 checks. We need to ensure that the current Exp-SampleSheet
+;;; data match the phase-0 generated data sets
+
+(defn samp-fqs? [pair]
+  (and (vector? pair) (seq (pair 1))))
+
+(s/def ::samp-fqs? samp-fqs?)
+(s/def ::phase1-chks (s/coll-of ::samp-fqs? :kind vector?))
+
+(p/defphraser samp-fqs?
+  [_ problem]
+  (format "There are no associated fastq files for sample '%s'"
+          (-> problem :val first)))
+
+(def validate-phase1 (make-validator ::phase1-chks :sep "\n"))
+
+(defn validate-phase-1 [EID]
+  (let [samp-fqs-pairs (mapv vec (ac/get-all-replicate-fqzs EID))
+        vstg (->> samp-fqs-pairs
+                  validate-phase1
+                  (str/split #"\n")
+                  (filter not-empty)
+                  (map #(format " %s. %s" %1 %2) (iterate inc 1))
+                  (cljstr/join "\n"))]
+    (with-out-str
+      (when (not (empty? vstg))
+        (print (format "There are errors in '%s' phase-1 datasets\n" EID)))
+      (print vstg))))
+
+
+
+;;; phase-2 checks. We need to ensure that there are bams for each
+;;; group of comparisons being requested.
+
+(defn comp-bams? [pair]
+  (and (vector? pair) (seq (pair 0))))
+
+(s/def ::comp-bams? comp-bams?)
+(s/def ::phase2-chks (s/coll-of ::comp-bams? :kind vector?))
+
+(p/defphraser comp-bams?
+  [_ problem]
+  (format "There are no associated bam files for comparing '%s'"
+          (-> problem :val second fs/basename (fs/replace-type ""))))
+
+(def validate-compbams (make-validator ::comp-bams?))
+(def validate-phase2 (make-validator ::phase2-chks :sep "\n"))
+
+(defn validate-phase-2
+  [EID & {:keys [compfile] :or {compfile "ComparisonSheet.csv"}}]
+  (let [exp (ac/get-exp-info EID :exp)
+        bams-csv-pairs (ac/get-comparison-files exp EID compfile true)
+        vstg (->> bams-csv-pairs
+                  validate-phase2
+                  (str/split #"\n")
+                  (filter not-empty)
+                  (map #(format " %s. %s" %1 %2) (iterate inc 1))
+                  (cljstr/join "\n"))]
+    (with-out-str
+      (when (not (empty? vstg))
+        (print (format "There are errors in '%s' phase-2 datasets\n" EID)))
+      (print vstg))))
+
+
+(comment
+
+  (validate-expexists "foo")
+  (validate-bclfiles "foo")
+  (validate-phase0 "Ngon")
+  (validate-phase0 "Ngon_cipro")
+
+  (cmn/get-comparison-files :rnaseq "Ngon_cipro" "ComparisonSheet.csv" true)
+
+  (validate-phase-1 "Ngon_cipro")
+
+  (comp-bams?
+   [() "/ExpOut/Ngon_cipro/Out/Rep/Fcnts/Ng-CIP5minR-Ng-NDC5minR.csv"/])
+
+  (validate-phase2
+   '[[() "/ExpOut/Ngon_cipro/Out/Rep/Fcnts/Ng-CIP5minR-Ng-NDC5minR.csv"]
+     [() "/ExpOut/Ngon_cipro/Out/Rep/Fcnts/Ng-CIP10minR-Ng-NDC10minR.csv"]
+     [() "/ExpOut/Ngon_cipro/Out/Rep/Fcnts/Ng-CIP15minR-Ng-NDC15minR.csv"]
+     [() "/ExpOut/Ngon_cipro/Out/Rep/Fcnts/Ng-CIP5minS-Ng-NDC5minS.csv"]
+     [() "/ExpOut/Ngon_cipro/Out/Rep/Fcnts/Ng-CIP10minS-Ng-NDC10minS.csv"]
+     [() "/ExpOut/Ngon_cipro/Out/Rep/Fcnts/Ng-CIP15minS-Ng-NDC15minS.csv"]])
+)


double-check 0.5.7 fix

double-check 0.5.7 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/QuiltProject/sedan.git/'


- sparkling sample added

- sparkling sample added

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

--- examples/sparkling.clj
+++ examples/sparkling.clj
@@ -0,0 +1,42 @@
+;; gorilla-repl.fileformat = 2
+
+;; **
+;;; # Gorilla REPL
+;;;
+;;; Welcome to gorilla :-)
+;;;
+;;; Shift + enter evaluates code. Hit alt+g twice in quick succession or click the menu icon (upper-right corner) for more commands ...
+;;;
+;;; It's a good habit to run each worksheet in its own namespace: feel free to use the declaration we've provided below if you'd like.
+;; **
+
+;; @@
+(ns harmonious-aurora
+  (:use [cemerick.pomegranate :only (add-dependencies)])
+  (:require [gorilla-plot.core :as plot]))
+;; @@
+
+;; @@
+(add-dependencies :coordinates '[[gorillalabs/sparkling "1.2.5"]
+                                 [org.apache.spark/spark-core_2.10 "1.5.1"]]
+                  :repositories (merge cemerick.pomegranate.aether/maven-central
+                                          {"clojars" "http://clojars.org/repo"}))
+;; @@
+
+;; @@
+(require '[sparkling.conf :as conf])
+;; @@
+
+;; @@
+(require '[sparkling.core :as spark])
+;; @@
+
+;; @@
+(def c (-> (conf/spark-conf)
+           (conf/master "local")
+           (conf/app-name "sparkling-example")))
+;; @@
+
+;; @@
+(def sc (spark/spark-context c))
+;; @@


Add namespace/module to track keypresses

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

--- src/blue_salamander/keypresses.cljs
+++ src/blue_salamander/keypresses.cljs
@@ -0,0 +1,27 @@
+(ns blue-salamander.keypresses)
+
+;;
+;; All this code does is track which keys are currently pressed by listening
+;; for keyup/keydown events and putting the currently pressed keys into a
+;; set. You pass in an atom that contains the (initially empty set) and
+;; as keys are pressed/released their keycodes are swap!'d into and out of the set
+
+
+;; KeyboardEvent.keyCode is deprecated but .key doesn't seem
+;; to be supported everywhere
+
+(defn process-key-down [keys-pressed-atom key-event]
+  (let [key (.-keyCode key-event)]
+    (swap! keys-pressed-atom #(conj % key))
+    #_(js/console.log (str "key down: " key))))
+
+(defn process-key-up [keys-pressed-atom key-event]
+  (let [key (.-keyCode key-event)]
+    (swap! keys-pressed-atom #(disj % key))
+    #_(js/console.log (str "key up: " key))))
+
+(defn track-keypresses-in-atom
+  [keytrack-atom]
+  (let []
+    (aset js/window "onkeydown" #(process-key-down keytrack-atom %))
+    (aset js/window "onkeyup" #(process-key-up keytrack-atom %))))


add explicit width to hr tag

add explicit width to hr tag

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


Refactoring.

Refactoring.

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


Code for 11013

Code for 11013

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

--- src/clj_simple_chart/ssb/nettokontantstraum.clj
+++ src/clj_simple_chart/ssb/nettokontantstraum.clj
@@ -0,0 +1,56 @@
+(ns clj-simple-chart.ssb.nettokontantstraum
+  (:require [clojure.data.json :as json]
+            [clojure.test :as test]
+            [clj-http.client :as client]
+            [clojure.pprint :refer [pprint]]
+            [clj-simple-chart.csv.csvmap :as csv]
+            [clojure.string :as string]))
+
+(def url "http://data.ssb.no/api/v0/no/table/11013")
+(def qq [{:code "ContentsCode" :selection {:filter "all" :values ["*"]}}
+         {:code "Tid" :selection {:filter "all" :values ["*"]}}])
+(def q {:query qq :response {:format "csv"}})
+(def response (client/post url {:form-params q :content-type :json :as :byte-array}))
+(test/is (= "text/csv; charset=Windows-1252" (get (:headers response) "Content-Type")))
+
+(def resp (String. (:body response) "Windows-1252"))
+(def csv-parsed (csv/csv-map resp))
+(def columns (:columns csv-parsed))
+(def data (:data csv-parsed))
+
+(def sample-column "Skatter på utvinning av petroleum 1991K1")
+
+(defn year-and-quarter [x]
+  (cond (keyword? x) (recur (name x))
+        (re-matches #"^.+ \d{4}K\d$" x) (last (string/split x #" "))
+        :else nil))
+
+(defn prop [x]
+  (cond (keyword? x) (recur (name x))
+        (re-matches #"^.+ \d{4}K\d$" x) (string/join " " (drop-last (string/split x #" ")))
+        :else nil))
+
+(defn process-entry [[k v]]
+  {:dato  (year-and-quarter k)
+   :prop  (keyword (prop k))
+   :value v})
+
+(defn process-grouped [values]
+  (reduce (fn [o v]
+            (assoc o (:prop v)
+                     (:value v)))
+          {:dato (:dato (first values))}
+          values))
+
+(def parsed (->> data
+                 (mapcat (partial mapv process-entry))
+                 (remove #(nil? (:dato %)))
+                 (group-by :dato)
+                 (vals)
+                 (mapv process-grouped)
+                 (sort-by :dato)))
+
+(def actual-columns (flatten [:dato (mapv keyword (distinct (filter string? (map prop columns))))]))
+
+(csv/write-csv "./data/11013/11013.csv" {:data parsed
+                                         :columns actual-columns})


(progress)

(progress)

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


Add scaling

Add scaling

error: pathspec 'src/clj/clojurewerkz/statistiker/scaling.clj' did not match any file(s) known to git

--- src/clj/clojurewerkz/statistiker/scaling.clj
+++ src/clj/clojurewerkz/statistiker/scaling.clj
@@ -0,0 +1,18 @@
+(ns clojurewerkz.statistiker.scaling
+  (:require [clojurewerkz.statistiker.summary :as summary]))
+
+(defn rescale
+  "Linear transformation"
+  [x]
+  (let [xmin        (apply min x)
+        xmax        (apply max x)
+        scale-fn (fn [x] (double (/ (- x xmin) (- xmax xmin))))]
+    (mapv scale-fn x)))
+
+(defn z-transform
+  "Z-Transformation"
+  [x]
+  (let [xmean    (summary/mean x)
+        xsd      (summary/sd x)
+        scale-fn (fn [x] (double (/ (- x xmean) xsd)))]
+    (map scale-fn x)))


change name of resulting subscription

change name of resulting subscription

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


Add state extensions State extensions are for a log type to implement for storage and playback of state commands

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

--- src/onyx/state/state_extensions.clj
+++ src/onyx/state/state_extensions.clj
@@ -0,0 +1,31 @@
+(ns onyx.state-extensions)
+
+(defmulti initialise-log
+  (fn [log-type event]
+    log-type))
+
+(defmulti close-log
+  (fn [log]
+    (type log)))
+
+;; For onyx to implement
+;; We can implement log storage for Kafka and maybe ZK (if small data is used and we gc)
+(defmulti store-log-entries
+  "Store state update [op k v] entries in a log"
+  (fn [log event entries]
+    (type log)))
+
+(defmulti playback-log-entries
+  "Read state update [op k v] entries from log"
+  (fn [log event state apply-fn]
+    (type log)))
+
+(defmulti store-seen-ids
+  "Store seen ids in a log. Ideally these will be timestamped for auto expiry"
+  (fn [log event seen-ids]
+    (type log)))
+
+(defmulti playback-seen-ids
+  "Read seen ids from a log"
+  (fn [log event bucket-state apply-fn]
+    (type log)))


Added archives template.

Added archives template.

error: pathspec 'src/lambda_blog/templates/archives.clj' did not match any file(s) known to git

--- src/lambda_blog/templates/archives.clj
+++ src/lambda_blog/templates/archives.clj
@@ -0,0 +1,51 @@
+(ns lambda-blog.templates.archives
+  (:require [lambda-blog.templates.entry :refer [format-date]]
+            [lambda-blog.templates.static :refer [static-page-template]]
+            [lambda-blog.utils :refer [path]]
+            [ring.util.codec :refer [url-encode]]
+            [s-html.tags :refer [a div h1 hr kbd nav p script span table tbody td th thead tr]]))
+
+(defn archive-entry [{:keys [path-to-root summary tags timestamp title url]}]
+  (tr (td (format-date timestamp))
+      (td (a {:href url}
+             title))
+      (td (map #(span {:class "label label-info small"}
+                      (a {:class "tag"
+                          :href (path path-to-root (format "/tags/%s.html" (url-encode %)))}
+                         %))
+               (sort tags)))
+      (td {:class "hidden-xs hidden-sm"}
+          summary)))
+
+(def tablesorter-script
+  ;; FIXME This ought to be ClojureScript.
+  "$(document).ready(function() {
+     $('table').tablesorter({
+     textExtraction: function(node) {
+       var t = $(node).find('a').text();
+       return t != \"\" ? t : node.innerHTML;
+     }});
+   });")
+
+(def archives (partial static-page-template
+                       (fn [{:keys [entries path-to-root]}]
+                         [(div {:class :well}
+                               (div {:class :row}
+                                    (h1 {:class :text-center}
+                                        "Archives")))
+                          (div {:class :article-content}
+                               (nav {:class :archives}
+                                    (table {:class "table table-bordered table-striped tablesorter"}
+                                           (thead (tr (th (span "Posted on"))
+                                                      (th (span "Title"))
+                                                      (th (span "Tags"))
+                                                      (th {:class "sorter-false hidden-xs hidden-sm"}
+                                                          (span "Summary"))))
+                                           (tbody (map archive-entry entries))))
+                               (p {:class "hidden-xs hidden-sm"}
+                                  (span {:class "label label-warning"}
+                                        "ProTip:")
+                                  "Hold " (kbd "Shift") " to sort by several columns at the same time.")
+                               (script {:type "application/javascript"}
+                                       tablesorter-script))
+                          (hr)])))


[WM] return response map from vote-tomorrow/handle-update

Not sure what this was trying to do before.


update to map to first if condition in template


rename election-authority binding so it doesn't look so weird


Create simplified form of dummy-response for easy cases

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


Data migration to new schema

Data migration to new schema

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

--- src/territory_bro/migration.clj
+++ src/territory_bro/migration.clj
@@ -0,0 +1,42 @@
+;; Copyright © 2015-2019 Esko Luontola
+;; This software is released under the Apache License 2.0.
+;; The license text is at http://www.apache.org/licenses/LICENSE-2.0
+
+(ns territory-bro.migration
+  (:require [clojure.tools.logging :as log]
+            [territory-bro.config :as config]
+            [territory-bro.congregation :as congregation]
+            [territory-bro.db :as db]
+            [territory-bro.gis-user :as gis-user]
+            [territory-bro.region :as region]
+            [territory-bro.territory :as territory]
+            [territory-bro.user :as user]))
+
+(defn migrate-congregation [tenant]
+  (db/as-tenant tenant
+    (let [regions (db/query :find-regions)
+          territories (db/query :find-territories)
+          admins (get-in config/env [:tenant tenant :admins])]
+      (db/with-db [conn {}] ; to be able to see the new schema
+        (let [cong-id (congregation/create-congregation! conn (.toUpperCase (name tenant)))]
+
+          (doseq [admin admins]
+            (let [user-id (user/save-user! conn admin {})]
+              (congregation/grant-access! conn cong-id user-id)
+              (gis-user/create-gis-user! conn cong-id user-id)))
+
+          (congregation/use-schema conn cong-id)
+
+          (doseq [region regions]
+            (cond
+              (:congregation region) (region/create-congregation-boundary! conn (:location region))
+              (:subregion region) (region/create-subregion! conn (:name region) (:location region))
+              (:minimap_viewport region) (region/create-card-minimap-viewport! conn (:location region))
+              :else (region/create-subregion! conn (:name region) (:location region))))
+
+          (doseq [territory territories]
+            (territory/create-territory! conn {::territory/number (:number territory)
+                                               ::territory/addresses (:address territory)
+                                               ::territory/subregion (:region territory)
+                                               ::territory/location (:location territory)}))))))
+  (log/info "Migrated congregation" tenant))


jaden-casing-strings challenge

jaden-casing-strings challenge

error: pathspec 'jaden-casing-strings/main.clj' did not match any file(s) known to git

--- jaden-casing-strings/main.clj
+++ jaden-casing-strings/main.clj
@@ -0,0 +1,10 @@
+; Jaden Casing Strings
+; Link: http://www.codewars.com/kata/jaden-casing-strings/clojure
+(require '[clojure.string :as str])
+
+(defn jaden-case
+  [s]
+    (str/join " " (map str/capitalize (str/split s #" "))))
+
+(println (= "How Can Mirrors Be Real If Our Eyes Aren't Real"
+         (jaden-case "How can mirrors be real if our eyes aren't real")))


initial logistic regression stuff

initial logistic regression stuff

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

--- src/brevis/logistic_regression.clj
+++ src/brevis/logistic_regression.clj
@@ -0,0 +1,37 @@
+(ns brevis.logistic-regression
+    (:use [brevis matrix]))
+
+
+(defn sigmoid
+  "Hyperbolic-tangent function."
+  [num]
+  (java.lang.Math/tanh num))
+
+(defn theta-rand
+  "Returns number between -1 & 1."
+  []
+  (let [switch (rand-int 2)]
+    (if (= switch 0)
+      (rand)
+      (unchecked-negate (rand)))))
+
+(defn theta-init
+  "Random m x n matrix with all element values between -1 & 1."
+  [num]
+  (seq-to-matrix num 1 (repeatedly num #(theta-rand))))
+
+(defn logistic-regression
+  "Logistic regression. x feature matrix, y label vector."
+  [x y]
+  (let [num-features (matrix-width x)]
+    (loop [stop 0
+           theta (theta-init num-features)
+           ]
+      (if (= stop 500)
+        theta
+        (recur (inc stop)
+               (matrix-mult x
+                            (transpose (sub y
+                                            (matrix-map sigmoid
+                                                        (matrix-mult (transpose theta)
+                                                                     x))))))))))


Adding base url extractor

Adding base url extractor

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


Add a bunch of tests for handler execution

error: pathspec 'test/icecap/handlers/core_test.clj' did not match any file(s) known to git

--- test/icecap/handlers/core_test.clj
+++ test/icecap/handlers/core_test.clj
@@ -0,0 +1,76 @@
+(ns icecap.handlers.core-test
+  (:require [icecap.handlers.core :refer :all]
+            [icecap.test-data :refer :all]
+            [clojure.test :refer :all]
+            [clojure.core.async :as a :refer [<!!]]))
+
+(defn match-seq-spec
+  "Matches a seq to a simple seq spec.
+
+  Simple seq specs are seqs of colls. For each of those colls, this
+  takes as many elements as that coll has off of the thing to match
+  into a coll of the same type, and compares it to that coll.
+  "
+  [spec to-match]
+  (loop [spec spec
+         to-match to-match]
+    (let [spec-part (first spec)
+          [candidate to-match] (split-at (count spec-part) to-match)
+          candidate (into (empty spec-part) candidate)]
+      (cond (not= candidate spec-part) false
+            (seq spec) (recur (rest spec) to-match)
+            :else (not (seq to-match))))))
+
+(deftest match-seq-spec-tests
+  (testing "match single matching items"
+    (are [spec to-match] (match-seq-spec spec to-match)
+         [[1]] [1]
+         [#{1}] [1]))
+  (testing "don't match single nonmatching items"
+    (are [spec to-match] (not (match-seq-spec spec to-match))
+         [[1]] [2]
+         [[2]] [1]
+         [#{1}] [2]
+         [#{2}] [1]))
+  (testing "match empty items"
+    (are [spec to-match] (match-seq-spec spec to-match)
+         [[]] []
+         [#{}] []))
+  (testing "match complex specs"
+    (are [spec to-match] (match-seq-spec spec to-match)
+         [[1 2 3] #{4 5 6} [7 8 9]] [1 2 3 4 5 6 7 8 9]
+         [[1 2 3] #{4 5 6} [7 8 9]] [1 2 3 6 5 4 7 8 9])))
+
+(defn ^:private execution-order
+  "Given a plan, returns the names of the steps in the order of which
+  they would be executed."
+  [plan]
+  (map :name (<!! (a/into [] (execute plan)))))
+
+(defn ^:private success-steps
+  [names]
+  (into (empty names) (map success-step names)))
+
+(deftest execute-tests
+  (testing "execute single step"
+    (is (= (execution-order (success-step 1))
+           [1])))
+  (testing "execute some plans consisting of ordered steps"
+    (let [names (vec (range 10))
+          plan (success-steps names)
+          order (execution-order plan)]
+      (is (= order names))))
+  (testing "execute some plans consisting of unordered steps"
+    (let [names (set (range 10))
+          plan (success-steps names)
+          order (execution-order plan)
+          spec [(into #{} names)]]
+      (is (match-seq-spec spec order))))
+  (testing "execute complex plans"
+    (let [ordered-head (success-steps [1 2 3])
+          unordered-middle (success-steps #{4 5 6})
+          ordered-tail (success-steps [7 8 9])
+          plan (into (conj ordered-head unordered-middle)
+                     ordered-tail)
+          spec [[1 2 3] #{4 5 6} [7 8 9]]]
+      (is (match-seq-spec spec (execution-order plan))))))


finish new

finish new

error: pathspec 'quick-sort/QS.clj' did not match any file(s) known to git

--- quick-sort/QS.clj
+++ quick-sort/QS.clj
@@ -0,0 +1,7 @@
+(defn quick-sort [l] ;; l = array
+  (let [key (first l)]
+    (if (= 0 (count l))
+      []
+     (into [] (concat
+               (conj (quick-sort (filter #(if (< % key) %) (into [] (rest l)))) key)
+               (quick-sort (filter #(if (>= % key) %) (into [] (rest l)))))))))


bump reactor version dependency

bump reactor version dependency

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


CMR-3525: Add new simple background jobs namespace for running jobs

error: pathspec 'common-lib/src/cmr/common/background_jobs.clj' did not match any file(s) known to git

--- common-lib/src/cmr/common/background_jobs.clj
+++ common-lib/src/cmr/common/background_jobs.clj
@@ -0,0 +1,49 @@
+(ns cmr.common.background-jobs
+  "Namespace for creating simple background jobs that run at a specified interval in a thread.
+  For more complex requirements see the cmr.common.jobs namespace which use Quartz."
+  (:require [cmr.common.lifecycle :as lifecycle]))
+
+(defrecord BackgroundJob
+  [
+   ;; The job-function to run
+   job-fn
+
+   ;; The interval (in seconds) to run the job
+   job-interval-secs
+
+   ;; A reference to the thread to run the background job
+   thread-ref]
+
+  lifecycle/Lifecycle
+
+  (start
+    [this system]
+    (when thread-ref (.interrupt thread-ref))
+    (let [thread (Thread.
+                   (fn []
+                     (try
+                      (while (not (.isInterrupted (Thread/currentThread)))
+                        (job-fn)
+                        (Thread/sleep (* 1000 job-interval-secs)))
+                      (catch InterruptedException _))))
+          ;; Have to set the thread reference before starting the thread otherwise interrupt fails
+          updated-this (assoc this :thread-ref thread)]
+      (.start (:thread-ref updated-this))
+      updated-this))
+
+  (stop
+    [this system]
+    (when thread-ref (.interrupt thread-ref))
+    (assoc this :thread-ref nil)))
+
+(defn create-background-job
+  "Creates a background job using the provided job-fn and how often to run the job in seconds."
+  [job-fn job-interval-secs]
+  (->BackgroundJob job-fn job-interval-secs nil))
+
+(comment
+  (def counter (atom 1))
+  (def job (create-background-job #(swap! counter inc) 0.1))
+  (def job (lifecycle/start job nil))
+  (def job (lifecycle/stop job nil))
+  @counter)


Add more examples

Add more examples

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

--- src/clojure/cfbt/ch10.clj
+++ src/clojure/cfbt/ch10.clj
@@ -0,0 +1,89 @@
+(ns cfbt.ch10)
+
+(def fred (atom {:cuddle-hunger-level 0
+                 :percent-deteriorate 0}))
+
+@fred ;; {:cuddle-hunger-level 0, :percent-deteriorate 0}
+
+(let [zombie-state @fred]
+  (if (>= (:percent-deteriorate zombie-state) 50)
+    (future (println (:percent-deteriorate zombie-state)))))
+
+(swap! fred
+       (fn [current-state]
+         (merge-with + current-state {:current-hunger-level 1})))
+;; {:cuddle-hunger-level 0, :percent-deteriorate 0, :current-hunger-level 3}
+@fred
+;; {:cuddle-hunger-level 0, :percent-deteriorate 0, :current-hunger-level 3}
+(swap! fred
+       (fn [current-state]
+         (merge-with + current-state {:cuddle-hunger-level 2
+                                      :percent-deteriorated 1})))
+
+@fred
+
+(swap! fred
+       (fn [current-state]
+         (merge-with + current-state {:cuddle-hunger-level 1
+                                      :percent-deteriorated 1})))
+
+(defn increase-cuddle-hunger-level
+  [zombie-state increase-by]
+  (merge-with + zombie-state {:cuddle-hunger-level increase-by}))
+
+;; No update will be applied without the use of swap
+(increase-cuddle-hunger-level @fred 10)
+
+@fred
+
+(swap! fred increase-cuddle-hunger-level 10)
+
+@fred
+
+;; use Clojure built-in
+(update-in {:a {:b 3}} [:a :b] inc)
+;; {:a {:b 4}}
+
+(update-in {:a {:b 3}} [:a :b] + 10)
+;; {:a {:b 13}}
+
+(swap! fred update-in [:cuddle-hunger-level] + 10)
+
+(let [num (atom 1)
+      s1 num]
+  (swap! num inc)
+  (println "State 1:" s1)
+  (println "Current state:" @num))
+
+(reset! fred {:cuddle-hungerlevel 0
+              :percent-deteriorated 0})
+;; {:cuddle-hungerlevel 0, :percent-deteriorated 0}
+
+;; Watches and Validators ::
+(defn shuffle-speed
+  [zombie]
+  (* (:cuddle-hunger-level zombie)
+     (- 100 (:percent-deteriorated zombie))))
+
+(defn shuffle-alert
+  [key watched old-state new-state]
+  (let [sph (shuffle-speed new-state)]
+    (if (> sph 5000)
+      (do
+        (println "Run, you fool!")
+        (println "The zombie's SPH is now " sph)
+        (println "This message brought to you courtesy of " key))
+      (do
+        (println "All's well with " key)
+        (println "Cuddle hunger: " (:cuddle-hunger-level new-state))
+        (println "Percent deteriorated: " (:percent-deteriorated new-state))
+        (println "SPH: " sph)))))
+
+(reset! fred {:cuddle-hunger-level 22
+              :percent-deteriorated 2})
+;; {:cuddle-hunger-level 22, :percent-deteriorated 2}
+(add-watch fred :fred-shuffle-alert shuffle-alert)
+(swap! fred update-in [:percent-deteriorated] + 2)
+(swap! fred update-in [:cuddle-hunger-level] + 30)
+
+;; Validators :: p217


Starting Tank Truck codewars kata in clojure

error: pathspec 'hackerrank/functional_programming/clojure/codewars/tankTruck.clj' did not match any file(s) known to git

--- hackerrank/functional_programming/clojure/codewars/tankTruck.clj
+++ hackerrank/functional_programming/clojure/codewars/tankTruck.clj
@@ -0,0 +1,16 @@
+;; Tank Truck
+;;
+;; To introduce the problem think to my neighbor who drives a tanker truck. The level indicator is down and is worried because he does not know if he will be able to make deliveries. We put the truck on a horizontal ground and measured the height of liquid in the tank. Fortunately the tank is a perfect cylinder and its vertical walls are flat. The height of the remaining liquid is h, the diameter of the cylinder is d, the total volume is vt (h,d,vtare positive or null integers). You can assume that h <= d.
+;;
+;; Could you calculate the remaining volume? Your function tankvol(h, d, vt) returns an integer which is the truncated result (e.g floor) of your float calculation.
+;;
+;; Examples:
+;;
+;; tankvol(40,120,3500)) should return 1021 (calculation gives about: 1021.26992027)
+;;
+;; tankvol(60,120,3500)) should return 1750
+;;
+;; tankvol(80,120,3500)) should return 2478 (calculation gives about: 2478.73007973)
+
+(defn tank-vol [h d vt]
+  )


hide renewal modal on renewal success

hide renewal modal on renewal success


add 'electric-bass' alias to midi-electric-bass-finger

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


add a namespace for emailreport related tasks, specifically creating the `(execute-and-send)` function which allows us to pass in the :id of an `EmailReport` and have the report be executed and sent out via email.

error: pathspec 'src/metabase/tasks/email_report.clj' did not match any file(s) known to git

--- src/metabase/tasks/email_report.clj
+++ src/metabase/tasks/email_report.clj
@@ -0,0 +1,73 @@
+(ns metabase.tasks.email-report
+  "Tasks related to running `EmailReports`."
+  (:require [clojure.tools.logging :as log]
+            [korma.core :refer :all]
+            [metabase.db :refer :all]
+            [metabase.driver :as driver]
+            [metabase.email.messages :refer [send-email-report]]
+            (metabase.models [emailreport :refer [EmailReport execution-details-fields]]
+                             [emailreport-executions :refer [EmailReportExecutions]]
+                             [emailreport-recipients :refer [EmailReportRecipients]]
+                             [hydrate :refer :all])
+            [metabase.util :as u]))
+
+
+(declare execute report-fail report-complete)
+
+(defn execute-and-send
+  "Execute and Send an `EmailReport`.  This includes running the data query behind the report, formatting the email,
+   and sending the email to any specified recipients."
+  [report-id]
+  {:pre [(integer? report-id)]}
+  (let [email-report (-> (sel :one :fields execution-details-fields :id report-id)
+                         ;; TODO - this feels heavy handed.  need to check `sel` macro about clob handling
+                         (u/assoc* :description (u/jdbc-clob->str (:description <>))
+                                   :email_addresses (u/jdbc-clob->str (:email_addresses <>))
+                                   :recipients (sel :many :fields ['metabase.models.user/User :id :email]
+                                                 (where {:id [in (subselect EmailReportRecipients
+                                                                   (fields :user_id)
+                                                                   (where {:emailreport_id report-id}))]}))))
+        query-execution (ins EmailReportExecutions
+                          :report_id report-id
+                          :organization_id (:organization_id email-report)
+                          :details email-report
+                          :status "running"
+                          :created_at (u/new-sql-timestamp)
+                          :started_at (u/new-sql-timestamp)
+                          :error ""
+                          :sent_email "")]
+    (log/debug (format "Starting EmailReport Execution: %d" (:id query-execution)))
+    (execute query-execution)
+    (log/debug (format "Finished EmailReport Execution: %d" (:id query-execution)))))
+
+
+(defn- execute
+  "Internal handling of EmailReport sending."
+  [{execution-id :id {:keys [name creator_id dataset_query recipients email_addresses]} :details}]
+  (let [email-subject (str (or name "Your Email Report") " - " (u/now-with-format "MMMM dd, YYYY"))
+        email-recipients (->> (filter identity (map (fn [recip] (:email recip)) recipients))
+                              (into (clojure.string/split email_addresses #","))
+                              (filter u/is-email?)
+                              (into []))
+        email-data (driver/dataset-query dataset_query {:executed_by creator_id
+                                                        :synchronously true})]
+    (if (= :completed (:status email-data))
+      (->> (send-email-report email-subject email-recipients email-data)
+           (report-complete execution-id))
+      (report-fail execution-id (format "dataset_query() failed for email report (%d): %s" execution-id (:error email-data))))))
+
+(defn- report-fail
+  "Record report failure"
+  [execution-id msg]
+  (upd EmailReportExecutions execution-id
+    :status "failed"
+    :error msg
+    :finished_at (u/new-sql-timestamp)))
+
+(defn- report-complete
+  "Record report completion"
+  [execution-id sent-email]
+  (upd EmailReportExecutions execution-id
+    :status "completed"
+    :finished_at (u/new-sql-timestamp)
+    :sent_email (or sent-email "")))


Small tweak to docstring

Small tweak to docstring

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


highlight current loop

highlight current loop

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/wilkerlucio/youtube-looper.git/'


handler to add food, fn to list

handler to add food, fn to list

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


Problem 0071.

Problem 0071.

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

--- src/project_euler/problem_0071.clj
+++ src/project_euler/problem_0071.clj
@@ -0,0 +1,33 @@
+(ns project-euler.problem-0071)
+
+;; Consider the fraction, n/d, where n and d are positive integers.
+;; If n<d and HCF(n,d)=1, it is called a reduced proper fraction.
+
+;; If we list the set of reduced proper fractions for d ≤ 8 in ascending order of size, we get:
+
+;; 1/8, 1/7, 1/6, 1/5, 1/4, 2/7, 1/3, 3/8, 2/5, 3/7, 1/2, 4/7, 3/5, 5/8, 2/3, 5/7, 3/4, 4/5, 5/6, 6/7, 7/8
+
+;; It can be seen that 2/5 is the fraction immediately to the left of 3/7.
+
+;; By listing the set of reduced proper fractions for d ≤ 1,000,000 in ascending order of size,
+;; find the numerator of the fraction immediately to the left of 3/7.
+
+(defn pgcd [a b]
+  (let [r (rem a b)]
+    (if (zero? r)
+      b
+      (recur b r))))
+
+(defn brute-force-solution []
+  (->> (range 8 1000001)
+       (map (fn [d] [(quot (* 3 d) 7) d]))
+       (filter (fn [[n d]] (== 1 (pgcd n d))))
+       (map (fn [[n d]] [n d (- 3/7 (/ n d))]))
+       (reduce (fn [[n-min d-min diff-min :as fr-min] [n d diff :as fr]]
+                 (if (< diff diff-min) fr fr-min))
+               [nil nil 1])
+       (first)
+       ))
+
+(def solution brute-force-solution)
+;;-> 428570


Remove unneeded `with-redefs-fn` in llvm-jack.main_test

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


show email addresses on team page

show email addresses on team page

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


More consistent quoting

More consistent quoting

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


Add snippets for Shape - Attributes category. Issue #87.

error: pathspec 'test/snippets/shape/attributes.clj' did not match any file(s) known to git

--- test/snippets/shape/attributes.clj
+++ test/snippets/shape/attributes.clj
@@ -0,0 +1,100 @@
+(ns snippets.shape.attributes
+  (:require [quil.snippet :refer [defsnippet]]
+            [quil.core :refer :all]))
+
+(defsnippet ellipse-mode-s {}
+  (stroke-weight 5)
+  (ellipse-mode :center)
+  (with-translation [125 125]
+   (ellipse 0 0 100 70)
+   (point 0 0))
+
+  (ellipse-mode :radius)
+  (with-translation [375 125]
+    (ellipse 0 0 100 70)
+    (point 0 0))
+
+  (ellipse-mode :corner)
+  (with-translation [125 375]
+    (ellipse 0 0 100 70)
+    (point 0 0))
+
+  (ellipse-mode :corners)
+  (with-translation [375 375]
+    (ellipse -50 -35 50 35)
+    (point -50 -35)
+    (point 50 35)))
+
+(defsnippet smooth-no-smooth-s {:renderer :p2d}
+  (smooth)
+  (with-translation [125 125]
+   (ellipse 0 0 200 200))
+
+  (smooth 2)
+  (with-translation [125 375]
+   (ellipse 0 0 200 200))
+
+  (no-smooth)
+  (with-translation [375 125]
+    (ellipse 0 0 200 200)))
+
+(defsnippet rect-mode-s {}
+  (stroke-weight 5)
+  (rect-mode :center)
+  (with-translation [125 125]
+    (stroke 0)
+    (rect 0 0 100 70)
+    (stroke 255 0 0)
+    (point 0 0))
+
+  (rect-mode :radius)
+  (with-translation [375 125]
+    (stroke 0)
+    (rect 0 0 100 70)
+    (stroke 255 0 0)
+    (point 0 0))
+
+  (rect-mode :corner)
+  (with-translation [125 375]
+    (stroke 0)
+    (rect 0 0 100 70)
+    (stroke 255 0 0)
+    (point 0 0))
+
+  (rect-mode :corners)
+  (with-translation [375 375]
+    (stroke 0)
+    (rect -50 -35 50 35)
+    (stroke 255 0 0)
+    (point -50 -35)
+    (point 50 35)))
+
+(defsnippet stroke-cap-s {}
+  (stroke-weight 12)
+  (stroke-cap :square)
+  (line 230 200 270 200)
+
+  (stroke-cap :project)
+  (line 230 250 270 250)
+
+  (stroke-cap :round)
+  (line 230 300 270 300))
+
+(defsnippet stroke-join-s {}
+  (rect-mode :center)
+  (stroke-weight 12)
+  (stroke-join :miter)
+  (rect 125 125 100 100)
+
+  (stroke-join :bevel)
+  (rect 375 125 100 100)
+
+  (stroke-join :round)
+  (rect 125 375 100 100))
+
+(defsnippet stroke-weight-s {}
+  (doseq [i (range 1 10)]
+    (stroke-weight i)
+    (line 230 (+ (* i 30) 100)
+          270 (+ (* i 30) 100))))
+


Typo.

Typo.

--- src/clojars/repo.clj
+++ src/clojars/repo.clj
@@ -30,7 +30,7 @@
   (.list (io/file (config :repo) group-id)))

 (defn user-artifacts [username]
-  (mapcat group-artifacts (:groups (@users username))))
+  (mapcat group-artifacts (:groups (@ev/users username))))

 ;; web handlers


add params and body to http call in put-uri and patch-uri

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


DatePicker done

DatePicker done

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


Fix defn syntax in client.three-scale

Fix defn syntax in client.three-scale

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


Cleanup requires in queue ns

Cleanup requires in queue ns

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


Slow down electorate creates in verify script

We seemed to be overwhelming the system before. It was much happier with
this rate.

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


Tn-Seq job flow template

Tn-Seq job flow template

error: pathspec 'Jobs/tnseq-phase-1-job-template.clj' did not match any file(s) known to git

--- Jobs/tnseq-phase-1-job-template.clj
+++ Jobs/tnseq-phase-1-job-template.clj
@@ -0,0 +1,10 @@
+
+{:nodes
+ {:ph1
+  {:name "tnseq-phase1",
+   :type "tool",
+   :args []}
+  :prn1 {:type "func",
+         :name "prn"}},
+ :edges
+ {:ph1 [:prn1]}}


Change content type based on SNS header, not request URL


auth ns

auth ns

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

--- src/clj/swarmpit/authentication.clj
+++ src/clj/swarmpit/authentication.clj
@@ -0,0 +1,27 @@
+(ns swarmpit.authentication
+  (:import (clojure.lang ExceptionInfo))
+  (:require [buddy.auth.backends.token :refer [jws-backend]]
+            [buddy.auth.middleware :refer [authentication-request]]
+            [swarmpit.handler :refer [resp-unauthorized]]
+            [swarmpit.couchdb.client :as cc]))
+
+(defn- authentication-backend
+  [secret]
+  (jws-backend
+    {:secret     secret
+     :token-name "Bearer"
+     :on-error   (fn [_ ex] (throw ex))}))
+
+(defn wrap-authentication
+  [handler]
+  (fn [request]
+    (let [secret (:secret (cc/get-secret))
+          auth-backend (authentication-backend secret)]
+      (try
+        (handler (authentication-request request auth-backend))
+        (catch ExceptionInfo ex
+          (let [error (case (:cause (ex-data ex))
+                        :exp "Token expired"
+                        :signature "Token invalid"
+                        (Throwable->map ex))]
+            (resp-unauthorized error)))))))


Rename user -> author for see alsos

Rename user -> author for see alsos

--- src/cljs/clojuredocs/see_alsos.cljs
+++ src/cljs/clojuredocs/see_alsos.cljs
@@ -17,7 +17,7 @@
                             (assoc state key (not (get state key)))))
   false)

-(defn $see-also [{:keys [ns name created-at doc user] :as sa}]
+(defn $see-also [{:keys [ns name created-at doc author] :as sa}]
   [:div.col-sm-6.see-also
    [:div
     (util/$var-link ns name
@@ -30,7 +30,7 @@
     (when (> (count doc) 100)
       "...")]
    [:div.meta
-    "Added by " [:a {:href (str "/u/" (:login user))} (:login user)]]])
+    "Added by " [:a {:href (str "/u/" (:login author))} (:login author)]]])

 (defn $add [{:keys [user]} owner]
   (reify


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


Fix _debug on async-manager-handler

Fix _debug on async-manager-handler

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


add ritz

add ritz

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


Gurasoak bidali

Gurasoak bidali

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


Datu hutsak kendu

Datu hutsak kendu

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


Formatuarena berehala abisatu

Formatuarena berehala abisatu


Java interop example.

Java interop example.

error: pathspec 'src/main/clj/clojure_club/x113_making_data_dance/java_interop.clj' did not match any file(s) known to git

--- src/main/clj/clojure_club/x113_making_data_dance/java_interop.clj
+++ src/main/clj/clojure_club/x113_making_data_dance/java_interop.clj
@@ -0,0 +1,45 @@
+(ns clojure-club.x113-making-data-dance.java-interop
+  (:require [clojure.string :as cs])
+  (:import (javax.swing JFrame JTable JScrollPane JMenuBar JMenu JMenuItem Action AbstractAction JFileChooser)
+           (java.awt BorderLayout Color)
+           (javax.swing.table AbstractTableModel)
+           (java.awt.event ActionEvent)))
+
+(defn ^Action openAction [state]
+  (proxy [AbstractAction] ["Open"]
+    (actionPerformed [^ActionEvent event]
+      (let [jc (JFileChooser.)]
+        (when (= JFileChooser/APPROVE_OPTION (.showOpenDialog jc (.getSource event)))
+          (->> (.getSelectedFile jc)
+               slurp
+               cs/split-lines
+               (mapv #(cs/split % #","))
+               (swap! state assoc :data)))))))
+
+(defn model [state]
+  (let [table-model (proxy [AbstractTableModel] []
+                      (getRowCount [] (count (get-in @state [:data])))
+                      (getColumnCount [] (count (get-in @state [:data 0])))
+                      (getValueAt [row col] (get-in @state [:data row col])))]
+    (add-watch state ::table-data-changed
+               (fn [_ _ o n]
+                 (do
+                   (.fireTableDataChanged table-model)
+                   (.fireTableStructureChanged table-model))))
+    table-model))
+
+(def state (atom {:data [[1 2] [3 4]]}))
+
+(doto (JFrame. "The App")
+  (.setSize 800 600)
+  (.setDefaultCloseOperation JFrame/DISPOSE_ON_CLOSE)
+  (.setLayout (BorderLayout.))
+  (.setJMenuBar (doto (JMenuBar.)
+                  (.add (doto (JMenu. "File")
+                          (.add (JMenuItem. (openAction state)))))
+                  (.add (JMenu. "Edit"))))
+  (.add (doto (JScrollPane.
+                (doto (JTable. (model state))
+                  (.setGridColor Color/BLACK))))
+        BorderLayout/CENTER)
+  (.setVisible true))


eliminate reflection

eliminate reflection

--- src/clj_http/core.clj
+++ src/clj_http/core.clj
@@ -1,12 +1,14 @@
 (ns clj-http.core
   "Core HTTP request/response implementation."
+  (:import (org.apache.http HttpRequest HttpResponse Header))
   (:import (org.apache.http.util EntityUtils))
   (:import (org.apache.http.entity ByteArrayEntity))
+  (:import (org.apache.http.message BasicHttpEntityEnclosingRequest))
   (:import (org.apache.http.client.methods HttpGet HttpHead HttpPut HttpPost HttpDelete))
   (:import (org.apache.http.impl.client DefaultHttpClient)))

-(defn parse-headers [http-resp]
-  (into {} (map (fn [h] [(.toLowerCase (.getName h)) (.getValue h)])
+(defn parse-headers [#^HttpResponse http-resp]
+  (into {} (map (fn [#^Header h] [(.toLowerCase (.getName h)) (.getValue h)])
                 (iterator-seq (.headerIterator http-resp)))))

 (defn request
@@ -23,12 +25,13 @@
                           (if server-port (str ":" server-port))
                           uri
                           (if query-string (str "?" query-string)))
-            http-req (case request-method
-                       :get    (HttpGet. http-url)
-                       :head   (HttpHead. http-url)
-                       :put    (HttpPut. http-url)
-                       :post   (HttpPost. http-url)
-                       :delete (HttpDelete. http-url))]
+            #^HttpRequest
+              http-req (case request-method
+                         :get    (HttpGet. http-url)
+                         :head   (HttpHead. http-url)
+                         :put    (HttpPut. http-url)
+                         :post   (HttpPost. http-url)
+                         :delete (HttpDelete. http-url))]
         (doseq [[header-n header-v] headers]
           (.addHeader http-req header-n header-v))
         (if (and content-type character-encoding)
@@ -38,7 +41,7 @@
           (.addHeader http-req "Content-Type" content-type))
         (if body
           (let [http-body (ByteArrayEntity. body)]
-            (.setEntity http-req http-body)))
+            (.setEntity #^BasicHttpEntityEnclosingRequest http-req http-body)))
         (let [http-resp (.execute http-client http-req)
               http-entity (.getEntity http-resp)
               resp {:status (.getStatusCode (.getStatusLine http-resp))


updated url regex

updated url regex

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


stub for the defcontract tests

stub for the defcontract tests

error: pathspec 'test/fogus/me/defcontract_tests.clj' did not match any file(s) known to git


better mobile interaction with editables

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/talexand/velcro-notes.git/'


cleanup

cleanup

--- src/metabase/models/common.clj
+++ src/metabase/models/common.clj
@@ -30,9 +30,8 @@
     (name->human-readable-name \"admin_users\") -> \"Admin Users\""
   [^String n]
   (when (seq n)
-    (when-let [n (some-> n
-                         (s/split #"_|-"))]                                           ; explode string on underscores and hyphens
-      (->> (for [[first-letter & rest-letters] (filter (complement s/blank?) n)]      ; for each part of the string,
-             (apply str (s/upper-case first-letter) (map s/lower-case rest-letters))) ; upcase the first char and downcase the rest
-           (interpose " ")                                                            ; add a space between each part
-           (apply str)))))                                                            ; convert back to a single string
+    (->> (for [[first-letter & rest-letters] (->> (s/split n #"_|-")                 ; explode string on underscores and hyphens
+                                                  (filter (complement s/blank?)))]   ; for each part of the string,
+           (apply str (s/upper-case first-letter) (map s/lower-case rest-letters)))  ; upcase the first char and downcase the rest
+         (interpose " ")                                                             ; add a space between each part
+         (apply str))))                                                              ; convert back to a single string


Add integration tests for newsfeed service

error: pathspec 'newsfeed/test/newsfeed/integration/api.clj' did not match any file(s) known to git

--- newsfeed/test/newsfeed/integration/api.clj
+++ newsfeed/test/newsfeed/integration/api.clj
@@ -0,0 +1,22 @@
+(ns newsfeed.integration.api
+  (:require [midje.sweet :refer :all]
+            [peridot.core :as p]
+            [clojure.data.json :as json]
+            [newsfeed.core :as nf]
+            [newsfeed.api :as api]))
+
+(facts "about 'api'"
+       (let [app (p/session nf/app)]
+         (fact "returns 200 on /ping"
+               (get-in (p/request app "/ping") [:response :status]) => 200)
+         (fact "returns 403 when no token given"
+               (get-in (p/request app "/api") [:response :status]) => 403)
+         (fact "returns 403 when invalid token given"
+               (get-in (p/request app "/api" :headers {"X-Auth-Token" "invalid"}) [:response :status]) => 403)
+         (fact "returns 404 when valid token given but invalid route"
+               (get-in (p/request app "/api/404" :headers {"X-Auth-Token" "valid"}) [:response :status]) => 404
+               (provided (contains? nf/tokens "valid") => true))
+         (fact "returns 200 on /api/feeds when valid token given"
+               (get-in (p/request app "/api/feeds" :headers {"X-Auth-Token" "valid"}) [:response :status]) => 200
+               (provided (contains? nf/tokens "valid") => true
+                         (api/get-feeds anything) => '()))))


adding async component

adding async component

error: pathspec 'src/cljc/ow/starbuck/component.cljc' did not match any file(s) known to git

--- src/cljc/ow/starbuck/component.cljc
+++ src/cljc/ow/starbuck/component.cljc
@@ -0,0 +1,42 @@
+(ns ow.starbuck.component
+  #?(:cljs (:require-macros [cljs.core.async.macros :refer [go-loop]]))
+  (:require #?(:clj  [clojure.core.async.impl.protocols :as ap]
+               :cljs [cljs.core.async.impl.protocols :as ap])
+            #?(:clj  [clojure.core.async :refer [go-loop] :as a]
+               :cljs [cljs.core.async :as a])
+            [ow.clojure :as owc]
+            [ow.starbuck.routing :as r]))
+
+(defrecord Component [name input-pub input-sub output-ch process-fn])
+
+(defn- safe-process [process-fn msg]
+  ;;; to prevent go-loop from aborting due to exception in component
+  (try
+    (process-fn msg)
+    (catch Exception e
+      (println "EXCEPTION (COMPONENT):" e)
+      #_(assoc msg :ow.starbuck.routing/error e) ;; TODO: offer default error handling?
+      )
+    (catch Error e
+      (println "ERROR (COMPONENT):" e)
+      #_(assoc msg :ow.starbuck.routing/error e) ;; TODO: offer default error handling?
+      )))
+
+(defn component [name input-pub output-ch process-fn]
+  (map->Component {:name name
+                   :input-pub input-pub
+                   :input-sub (a/sub input-pub name (a/chan))
+                   :output-ch output-ch
+                   :process-fn process-fn}))
+
+(defn start [{:keys [input-sub output-ch process-fn] :as this}]
+  (go-loop [msg (a/<! input-sub)]
+    (when-not (or (nil? msg)
+                  (= msg ::stop))
+      (a/put! output-ch (safe-process process-fn msg))
+      (recur (a/<! input-sub))))
+  this)
+
+(defn stop [{:keys [input-sub] :as this}]
+  (a/put! input-sub ::stop)
+  this)


Add a basic working example in Clojure

Add a basic working example in Clojure

error: pathspec '2016/expression-problem/clojure/expression/src/expression/protocols.clj' did not match any file(s) known to git

--- 2016/expression-problem/clojure/expression/src/expression/protocols.clj
+++ 2016/expression-problem/clojure/expression/src/expression/protocols.clj
@@ -0,0 +1,51 @@
+; Eli Bendersky [http://eli.thegreenplace.net]
+; This code is in the public domain.
+(ns expression.protocols)
+
+(defrecord Constant [value])
+(defrecord BinaryPlus [lhs rhs])
+
+(defprotocol Evaluatable
+  (evaluate [this]))
+
+(defprotocol Stringable
+  (stringify [this]))
+
+(extend-type Constant
+  Evaluatable
+    (evaluate [this] (:value this))
+  Stringable
+    (stringify [this] (str (:value this))))
+
+(extend-type BinaryPlus
+  Evaluatable
+    (evaluate [this] (+ (evaluate (:lhs this)) (evaluate (:rhs this))))
+  Stringable
+    (stringify [this]
+      (clojure.string/join " + " [(stringify (:lhs this))
+                                  (stringify (:rhs this))])))
+
+; Also have an alternative to use extend-protocol here...
+; the core is 'extend' - a true matrix of type/op
+
+(def c1 (Constant. 1.1))
+(def c2 (Constant. 2.2))
+(def p1 (BinaryPlus. c1 c2))
+(def p2 (BinaryPlus. p1 c2))
+
+(evaluate p2)
+(stringify p2)
+
+; "Adding" a new data type - the built-in double type and showing how to extend
+; all protocols for it.
+(extend-type java.lang.Double
+  Evaluatable
+    (evaluate [this] this)
+  Stringable
+    (stringify [this] (str this)))
+
+(def f1 11.5)
+(def p3 (BinaryPlus. c1 f1))
+
+(evaluate p3)
+(stringify p3)


prevent blank files from ending the process

--- support/src/figwheel/core.clj
+++ support/src/figwheel/core.clj
@@ -80,13 +80,16 @@
       underscore))

 (defn get-ns-from-source-file-path [file-path]
-  (when (.exists (as-file file-path))
-    (with-open [rdr (io/reader file-path)]
-      (-> (java.io.PushbackReader. rdr)
-          read
-          second
-          name
-          underscore))))
+  (try
+    (when (.exists (as-file file-path))
+      (with-open [rdr (io/reader file-path)]
+        (-> (java.io.PushbackReader. rdr)
+            read
+            second
+            name
+            underscore)))
+    (catch java.lang.RuntimeException e
+      nil)))

 (defn get-changed-source-file-paths [old-mtimes new-mtimes]
   (group-by


View helpers

View helpers

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

--- src/ultimate_ttt/view_helpers.cljs
+++ src/ultimate_ttt/view_helpers.cljs
@@ -0,0 +1,8 @@
+(ns ultimate-ttt.view-helpers)
+
+(defn owner->player [owner]
+  (case owner
+    1 "X"
+    2 "O"
+    nil))
+


Corrected test

Corrected test

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


clean up spec

clean up spec

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

--- test/atom_finder/ast_spec_test.clj
+++ test/atom_finder/ast_spec_test.clj
@@ -0,0 +1,10 @@
+(ns atom-finder.ast-spec-test
+  (:require [clojure.test :refer :all]
+            [atom-finder.ast-spec :refer :all]
+            [clojure.spec :as s]
+            ))
+
+(deftest count-nodes-test
+  (testing "spec for literal-expression"
+     (is (= 10 (count (s/exercise :atom-finder.ast-spec/literal-expression 10))))
+    ))


Bit of refactoring based on a suggestion from Mike

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/vote-by-mail-works.git/'


First cut of a datastore implementation. A lot of things don't work.

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

--- src/appengine_magic/services/datastore.clj
+++ src/appengine_magic/services/datastore.clj
@@ -0,0 +1,95 @@
+(ns appengine-magic.services.datastore
+  (:import [com.google.appengine.api.datastore DatastoreService DatastoreServiceFactory
+            Key KeyFactory KeyRange
+            Entity]))
+
+
+(defonce *default-datastore-service* (atom nil))
+
+
+(defn- get-datastore-service [& {:keys [service]}]
+  (if (nil? service)
+      (do (when (nil? @*default-datastore-service*)
+            (reset! *default-datastore-service* (DatastoreServiceFactory/getDatastoreService)))
+          @*default-datastore-service*)
+      service))
+
+
+(defn- unqualified-name [sym]
+  (let [s (str sym)
+        last-slash (.lastIndexOf s "/")]
+    (.substring (str s) (inc (if (neg? last-slash)
+                                 (.lastIndexOf s ".")
+                                 last-slash)))))
+
+
+(defprotocol EntityProtocol
+  (create-key [this])
+  (save! [this]))
+
+
+(defn entity-key-helper [entity-record parent key-info datastore-entity-name]
+  ;; TODO: Deal with parent entities.
+  (let [key-info (key-info entity-record)
+        key-object (if key-info
+                       (KeyFactory/createKey datastore-entity-name key-info)
+x                       ;; TODO: This looks really broken. Always 1?
+                       (.getStart (KeyRange. parent datastore-entity-name 1 1)))]
+    (clojure.pprint/pprint key-object)
+    key-object))
+
+
+(defn entity-save-helper [entity-record]
+  (let [key-object (create-key entity-record)
+        entity (Entity. key-object)]
+    (doseq [[property-kw value] entity-record]
+      (let [property-name (.substring (str property-kw) 1)]
+        (.setProperty entity property-name value)))
+    ;; TODO: Allow optional :service argument!
+    (.put (get-datastore-service) entity)))
+
+
+(defn retrieve [entity-record-type key-info &
+                {:keys [parent datastore-entity-name]
+                 :or {datastore-entity-name (unqualified-name (.getName entity-record-type))}}]
+  ;; TODO: Allow optional :service argument!
+  (let [key-object (KeyFactory/createKey datastore-entity-name key-info)
+        entity (.get (get-datastore-service) key-object)
+        properties (into {} (.getProperties entity))
+        kw-keys-properties (reduce (fn [m [k v]] (assoc m (keyword k) v)) {} properties)
+        ;; XXX: No good choice but to use eval here. No way to know the number
+        ;; of arguments to the record constructor at compile-time, and no clean
+        ;; way to access any custom constructor defined by defentity, since that
+        ;; constructor would be in a different namespace.
+        entity-record (eval `(new ~entity-record-type ~@(repeat (count properties) nil)))]
+    (merge entity-record kw-keys-properties)))
+
+
+(defmacro defentity [name properties &
+                     {:keys [parent key-fn datastore-entity-name]
+                      :or {datastore-entity-name (unqualified-name name)}}]
+  ;; All entities need keys. Verify that exactly one of the properties has a
+  ;; :key metadata tag, or a :key-fn optional parameter is given. :key metadata
+  ;; takes precedence over :key-fn.
+  ;; TODO: This ain't checking for :tag :key!
+  (let [key-info (or (keyword (str (first (filter #(meta %) properties))))
+                     key-fn)]
+    (when-not key-info
+      (throw (RuntimeException. "either provide ^:key on one property, or a :key-fn")))
+    `(defrecord ~name ~properties
+       EntityProtocol
+       (create-key [this#] (entity-key-helper this# ~parent ~key-info ~datastore-entity-name))
+       (save! [this#] (entity-save-helper this#)))))
+
+
+;; - Is type metadata necessary, or can it be determined at runtime?
+;;   It helps with optional checking, improves error messages.
+;; - Either give a ^:key metadata to a property, or provide a key-fn.
+;; - Implement transactions.
+
+
+;; (query
+;;  :filter (filter-operator filter-property filter-value) ; can be a vector of filters
+;;  :sort (property direction)                             ; can specify multiples
+;;  :keys-only true                                        ; default is false
+;;  :kind "Person")


change snake case to kebab case

change snake case to kebab case

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


Adding gdx tile macro.

Adding gdx tile macro.

fatal: unable to access 'https://github.com/Yoshiyuka/cthulhu.git/': The requested URL returned error: 403


fixed another minor error

fixed another minor error